{-# OPTIONS_HADDOCK hide #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
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
-- | This is the top-level representation of a program in LLVM. This
-- is the type returned from all of the parsers, and all analysis
-- begins at the Module level.
data Module = Module { moduleIdentifier :: Text
, moduleDataLayout :: DataLayout
, moduleDataLayoutString :: Text
-- ^ The layout of the primitive datatypes on
-- the architecture this module was generated
-- for
, moduleTarget :: Text -- TargetTriple
-- ^ The architecture that this module was
-- generated for
, moduleAssembly :: Assembly
-- ^ Module-level assembly declarations
, moduleDefinedFunctions :: [Function]
, moduleGlobalVariables :: [GlobalVariable]
, moduleExternalValues :: [ExternalValue]
, moduleExternalFunctions :: [ExternalFunction]
, moduleAliases :: [GlobalAlias]
, moduleEnumMetadata :: [Metadata]
-- ^ All enumerations in the Module. These
-- should provide a bit more information than
-- just combing the types appearing in
-- interfaces.
, moduleRetainedTypeMetadata :: [Metadata]
-- ^ The retained types in the Module. Only
-- available with new-style metadata.
, moduleRetainedTypes :: [Type]
-- ^ All of the IR-level types retained by the
-- module.
, moduleNextId :: UniqueId
, moduleTypeSizes :: Type -> Maybe Int
}
-- | Implementation of the Show instance
--
-- FIXME: Print out the external values and functions
printModule :: Module -> Builder
printModule Module { moduleIdentifier = _
, moduleDataLayoutString = layout
, moduleTarget = triple
, moduleAssembly = asm
, moduleAliases = aliases
, moduleGlobalVariables = vars
, moduleDefinedFunctions = funcs
, moduleExternalValues = _ -- evars
, moduleExternalFunctions = _ -- efuncs
} =
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
-- | Get a list of all types of globals in the Module (functions,
-- aliases, and global variables)
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` ()
-- | Force the module to be fully evaluated to rnf form from the
-- top-down. There are cycles, so we have to be careful to avoid
-- traversing them infinitely.
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
-- | Find a function in the Module by its name.
findFunctionByName :: Module -> String -> Maybe Function
findFunctionByName m s = find isFunc $ moduleDefinedFunctions m
where
funcIdent = makeGlobalIdentifier (T.pack s)
isFunc f = functionName f == funcIdent
-- | Find the function named 'main' in the 'Module', if any.
findMain :: Module -> Maybe Function
findMain m = findFunctionByName m "main"