llvm-general-3.2.6.0: src/LLVM/General/Internal/DataLayout.hs
module LLVM.General.Internal.DataLayout where
import Text.ParserCombinators.Parsec
import Control.Monad.Error
import Control.Monad.AnyCont
import Control.Exception
import Data.Word
import Data.Functor
import Foreign.Ptr
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified LLVM.General.Internal.FFI.DataLayout as FFI
import LLVM.General.AST.DataLayout
import LLVM.General.AST.AddrSpace
import LLVM.General.Internal.Coding
import LLVM.General.Internal.String ()
withFFIDataLayout :: DataLayout -> (Ptr FFI.DataLayout -> IO a) -> IO a
withFFIDataLayout dl f = flip runAnyContT return $ do
dls <- encodeM (dataLayoutToString dl)
liftIO $ bracket (FFI.createDataLayout dls) FFI.disposeDataLayout f
dataLayoutToString :: DataLayout -> String
dataLayoutToString dl =
let sTriple :: (Word32, AlignmentInfo) -> String
sTriple (s, ai) = show s ++ ":" ++ show (abiAlignment ai) ++ (maybe "" (\p -> ":" ++ show p) (preferredAlignment ai))
atChar at = case at of
IntegerAlign -> "i"
VectorAlign -> "v"
FloatAlign -> "f"
AggregateAlign -> "a"
StackAlign -> "s"
in
List.intercalate "-" (
(case endianness dl of Just BigEndian -> ["E"]; Just LittleEndian -> ["e"]; _ -> [])
++
(maybe [] (\s -> ["S" ++ show s]) (stackAlignment dl))
++
[ "p" ++ (if a == 0 then "" else show a) ++ ":" ++ sTriple t | (AddrSpace a, t) <- Map.toList . pointerLayouts $ dl]
++
[ atChar at ++ sTriple (s, ai) | ((at, s), ai) <- Map.toList . typeLayouts $ dl ]
++
(maybe [] (\ns -> ["n" ++ (List.intercalate ":" (map show . Set.toList $ ns))]) (nativeSizes dl))
)
parseDataLayout :: String -> Maybe DataLayout
parseDataLayout "" = Nothing
parseDataLayout s =
let
num :: Parser Word32
num = read <$> many digit
triple :: Parser (Word32, AlignmentInfo)
triple = do
s <- num
char ':'
abi <- num
pref <- optionMaybe $ do
char ':'
num
return (s, (AlignmentInfo abi pref))
parseSpec :: Parser (DataLayout -> DataLayout)
parseSpec = choice [
do
char 'e'
return $ \dl -> dl { endianness = Just LittleEndian },
do
char 'E'
return $ \dl -> dl { endianness = Just BigEndian },
do
char 'S'
n <- num
return $ \dl -> dl { stackAlignment = Just n },
do
char 'p'
a <- AddrSpace <$> option 0 (read <$> many1 digit)
char ':'
t <- triple
return $ \dl -> dl { pointerLayouts = Map.insert a t (pointerLayouts dl) },
do
at <- choice [
char 'i' >> return IntegerAlign,
char 'v' >> return VectorAlign,
char 'f' >> return FloatAlign,
char 'a' >> return AggregateAlign,
char 's' >> return StackAlign
]
(sz,ai) <- triple
return $ \dl -> dl { typeLayouts = Map.insert (at,sz) ai (typeLayouts dl) },
do
char 'n'
ns <- num `sepBy` (char ':')
return $ \dl -> dl { nativeSizes = Just (Set.fromList ns) }
]
in
case parse (parseSpec `sepBy` (char '-')) "" s of
Left _ -> error $ "ill formed data layout: " ++ show s
Right fs -> Just $ foldr ($) defaultDataLayout fs