{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DeriveGeneric #-}
#ifndef MIN_VERSION_base
#define MIN_VERSION_base(x,y,z) 1
#endif
module Text.LLVM.AST where
import Data.Functor.Identity (Identity(..))
import Data.Coerce (coerce)
import Data.Data (Data)
import Data.Typeable (Typeable)
import Control.Monad (MonadPlus(mzero,mplus),(<=<),guard)
import Data.Int (Int32,Int64)
import Data.List (genericIndex,genericLength)
import qualified Data.Map as Map
import Data.Semigroup as Sem
import Data.String (IsString(fromString))
import Data.Word (Word8,Word16,Word32,Word64)
import GHC.Generics (Generic, Generic1)
import Text.Parsec
import Text.Parsec.String
#if !(MIN_VERSION_base(4,8,0))
import Control.Applicative ((<$))
import Data.Foldable (Foldable(foldMap))
import Data.Monoid (Monoid(..))
import Data.Traversable (Traversable(sequenceA))
#endif
data Module = Module
{ modSourceName :: Maybe String
, modDataLayout :: DataLayout
, modTypes :: [TypeDecl]
, modNamedMd :: [NamedMd]
, modUnnamedMd :: [UnnamedMd]
, modComdat :: Map.Map String SelectionKind
, modGlobals :: [Global]
, modDeclares :: [Declare]
, modDefines :: [Define]
, modInlineAsm :: InlineAsm
, modAliases :: [GlobalAlias]
} deriving (Data, Eq, Ord, Generic, Show, Typeable)
instance Sem.Semigroup Module where
m1 <> m2 = Module
{ modSourceName = modSourceName m1 `mplus` modSourceName m2
, modDataLayout = modDataLayout m1 <> modDataLayout m2
, modTypes = modTypes m1 <> modTypes m2
, modUnnamedMd = modUnnamedMd m1 <> modUnnamedMd m2
, modNamedMd = modNamedMd m1 <> modNamedMd m2
, modGlobals = modGlobals m1 <> modGlobals m2
, modDeclares = modDeclares m1 <> modDeclares m2
, modDefines = modDefines m1 <> modDefines m2
, modInlineAsm = modInlineAsm m1 <> modInlineAsm m2
, modAliases = modAliases m1 <> modAliases m2
, modComdat = modComdat m1 <> modComdat m2
}
instance Monoid Module where
mempty = emptyModule
mappend m1 m2 = m1 <> m2
emptyModule :: Module
emptyModule = Module
{ modSourceName = mempty
, modDataLayout = mempty
, modTypes = mempty
, modNamedMd = mempty
, modUnnamedMd = mempty
, modGlobals = mempty
, modDeclares = mempty
, modDefines = mempty
, modInlineAsm = mempty
, modAliases = mempty
, modComdat = mempty
}
data NamedMd = NamedMd
{ nmName :: String
, nmValues :: [Int]
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data UnnamedMd = UnnamedMd
{ umIndex :: !Int
, umValues :: ValMd
, umDistinct :: Bool
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data GlobalAlias = GlobalAlias
{ aliasName :: Symbol
, aliasType :: Type
, aliasTarget :: Value
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
type DataLayout = [LayoutSpec]
data LayoutSpec
= BigEndian
| LittleEndian
| PointerSize !Int !Int !Int (Maybe Int)
| IntegerSize !Int !Int (Maybe Int)
| VectorSize !Int !Int (Maybe Int)
| FloatSize !Int !Int (Maybe Int)
| StackObjSize !Int !Int (Maybe Int)
| AggregateSize !Int !Int (Maybe Int)
| NativeIntSize [Int]
| StackAlign !Int
| Mangling Mangling
deriving (Data, Eq, Generic, Ord, Show, Typeable)
data Mangling = ElfMangling
| MipsMangling
| MachOMangling
| WindowsCoffMangling
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
parseDataLayout :: MonadPlus m => String -> m DataLayout
parseDataLayout str =
case parse (pDataLayout <* eof) "<internal>" str of
Left _err -> mzero
Right specs -> return specs
where
pDataLayout :: Parser DataLayout
pDataLayout = sepBy pLayoutSpec (char '-')
pLayoutSpec :: Parser LayoutSpec
pLayoutSpec =
do c <- letter
case c of
'E' -> return BigEndian
'e' -> return LittleEndian
'S' -> StackAlign <$> pInt
'p' -> PointerSize <$> pInt0 <*> pCInt <*> pCInt <*> pPref
'i' -> IntegerSize <$> pInt <*> pCInt <*> pPref
'v' -> VectorSize <$> pInt <*> pCInt <*> pPref
'f' -> FloatSize <$> pInt <*> pCInt <*> pPref
's' -> StackObjSize <$> pInt <*> pCInt <*> pPref
'a' -> AggregateSize <$> pInt <*> pCInt <*> pPref
'n' -> NativeIntSize <$> sepBy pInt (char ':')
'm' -> Mangling <$> (char ':' >> pMangling)
_ -> mzero
pMangling :: Parser Mangling
pMangling =
do c <- letter
case c of
'e' -> return ElfMangling
'm' -> return MipsMangling
'o' -> return MachOMangling
'w' -> return WindowsCoffMangling
_ -> mzero
pInt :: Parser Int
pInt = read <$> many1 digit
pInt0 :: Parser Int
pInt0 = pInt <|> return 0
pCInt :: Parser Int
pCInt = char ':' >> pInt
pPref :: Parser (Maybe Int)
pPref = optionMaybe pCInt
type InlineAsm = [String]
data SelectionKind = ComdatAny
| ComdatExactMatch
| ComdatLargest
| ComdatNoDuplicates
| ComdatSameSize
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
newtype Ident = Ident String
deriving (Data, Eq, Generic, Ord, Show, Typeable)
instance IsString Ident where
fromString = Ident
newtype Symbol = Symbol String
deriving (Data, Eq, Generic, Ord, Show, Typeable)
instance Sem.Semigroup Symbol where
Symbol a <> Symbol b = Symbol (a <> b)
instance Monoid Symbol where
mappend = (<>)
mempty = Symbol mempty
instance IsString Symbol where
fromString = Symbol
data PrimType
= Label
| Void
| Integer Word32
| FloatType FloatType
| X86mmx
| Metadata
deriving (Data, Eq, Generic, Ord, Show, Typeable)
data FloatType
= Half
| Float
| Double
| Fp128
| X86_fp80
| PPC_fp128
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
type Type = Type' Ident
data Type' ident
= PrimType PrimType
| Alias ident
| Array Word64 (Type' ident)
| FunTy (Type' ident) [Type' ident] Bool
| PtrTo (Type' ident)
| Struct [Type' ident]
| PackedStruct [Type' ident]
| Vector Word64 (Type' ident)
| Opaque
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
updateAliasesA :: (Applicative f) => (a -> f (Type' b)) -> Type' a -> f (Type' b)
updateAliasesA f = loop
where
loop ty = case ty of
Array len ety -> Array len <$> (loop ety)
FunTy res ps var -> FunTy <$> (loop res) <*> (traverse loop ps) <*> pure var
PtrTo pty -> PtrTo <$> (loop pty)
Struct fs -> Struct <$> (traverse loop fs)
PackedStruct fs -> PackedStruct <$> (traverse loop fs)
Vector len ety -> Vector <$> pure len <*> (loop ety)
PrimType pty -> pure $ PrimType pty
Opaque -> pure $ Opaque
Alias lab -> f lab
updateAliases :: (a -> Type' b) -> Type' a -> Type' b
updateAliases f = coerce $ updateAliasesA (Identity . f)
isFloatingPoint :: PrimType -> Bool
isFloatingPoint (FloatType _) = True
isFloatingPoint _ = False
isAlias :: Type -> Bool
isAlias Alias{} = True
isAlias _ = False
isPrimTypeOf :: (PrimType -> Bool) -> Type -> Bool
isPrimTypeOf p (PrimType pt) = p pt
isPrimTypeOf _ _ = False
isLabel :: PrimType -> Bool
isLabel Label = True
isLabel _ = False
isInteger :: PrimType -> Bool
isInteger Integer{} = True
isInteger _ = False
isVector :: Type -> Bool
isVector Vector{} = True
isVector _ = False
isVectorOf :: (Type -> Bool) -> Type -> Bool
isVectorOf p (Vector _ e) = p e
isVectorOf _ _ = False
isArray :: Type -> Bool
isArray ty = case ty of
Array _ _ -> True
_ -> False
isPointer :: Type -> Bool
isPointer (PtrTo _) = True
isPointer _ = False
data NullResult lab
= HasNull (Value' lab)
| ResolveNull Ident
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
primTypeNull :: PrimType -> Value' lab
primTypeNull (Integer 1) = ValBool False
primTypeNull (Integer _) = ValInteger 0
primTypeNull (FloatType ft) = floatTypeNull ft
primTypeNull _ = ValZeroInit
floatTypeNull :: FloatType -> Value' lab
floatTypeNull Float = ValFloat 0
floatTypeNull Double = ValDouble 0
floatTypeNull X86_fp80 = ValFP80 $ FP80_LongDouble 0 0
floatTypeNull _ = error "must be a float type"
typeNull :: Type -> NullResult lab
typeNull (PrimType pt) = HasNull (primTypeNull pt)
typeNull PtrTo{} = HasNull ValNull
typeNull (Alias i) = ResolveNull i
typeNull _ = HasNull ValZeroInit
elimFunTy :: MonadPlus m => Type -> m (Type,[Type],Bool)
elimFunTy (FunTy ret args va) = return (ret,args,va)
elimFunTy _ = mzero
elimAlias :: MonadPlus m => Type -> m Ident
elimAlias (Alias i) = return i
elimAlias _ = mzero
elimPtrTo :: MonadPlus m => Type -> m Type
elimPtrTo (PtrTo ty) = return ty
elimPtrTo _ = mzero
elimVector :: MonadPlus m => Type -> m (Word64,Type)
elimVector (Vector n pty) = return (n,pty)
elimVector _ = mzero
elimArray :: MonadPlus m => Type -> m (Word64, Type)
elimArray (Array n ety) = return (n, ety)
elimArray _ = mzero
elimFunPtr :: MonadPlus m => Type -> m (Type,[Type],Bool)
elimFunPtr = elimFunTy <=< elimPtrTo
elimPrimType :: MonadPlus m => Type -> m PrimType
elimPrimType (PrimType pt) = return pt
elimPrimType _ = mzero
elimFloatType :: MonadPlus m => PrimType -> m FloatType
elimFloatType (FloatType ft) = return ft
elimFloatType _ = mzero
elimSequentialType :: MonadPlus m => Type -> m Type
elimSequentialType ty = case ty of
Array _ elTy -> return elTy
PtrTo elTy -> return elTy
Vector _ pty -> return pty
_ -> mzero
data TypeDecl = TypeDecl
{ typeName :: Ident
, typeValue :: Type
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data Global = Global
{ globalSym :: Symbol
, globalAttrs :: GlobalAttrs
, globalType :: Type
, globalValue :: Maybe Value
, globalAlign :: Maybe Align
, globalMetadata :: GlobalMdAttachments
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
addGlobal :: Global -> Module -> Module
addGlobal g m = m { modGlobals = g : modGlobals m }
data GlobalAttrs = GlobalAttrs
{ gaLinkage :: Maybe Linkage
, gaVisibility :: Maybe Visibility
, gaConstant :: Bool
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
emptyGlobalAttrs :: GlobalAttrs
emptyGlobalAttrs = GlobalAttrs
{ gaLinkage = Nothing
, gaVisibility = Nothing
, gaConstant = False
}
data Declare = Declare
{ decRetType :: Type
, decName :: Symbol
, decArgs :: [Type]
, decVarArgs :: Bool
, decAttrs :: [FunAttr]
, decComdat :: Maybe String
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
decFunType :: Declare -> Type
decFunType Declare { .. } = PtrTo (FunTy decRetType decArgs decVarArgs)
data Define = Define
{ defLinkage :: Maybe Linkage
, defRetType :: Type
, defName :: Symbol
, defArgs :: [Typed Ident]
, defVarArgs :: Bool
, defAttrs :: [FunAttr]
, defSection :: Maybe String
, defGC :: Maybe GC
, defBody :: [BasicBlock]
, defMetadata :: FnMdAttachments
, defComdat :: Maybe String
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
defFunType :: Define -> Type
defFunType Define { .. } =
PtrTo (FunTy defRetType (map typedType defArgs) defVarArgs)
addDefine :: Define -> Module -> Module
addDefine d m = m { modDefines = d : modDefines m }
data FunAttr
= AlignStack Int
| Alwaysinline
| Builtin
| Cold
| Inlinehint
| Jumptable
| Minsize
| Naked
| Nobuiltin
| Noduplicate
| Noimplicitfloat
| Noinline
| Nonlazybind
| Noredzone
| Noreturn
| Nounwind
| Optnone
| Optsize
| Readnone
| Readonly
| ReturnsTwice
| SanitizeAddress
| SanitizeMemory
| SanitizeThread
| SSP
| SSPreq
| SSPstrong
| UWTable
deriving (Data, Eq, Generic, Ord, Show, Typeable)
data BlockLabel
= Named Ident
| Anon Int
deriving (Data, Eq, Generic, Ord, Show, Typeable)
instance IsString BlockLabel where
fromString str = Named (fromString str)
data BasicBlock' lab = BasicBlock
{ bbLabel :: Maybe lab
, bbStmts :: [Stmt' lab]
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type BasicBlock = BasicBlock' BlockLabel
brTargets :: BasicBlock' lab -> [lab]
brTargets (BasicBlock _ stmts) =
case stmtInstr (last stmts) of
Br _ t1 t2 -> [t1, t2]
Invoke _ _ _ to uw -> [to, uw]
Jump t -> [t]
Switch _ l ls -> l : map snd ls
IndirectBr _ ls -> ls
_ -> []
data Linkage
= Private
| LinkerPrivate
| LinkerPrivateWeak
| LinkerPrivateWeakDefAuto
| Internal
| AvailableExternally
| Linkonce
| Weak
| Common
| Appending
| ExternWeak
| LinkonceODR
| WeakODR
| External
| DLLImport
| DLLExport
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
data Visibility = DefaultVisibility
| HiddenVisibility
| ProtectedVisibility
deriving (Data, Eq, Generic, Ord, Show, Typeable)
newtype GC = GC
{ getGC :: String
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data Typed a = Typed
{ typedType :: Type
, typedValue :: a
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
instance Foldable Typed where
foldMap f t = f (typedValue t)
instance Traversable Typed where
sequenceA t = mk `fmap` typedValue t
where
mk b = t { typedValue = b }
mapMTyped :: Monad m => (a -> m b) -> Typed a -> m (Typed b)
mapMTyped f t = do
b <- f (typedValue t)
return t { typedValue = b }
data ArithOp
= Add Bool Bool
| FAdd
| Sub Bool Bool
| FSub
| Mul Bool Bool
| FMul
| UDiv Bool
| SDiv Bool
| FDiv
| URem
| SRem
| FRem
deriving (Data, Eq, Generic, Ord, Show, Typeable)
isIArith :: ArithOp -> Bool
isIArith Add{} = True
isIArith Sub{} = True
isIArith Mul{} = True
isIArith UDiv{} = True
isIArith SDiv{} = True
isIArith URem = True
isIArith SRem = True
isIArith _ = False
isFArith :: ArithOp -> Bool
isFArith = not . isIArith
data BitOp
= Shl Bool Bool
| Lshr Bool
| Ashr Bool
| And
| Or
| Xor
deriving (Data, Eq, Generic, Ord, Show, Typeable)
data ConvOp
= Trunc
| ZExt
| SExt
| FpTrunc
| FpExt
| FpToUi
| FpToSi
| UiToFp
| SiToFp
| PtrToInt
| IntToPtr
| BitCast
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
data AtomicRWOp
= AtomicXchg
| AtomicAdd
| AtomicSub
| AtomicAnd
| AtomicNand
| AtomicOr
| AtomicXor
| AtomicMax
| AtomicMin
| AtomicUMax
| AtomicUMin
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
data AtomicOrdering
= Unordered
| Monotonic
| Acquire
| Release
| AcqRel
| SeqCst
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
type Align = Int
data Instr' lab
= Ret (Typed (Value' lab))
| RetVoid
| Arith ArithOp (Typed (Value' lab)) (Value' lab)
| Bit BitOp (Typed (Value' lab)) (Value' lab)
| Conv ConvOp (Typed (Value' lab)) Type
| Call Bool Type (Value' lab) [Typed (Value' lab)]
| Alloca Type (Maybe (Typed (Value' lab))) (Maybe Int)
| Load (Typed (Value' lab)) (Maybe AtomicOrdering) (Maybe Align)
| Store (Typed (Value' lab)) (Typed (Value' lab)) (Maybe AtomicOrdering) (Maybe Align)
| Fence (Maybe String) AtomicOrdering
| CmpXchg Bool Bool (Typed (Value' lab)) (Typed (Value' lab)) (Typed (Value' lab)) (Maybe String) AtomicOrdering AtomicOrdering
| AtomicRW Bool AtomicRWOp (Typed (Value' lab)) (Typed (Value' lab)) (Maybe String) AtomicOrdering
| ICmp ICmpOp (Typed (Value' lab)) (Value' lab)
| FCmp FCmpOp (Typed (Value' lab)) (Value' lab)
| Phi Type [(Value' lab,lab)]
| GEP Bool (Typed (Value' lab)) [Typed (Value' lab)]
| Select (Typed (Value' lab)) (Typed (Value' lab)) (Value' lab)
| ExtractValue (Typed (Value' lab)) [Int32]
| InsertValue (Typed (Value' lab)) (Typed (Value' lab)) [Int32]
| ExtractElt (Typed (Value' lab)) (Value' lab)
| InsertElt (Typed (Value' lab)) (Typed (Value' lab)) (Value' lab)
| ShuffleVector (Typed (Value' lab)) (Value' lab) (Typed (Value' lab))
| Jump lab
| Br (Typed (Value' lab)) lab lab
| Invoke Type (Value' lab) [Typed (Value' lab)] lab lab
| Comment String
| Unreachable
| Unwind
| VaArg (Typed (Value' lab)) Type
| IndirectBr (Typed (Value' lab)) [lab]
| Switch (Typed (Value' lab)) lab [(Integer,lab)]
| LandingPad Type (Maybe (Typed (Value' lab))) Bool [Clause' lab]
| Resume (Typed (Value' lab))
deriving (Data, Eq, Functor, Generic, Ord, Show, Typeable)
type Instr = Instr' BlockLabel
data Clause' lab
= Catch (Typed (Value' lab))
| Filter (Typed (Value' lab))
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type Clause = Clause' BlockLabel
isTerminator :: Instr' lab -> Bool
isTerminator instr = case instr of
Ret{} -> True
RetVoid -> True
Jump{} -> True
Br{} -> True
Unreachable -> True
Unwind -> True
Invoke{} -> True
IndirectBr{} -> True
Switch{} -> True
Resume{} -> True
_ -> False
isComment :: Instr' lab -> Bool
isComment Comment{} = True
isComment _ = False
isPhi :: Instr' lab -> Bool
isPhi Phi{} = True
isPhi _ = False
data ICmpOp = Ieq | Ine | Iugt | Iuge | Iult | Iule | Isgt | Isge | Islt | Isle
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
data FCmpOp = Ffalse | Foeq | Fogt | Foge | Folt | Fole | Fone
| Ford | Fueq | Fugt | Fuge | Fult | Fule | Fune
| Funo | Ftrue
deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)
data Value' lab
= ValInteger Integer
| ValBool Bool
| ValFloat Float
| ValDouble Double
| ValFP80 FP80Value
| ValIdent Ident
| ValSymbol Symbol
| ValNull
| ValArray Type [Value' lab]
| ValVector Type [Value' lab]
| ValStruct [Typed (Value' lab)]
| ValPackedStruct [Typed (Value' lab)]
| ValString [Word8]
| ValConstExpr (ConstExpr' lab)
| ValUndef
| ValLabel lab
| ValZeroInit
| ValAsm Bool Bool String String
| ValMd (ValMd' lab)
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type Value = Value' BlockLabel
data FP80Value = FP80_LongDouble Word16 Word64
deriving (Data, Eq, Ord, Generic, Show, Typeable)
data ValMd' lab
= ValMdString String
| ValMdValue (Typed (Value' lab))
| ValMdRef Int
| ValMdNode [Maybe (ValMd' lab)]
| ValMdLoc (DebugLoc' lab)
| ValMdDebugInfo (DebugInfo' lab)
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type ValMd = ValMd' BlockLabel
type KindMd = String
type FnMdAttachments = Map.Map KindMd ValMd
type GlobalMdAttachments = Map.Map KindMd ValMd
data DebugLoc' lab = DebugLoc
{ dlLine :: Word32
, dlCol :: Word32
, dlScope :: ValMd' lab
, dlIA :: Maybe (ValMd' lab)
, dlImplicit :: Bool
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DebugLoc = DebugLoc' BlockLabel
isConst :: Value' lab -> Bool
isConst ValInteger{} = True
isConst ValBool{} = True
isConst ValFloat{} = True
isConst ValDouble{} = True
isConst ValFP80{} = True
isConst ValConstExpr{} = True
isConst ValZeroInit = True
isConst ValNull = True
isConst _ = False
elimValSymbol :: MonadPlus m => Value' lab -> m Symbol
elimValSymbol (ValSymbol sym) = return sym
elimValSymbol _ = mzero
elimValInteger :: MonadPlus m => Value' lab -> m Integer
elimValInteger (ValInteger i) = return i
elimValInteger _ = mzero
data Stmt' lab
= Result Ident (Instr' lab) [(String,ValMd' lab)]
| Effect (Instr' lab) [(String,ValMd' lab)]
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type Stmt = Stmt' BlockLabel
stmtInstr :: Stmt' lab -> Instr' lab
stmtInstr (Result _ i _) = i
stmtInstr (Effect i _) = i
stmtMetadata :: Stmt' lab -> [(String,ValMd' lab)]
stmtMetadata stmt = case stmt of
Result _ _ mds -> mds
Effect _ mds -> mds
extendMetadata :: (String,ValMd' lab) -> Stmt' lab -> Stmt' lab
extendMetadata md stmt = case stmt of
Result r i mds -> Result r i (md:mds)
Effect i mds -> Effect i (md:mds)
data ConstExpr' lab
= ConstGEP Bool (Maybe Word64) (Maybe Type) [Typed (Value' lab)]
| ConstConv ConvOp (Typed (Value' lab)) Type
| ConstSelect (Typed (Value' lab)) (Typed (Value' lab)) (Typed (Value' lab))
| ConstBlockAddr Symbol lab
| ConstFCmp FCmpOp (Typed (Value' lab)) (Typed (Value' lab))
| ConstICmp ICmpOp (Typed (Value' lab)) (Typed (Value' lab))
| ConstArith ArithOp (Typed (Value' lab)) (Value' lab)
| ConstBit BitOp (Typed (Value' lab)) (Value' lab)
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type ConstExpr = ConstExpr' BlockLabel
data DebugInfo' lab
= DebugInfoBasicType DIBasicType
| DebugInfoCompileUnit (DICompileUnit' lab)
| DebugInfoCompositeType (DICompositeType' lab)
| DebugInfoDerivedType (DIDerivedType' lab)
| DebugInfoEnumerator String !Int64
| DebugInfoExpression DIExpression
| DebugInfoFile DIFile
| DebugInfoGlobalVariable (DIGlobalVariable' lab)
| DebugInfoGlobalVariableExpression (DIGlobalVariableExpression' lab)
| DebugInfoLexicalBlock (DILexicalBlock' lab)
| DebugInfoLexicalBlockFile (DILexicalBlockFile' lab)
| DebugInfoLocalVariable (DILocalVariable' lab)
| DebugInfoSubprogram (DISubprogram' lab)
| DebugInfoSubrange DISubrange
| DebugInfoSubroutineType (DISubroutineType' lab)
| DebugInfoNameSpace (DINameSpace' lab)
| DebugInfoTemplateTypeParameter (DITemplateTypeParameter' lab)
| DebugInfoTemplateValueParameter (DITemplateValueParameter' lab)
| DebugInfoImportedEntity (DIImportedEntity' lab)
| DebugInfoLabel (DILabel' lab)
deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DebugInfo = DebugInfo' BlockLabel
type DILabel = DILabel' BlockLabel
data DILabel' lab = DILabel
{ dilScope :: Maybe (ValMd' lab)
, dilName :: String
, dilFile :: Maybe (ValMd' lab)
, dilLine :: Word32
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DIImportedEntity = DIImportedEntity' BlockLabel
data DIImportedEntity' lab = DIImportedEntity
{ diieTag :: DwarfTag
, diieScope :: Maybe (ValMd' lab)
, diieEntity :: Maybe (ValMd' lab)
, diieFile :: Maybe (ValMd' lab)
, diieLine :: Word32
, diieName :: Maybe String
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DITemplateTypeParameter = DITemplateTypeParameter' BlockLabel
data DITemplateTypeParameter' lab = DITemplateTypeParameter
{ dittpName :: Maybe String
, dittpType :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DITemplateValueParameter = DITemplateValueParameter' BlockLabel
data DITemplateValueParameter' lab = DITemplateValueParameter
{ ditvpTag :: DwarfTag
, ditvpName :: Maybe String
, ditvpType :: Maybe (ValMd' lab)
, ditvpValue :: ValMd' lab
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DINameSpace = DINameSpace' BlockLabel
data DINameSpace' lab = DINameSpace
{ dinsName :: Maybe String
, dinsScope :: ValMd' lab
, dinsFile :: ValMd' lab
, dinsLine :: Word32
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DwarfAttrEncoding = Word16
type DwarfLang = Word16
type DwarfTag = Word16
type DwarfVirtuality = Word8
type DIFlags = Word32
type DIEmissionKind = Word8
data DIBasicType = DIBasicType
{ dibtTag :: DwarfTag
, dibtName :: String
, dibtSize :: Word64
, dibtAlign :: Word64
, dibtEncoding :: DwarfAttrEncoding
, dibtFlags :: Maybe DIFlags
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data DICompileUnit' lab = DICompileUnit
{ dicuLanguage :: DwarfLang
, dicuFile :: Maybe (ValMd' lab)
, dicuProducer :: Maybe String
, dicuIsOptimized :: Bool
, dicuFlags :: Maybe String
, dicuRuntimeVersion :: Word16
, dicuSplitDebugFilename :: Maybe FilePath
, dicuEmissionKind :: DIEmissionKind
, dicuEnums :: Maybe (ValMd' lab)
, dicuRetainedTypes :: Maybe (ValMd' lab)
, dicuSubprograms :: Maybe (ValMd' lab)
, dicuGlobals :: Maybe (ValMd' lab)
, dicuImports :: Maybe (ValMd' lab)
, dicuMacros :: Maybe (ValMd' lab)
, dicuDWOId :: Word64
, dicuSplitDebugInlining :: Bool
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DICompileUnit = DICompileUnit' BlockLabel
data DICompositeType' lab = DICompositeType
{ dictTag :: DwarfTag
, dictName :: Maybe String
, dictFile :: Maybe (ValMd' lab)
, dictLine :: Word32
, dictScope :: Maybe (ValMd' lab)
, dictBaseType :: Maybe (ValMd' lab)
, dictSize :: Word64
, dictAlign :: Word64
, dictOffset :: Word64
, dictFlags :: DIFlags
, dictElements :: Maybe (ValMd' lab)
, dictRuntimeLang :: DwarfLang
, dictVTableHolder :: Maybe (ValMd' lab)
, dictTemplateParams :: Maybe (ValMd' lab)
, dictIdentifier :: Maybe String
, dictDiscriminator :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DICompositeType = DICompositeType' BlockLabel
data DIDerivedType' lab = DIDerivedType
{ didtTag :: DwarfTag
, didtName :: Maybe String
, didtFile :: Maybe (ValMd' lab)
, didtLine :: Word32
, didtScope :: Maybe (ValMd' lab)
, didtBaseType :: Maybe (ValMd' lab)
, didtSize :: Word64
, didtAlign :: Word64
, didtOffset :: Word64
, didtFlags :: DIFlags
, didtExtraData :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DIDerivedType = DIDerivedType' BlockLabel
data DIExpression = DIExpression
{ dieElements :: [Word64]
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data DIFile = DIFile
{ difFilename :: FilePath
, difDirectory :: FilePath
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data DIGlobalVariable' lab = DIGlobalVariable
{ digvScope :: Maybe (ValMd' lab)
, digvName :: Maybe String
, digvLinkageName :: Maybe String
, digvFile :: Maybe (ValMd' lab)
, digvLine :: Word32
, digvType :: Maybe (ValMd' lab)
, digvIsLocal :: Bool
, digvIsDefinition :: Bool
, digvVariable :: Maybe (ValMd' lab)
, digvDeclaration :: Maybe (ValMd' lab)
, digvAlignment :: Maybe Word32
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DIGlobalVariable = DIGlobalVariable' BlockLabel
data DIGlobalVariableExpression' lab = DIGlobalVariableExpression
{ digveVariable :: Maybe (ValMd' lab)
, digveExpression :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DIGlobalVariableExpression = DIGlobalVariableExpression' BlockLabel
data DILexicalBlock' lab = DILexicalBlock
{ dilbScope :: Maybe (ValMd' lab)
, dilbFile :: Maybe (ValMd' lab)
, dilbLine :: Word32
, dilbColumn :: Word16
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DILexicalBlock = DILexicalBlock' BlockLabel
data DILexicalBlockFile' lab = DILexicalBlockFile
{ dilbfScope :: ValMd' lab
, dilbfFile :: Maybe (ValMd' lab)
, dilbfDiscriminator :: Word32
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DILexicalBlockFile = DILexicalBlockFile' BlockLabel
data DILocalVariable' lab = DILocalVariable
{ dilvScope :: Maybe (ValMd' lab)
, dilvName :: Maybe String
, dilvFile :: Maybe (ValMd' lab)
, dilvLine :: Word32
, dilvType :: Maybe (ValMd' lab)
, dilvArg :: Word16
, dilvFlags :: DIFlags
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DILocalVariable = DILocalVariable' BlockLabel
data DISubprogram' lab = DISubprogram
{ dispScope :: Maybe (ValMd' lab)
, dispName :: Maybe String
, dispLinkageName :: Maybe String
, dispFile :: Maybe (ValMd' lab)
, dispLine :: Word32
, dispType :: Maybe (ValMd' lab)
, dispIsLocal :: Bool
, dispIsDefinition :: Bool
, dispScopeLine :: Word32
, dispContainingType :: Maybe (ValMd' lab)
, dispVirtuality :: DwarfVirtuality
, dispVirtualIndex :: Word32
, dispThisAdjustment :: Int64
, dispFlags :: DIFlags
, dispIsOptimized :: Bool
, dispUnit :: Maybe (ValMd' lab)
, dispTemplateParams :: Maybe (ValMd' lab)
, dispDeclaration :: Maybe (ValMd' lab)
, dispVariables :: Maybe (ValMd' lab)
, dispThrownTypes :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DISubprogram = DISubprogram' BlockLabel
data DISubrange = DISubrange
{ disrCount :: Int64
, disrLowerBound :: Int64
} deriving (Data, Eq, Generic, Ord, Show, Typeable)
data DISubroutineType' lab = DISubroutineType
{ distFlags :: DIFlags
, distTypeArray :: Maybe (ValMd' lab)
} deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)
type DISubroutineType = DISubroutineType' BlockLabel
data IndexResult
= Invalid
| HasType Type
| Resolve Ident (Type -> IndexResult)
deriving (Generic, Typeable)
isInvalid :: IndexResult -> Bool
isInvalid ir = case ir of
Invalid -> True
_ -> False
resolveGepFull ::
(Ident -> Maybe Type) ->
Type ->
[Typed (Value' lab)] ->
Maybe Type
resolveGepFull env t ixs = go (resolveGep t ixs)
where
go Invalid = Nothing
go (HasType result) = Just result
go (Resolve ident resume) = go . resume =<< env ident
resolveGep :: Type -> [Typed (Value' lab)] -> IndexResult
resolveGep (PtrTo ty0) (v:ixs0)
| isGepIndex v =
resolveGepBody ty0 ixs0
resolveGep ty0@PtrTo{} (v:ixs0)
| Just i <- elimAlias (typedType v) =
Resolve i (\ty' -> resolveGep ty0 (Typed ty' (typedValue v):ixs0))
resolveGep (Alias i) ixs =
Resolve i (\ty' -> resolveGep ty' ixs)
resolveGep _ _ = Invalid
resolveGepBody :: Type -> [Typed (Value' lab)] -> IndexResult
resolveGepBody (Struct fs) (v:ixs)
| Just i <- isGepStructIndex v, genericLength fs > i =
resolveGepBody (genericIndex fs i) ixs
resolveGepBody (PackedStruct fs) (v:ixs)
| Just i <- isGepStructIndex v, genericLength fs > i =
resolveGepBody (genericIndex fs i) ixs
resolveGepBody (Alias name) is
| not (null is) =
Resolve name (\ty' -> resolveGepBody ty' is)
resolveGepBody (Array _ ty') (v:ixs)
| isGepIndex v =
resolveGepBody ty' ixs
resolveGepBody (Vector _ tp) [val]
| isGepIndex val =
HasType tp
resolveGepBody ty (v:ixs)
| Just i <- elimAlias (typedType v) =
Resolve i (\ty' -> resolveGepBody ty (Typed ty' (typedValue v):ixs))
resolveGepBody ty [] =
HasType ty
resolveGepBody _ _ =
Invalid
isGepIndex :: Typed (Value' lab) -> Bool
isGepIndex tv =
isPrimTypeOf isInteger (typedType tv) ||
isVectorOf (isPrimTypeOf isInteger) (typedType tv)
isGepStructIndex :: Typed (Value' lab) -> Maybe Integer
isGepStructIndex tv = do
guard (isGepIndex tv)
elimValInteger (typedValue tv)
resolveValueIndex :: Type -> [Int32] -> IndexResult
resolveValueIndex ty is@(ix:ixs) = case ty of
Struct fs | genericLength fs > ix
-> resolveValueIndex (genericIndex fs ix) ixs
PackedStruct fs | genericLength fs > ix
-> resolveValueIndex (genericIndex fs ix) ixs
Array n ty' | fromIntegral ix < n
-> resolveValueIndex ty' ixs
Alias name
-> Resolve name (\ty' -> resolveValueIndex ty' is)
_ -> Invalid
resolveValueIndex ty [] = HasType ty