module Data.LLVM.Types (
Module(..),
moduleGlobals,
findFunctionByName,
findMain,
module Data.LLVM.Types.Attributes,
module Data.LLVM.Types.Dwarf,
module Data.LLVM.Types.Identifiers,
module Data.LLVM.Types.Referential,
module Data.LLVM.Internal.DataLayout
) where
import Control.DeepSeq
import Control.Monad.Trans.State.Strict
import qualified Data.HashSet as S
import Data.List ( find, intersperse )
import Data.Monoid
import Data.Text ( Text )
import qualified Data.Text as T
import Data.Text.Lazy ( toStrict )
import Data.Text.Lazy.Builder
import Data.LLVM.Internal.ForceModule
import Data.LLVM.Internal.Printers
import Data.LLVM.Internal.DataLayout
import Data.LLVM.Types.Attributes
import Data.LLVM.Types.Dwarf
import Data.LLVM.Types.Identifiers
import Data.LLVM.Types.Referential
data Module = Module { moduleIdentifier :: Text
, moduleDataLayout :: DataLayout
, moduleDataLayoutString :: Text
, moduleTarget :: Text
, moduleAssembly :: Assembly
, moduleDefinedFunctions :: [Function]
, moduleGlobalVariables :: [GlobalVariable]
, moduleExternalValues :: [ExternalValue]
, moduleExternalFunctions :: [ExternalFunction]
, moduleAliases :: [GlobalAlias]
, moduleEnumMetadata :: [Metadata]
, moduleRetainedTypeMetadata :: [Metadata]
, moduleRetainedTypes :: [Type]
, moduleNextId :: UniqueId
, moduleTypeSizes :: Type -> Maybe Int
}
printModule :: Module -> Builder
printModule Module { moduleIdentifier = _
, moduleDataLayoutString = layout
, moduleTarget = triple
, moduleAssembly = asm
, moduleAliases = aliases
, moduleGlobalVariables = vars
, moduleDefinedFunctions = funcs
, moduleExternalValues = _
, moduleExternalFunctions = _
} =
mconcat [ layoutS, singleton '\n', tripleS, singleton '\n', asmS, singleton '\n'
, aliasesS, singleton '\n', varS, fromString "\n\n", funcS, singleton '\n'
]
where
layoutS = mconcat [ fromString "target datalayout = \""
, fromString (show layout), singleton '"'
]
tripleS = mconcat [ fromString "target triple = \"", fromString (show triple), singleton '"' ]
asmS = printAsm asm
aliasesS = mconcat $ intersperse (fromString "\n") $ map (printValue . toValue) aliases
varS = mconcat $ intersperse (fromString "\n") $ map (printValue . toValue) vars
funcS = mconcat $ intersperse (fromString "\n\n") $ map (printValue . toValue) funcs
moduleGlobals :: Module -> [Value]
moduleGlobals m = concat [ map toValue $ moduleAliases m
, map toValue $ moduleGlobalVariables m
, map toValue $ moduleDefinedFunctions m
, map toValue $ moduleExternalValues m
, map toValue $ moduleExternalFunctions m
]
instance Show Module where
show = T.unpack . toStrict . toLazyText . printModule
instance NFData Module where
rnf m = evalState (forceModule m) (S.empty, S.empty) `seq` ()
forceModule :: Module -> ForceMonad Module
forceModule m = do
mapM_ forceGlobalAlias (moduleAliases m)
mapM_ forceGlobalVariable (moduleGlobalVariables m)
mapM_ forceFunction (moduleDefinedFunctions m)
mapM_ forceExternalValue (moduleExternalValues m)
mapM_ forceExternalFunction (moduleExternalFunctions m)
mapM_ forceMetadataT (moduleEnumMetadata m)
mapM_ forceMetadataT (moduleRetainedTypeMetadata m)
return $ moduleAssembly m `deepseq` m `seq` m
findFunctionByName :: Module -> String -> Maybe Function
findFunctionByName m s = find isFunc $ moduleDefinedFunctions m
where
funcIdent = makeGlobalIdentifier (T.pack s)
isFunc f = functionName f == funcIdent
findMain :: Module -> Maybe Function
findMain m = findFunctionByName m "main"