llvm-pretty 0.13.1.0 → 0.14.0.0
raw patch · 13 files changed
+971/−231 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Text.LLVM.AST: data DIBasicType
- Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.DIBasicType
- Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.DIBasicType
- Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.DIBasicType
- Text.LLVM.AST: instance GHC.Enum.Enum Text.LLVM.AST.ConvOp
- Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.DIBasicType
- Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.DIBasicType
- Text.LLVM.PP: ppDIBasicType :: Fmt DIBasicType
- Text.LLVM.PP: ppLayoutBody :: Int -> Int -> Fmt (Maybe Int)
+ Text.LLVM: bbStmtModifier :: (Stmt -> Stmt) -> BB a -> BB a
+ Text.LLVM.AST: Alignment :: !NumBits -> Maybe NumBits -> Alignment
+ Text.LLVM.AST: AllocaAddrSpace :: !AddressSpace -> LayoutSpec
+ Text.LLVM.AST: DbgRecAssign :: ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> DbgRecAssign' lab
+ Text.LLVM.AST: DbgRecDeclare :: ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> DbgRecDeclare' lab
+ Text.LLVM.AST: DbgRecLabel :: ValMd' lab -> ValMd' lab -> DbgRecLabel' lab
+ Text.LLVM.AST: DbgRecValue :: ValMd' lab -> ValMd' lab -> ValMd' lab -> ValMd' lab -> DbgRecValue' lab
+ Text.LLVM.AST: DbgRecValueSimple :: ValMd' lab -> ValMd' lab -> ValMd' lab -> Typed (Value' lab) -> DbgRecValueSimple' lab
+ Text.LLVM.AST: DebugRecordAssign :: DbgRecAssign' lab -> DebugRecord' lab
+ Text.LLVM.AST: DebugRecordDeclare :: DbgRecDeclare' lab -> DebugRecord' lab
+ Text.LLVM.AST: DebugRecordLabel :: DbgRecLabel' lab -> DebugRecord' lab
+ Text.LLVM.AST: DebugRecordValue :: DbgRecValue' lab -> DebugRecord' lab
+ Text.LLVM.AST: DebugRecordValueSimple :: DbgRecValueSimple' lab -> DebugRecord' lab
+ Text.LLVM.AST: GEP_Inbounds :: GEPAttr
+ Text.LLVM.AST: GEP_NUSW :: GEPAttr
+ Text.LLVM.AST: GEP_NUW :: GEPAttr
+ Text.LLVM.AST: GlobalAddrSpace :: !AddressSpace -> LayoutSpec
+ Text.LLVM.AST: GoffMangling :: Mangling
+ Text.LLVM.AST: NonIntegralPointerSpaces :: [AddressSpace] -> LayoutSpec
+ Text.LLVM.AST: ProgramAddrSpace :: !AddressSpace -> LayoutSpec
+ Text.LLVM.AST: PtrSize :: !AddressSpace -> Storage -> Maybe NumBits -> PointerSize
+ Text.LLVM.AST: Range :: Int -> Integer -> Integer -> RangeSpec
+ Text.LLVM.AST: RangeIndex :: Word64 -> RangeSpec
+ Text.LLVM.AST: Storage :: !NumBits -> Alignment -> Storage
+ Text.LLVM.AST: WindowsX86CoffMangling :: Mangling
+ Text.LLVM.AST: XCoffMangling :: Mangling
+ Text.LLVM.AST: [alignABI] :: Alignment -> !NumBits
+ Text.LLVM.AST: [alignPreferred] :: Alignment -> Maybe NumBits
+ Text.LLVM.AST: [dibtNumExtraInhabitants] :: DIBasicType' lab -> Word64
+ Text.LLVM.AST: [dictBitStride] :: DICompositeType' lab -> Maybe (ValMd' lab)
+ Text.LLVM.AST: [dictEnumKind] :: DICompositeType' lab -> Maybe Word32
+ Text.LLVM.AST: [dictNumExtraInhabitants] :: DICompositeType' lab -> Word64
+ Text.LLVM.AST: [dictSpecification] :: DICompositeType' lab -> Maybe (ValMd' lab)
+ Text.LLVM.AST: [dilColumn] :: DILabel' lab -> Word32
+ Text.LLVM.AST: [dilCoroSuspendIdx] :: DILabel' lab -> Maybe Word32
+ Text.LLVM.AST: [dilIsArtificial] :: DILabel' lab -> Bool
+ Text.LLVM.AST: [dlAtomGroup] :: DebugLoc' lab -> Word64
+ Text.LLVM.AST: [dlAtomRank] :: DebugLoc' lab -> Word64
+ Text.LLVM.AST: [draAssignID] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draExpressionAddr] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draExpression] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draLocalVariable] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draLocation] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draValAsMetadataAddr] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [draValAsMetadata] :: DbgRecAssign' lab -> ValMd' lab
+ Text.LLVM.AST: [drdExpression] :: DbgRecDeclare' lab -> ValMd' lab
+ Text.LLVM.AST: [drdLocalVariable] :: DbgRecDeclare' lab -> ValMd' lab
+ Text.LLVM.AST: [drdLocation] :: DbgRecDeclare' lab -> ValMd' lab
+ Text.LLVM.AST: [drdValAsMetadata] :: DbgRecDeclare' lab -> ValMd' lab
+ Text.LLVM.AST: [drlLabel] :: DbgRecLabel' lab -> ValMd' lab
+ Text.LLVM.AST: [drlLocation] :: DbgRecLabel' lab -> ValMd' lab
+ Text.LLVM.AST: [drvExpression] :: DbgRecValue' lab -> ValMd' lab
+ Text.LLVM.AST: [drvLocalVariable] :: DbgRecValue' lab -> ValMd' lab
+ Text.LLVM.AST: [drvLocation] :: DbgRecValue' lab -> ValMd' lab
+ Text.LLVM.AST: [drvValAsMetadata] :: DbgRecValue' lab -> ValMd' lab
+ Text.LLVM.AST: [drvsExpression] :: DbgRecValueSimple' lab -> ValMd' lab
+ Text.LLVM.AST: [drvsLocalVariable] :: DbgRecValueSimple' lab -> ValMd' lab
+ Text.LLVM.AST: [drvsLocation] :: DbgRecValueSimple' lab -> ValMd' lab
+ Text.LLVM.AST: [drvsValue] :: DbgRecValueSimple' lab -> Typed (Value' lab)
+ Text.LLVM.AST: [ptrAddrIndexSize] :: PointerSize -> Maybe NumBits
+ Text.LLVM.AST: [ptrAddrSpace] :: PointerSize -> !AddressSpace
+ Text.LLVM.AST: [ptrStorage] :: PointerSize -> Storage
+ Text.LLVM.AST: [storageAlignment] :: Storage -> Alignment
+ Text.LLVM.AST: [storageSize] :: Storage -> !NumBits
+ Text.LLVM.AST: addDebugRecord :: DebugRecord' lab -> Stmt' lab -> Stmt' lab
+ Text.LLVM.AST: data Alignment
+ Text.LLVM.AST: data DIBasicType' lab
+ Text.LLVM.AST: data DbgRecAssign' lab
+ Text.LLVM.AST: data DbgRecDeclare' lab
+ Text.LLVM.AST: data DbgRecLabel' lab
+ Text.LLVM.AST: data DbgRecValue' lab
+ Text.LLVM.AST: data DbgRecValueSimple' lab
+ Text.LLVM.AST: data DebugRecord' lab
+ Text.LLVM.AST: data GEPAttr
+ Text.LLVM.AST: data PointerSize
+ Text.LLVM.AST: data RangeSpec
+ Text.LLVM.AST: data Storage
+ Text.LLVM.AST: dwarf_DW_APPLE_ENUM_KIND_invalid :: Word32
+ Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.Alignment
+ Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.GEPAttr
+ Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.PointerSize
+ Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.RangeSpec
+ Text.LLVM.AST: instance Data.Data.Data Text.LLVM.AST.Storage
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DIBasicType' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DbgRecAssign' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DbgRecDeclare' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DbgRecLabel' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DbgRecValue' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DbgRecValueSimple' lab)
+ Text.LLVM.AST: instance Data.Data.Data lab => Data.Data.Data (Text.LLVM.AST.DebugRecord' lab)
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DIBasicType'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DbgRecAssign'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DbgRecDeclare'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DbgRecLabel'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DbgRecValue'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DbgRecValueSimple'
+ Text.LLVM.AST: instance GHC.Base.Functor Text.LLVM.AST.DebugRecord'
+ Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.Alignment
+ Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.GEPAttr
+ Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.PointerSize
+ Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.RangeSpec
+ Text.LLVM.AST: instance GHC.Classes.Eq Text.LLVM.AST.Storage
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DIBasicType' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DbgRecAssign' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DbgRecDeclare' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DbgRecLabel' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DbgRecValue' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DbgRecValueSimple' lab)
+ Text.LLVM.AST: instance GHC.Classes.Eq lab => GHC.Classes.Eq (Text.LLVM.AST.DebugRecord' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.Alignment
+ Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.GEPAttr
+ Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.PointerSize
+ Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.RangeSpec
+ Text.LLVM.AST: instance GHC.Classes.Ord Text.LLVM.AST.Storage
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DIBasicType' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DbgRecAssign' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DbgRecDeclare' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DbgRecLabel' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DbgRecValue' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DbgRecValueSimple' lab)
+ Text.LLVM.AST: instance GHC.Classes.Ord lab => GHC.Classes.Ord (Text.LLVM.AST.DebugRecord' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DIBasicType' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DbgRecAssign' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DbgRecDeclare' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DbgRecLabel' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DbgRecValue' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DbgRecValueSimple' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic (Text.LLVM.AST.DebugRecord' lab)
+ Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.Alignment
+ Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.GEPAttr
+ Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.PointerSize
+ Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.RangeSpec
+ Text.LLVM.AST: instance GHC.Generics.Generic Text.LLVM.AST.Storage
+ Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.Alignment
+ Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.GEPAttr
+ Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.PointerSize
+ Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.RangeSpec
+ Text.LLVM.AST: instance GHC.Show.Show Text.LLVM.AST.Storage
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DIBasicType' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DbgRecAssign' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DbgRecDeclare' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DbgRecLabel' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DbgRecValue' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DbgRecValueSimple' lab)
+ Text.LLVM.AST: instance GHC.Show.Show lab => GHC.Show.Show (Text.LLVM.AST.DebugRecord' lab)
+ Text.LLVM.AST: orderedGEPAttrs :: [GEPAttr]
+ Text.LLVM.AST: type AddressSpace = Int
+ Text.LLVM.AST: type DIBasicType = DIBasicType' BlockLabel
+ Text.LLVM.AST: type DbgRecAssign = DbgRecAssign' BlockLabel
+ Text.LLVM.AST: type DbgRecDeclare = DbgRecDeclare' BlockLabel
+ Text.LLVM.AST: type DbgRecLabel = DbgRecLabel' BlockLabel
+ Text.LLVM.AST: type DbgRecValue = DbgRecValue' BlockLabel
+ Text.LLVM.AST: type DbgRecValueSimple = DbgRecValueSimple' BlockLabel
+ Text.LLVM.AST: type DebugRecord = DebugRecord' BlockLabel
+ Text.LLVM.AST: type NumBits = Int
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DIBasicType'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DbgRecAssign'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DbgRecDeclare'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DbgRecLabel'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DbgRecValue'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DbgRecValueSimple'
+ Text.LLVM.Labels: instance Text.LLVM.Labels.HasLabel Text.LLVM.AST.DebugRecord'
+ Text.LLVM.Lens: dibtNumExtraInhabitantsLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DIBasicType' lab -> f (DIBasicType' lab)
+ Text.LLVM.Lens: dictBitStrideLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dictEnumKindLens :: forall lab f. Functor f => (Maybe Word32 -> f (Maybe Word32)) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dictNumExtraInhabitantsLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dictSpecificationLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dlAtomGroupLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DebugLoc' lab -> f (DebugLoc' lab)
+ Text.LLVM.Lens: dlAtomRankLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DebugLoc' lab -> f (DebugLoc' lab)
+ Text.LLVM.PP: droppedInLLVM :: (?config :: Config) => LLVMVer -> String -> a -> a
+ Text.LLVM.PP: ppAlignment :: Fmt Alignment
+ Text.LLVM.PP: ppDIBasicType' :: Fmt i -> Fmt (DIBasicType' i)
+ Text.LLVM.PP: ppDbgRecAssign' :: Fmt lab -> Fmt (DbgRecAssign' lab)
+ Text.LLVM.PP: ppDbgRecDeclare' :: Fmt lab -> Fmt (DbgRecDeclare' lab)
+ Text.LLVM.PP: ppDbgRecLabel' :: Fmt lab -> Fmt (DbgRecLabel' lab)
+ Text.LLVM.PP: ppDbgRecValue' :: Fmt lab -> Fmt (DbgRecValue' lab)
+ Text.LLVM.PP: ppDbgRecValueSimple' :: Fmt lab -> Fmt (DbgRecValueSimple' lab)
+ Text.LLVM.PP: ppDebugRecord' :: Fmt lab -> Fmt (DebugRecord' lab)
+ Text.LLVM.PP: ppDebugRecords :: [DebugRecord' BlockLabel] -> Fmt Doc
+ Text.LLVM.PP: ppGepFlags :: Fmt [GEPAttr]
+ Text.LLVM.PP: ppGlobalMetadata :: Fmt [(String, ValMd' BlockLabel)]
+ Text.LLVM.PP: ppOptColonInt :: Fmt (Maybe Int)
+ Text.LLVM.PP: ppPointerSize :: Fmt PointerSize
+ Text.LLVM.PP: ppSizeOrOffsetValMd' :: Fmt i -> Fmt (ValMd' i)
+ Text.LLVM.PP: ppStorage :: Fmt Storage
- Text.LLVM.AST: AggregateSize :: !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: AggregateSize :: Maybe Int -> !Alignment -> LayoutSpec
- Text.LLVM.AST: ConstGEP :: Bool -> Maybe Word64 -> Type -> Typed (Value' lab) -> [Typed (Value' lab)] -> ConstExpr' lab
+ Text.LLVM.AST: ConstGEP :: [GEPAttr] -> Maybe RangeSpec -> Type -> Typed (Value' lab) -> [Typed (Value' lab)] -> ConstExpr' lab
- Text.LLVM.AST: DIBasicType :: DwarfTag -> String -> Word64 -> Word64 -> DwarfAttrEncoding -> Maybe DIFlags -> DIBasicType
+ Text.LLVM.AST: DIBasicType :: DwarfTag -> String -> Maybe (ValMd' lab) -> Word64 -> DwarfAttrEncoding -> Maybe DIFlags -> Word64 -> DIBasicType' lab
- Text.LLVM.AST: DICompositeType :: DwarfTag -> Maybe String -> Maybe (ValMd' lab) -> Word32 -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Word64 -> Word64 -> Word64 -> DIFlags -> Maybe (ValMd' lab) -> DwarfLang -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe String -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> DICompositeType' lab
+ Text.LLVM.AST: DICompositeType :: DwarfTag -> Maybe String -> Maybe (ValMd' lab) -> Word32 -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Word64 -> Maybe (ValMd' lab) -> DIFlags -> Maybe (ValMd' lab) -> DwarfLang -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe String -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Word64 -> Maybe (ValMd' lab) -> Maybe Word32 -> Maybe (ValMd' lab) -> DICompositeType' lab
- Text.LLVM.AST: DIDerivedType :: DwarfTag -> Maybe String -> Maybe (ValMd' lab) -> Word32 -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Word64 -> Word64 -> Word64 -> DIFlags -> Maybe (ValMd' lab) -> Maybe Word32 -> Maybe (ValMd' lab) -> DIDerivedType' lab
+ Text.LLVM.AST: DIDerivedType :: DwarfTag -> Maybe String -> Maybe (ValMd' lab) -> Word32 -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Maybe (ValMd' lab) -> Word64 -> Maybe (ValMd' lab) -> DIFlags -> Maybe (ValMd' lab) -> Maybe Word32 -> Maybe (ValMd' lab) -> DIDerivedType' lab
- Text.LLVM.AST: DILabel :: Maybe (ValMd' lab) -> String -> Maybe (ValMd' lab) -> Word32 -> DILabel' lab
+ Text.LLVM.AST: DILabel :: Maybe (ValMd' lab) -> String -> Maybe (ValMd' lab) -> Word32 -> Word32 -> Bool -> Maybe Word32 -> DILabel' lab
- Text.LLVM.AST: DebugInfoBasicType :: DIBasicType -> DebugInfo' lab
+ Text.LLVM.AST: DebugInfoBasicType :: DIBasicType' lab -> DebugInfo' lab
- Text.LLVM.AST: DebugLoc :: Word32 -> Word32 -> ValMd' lab -> Maybe (ValMd' lab) -> Bool -> DebugLoc' lab
+ Text.LLVM.AST: DebugLoc :: Word32 -> Word32 -> ValMd' lab -> Maybe (ValMd' lab) -> Bool -> Word64 -> Word64 -> DebugLoc' lab
- Text.LLVM.AST: Effect :: Instr' lab -> [(String, ValMd' lab)] -> Stmt' lab
+ Text.LLVM.AST: Effect :: Instr' lab -> [DebugRecord' lab] -> [(String, ValMd' lab)] -> Stmt' lab
- Text.LLVM.AST: FloatSize :: !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: FloatSize :: Storage -> LayoutSpec
- Text.LLVM.AST: FunctionPointerAlign :: !FunctionPointerAlignType -> !Int -> LayoutSpec
+ Text.LLVM.AST: FunctionPointerAlign :: !FunctionPointerAlignType -> !NumBits -> LayoutSpec
- Text.LLVM.AST: GEP :: Bool -> Type -> Typed (Value' lab) -> [Typed (Value' lab)] -> Instr' lab
+ Text.LLVM.AST: GEP :: [GEPAttr] -> Type -> Typed (Value' lab) -> [Typed (Value' lab)] -> Instr' lab
- Text.LLVM.AST: ICmp :: ICmpOp -> Typed (Value' lab) -> Value' lab -> Instr' lab
+ Text.LLVM.AST: ICmp :: Bool -> ICmpOp -> Typed (Value' lab) -> Value' lab -> Instr' lab
- Text.LLVM.AST: IntegerSize :: !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: IntegerSize :: Storage -> LayoutSpec
- Text.LLVM.AST: NativeIntSize :: [Int] -> LayoutSpec
+ Text.LLVM.AST: NativeIntSize :: [NumBits] -> LayoutSpec
- Text.LLVM.AST: PointerSize :: !Int -> !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: PointerSize :: PointerSize -> LayoutSpec
- Text.LLVM.AST: Result :: Ident -> Instr' lab -> [(String, ValMd' lab)] -> Stmt' lab
+ Text.LLVM.AST: Result :: Ident -> Instr' lab -> [DebugRecord' lab] -> [(String, ValMd' lab)] -> Stmt' lab
- Text.LLVM.AST: StackAlign :: !Int -> LayoutSpec
+ Text.LLVM.AST: StackAlign :: !NumBits -> LayoutSpec
- Text.LLVM.AST: StackObjSize :: !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: StackObjSize :: Storage -> LayoutSpec
- Text.LLVM.AST: Trunc :: ConvOp
+ Text.LLVM.AST: Trunc :: Bool -> Bool -> ConvOp
- Text.LLVM.AST: UiToFp :: ConvOp
+ Text.LLVM.AST: UiToFp :: Bool -> ConvOp
- Text.LLVM.AST: VectorSize :: !Int -> !Int -> Maybe Int -> LayoutSpec
+ Text.LLVM.AST: VectorSize :: Storage -> LayoutSpec
- Text.LLVM.AST: ZExt :: ConvOp
+ Text.LLVM.AST: ZExt :: Bool -> ConvOp
- Text.LLVM.AST: [dibtAlign] :: DIBasicType -> Word64
+ Text.LLVM.AST: [dibtAlign] :: DIBasicType' lab -> Word64
- Text.LLVM.AST: [dibtEncoding] :: DIBasicType -> DwarfAttrEncoding
+ Text.LLVM.AST: [dibtEncoding] :: DIBasicType' lab -> DwarfAttrEncoding
- Text.LLVM.AST: [dibtFlags] :: DIBasicType -> Maybe DIFlags
+ Text.LLVM.AST: [dibtFlags] :: DIBasicType' lab -> Maybe DIFlags
- Text.LLVM.AST: [dibtName] :: DIBasicType -> String
+ Text.LLVM.AST: [dibtName] :: DIBasicType' lab -> String
- Text.LLVM.AST: [dibtSize] :: DIBasicType -> Word64
+ Text.LLVM.AST: [dibtSize] :: DIBasicType' lab -> Maybe (ValMd' lab)
- Text.LLVM.AST: [dibtTag] :: DIBasicType -> DwarfTag
+ Text.LLVM.AST: [dibtTag] :: DIBasicType' lab -> DwarfTag
- Text.LLVM.AST: [dictOffset] :: DICompositeType' lab -> Word64
+ Text.LLVM.AST: [dictOffset] :: DICompositeType' lab -> Maybe (ValMd' lab)
- Text.LLVM.AST: [dictSize] :: DICompositeType' lab -> Word64
+ Text.LLVM.AST: [dictSize] :: DICompositeType' lab -> Maybe (ValMd' lab)
- Text.LLVM.AST: [didtOffset] :: DIDerivedType' lab -> Word64
+ Text.LLVM.AST: [didtOffset] :: DIDerivedType' lab -> Maybe (ValMd' lab)
- Text.LLVM.AST: [didtSize] :: DIDerivedType' lab -> Word64
+ Text.LLVM.AST: [didtSize] :: DIDerivedType' lab -> Maybe (ValMd' lab)
- Text.LLVM.AST: extendMetadata :: (String, ValMd' lab) -> Stmt' lab -> Stmt' lab
+ Text.LLVM.AST: extendMetadata :: Show lab => (String, ValMd' lab) -> Stmt' lab -> Stmt' lab
- Text.LLVM.Lens: dibtAlignLens :: Lens' DIBasicType Word64
+ Text.LLVM.Lens: dibtAlignLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DIBasicType' lab -> f (DIBasicType' lab)
- Text.LLVM.Lens: dibtEncodingLens :: Lens' DIBasicType DwarfAttrEncoding
+ Text.LLVM.Lens: dibtEncodingLens :: forall lab f. Functor f => (DwarfAttrEncoding -> f DwarfAttrEncoding) -> DIBasicType' lab -> f (DIBasicType' lab)
- Text.LLVM.Lens: dibtFlagsLens :: Lens' DIBasicType (Maybe DIFlags)
+ Text.LLVM.Lens: dibtFlagsLens :: forall lab f. Functor f => (Maybe DIFlags -> f (Maybe DIFlags)) -> DIBasicType' lab -> f (DIBasicType' lab)
- Text.LLVM.Lens: dibtNameLens :: Lens' DIBasicType String
+ Text.LLVM.Lens: dibtNameLens :: forall lab f. Functor f => (String -> f String) -> DIBasicType' lab -> f (DIBasicType' lab)
- Text.LLVM.Lens: dibtSizeLens :: Lens' DIBasicType Word64
+ Text.LLVM.Lens: dibtSizeLens :: forall lab1 lab2 f. Functor f => (Maybe (ValMd' lab1) -> f (Maybe (ValMd' lab2))) -> DIBasicType' lab1 -> f (DIBasicType' lab2)
- Text.LLVM.Lens: dibtTagLens :: Lens' DIBasicType DwarfTag
+ Text.LLVM.Lens: dibtTagLens :: forall lab f. Functor f => (DwarfTag -> f DwarfTag) -> DIBasicType' lab -> f (DIBasicType' lab)
- Text.LLVM.Lens: dictOffsetLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dictOffsetLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DICompositeType' lab -> f (DICompositeType' lab)
- Text.LLVM.Lens: dictSizeLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DICompositeType' lab -> f (DICompositeType' lab)
+ Text.LLVM.Lens: dictSizeLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DICompositeType' lab -> f (DICompositeType' lab)
- Text.LLVM.Lens: didtOffsetLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DIDerivedType' lab -> f (DIDerivedType' lab)
+ Text.LLVM.Lens: didtOffsetLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DIDerivedType' lab -> f (DIDerivedType' lab)
- Text.LLVM.Lens: didtSizeLens :: forall lab f. Functor f => (Word64 -> f Word64) -> DIDerivedType' lab -> f (DIDerivedType' lab)
+ Text.LLVM.Lens: didtSizeLens :: forall lab f. Functor f => (Maybe (ValMd' lab) -> f (Maybe (ValMd' lab))) -> DIDerivedType' lab -> f (DIDerivedType' lab)
- Text.LLVM.PP: ppGEP :: Bool -> Type -> Typed Value -> Fmt [Typed Value]
+ Text.LLVM.PP: ppGEP :: [GEPAttr] -> Type -> Typed Value -> Fmt [Typed Value]
Files
- CHANGELOG.md +61/−0
- llvm-pretty.cabal +5/−2
- src/Text/LLVM.hs +41/−12
- src/Text/LLVM/AST.hs +432/−124
- src/Text/LLVM/DebugUtils.hs +21/−9
- src/Text/LLVM/Labels.hs +9/−1
- src/Text/LLVM/Lens.hs +1/−1
- src/Text/LLVM/PP.hs +251/−65
- src/Text/LLVM/Triple/AST.hs +7/−8
- test/DataLayout.hs +31/−0
- test/Main.hs +6/−2
- test/Metadata.hs +34/−0
- test/Output.hs +72/−7
CHANGELOG.md view
@@ -1,5 +1,66 @@ # Revision history for llvm-pretty +## 0.14.0.0 -- 2026-01-22++* Changes to support LLVM 19 (some of these changes are not backward-compatible):+ * Changes to `LayoutSpec` for DataLayout:+ * Size specification fields use a common sub-structure `Storage` which itself+ contains an `Alignment` common sub-structure: `IntegerSize`, `VectorSize`,+ `FloatSize`, and `StackObjSize`.+ * The pointer size specification field uses a `PointerSize` sub-structure+ that itself contains a `Storage` sub-structure.+ * Updated `AggregateSize` to make first field optional (it was dropped in+ LLVM 4) and the remaining fields are now provided via the `Alignment`+ sub-structure.+ * Added `ProgramAddrSpace`, `GlobalAddrSpace`, and `AllocaAddrSpace`+ constructors, each defined via an `AddressSpace` sub-structure.+ * Added `NonIntegralPointerSpaces` to record address spaces with an+ unspecified bitwise representation.+ * Added `GoffMangling`, `WindowsX86CoffMangling`, and `XCoffMangling` forms+ of Mangling.+ * Added `GEPAttr` flags for `GEP` instruction and constant expression, with+ `RangeSpec` for the latter.+ * Added `numExtraInhabitants` to `DIBasicType`.+ * Added support for `DebugRecord` parsing, specifically for:++ * `FUNC_CODE_DEBUG_RECORD_VALUE`+ * `FUNC_CODE_DEBUG_RECORD_DECLARE`+ * `FUNC_CODE_DEBUG_RECORD_ASSIGN`+ * `FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE`+ * `FUNC_CODE_DEBUG_RECORD_LABEL`++ This adds a new field to both the `Result` and `Effect` constructors of the `Stmt` type.+ * Pretty-printing with an LLVM version >= 19 now generates an error for `icmp`,+ `fcmp`, and `shl` constant expressions that are no longer supported as of+ LLVM 19.+* Changes to cast-related instructions:+ * Add a `Bool` field to `ZExt` which, if `True`, indicates that the+ argument must be non-negative. This is used by LLVM 18 and up.+ * Add a `Bool` field to `UiToFp` which, if `True`, indicates that the+ argument must be non-negative. This is used by LLVM 19 and up.+ * Add `Bool` fields to `Trunc` to check if the truncation would cause+ unsigned or signed overflow. These are used by LLVM 20 and up.+* Add a `Bool` field to `ICmp`, which indicates that the arguments must have+ the same sign. This is used by LLVM 20 and up.+* Add `dlAtomGroup` and `dlAtomRank` fields to `DebugLoc'`, which were+ introduced in LLVM 21.+* Add `dilColumn`, `dilIsArtificial`, and `dilCoroSuspendIdx` fields to+ `DILabel'`, which were introduced in LLVM 21.+* The following debug-related fields have had their types changed from `Word64`+ to `Maybe (ValMd' lab)`:++ * `DIBasicType'`: `dibtSize`+ * `DICompositeType'`: `dictSize` and `dictOffset`+ * `DIDerivedType'`: `didtSize` and `didtOffset`++ This allows them to encode non-constant sizes and offsets (a capability used+ by Ada, for instance) in LLVM 21 or later.+* Added the `bbStmtModifier` which can be used to modify individual statements as+ they are emitted from the top-level instruction generator functions (e.g to add+ Debug Metadata to each statement).+* Fix a bug that would cause `indirectbr` statements to be pretty-printed+ incorrectly.+ ## 0.13.1.0 (October 2025) * Add a `FunctionPointerAlign` constructor to `LayoutSpec`.
llvm-pretty.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: llvm-pretty-Version: 0.13.1.0+Version: 0.14.0.0 License: BSD-3-Clause License-file: LICENSE Author: Trevor Elliott@@ -13,7 +13,7 @@ Augustsson. The library provides a monadic interface to a pretty printer, that allows functions to be defined and called, generating the corresponding LLVM assembly when run.-tested-with: GHC==9.10.1, GHC==9.8.4, GHC==9.6.6+tested-with: GHC==9.12.3, GHC==9.10.1, GHC==9.8.4 extra-doc-files: CHANGELOG.md, README.md @@ -25,6 +25,7 @@ Default-language: Haskell2010 Ghc-options: -Wall+ -fhide-source-paths Library Import: common@@ -62,6 +63,8 @@ Type: exitcode-stdio-1.0 Main-is: Main.hs Other-modules:+ DataLayout+ Metadata Output Triple TQQDefs
src/Text/LLVM.hs view
@@ -41,6 +41,7 @@ -- * Basic Blocks , BB() , runBB+ , bbStmtModifier , freshLabel , label , comment@@ -314,9 +315,36 @@ -- Basic Block Monad ----------------------------------------------------------- newtype BB a = BB- { unBB :: WriterT [BasicBlock] (StateT RW Id) a+ { unBB :: ReaderT (Stmt -> Stmt) (WriterT [BasicBlock] (StateT RW Id)) a } deriving (Functor,Applicative,Monad,MonadFix) ++-- | The 'bbStmtModifier' function can be used to register a function that can+-- modify the subsequent statements generated into this block.+--+-- For example, the following 'BB' monad code segment will emit a couple of LLVM+-- statements:+--+-- > v <- load (iT 8) globalVar Nothing+-- > call fooFunc [v]+-- > jump end+--+-- But these statements will be \"plain\" in the resulting 'BasicBlock'. If the+-- caller wishes to add debug Metadata for location, they could instead write:+--+-- > bbStmtModifier (extendMetadata ("dbg", ValMdRef i))+-- > v <- load (iT 8) globalVar Nothing+-- > bbStmtModifier (extendMetadata ("dbg", ValMdRef j))+-- > call fooFunc [v]+-- > jump end+--+-- Where @i@ and @j@ are the metadata index values of the 'DebugLoc' entries+-- describing the source location of the \"load\" and \"call\"+\"jump\" statements,+-- respectively.++bbStmtModifier :: (Stmt -> Stmt) -> BB a -> BB a+bbStmtModifier stmtModifier = BB . local stmtModifier . unBB+ avoidName :: String -> BB () avoidName name = BB $ do rw <- get@@ -333,7 +361,7 @@ runBB :: BB a -> (a,[BasicBlock]) runBB m =- case runId (runStateT emptyRW (runWriterT (unBB body))) of+ case runId (runStateT emptyRW (runWriterT (runReaderT id (unBB body)))) of ((a,bbs),_rw) -> (a,bbs) where -- make sure that the last block is terminated@@ -367,17 +395,18 @@ emitStmt stmt = do BB $ do rw <- get- set $! rw { rwStmts = rwStmts rw Seq.|> stmt }+ smod <- ask+ set $! rw { rwStmts = rwStmts rw Seq.|> smod stmt } when (isTerminator (stmtInstr stmt)) terminateBasicBlock effect :: Instr -> BB ()-effect i = emitStmt (Effect i [])+effect i = emitStmt (Effect i mempty []) observe :: Type -> Instr -> BB (Typed Value) observe ty i = do name <- freshNameBB "r" let res = Ident name- emitStmt (Result res i [])+ emitStmt (Result res i mempty []) return (Typed ty (ValIdent res)) @@ -508,8 +537,8 @@ rw <- BB get case Seq.viewr (rwStmts rw) of - stmts Seq.:> Result _ i m ->- do BB (set rw { rwStmts = stmts Seq.|> Result r i m })+ stmts Seq.:> Result _ i d m ->+ do BB (set rw { rwStmts = stmts Seq.|> Result r i d m }) return (const (ValIdent r) `fmap` tv) _ -> error "assign: invalid argument"@@ -640,10 +669,10 @@ convop k a ty = observe ty (k (toValue `fmap` a) ty) trunc :: IsValue a => Typed a -> Type -> BB (Typed Value)-trunc = convop (Conv Trunc)+trunc = convop (Conv (Trunc False False)) zext :: IsValue a => Typed a -> Type -> BB (Typed Value)-zext = convop (Conv ZExt)+zext = convop (Conv (ZExt False)) sext :: IsValue a => Typed a -> Type -> BB (Typed Value) sext = convop (Conv SExt)@@ -661,7 +690,7 @@ fptosi = convop (Conv FpToSi) uitofp :: IsValue a => Typed a -> Type -> BB (Typed Value)-uitofp = convop (Conv UiToFp)+uitofp = convop (Conv (UiToFp False)) sitofp :: IsValue a => Typed a -> Type -> BB (Typed Value) sitofp = convop (Conv SiToFp)@@ -676,7 +705,7 @@ bitcast = convop (Conv BitCast) icmp :: (IsValue a, IsValue b) => ICmpOp -> Typed a -> b -> BB (Typed Value)-icmp op l r = observe (iT 1) (ICmp op (toValue `fmap` l) (toValue r))+icmp op l r = observe (iT 1) (ICmp False op (toValue `fmap` l) (toValue r)) fcmp :: (IsValue a, IsValue b) => FCmpOp -> Typed a -> b -> BB (Typed Value) fcmp op l r = observe (iT 1) (FCmp op (toValue `fmap` l) (toValue r))@@ -696,7 +725,7 @@ getelementptr :: IsValue a => Type -> Typed a -> [Typed Value] -> BB (Typed Value)-getelementptr ty ptr ixs = observe ty (GEP False ty (toValue `fmap` ptr) ixs)+getelementptr ty ptr ixs = observe ty (GEP [] ty (toValue `fmap` ptr) ixs) -- | Emit a call instruction, and generate a new variable for its result. call :: IsValue a => Typed a -> [Typed Value] -> BB (Typed Value)
src/Text/LLVM/AST.hs view
@@ -9,12 +9,15 @@ incomplete: there are some values that new LLVM versions would accept but are not yet represented here. -}++{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveLift #-}+ module Text.LLVM.AST ( -- * Modules Module(..)@@ -28,7 +31,12 @@ -- * Data Layout , DataLayout , LayoutSpec(..)+ , Alignment(..) , FunctionPointerAlignType(..)+ , Storage(..)+ , PointerSize(..)+ , AddressSpace+ , NumBits , Mangling(..) , parseDataLayout -- * Inline Assembly@@ -132,8 +140,12 @@ , stmtInstr , stmtMetadata , extendMetadata+ , addDebugRecord -- * Constant Expressions , ConstExpr'(..), ConstExpr+ , GEPAttr(..)+ , orderedGEPAttrs+ , RangeSpec(RangeIndex, Range) -- * DWARF Debug Info , DebugInfo'(..), DebugInfo , DILabel, DILabel'(..)@@ -147,7 +159,7 @@ , DwarfVirtuality , DIFlags , DIEmissionKind- , DIBasicType(..)+ , DIBasicType'(..), DIBasicType , DICompileUnit'(..), DICompileUnit , DICompositeType'(..), DICompositeType , DIDerivedType'(..), DIDerivedType@@ -162,6 +174,13 @@ , DISubrange'(..), DISubrange , DISubroutineType'(..), DISubroutineType , DIArgList'(..), DIArgList+ , dwarf_DW_APPLE_ENUM_KIND_invalid+ , DebugRecord, DebugRecord'(..)+ , DbgRecAssign, DbgRecAssign'(..)+ , DbgRecDeclare, DbgRecDeclare'(..)+ , DbgRecLabel, DbgRecLabel'(..)+ , DbgRecValueSimple, DbgRecValueSimple'(..)+ , DbgRecValue, DbgRecValue'(..) -- * Aggregate Utilities , IndexResult(..) , isInvalid@@ -173,18 +192,19 @@ , resolveValueIndex ) where -import Data.Functor.Identity (Identity(..))+import Control.Monad (MonadPlus(mzero,mplus),(<=<),guard)+import Data.Bits ( complement ) 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.Functor.Identity (Identity(..)) import Data.Generics (everywhere, extQ, mkT, something)+import Data.Int (Int32,Int64) import Data.List (genericIndex,genericLength) import qualified Data.Map as Map import Data.Maybe (isJust) import Data.Semigroup as Sem import Data.String (IsString(fromString))+import Data.Typeable (Typeable) import Data.Word (Word8,Word16,Word32,Word64) import GHC.Generics (Generic, Generic1) import Language.Haskell.TH.Syntax (Lift)@@ -210,7 +230,7 @@ , modDefines :: [Define] -- ^ internal function declarations (with definitions) , modInlineAsm :: InlineAsm , modAliases :: [GlobalAlias]- } deriving (Data, Eq, Ord, Generic, Show, Typeable)+ } deriving (Data, Eq, Ord, Generic, Show) -- | Combines fields pointwise. instance Sem.Semigroup Module where@@ -255,7 +275,7 @@ data NamedMd = NamedMd { nmName :: String , nmValues :: [Int]- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- Unnamed Metadata ------------------------------------------------------------@@ -264,7 +284,7 @@ { umIndex :: !Int , umValues :: ValMd , umDistinct :: Bool- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- Aliases ---------------------------------------------------------------------@@ -275,28 +295,39 @@ , aliasName :: Symbol , aliasType :: Type , aliasTarget :: Value- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- Data Layout -----------------------------------------------------------------+-- https://releases.llvm.org/19.1.0/docs/LangRef.html#data-layout type DataLayout = [LayoutSpec] data LayoutSpec = BigEndian | LittleEndian- | PointerSize !Int !Int !Int (Maybe Int) -- ^ address space, size, abi, pref- | IntegerSize !Int !Int (Maybe Int) -- ^ size, abi, pref- | VectorSize !Int !Int (Maybe Int) -- ^ size, abi, pref- | FloatSize !Int !Int (Maybe Int) -- ^ size, abi, pref- | StackObjSize !Int !Int (Maybe Int) -- ^ size, abi, pref- | AggregateSize !Int !Int (Maybe Int) -- ^ size, abi, pref- | NativeIntSize [Int]- | StackAlign !Int -- ^ size- | FunctionPointerAlign !FunctionPointerAlignType !Int -- ^ type, abi+ | PointerSize PointerSize+ | IntegerSize Storage+ | VectorSize Storage+ | FloatSize Storage+ | StackObjSize Storage+ | AggregateSize (Maybe Int) !Alignment -- n.b. first Int present pre-LLVM4+ | NativeIntSize [NumBits]+ | StackAlign !NumBits -- ^ size+ | ProgramAddrSpace !AddressSpace+ | GlobalAddrSpace !AddressSpace+ | AllocaAddrSpace !AddressSpace+ | FunctionPointerAlign !FunctionPointerAlignType !NumBits -- ^ type, abi | Mangling Mangling- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ | NonIntegralPointerSpaces [AddressSpace]+ deriving (Data, Eq, Generic, Ord, Show) +data Alignment = Alignment+ { alignABI :: !NumBits+ , alignPreferred :: Maybe NumBits -- ^ default = alignABI+ }+ deriving (Data, Eq, Generic, Ord, Show)+ -- | How should a function pointer be aligned? data FunctionPointerAlignType = IndependentOfFunctionAlign@@ -305,19 +336,38 @@ | MultipleOfFunctionAlign -- ^ The alignment of function pointers is a multiple of the explicit -- alignment specified on the function.- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) +data Storage = Storage+ { storageSize :: !NumBits -- ^ valid range [1,2^24)+ , storageAlignment :: Alignment+ }+ deriving (Data, Eq, Generic, Ord, Show)++data PointerSize = PtrSize+ { ptrAddrSpace :: !AddressSpace+ , ptrStorage :: Storage+ , ptrAddrIndexSize :: Maybe NumBits -- ^ m.b. <= ptrSize, default = ptrSize+ }+ deriving (Data, Eq, Generic, Ord, Show)++type AddressSpace = Int+type NumBits = Int+ data Mangling = ElfMangling+ | GoffMangling | MipsMangling | MachOMangling | WindowsCoffMangling- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ | WindowsX86CoffMangling+ | XCoffMangling+ deriving (Data, Eq, Enum, Generic, Ord, Show) -- | Parse the data layout string. parseDataLayout :: MonadPlus m => String -> m DataLayout parseDataLayout str = case parse (pDataLayout <* eof) "<internal>" str of- Left _err -> mzero+ Left _err -> {- debugging: trace (show err) -} mzero Right specs -> return specs where pDataLayout :: Parser DataLayout@@ -329,12 +379,17 @@ case c of 'E' -> return BigEndian 'e' -> return LittleEndian- 'S' -> StackAlign <$> pInt- 'F' -> FunctionPointerAlign <$> pFunctionPointerAlignType <*> pInt- 'p' -> PointerSize <$> pInt0 <*> pCInt <*> pCInt <*> pPref- 'i' -> IntegerSize <$> pInt <*> pCInt <*> pPref- 'v' -> VectorSize <$> pInt <*> pCInt <*> pPref- 'f' -> FloatSize <$> pInt <*> pCInt <*> pPref -- size of float, abi-align, pref-align+ 'S' -> StackAlign <$> pInt+ 'P' -> ProgramAddrSpace <$> pInt -- Added in LLVM7+ 'G' -> GlobalAddrSpace <$> pInt -- Added in LLVM11+ 'A' -> AllocaAddrSpace <$> pInt -- Added in LLVM11+ 'p' -> do as <- pInt <|> return 0+ st <- char ':' >> pStorage+ idx <- pCOInt -- Added in LLVM7+ return $ PointerSize $ PtrSize as st idx+ 'i' -> IntegerSize <$> pStorage+ 'v' -> VectorSize <$> pStorage+ 'f' -> FloatSize <$> pStorage -- Note that the data layout specified in the LLVM -- BC/IR file is not a directive to the backend, but -- is instead an indication of what the particular@@ -349,10 +404,19 @@ -- (for example) references to LongDoubleWidth and -- LongDoubleFormat in -- https://github.com/llvm/llvm-project/blob/release_60/clang/lib/Basic/Targets/X86.h- 's' -> StackObjSize <$> pInt <*> pCInt <*> pPref- 'a' -> AggregateSize <$> pInt <*> pCInt <*> pPref- 'n' -> NativeIntSize <$> sepBy pInt (char ':')- 'm' -> Mangling <$> (char ':' >> pMangling)+ 's' -> StackObjSize <$> pStorage -- Obsoleted in LLVM4+ 'a' -> alphaNum >>= \case+ ':' -> AggregateSize Nothing <$> pAlignment+ d -> AggregateSize <$> (Just <$> pIntWithFirstDigit d)+ <* char ':' <*> pAlignment+ 'F' -> FunctionPointerAlign <$> pFunctionPointerAlignType <*> pInt -- Added in LLVM9+ 'm' -> Mangling <$ char ':' <*> pMangling+ 'n' -> alphaNum >>= \case+ 'i' -> char ':'+ >> (NonIntegralPointerSpaces <$> sepBy pInt (char ':'))+ d -> do fs <- pIntWithFirstDigit d+ ss <- char ':' *> sepBy pInt (char ':')+ return $ NativeIntSize $ fs : ss _ -> mzero pFunctionPointerAlignType :: Parser FunctionPointerAlignType@@ -368,22 +432,31 @@ do c <- letter case c of 'e' -> return ElfMangling+ 'l' -> return GoffMangling 'm' -> return MipsMangling 'o' -> return MachOMangling 'w' -> return WindowsCoffMangling+ 'x' -> return WindowsX86CoffMangling+ 'a' -> return XCoffMangling _ -> mzero + pAlignment :: Parser Alignment+ pAlignment = Alignment <$> pInt <*> pCOInt++ pStorage :: Parser Storage+ pStorage = Storage <$> pInt <* char ':' <*> pAlignment+ pInt :: Parser Int pInt = read <$> many1 digit - pInt0 :: Parser Int- pInt0 = pInt <|> return 0+ pIntWithFirstDigit :: Char -> Parser Int+ pIntWithFirstDigit d0 = read . (d0:) <$> many digit pCInt :: Parser Int pCInt = char ':' >> pInt - pPref :: Parser (Maybe Int)- pPref = optionMaybe pCInt+ pCOInt :: Parser (Maybe Int)+ pCOInt = optionMaybe pCInt -- Inline Assembly ------------------------------------------------------------- @@ -396,12 +469,12 @@ | ComdatLargest | ComdatNoDuplicates | ComdatSameSize- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) -- Identifiers ----------------------------------------------------------------- newtype Ident = Ident String- deriving (Data, Eq, Generic, Ord, Show, Typeable, Lift)+ deriving (Data, Eq, Generic, Ord, Show, Lift) instance IsString Ident where fromString = Ident@@ -409,7 +482,7 @@ -- Symbols --------------------------------------------------------------------- newtype Symbol = Symbol String- deriving (Data, Eq, Generic, Ord, Show, Typeable, Lift)+ deriving (Data, Eq, Generic, Ord, Show, Lift) instance Sem.Semigroup Symbol where Symbol a <> Symbol b = Symbol (a <> b)@@ -430,7 +503,7 @@ | FloatType FloatType | X86mmx | Metadata- deriving (Data, Eq, Generic, Ord, Show, Typeable, Lift)+ deriving (Data, Eq, Generic, Ord, Show, Lift) data FloatType = Half@@ -439,7 +512,7 @@ | Fp128 | X86_fp80 | PPC_fp128- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable, Lift)+ deriving (Data, Eq, Enum, Generic, Ord, Show, Lift) type Type = Type' Ident @@ -475,7 +548,7 @@ -- -- 'Opaque' should not be confused with 'PtrOpaque', which is a completely -- separate type with a similar-sounding name.- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) -- | Applicatively traverse a type, updating or removing aliases. updateAliasesA :: (Applicative f) => (a -> f (Type' b)) -> Type' a -> f (Type' b)@@ -631,7 +704,7 @@ data NullResult lab = HasNull (Value' lab) | ResolveNull Ident- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) primTypeNull :: PrimType -> Value' lab primTypeNull (Integer 1) = ValBool False@@ -699,7 +772,7 @@ data TypeDecl = TypeDecl { typeName :: Ident , typeValue :: Type- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- Globals ---------------------------------------------------------------------@@ -711,7 +784,7 @@ , globalValue :: Maybe Value , globalAlign :: Maybe Align , globalMetadata :: GlobalMdAttachments- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) addGlobal :: Global -> Module -> Module addGlobal g m = m { modGlobals = g : modGlobals m }@@ -720,7 +793,7 @@ { gaLinkage :: Maybe Linkage , gaVisibility :: Maybe Visibility , gaConstant :: Bool- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) emptyGlobalAttrs :: GlobalAttrs emptyGlobalAttrs = GlobalAttrs@@ -741,7 +814,7 @@ , decVarArgs :: Bool , decAttrs :: [FunAttr] , decComdat :: Maybe String- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- | The function type of this declaration decFunType :: Declare -> Type@@ -763,7 +836,7 @@ , defBody :: [BasicBlock] , defMetadata :: FnMdAttachments , defComdat :: Maybe String- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) defFunType :: Define -> Type defFunType Define { .. } =@@ -804,14 +877,14 @@ | SSPreq | SSPstrong | UWTable- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) -- Basic Block Labels ---------------------------------------------------------- data BlockLabel = Named Ident | Anon Int- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) instance IsString BlockLabel where fromString str = Named (fromString str)@@ -821,7 +894,7 @@ data BasicBlock' lab = BasicBlock { bbLabel :: Maybe lab , bbStmts :: [Stmt' lab]- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type BasicBlock = BasicBlock' BlockLabel @@ -855,23 +928,23 @@ | External | DLLImport | DLLExport- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) data Visibility = DefaultVisibility | HiddenVisibility | ProtectedVisibility- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) newtype GC = GC { getGC :: String- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) -- Typed Things ---------------------------------------------------------------- data Typed a = Typed { typedType :: Type , typedValue :: a- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) instance Foldable Typed where foldMap f t = f (typedValue t)@@ -941,7 +1014,7 @@ -- ^ * Floating point reminder resulting from floating point division. -- * The reminder has the same sign as the divident (first parameter). - deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) isIArith :: ArithOp -> Bool isIArith Add{} = True@@ -959,7 +1032,7 @@ data UnaryArithOp = FNeg -- ^ Floating point negation.- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) -- | Binary bitwise operators. data BitOp@@ -996,23 +1069,55 @@ | And | Or | Xor- deriving (Data, Eq, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) -- | Conversions from one type to another. data ConvOp- = Trunc- | ZExt+ = Trunc Bool Bool+ -- ^ Truncate an integer value to a smaller integer type.+ --+ -- The 'Bool' fields (added in in LLVM 20) encode whether to perform+ -- overflow-related checks:+ --+ -- * First 'Bool': check for unsigned overflow.+ -- * Second 'Bool': check for signed overflow.+ --+ -- If the checks fail, then the result is poisoned.+ --+ -- These fields can only ever 'True' in 'Conv' instructions in LLVM 20 or+ -- later. These fields are always 'False' in 'ConstConv' constant+ -- expressions or if the LLVM version is older than 20.+ | ZExt Bool+ -- ^ Zero extension.+ --+ -- The 'Bool' field (added in LLVM 18) encodes whether to enforce that the+ -- argument is non-negative. If the 'Bool' is 'True' and the argument is+ -- negative, then the result is poisoned.+ --+ -- This field can only ever 'True' in 'Conv' instructions in LLVM 18 or+ -- later. This field is always 'False' in 'ConstConv' constant expressions+ -- or if the LLVM version is older than 18. | SExt | FpTrunc | FpExt | FpToUi | FpToSi- | UiToFp+ | UiToFp Bool+ -- ^ Convert the argument from an unsigned integer to a floating-point+ -- value.+ --+ -- The 'Bool' field (added in LLVM 19) encodes whether to enforce that the+ -- argument is non-negative. If the 'Bool' is 'True' and the argument is+ -- negative, then the result is poisoned.+ --+ -- This field can only ever 'True' in 'Conv' instructions in LLVM 19 or+ -- later. This field is always 'False' in 'ConstConv' constant expressions+ -- or if the LLVM version is older than 19. | SiToFp | PtrToInt | IntToPtr | BitCast- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Generic, Ord, Show) data AtomicRWOp = AtomicXchg@@ -1032,7 +1137,7 @@ | AtomicFMin -- ^ Introduced in LLVM 15 | AtomicUIncWrap -- ^ Introduced in LLVM 16 | AtomicUDecWrap -- ^ Introduced in LLVM 16- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) data AtomicOrdering = Unordered@@ -1041,7 +1146,7 @@ | Release | AcqRel | SeqCst- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) type Align = Int @@ -1150,10 +1255,14 @@ * Middle of basic block. * Effect. -} - | ICmp ICmpOp (Typed (Value' lab)) (Value' lab)+ | ICmp Bool ICmpOp (Typed (Value' lab)) (Value' lab) {- ^ * Compare two integral values. * Middle of basic block.- * Returns a boolean value. -}+ * Returns a boolean value.+ * The 'Bool' field (added in LLVM 20) encodes whether to enforce that+ the arguments have the same sign. If the 'Bool' is 'True' and the+ arguments have mismatched signs, then the result is poisoned. This+ field is always 'False' if the LLVM version is older than 20. -} | FCmp FCmpOp (Typed (Value' lab)) (Value' lab) {- ^ * Compare two floating point values.@@ -1166,16 +1275,19 @@ * Middle of basic block. * Returns a value of the specified type. -} - | GEP Bool Type (Typed (Value' lab)) [Typed (Value' lab)]+ | GEP [GEPAttr] Type (Typed (Value' lab)) [Typed (Value' lab)] {- ^ * "Get element pointer", compute the address of a field in a structure:- inbounds check (value poisoned if this fails);+ inbounds check attr (value poisoned if this fails); type to use as a basis for calculations; pointer to parent structure; path to a sub-component of a structure. * Middle of basic block. * Returns the address of the requested member. + It's recommended that the GEPAttr list should be normalized (i.e. only one of+ each entry).+ The types in path are the types of the index, not the fields. The indexes are in units of fields (i.e., the first element in@@ -1301,14 +1413,14 @@ returns its argument. * Middle of basic block. -} - deriving (Data, Eq, Functor, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Ord, Show) type Instr = Instr' BlockLabel data Clause' lab = Catch (Typed (Value' lab)) | Filter (Typed (Value' lab))- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type Clause = Clause' BlockLabel @@ -1338,15 +1450,89 @@ -- | Integer comparison operators. data ICmpOp = Ieq | Ine | Iugt | Iuge | Iult | Iule | Isgt | Isge | Islt | Isle- deriving (Data, Eq, Enum, Generic, Ord, Show, Typeable)+ deriving (Data, Eq, Enum, Generic, Ord, Show) -- | Floating-point comparison operators. 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)+ deriving (Data, Eq, Enum, Generic, Ord, Show) +-- Debug Instructions ----------------------------------------------------------++-- | Debug Instructions+--+-- In LLVM 19, debug instructions were added as a replacement for the intrinsic+-- functions previously used. This addition is described in+-- llvm-project/llvm/docs/RemoveDIsDebugInfo.md in the LLVM repository.+data DebugRecord' lab+ = DebugRecordValue (DbgRecValue' lab)+ | DebugRecordDeclare (DbgRecDeclare' lab)+ | DebugRecordAssign (DbgRecAssign' lab)+ | DebugRecordValueSimple (DbgRecValueSimple' lab)+ | DebugRecordLabel (DbgRecLabel' lab)+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DebugRecord = DebugRecord' BlockLabel++data DbgRecValue' lab = DbgRecValue+ {+ drvLocation :: ValMd' lab -- ^ Expected to be a DILocation+ , drvLocalVariable :: ValMd' lab -- ^ Expected to be a DILocalVariable+ , drvExpression :: ValMd' lab -- ^ Expected to be a DIExpression+ , drvValAsMetadata :: ValMd' lab+ }+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DbgRecValue = DbgRecValue' BlockLabel++data DbgRecValueSimple' lab = DbgRecValueSimple+ {+ drvsLocation :: ValMd' lab -- ^ Expected to be a DILocation+ , drvsLocalVariable :: ValMd' lab -- ^ Expected to be a DILocalVariable+ , drvsExpression :: ValMd' lab -- ^ Expected to be a DIExpression+ , drvsValue :: Typed (Value' lab)+ }+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DbgRecValueSimple = DbgRecValueSimple' BlockLabel++data DbgRecDeclare' lab = DbgRecDeclare+ {+ drdLocation :: ValMd' lab -- ^ Expected to be a DILocation+ , drdLocalVariable :: ValMd' lab -- ^ Expected to be a DILocalVariable+ , drdExpression :: ValMd' lab -- ^ Expected to be a DIExpression+ , drdValAsMetadata :: ValMd' lab+ }+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DbgRecDeclare = DbgRecDeclare' BlockLabel++data DbgRecAssign' lab = DbgRecAssign+ {+ draLocation :: ValMd' lab -- ^ Expected to be a DILocation+ , draLocalVariable :: ValMd' lab -- ^ Expected to be a DILocalVariable+ , draExpression :: ValMd' lab -- ^ Expected to be a DIExpression+ , draValAsMetadata :: ValMd' lab+ , draAssignID :: ValMd' lab -- ^ Expected to be a DIAssignID+ , draExpressionAddr :: ValMd' lab -- ^ Expected to be a DIExpression+ , draValAsMetadataAddr :: ValMd' lab+ }+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DbgRecAssign = DbgRecAssign' BlockLabel++data DbgRecLabel' lab = DbgRecLabel+ {+ drlLocation :: ValMd' lab -- ^ Expected to be a DILocation+ , drlLabel :: ValMd' lab -- ^ Expected to be a DILabel+ }+ deriving (Data, Eq, Functor, Generic, Ord, Show)++type DbgRecLabel = DbgRecLabel' BlockLabel++ -- Values ---------------------------------------------------------------------- data Value' lab@@ -1370,12 +1556,12 @@ | ValAsm Bool Bool String String | ValMd (ValMd' lab) | ValPoison- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type Value = Value' BlockLabel data FP80Value = FP80_LongDouble Word16 Word64- deriving (Data, Eq, Ord, Generic, Show, Typeable)+ deriving (Data, Eq, Ord, Generic, Show) data ValMd' lab = ValMdString String@@ -1384,7 +1570,7 @@ | ValMdNode [Maybe (ValMd' lab)] | ValMdLoc (DebugLoc' lab) | ValMdDebugInfo (DebugInfo' lab)- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type ValMd = ValMd' BlockLabel @@ -1398,7 +1584,9 @@ , dlScope :: ValMd' lab , dlIA :: Maybe (ValMd' lab) , dlImplicit :: Bool- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ , dlAtomGroup :: Word64 -- ^ Introduced in LLVM 21+ , dlAtomRank :: Word64 -- ^ Introduced in LLVM 21+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DebugLoc = DebugLoc' BlockLabel @@ -1425,36 +1613,66 @@ -- Statements ------------------------------------------------------------------ +-- | Each statement, which can return a value (`Result`) referenced by the+-- `Ident` or else it has no return value (`Effect`). The statement has a single+-- Instruction, followed by any Debug Records or associated metadata.+--+-- See llvm-project/llvm/docs/RemoveDIsDebugInfo.md for discussion on the+-- [DebugRecord] fields. Note that DebugRecords and debug intrinsics may not be+-- mixed in a module; the former is new and preferred over the latter.+--+-- Technically, DebugRecords are attached to Instructions, but since there's a+-- 1:1 correspondence between Stmt and Instr, it is cleaner to attach the+-- DebugRecords to the Stmt to keep the Instrs from getting additional+-- complications.+--+-- Each statement may have both Debug Records (2nd-to-last field) and a list of+-- metadata attributes (last field). As noted above, bitcode file should not mix+-- Debug Records and intrinsics; if Debug Records are used, the metadata+-- attribute list should not contain intrinsics (although it may contain other+-- metadata associated with this statement).+ 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)+ = Result Ident (Instr' lab) [DebugRecord' lab] [(String, ValMd' lab)]+ | Effect (Instr' lab) [DebugRecord' lab] [(String, ValMd' lab)]+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type Stmt = Stmt' BlockLabel -stmtInstr :: Stmt' lab -> Instr' lab-stmtInstr (Result _ i _) = i-stmtInstr (Effect i _) = i+stmtMetadata :: Stmt' lab -> [(String, ValMd' lab)]+stmtMetadata = \case+ Result _ _ _ mds -> mds+ Effect _ _ mds -> mds -stmtMetadata :: Stmt' lab -> [(String,ValMd' lab)]-stmtMetadata stmt = case stmt of- Result _ _ mds -> mds- Effect _ mds -> mds+stmtInstr :: Stmt' lab -> Instr' lab+stmtInstr (Result _ i _ _) = i+stmtInstr (Effect i _ _) = i -extendMetadata :: (String,ValMd' lab) -> Stmt' lab -> Stmt' lab+extendMetadata :: Show lab => (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)+ Result r i [] mds -> Result r i [] (md:mds)+ Result _ _ _ _ -> error $ "Adding MD " <> show md <> " after DebugRecord"+ Effect i drs mds -> Effect i drs (md:mds) +addDebugRecord :: DebugRecord' lab -> Stmt' lab -> Stmt' lab+addDebugRecord dr = \case+ Result r i drs mds -> Result r i (snoc dr drs) mds+ Effect i drs mds -> Effect i (snoc dr drs) mds+ where+ snoc e ls = ls <> [e] -- Constant Expressions -------------------------------------------------------- data ConstExpr' lab- = ConstGEP Bool (Maybe Word64) Type (Typed (Value' lab)) [Typed (Value' lab)]+ = ConstGEP [GEPAttr] (Maybe RangeSpec) Type (Typed (Value' lab)) [Typed (Value' lab)] -- ^ Since LLVM 3.7, constant @getelementptr@ expressions include an explicit -- type to use as a basis for calculations. For older versions of LLVM, this -- type can be reconstructed by inspecting the pointee type of the parent -- pointer value.+ --+ -- Since LLVM 19, the bool "inbounds" is now [GEPAttr] and range is via+ -- RangeSpec instead of just Word64. It's recommended that the GEPAttr list+ -- should be normalized (i.e. only one of each entry). | ConstConv ConvOp (Typed (Value' lab)) Type | ConstSelect (Typed (Value' lab)) (Typed (Value' lab)) (Typed (Value' lab)) | ConstBlockAddr (Typed (Value' lab)) lab@@ -1463,14 +1681,67 @@ | ConstArith ArithOp (Typed (Value' lab)) (Value' lab) | ConstUnaryArith UnaryArithOp (Typed (Value' lab)) | ConstBit BitOp (Typed (Value' lab)) (Value' lab)- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type ConstExpr = ConstExpr' BlockLabel +-- | Attributes imposing rules on the GEP; violating any rule results in a poison+-- value. If the base is a vector of pointers, the attributes apply to each+-- computation element-wise. See+-- https://llvm.org/docs/LangRef.html#getelementptr-instruction for more+-- information.+data GEPAttr+ = GEP_Inbounds+ -- ^ Rules:+ -- * Base pointer has an inbounds (but not necessarily live) address of the+ -- allocated object it is based on (i.e. points into that allocation or to+ -- its end. Size for a growable allocated object is the max size, not the+ -- current size.+ -- * Pointer must remain inbounds at all times when adding the offsets+ -- * Implies 'GEP_NUSW'+ | GEP_NUSW+ -- ^ No unsigned signed wrap.+ -- Rules:+ -- * If type of index is larger than ptr index type, truncation preserves+ -- the signed value.+ -- * Multiplication of an index by the type size does not wrap in a+ -- signed sense.+ -- * Offset additions (excluding base address) does not wrap in a+ -- signed sense+ -- * Addition of the current address (as unsigned, truncated to ptr+ -- index type) and each offset (as signed) does not wrap the ptr+ -- index type.+ | GEP_NUW+ -- ^ No unsigned wrap+ -- Rules:+ -- * If type of index is larger than ptr index type, truncation preserves+ -- the unsigned value.+ -- * Multiplication of an index by the type size does not wrap in an+ -- unsigned sense.+ -- * Offset additions (excluding base address) does not wrap in an+ -- unsigned sense+ -- * Addition of the current address (as unsigned, truncated to ptr+ -- index type) and each offset (as unsigned) does not wrap the ptr+ -- index type.+ deriving (Data, Eq, Generic, Ord, Show)++orderedGEPAttrs :: [GEPAttr]+orderedGEPAttrs = [GEP_Inbounds, GEP_NUSW, GEP_NUW] -- bit0, bit1, ...++data RangeSpec+ = RangeIndex Word64+ -- ^ index of valid range as used in pre-LLVM19 for when "inbounds" as a+ -- boolean was True. Deprecated.+ | Range Int Integer Integer+ -- ^ width of arbitrary-precision integer (in bits) and lower and upper+ -- arbitrary-precision integer bounds of that size as [lower, upper).+ deriving (Data, Eq, Generic, Ord, Show)++ -- DWARF Debug Info ------------------------------------------------------------ data DebugInfo' lab- = DebugInfoBasicType DIBasicType+ = DebugInfoBasicType (DIBasicType' lab) | DebugInfoCompileUnit (DICompileUnit' lab) | DebugInfoCompositeType (DICompositeType' lab) | DebugInfoDerivedType (DIDerivedType' lab)@@ -1492,9 +1763,8 @@ | DebugInfoImportedEntity (DIImportedEntity' lab) | DebugInfoLabel (DILabel' lab) | DebugInfoArgList (DIArgList' lab)- | DebugInfoAssignID- -- ^ Introduced in LLVM 17.- deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ | DebugInfoAssignID -- ^ Introduced in LLVM 17.+ deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DebugInfo = DebugInfo' BlockLabel @@ -1504,7 +1774,10 @@ , dilName :: String , dilFile :: Maybe (ValMd' lab) , dilLine :: Word32- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ , dilColumn :: Word32 -- ^ Introduced in LLVM 21.+ , dilIsArtificial :: Bool -- ^ Introduced in LLVM 21.+ , dilCoroSuspendIdx :: Maybe Word32 -- ^ Introduced in LLVM 21.+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DIImportedEntity = DIImportedEntity' BlockLabel data DIImportedEntity' lab = DIImportedEntity@@ -1514,14 +1787,14 @@ , diieFile :: Maybe (ValMd' lab) , diieLine :: Word32 , diieName :: Maybe String- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DITemplateTypeParameter = DITemplateTypeParameter' BlockLabel data DITemplateTypeParameter' lab = DITemplateTypeParameter { dittpName :: Maybe String , dittpType :: Maybe (ValMd' lab) , dittpIsDefault :: Maybe Bool -- since LLVM 11- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DITemplateValueParameter = DITemplateValueParameter' BlockLabel data DITemplateValueParameter' lab = DITemplateValueParameter@@ -1530,7 +1803,7 @@ , ditvpType :: Maybe (ValMd' lab) , ditvpIsDefault :: Maybe Bool -- since LLVM 11 , ditvpValue :: ValMd' lab- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DINameSpace = DINameSpace' BlockLabel data DINameSpace' lab = DINameSpace@@ -1538,7 +1811,7 @@ , dinsScope :: ValMd' lab , dinsFile :: ValMd' lab , dinsLine :: Word32- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) -- TODO: Turn these into sum types -- See https://github.com/llvm-mirror/llvm/blob/release_38/include/llvm/Support/Dwarf.def@@ -1553,15 +1826,27 @@ -- it stabilizes. type DIEmissionKind = Word8 -data DIBasicType = DIBasicType+-- See https://github.com/llvm/llvm-project/commit/eb8901bda11fd55deeecd067fc4c9dcc0fb89984+dwarf_DW_APPLE_ENUM_KIND_invalid :: Word32+dwarf_DW_APPLE_ENUM_KIND_invalid = complement (0 :: Word32) -- ~ LLVM 19++data DIBasicType' lab = DIBasicType { dibtTag :: DwarfTag , dibtName :: String- , dibtSize :: Word64+ , dibtSize :: Maybe (ValMd' lab)+ -- ^ If using LLVM 20 or older, this will always be @Just@ an 'ValMdValue',+ -- where the underlying value is a 64-bit 'ValInteger'. If using LLVM 21 or+ -- later, this can also be a null reference (i.e., 'Nothing'), a variable+ -- (i.e., @Just@ a 'DIGlobalVariable' or 'DILocalVariable'), or an+ -- expression (i.e., @Just@ a 'DIExpression'). , dibtAlign :: Word64 , dibtEncoding :: DwarfAttrEncoding , dibtFlags :: Maybe DIFlags- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ , dibtNumExtraInhabitants :: Word64 -- ^ added in LLVM 20.+ } deriving (Data, Eq, Functor, Generic, Ord, Show) +type DIBasicType = DIBasicType' BlockLabel+ data DICompileUnit' lab = DICompileUnit { dicuLanguage :: DwarfLang , dicuFile :: Maybe (ValMd' lab)@@ -1585,7 +1870,7 @@ , dicuRangesBaseAddress :: Bool , dicuSysRoot :: Maybe String , dicuSDK :: Maybe String- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DICompileUnit = DICompileUnit' BlockLabel @@ -1596,9 +1881,19 @@ , dictLine :: Word32 , dictScope :: Maybe (ValMd' lab) , dictBaseType :: Maybe (ValMd' lab)- , dictSize :: Word64+ , dictSize :: Maybe (ValMd' lab)+ -- ^ If using LLVM 20 or older, this will always be @Just@ an 'ValMdValue',+ -- where the underlying value is a 64-bit 'ValInteger'. If using LLVM 21 or+ -- later, this can also be a null reference (i.e., 'Nothing'), a variable+ -- (i.e., @Just@ a 'DIGlobalVariable' or 'DILocalVariable'), or an+ -- expression (i.e., @Just@ a 'DIExpression'). , dictAlign :: Word64- , dictOffset :: Word64+ , dictOffset :: Maybe (ValMd' lab)+ -- ^ If using LLVM 20 or older, this will always be @Just@ an 'ValMdValue',+ -- where the underlying value is a 64-bit 'ValInteger'. If using LLVM 21 or+ -- later, this can also be a null reference (i.e., 'Nothing'), a variable+ -- (i.e., @Just@ a 'DIGlobalVariable' or 'DILocalVariable'), or an+ -- expression (i.e., @Just@ a 'DIExpression'). , dictFlags :: DIFlags , dictElements :: Maybe (ValMd' lab) , dictRuntimeLang :: DwarfLang@@ -1610,9 +1905,12 @@ , dictAssociated :: Maybe (ValMd' lab) , dictAllocated :: Maybe (ValMd' lab) , dictRank :: Maybe (ValMd' lab)- , dictAnnotations :: Maybe (ValMd' lab)- -- ^ Introduced in LLVM 14.- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ , dictAnnotations :: Maybe (ValMd' lab) -- ^ Introduced in LLVM 14.+ , dictNumExtraInhabitants :: Word64 -- ^ added in LLVM 20.+ , dictSpecification :: Maybe (ValMd' lab) -- ^ added in LLVM 20.+ , dictEnumKind :: Maybe Word32 -- ^ added in LLVM 20.+ , dictBitStride :: Maybe (ValMd' lab) -- ^ added in LLVM 20.+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DICompositeType = DICompositeType' BlockLabel @@ -1623,9 +1921,19 @@ , didtLine :: Word32 , didtScope :: Maybe (ValMd' lab) , didtBaseType :: Maybe (ValMd' lab)- , didtSize :: Word64+ , didtSize :: Maybe (ValMd' lab)+ -- ^ If using LLVM 20 or older, this will always be @Just@ an 'ValMdValue',+ -- where the underlying value is a 64-bit 'ValInteger'. If using LLVM 21 or+ -- later, this can also be a null reference (i.e., 'Nothing'), a variable+ -- (i.e., @Just@ a 'DIGlobalVariable' or 'DILocalVariable'), or an+ -- expression (i.e., @Just@ a 'DIExpression'). , didtAlign :: Word64- , didtOffset :: Word64+ , didtOffset :: Maybe (ValMd' lab)+ -- ^ If using LLVM 20 or older, this will always be @Just@ an 'ValMdValue',+ -- where the underlying value is a 64-bit 'ValInteger'. If using LLVM 21 or+ -- later, this can also be a null reference (i.e., 'Nothing'), a variable+ -- (i.e., @Just@ a 'DIGlobalVariable' or 'DILocalVariable'), or an+ -- expression (i.e., @Just@ a 'DIExpression'). , didtFlags :: DIFlags , didtExtraData :: Maybe (ValMd' lab) , didtDwarfAddressSpace :: Maybe Word32@@ -1635,18 +1943,18 @@ -- space (in LLVM, the sentinel value @0@ is used for this). , didtAnnotations :: Maybe (ValMd' lab) -- ^ Introduced in LLVM 14- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DIDerivedType = DIDerivedType' BlockLabel data DIExpression = DIExpression { dieElements :: [Word64]- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) data DIFile = DIFile { difFilename :: FilePath , difDirectory :: FilePath- } deriving (Data, Eq, Generic, Ord, Show, Typeable)+ } deriving (Data, Eq, Generic, Ord, Show) data DIGlobalVariable' lab = DIGlobalVariable { digvScope :: Maybe (ValMd' lab)@@ -1662,14 +1970,14 @@ , digvAlignment :: Maybe Word32 , digvAnnotations :: Maybe (ValMd' lab) -- ^ Introduced in LLVM 14.- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) 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)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DIGlobalVariableExpression = DIGlobalVariableExpression' BlockLabel @@ -1678,7 +1986,7 @@ , dilbFile :: Maybe (ValMd' lab) , dilbLine :: Word32 , dilbColumn :: Word16- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DILexicalBlock = DILexicalBlock' BlockLabel @@ -1686,7 +1994,7 @@ { dilbfScope :: ValMd' lab , dilbfFile :: Maybe (ValMd' lab) , dilbfDiscriminator :: Word32- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DILexicalBlockFile = DILexicalBlockFile' BlockLabel @@ -1702,7 +2010,7 @@ -- ^ Introduced in LLVM 4. , dilvAnnotations :: Maybe (ValMd' lab) -- ^ Introduced in LLVM 14.- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DILocalVariable = DILocalVariable' BlockLabel @@ -1729,7 +2037,7 @@ , dispThrownTypes :: Maybe (ValMd' lab) , dispAnnotations :: Maybe (ValMd' lab) -- ^ Introduced in LLVM 14.- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DISubprogram = DISubprogram' BlockLabel @@ -1761,21 +2069,21 @@ , disrLowerBound :: Maybe (ValMd' lab) , disrUpperBound :: Maybe (ValMd' lab) , disrStride :: Maybe (ValMd' lab)- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DISubrange = DISubrange' BlockLabel data DISubroutineType' lab = DISubroutineType { distFlags :: DIFlags , distTypeArray :: Maybe (ValMd' lab)- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DISubroutineType = DISubroutineType' BlockLabel -- | See <https://releases.llvm.org/13.0.0/docs/LangRef.html#diarglist>. newtype DIArgList' lab = DIArgList { dialArgs :: [ValMd' lab]- } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show, Typeable)+ } deriving (Data, Eq, Functor, Generic, Generic1, Ord, Show) type DIArgList = DIArgList' BlockLabel @@ -1785,7 +2093,7 @@ = Invalid -- ^ An invalid use of GEP | HasType Type -- ^ A resolved type | Resolve Ident (Type -> IndexResult) -- ^ Continue, after resolving an alias- deriving (Generic, Typeable)+ deriving (Generic) isInvalid :: IndexResult -> Bool isInvalid ir = case ir of
src/Text/LLVM/DebugUtils.hs view
@@ -230,16 +230,28 @@ let bitfield | testBit (didtFlags dt) 19 , Just extraData <- didtExtraData dt , Just bitfieldOffset <- getInteger mdMap extraData- = Just $ BitfieldInfo { biFieldSize = didtSize dt- , biBitfieldOffset = fromInteger bitfieldOffset- }+ = do size <- getSizeOrOffset (didtSize dt)+ Just $ BitfieldInfo { biFieldSize = size+ , biBitfieldOffset = fromInteger bitfieldOffset+ } | otherwise = Nothing+ offset <- getSizeOrOffset (didtOffset dt) Just (StructFieldInfo { sfiName = fieldName- , sfiOffset = didtOffset dt+ , sfiOffset = offset , sfiBitfield = bitfield , sfiInfo = valMdToInfo' mdMap (didtBaseType dt) })+ where+ -- TODO: Currently, this only recognizes bare integer (i.e., 'ValInteger')+ -- sizes and offsets. This is likely good enough for Clang-derived LLVM, but+ -- Ada-derived LLVM may contain more complex metadata values that this+ -- currently doesn't handle.+ getSizeOrOffset :: Maybe ValMd -> Maybe Word64+ getSizeOrOffset (Just (ValMdValue tv))+ | ValInteger i <- typedValue tv+ = Just (fromInteger i)+ getSizeOrOffset _ = Nothing getUnionFields :: MdMap -> DICompositeType -> Maybe [UnionFieldInfo]@@ -365,10 +377,10 @@ where aux :: [Stmt] -> Map Ident Ident -> Map Ident Ident- aux ( Effect (Store src dst _ _) _- : Effect (Call _ _ (ValSymbol (Symbol what)) [var,md,_]) _+ aux ( Effect (Store src dst _ _) _ _+ : Effect (Call _ _ (ValSymbol (Symbol what)) [var,md,_]) _ _ : _) sofar- | what == "llvm.dbg.declare"+ | what == "llvm.dbg.declare" -- pre-LLVM19: intrinsic declaration match , Just dstIdent <- extractIdent dst , Just srcIdent <- extractIdent src , Just varIdent <- extractIdent var@@ -376,9 +388,9 @@ , Just name <- extractLvName md = Map.insert name srcIdent sofar - aux ( Effect (Call _ _ (ValSymbol (Symbol what)) [var,_,md,_]) _+ aux ( Effect (Call _ _ (ValSymbol (Symbol what)) [var,_,md,_]) _ _ : _) sofar- | what == "llvm.dbg.value"+ | what == "llvm.dbg.value" -- pre-LLVM19: intrinsic declaration match , Just key <- extractIdent var , Just name <- extractLvName md = Map.insert name key sofar
src/Text/LLVM/Labels.hs view
@@ -60,7 +60,8 @@ <*> traverse (relabel f) a <*> pure s <*> pure o- relabel f (ICmp op l r) = ICmp op+ relabel f (ICmp samesign op l r)+ = ICmp samesign op <$> traverse (relabel f) l <*> relabel f r relabel f (FCmp op l r) = FCmp op@@ -125,9 +126,16 @@ instance HasLabel Clause' where relabel = $(generateRelabel 'relabel ''Clause') instance HasLabel Value' where relabel = $(generateRelabel 'relabel ''Value') instance HasLabel ValMd' where relabel = $(generateRelabel 'relabel ''ValMd')+instance HasLabel DebugRecord' where relabel = $(generateRelabel 'relabel ''DebugRecord')+instance HasLabel DbgRecAssign' where relabel = $(generateRelabel 'relabel ''DbgRecAssign')+instance HasLabel DbgRecDeclare' where relabel = $(generateRelabel 'relabel ''DbgRecDeclare')+instance HasLabel DbgRecLabel' where relabel = $(generateRelabel 'relabel ''DbgRecLabel')+instance HasLabel DbgRecValueSimple' where relabel = $(generateRelabel 'relabel ''DbgRecValueSimple')+instance HasLabel DbgRecValue' where relabel = $(generateRelabel 'relabel ''DbgRecValue') instance HasLabel DILabel' where relabel = $(generateRelabel 'relabel ''DILabel') instance HasLabel DebugLoc' where relabel = $(generateRelabel 'relabel ''DebugLoc') instance HasLabel DebugInfo' where relabel = $(generateRelabel 'relabel ''DebugInfo')+instance HasLabel DIBasicType' where relabel = $(generateRelabel 'relabel ''DIBasicType') instance HasLabel DIDerivedType' where relabel = $(generateRelabel 'relabel ''DIDerivedType') instance HasLabel DISubroutineType' where relabel = $(generateRelabel 'relabel ''DISubroutineType') instance HasLabel DISubrange' where relabel = $(generateRelabel 'relabel ''DISubrange')
src/Text/LLVM/Lens.hs view
@@ -31,7 +31,7 @@ , ''DebugInfo' , ''DIFile , ''DISubrange'- , ''DIBasicType+ , ''DIBasicType' , ''DIExpression , ''DISubprogram' , ''DISubroutineType'
src/Text/LLVM/PP.hs view
@@ -24,7 +24,7 @@ import Control.Applicative ((<|>)) import Data.Bits ( shiftR, (.&.) ) import Data.Char (isAlphaNum,isAscii,isDigit,isPrint,ord,toUpper)-import Data.List (intersperse)+import Data.List ( intersperse, nub ) import qualified Data.Map as Map import Data.Maybe (catMaybes,fromMaybe,isJust) import GHC.Float (castDoubleToWord64, castFloatToWord32)@@ -73,7 +73,7 @@ -- this is used for defaulting and otherwise reporting the maximum LLVM version -- known to be supported. llvmVlatest :: LLVMVer-llvmVlatest = 17+llvmVlatest = 19 -- | The differences between various versions of the llvm textual AST.@@ -206,29 +206,45 @@ case ls of BigEndian -> char 'E' LittleEndian -> char 'e'- PointerSize 0 sz abi pref -> char 'p' <> char ':' <> ppLayoutBody sz abi pref- PointerSize n sz abi pref -> char 'p' <> int n <> char ':'- <> ppLayoutBody sz abi pref- IntegerSize sz abi pref -> char 'i' <> ppLayoutBody sz abi pref- VectorSize sz abi pref -> char 'v' <> ppLayoutBody sz abi pref- FloatSize sz abi pref -> char 'f' <> ppLayoutBody sz abi pref- StackObjSize sz abi pref -> char 's' <> ppLayoutBody sz abi pref- AggregateSize sz abi pref -> char 'a' <> ppLayoutBody sz abi pref+ PointerSize ps -> char 'p' <> ppPointerSize ps+ IntegerSize sz -> char 'i' <> ppStorage sz+ VectorSize sz -> char 'v' <> ppStorage sz+ FloatSize sz -> char 'f' <> ppStorage sz+ StackObjSize sz -> char 's' <> ppStorage sz+ AggregateSize Nothing a -> char 'a' <> char ':' <> ppAlignment a+ AggregateSize (Just s) a -> char 'a' <> int s <> char ':' <> ppAlignment a NativeIntSize szs -> char 'n' <> hcat (punctuate (char ':') (map int szs))+ StackAlign a -> char 'S' <> int a+ ProgramAddrSpace as -> char 'P' <> int as+ GlobalAddrSpace as -> char 'G' <> int as+ AllocaAddrSpace as -> char 'A' <> int as FunctionPointerAlign ty abi -> char 'F' <> ppFunctionPointerAlignType ty <> int abi- StackAlign a -> char 'S' <> int a Mangling m -> char 'm' <> char ':' <> ppMangling m+ NonIntegralPointerSpaces asl ->+ "ni:" <> hcat (punctuate (char ':') (map int asl)) --- | Pretty-print the common case for data layout specifications.-ppLayoutBody :: Int -> Int -> Fmt (Maybe Int)-ppLayoutBody size abi mb = int size <> char ':' <> int abi <> pref- where- pref = case mb of- Nothing -> empty- Just p -> char ':' <> int p+ppPointerSize :: Fmt PointerSize+ppPointerSize ps =+ if ptrAddrSpace ps == 0+ then char ':' <> ppStorage (ptrStorage ps)+ <> ppOptColonInt (ptrAddrIndexSize ps)+ else int (ptrAddrSpace ps) <> char ':' <> ppStorage (ptrStorage ps)+ <> ppOptColonInt (ptrAddrIndexSize ps) +ppStorage :: Fmt Storage+ppStorage s = int (storageSize s) <> char ':'+ <> ppAlignment (storageAlignment s)++ppAlignment :: Fmt Alignment+ppAlignment a = int (alignABI a) <> ppOptColonInt (alignPreferred a)++ppOptColonInt :: Fmt (Maybe Int)+ppOptColonInt = \case+ Nothing -> empty+ Just i -> char ':' <> int i+ ppFunctionPointerAlignType :: Fmt FunctionPointerAlignType ppFunctionPointerAlignType ty = case ty of@@ -237,9 +253,12 @@ ppMangling :: Fmt Mangling ppMangling ElfMangling = char 'e'+ppMangling GoffMangling = char 'l' ppMangling MipsMangling = char 'm' ppMangling MachOMangling = char 'o' ppMangling WindowsCoffMangling = char 'w'+ppMangling WindowsX86CoffMangling = char 'x'+ppMangling XCoffMangling = char 'a' -- Inline Assembly -------------------------------------------------------------@@ -321,8 +340,15 @@ <+> ppGlobalAttrs (isJust $ globalValue g) (globalAttrs g) <+> ppType (globalType g) <+> ppMaybe ppValue (globalValue g) <> ppAlign (globalAlign g)- <> ppAttachedMetadata (Map.toList (globalMetadata g))+ <> ppGlobalMetadata (Map.toList (globalMetadata g)) +ppGlobalMetadata :: Fmt [(String, ValMd' BlockLabel)]+ppGlobalMetadata mds+ | null mds = empty+ | otherwise = comma <+> commas (map step mds)+ where+ step (l,md) = ppMetadata (text l) <+> ppValMd md+ -- | Pretty-print Global Attributes (usually associated with a global variable -- declaration). The first argument to ppGlobalAttrs indicates whether there is a -- value associated with this global declaration: a global declaration with a@@ -451,9 +477,11 @@ ppStmt :: Fmt Stmt ppStmt stmt = case stmt of- Result var i mds -> ppIdent var <+> char '=' <+> ppInstr i- <> ppAttachedMetadata mds- Effect i mds -> ppInstr i <> ppAttachedMetadata mds+ Result var i drs mds -> ppDebugRecords drs (ppIdent var <+> char '='+ <+> ppInstr i+ <> ppAttachedMetadata mds)+ Effect i drs mds -> ppDebugRecords drs (ppInstr i+ <> ppAttachedMetadata mds) ppAttachedMetadata :: Fmt [(String,ValMd)] ppAttachedMetadata mds@@ -531,14 +559,14 @@ ppBitOp Xor = "xor" ppConvOp :: Fmt ConvOp-ppConvOp Trunc = "trunc"-ppConvOp ZExt = "zext"+ppConvOp (Trunc nuw nsw) = "trunc" <+> ppSignBits nuw nsw+ppConvOp (ZExt nneg) = "zext" <+> opt nneg "nneg" ppConvOp SExt = "sext" ppConvOp FpTrunc = "fptrunc" ppConvOp FpExt = "fpext" ppConvOp FpToUi = "fptoui" ppConvOp FpToSi = "fptosi"-ppConvOp UiToFp = "uitofp"+ppConvOp (UiToFp nneg) = "uitofp" <+> opt nneg "nneg" ppConvOp SiToFp = "sitofp" ppConvOp PtrToInt = "ptrtoint" ppConvOp IntToPtr = "inttoptr"@@ -607,7 +635,7 @@ <> comma <+> ppTyped ppValue a <+> ppScope s <+> ppAtomicOrdering o- ICmp op l r -> "icmp" <+> ppICmpOp op+ ICmp samesign op l r -> "icmp" <+> opt samesign "samesign" <+> ppICmpOp op <+> ppTyped ppValue l <> comma <+> ppValue r FCmp op l r -> "fcmp" <+> ppFCmpOp op <+> ppTyped ppValue l <> comma <+> ppValue r@@ -624,7 +652,7 @@ ShuffleVector a b m -> "shufflevector" <+> ppTyped ppValue a <> comma <+> ppTyped ppValue (b <$ a) <> comma <+> ppTyped ppValue m- GEP ib ty ptr ixs -> ppGEP ib ty ptr ixs+ GEP gf ty ptr ixs -> ppGEP gf ty ptr ixs Comment str -> char ';' <+> text str Jump i -> "br" <+> ppTypedLabel i@@ -647,7 +675,10 @@ <> comma <+> ppVectorIndex i IndirectBr d ls -> "indirectbr" <+> ppTyped ppValue d- <> comma <+> commas (map ppTypedLabel ls)+ <> comma+ <+> char '['+ <+> commas (map ppTypedLabel ls)+ <+> char ']' Switch c d ls -> "switch" <+> ppTyped ppValue c <> comma <+> ppTypedLabel d@@ -779,19 +810,20 @@ -> ppType res _ -> ppType ty -ppGEP :: Bool -> Type -> Typed Value -> Fmt [Typed Value]-ppGEP ib ty ptr ixs =- "getelementptr" <+> inbounds+ppGEP :: [GEPAttr] -> Type -> Typed Value -> Fmt [Typed Value]+ppGEP gf ty ptr ixs =+ "getelementptr"+ <+> (if inlineIsBool+ then (if GEP_Inbounds `elem` gf then "inbounds" else empty)+ else ppGepFlags gf) <+> (if isExplicit then explicit else empty) <+> commas (map (ppTyped ppValue) (ptr:ixs)) where isExplicit = llvmVer >= llvmV3_7+ inlineIsBool = llvmVer < 19 explicit = ppType ty <> comma - inbounds | ib = "inbounds"- | otherwise = empty- ppInvoke :: Type -> Value -> [Typed Value] -> BlockLabel -> Fmt BlockLabel ppInvoke ty f args to uw = body where@@ -893,13 +925,20 @@ <> parens (commas [ "line:" <+> integral (dlLine dl) , "column:" <+> integral (dlCol dl) , "scope:" <+> ppValMd' pp (dlScope dl)- ] <> mbIA <> mbImplicit)+ ] <> mbIA <> mbImplicit <>+ when' (llvmVer >= 21) (mbAtomGroup <> mbAtomRank)) where mbIA = case dlIA dl of Just md -> comma <+> "inlinedAt:" <+> ppValMd' pp md Nothing -> empty mbImplicit = if dlImplicit dl then comma <+> "implicit" else empty+ mbAtomGroup = if dlAtomGroup dl > 0+ then comma <+> "atomGroup:" <+> integral (dlAtomGroup dl)+ else empty+ mbAtomRank = if dlAtomRank dl > 0+ then comma <+> "atomRank:" <+> integral (dlAtomRank dl)+ else empty ppDebugLoc :: Fmt DebugLoc ppDebugLoc = ppDebugLoc' ppLabel@@ -942,24 +981,76 @@ ppConstExpr' :: Fmt i -> Fmt (ConstExpr' i) ppConstExpr' pp expr = case expr of- ConstGEP inb _mix ty ptr ixs ->+ ConstGEP optflgs mrng ty ptr ixs -> "getelementptr"- <+> opt inb "inbounds"- <+> parens (commas (ppType ty : map ppTyp' (ptr:ixs)))- ConstConv op tv t -> ppConvOp op <+> parens (ppTyp' tv <+> "to" <+> ppType t)+ <+> ppGepFlags optflgs+ <+> ppRange mrng+ <+> parens (commas (+ let argIndices = 0 : [0..] -- rval, ptr, then ixs indices+ in reverse -- ppTyp's pushes entries to the listg head+ $ foldl (ppTyp's mrng) [ppType ty]+ $ zip argIndices (ptr:ixs)))+ ConstConv op tv t ->+ let droppedIn18 = case op of+ -- https://github.com/llvm/llvm-project commit e4a4122 dropped ZExt and SExt+ ZExt _ -> True+ SExt -> True+ -- https://github.com/llvm/llvm-project commit 17764d2 dropped FpTrunc through SiToFP+ FpTrunc -> True+ FpExt -> True+ FpToUi -> True+ FpToSi -> True+ UiToFp _ -> True+ SiToFp -> True+ _ -> False+ ppConstConv = ppConvOp op <+> parens (ppTyp' tv <+> "to" <+> ppType t)+ in if droppedIn18+ then droppedInLLVM 18 "fptrunc/fpext/fptoui/fptosi/uitofp/sitofp constexprs" ppConstConv+ else ppConstConv ConstSelect c l r ->- "select" <+> parens (commas [ ppTyp' c, ppTyp' l , ppTyp' r])+ droppedInLLVM 17 "select constexpr" -- https://github.com/llvm/llvm-project commit bbfb13a++ $ "select" <+> parens (commas [ ppTyp' c, ppTyp' l , ppTyp' r]) ConstBlockAddr t l -> "blockaddress" <+> parens (ppVal' (typedValue t) <> comma <+> pp l)- ConstFCmp op a b -> "fcmp" <+> ppFCmpOp op <+> ppTupleT a b- ConstICmp op a b -> "icmp" <+> ppICmpOp op <+> ppTupleT a b+ ConstFCmp op a b -> droppedInLLVM 19 "fcmp constexprs"+ $ "fcmp" <+> ppFCmpOp op <+> ppTupleT a b+ ConstICmp op a b -> droppedInLLVM 19 "icmp constexprs"+ $ "icmp" <+> ppICmpOp op <+> ppTupleT a b ConstArith op a b -> ppArithOp op <+> ppTuple a b ConstUnaryArith op a -> ppUnaryArithOp op <+> ppTyp' a- ConstBit op a b -> ppBitOp op <+> ppTuple a b+ ConstBit op@(Shl _ _) a b -> droppedInLLVM 19 "shl constexprs"+ $ ppBitOp op <+> ppTuple a b+ ConstBit Xor a b -> ppBitOp Xor <+> ppTuple a b+ ConstBit op a b -> droppedInLLVM 18 "and/or/lshr/ashr constexprs"+ $ ppBitOp op <+> ppTuple a b where ppTuple a b = parens $ ppTyped ppVal' a <> comma <+> ppVal' b ppTupleT a b = parens $ ppTyped ppVal' a <> comma <+> ppTyp' b ppVal' = ppValue' pp ppTyp' = ppTyped ppVal'+ ppTyp's mrng a (i,t) =+ let inrangeMark = if Just (RangeIndex i) == mrng then "inrange" else empty+ in (inrangeMark <+> ppTyp' t) : a+ ppRange =+ let ppR = \case+ RangeIndex _i -> empty -- handled in ppTyp's+ Range _ l u ->+ "inrange(" <> integral l <> ", " <> integral u <> ")"+ in maybe empty ppR +ppGepFlags :: Fmt [GEPAttr]+ppGepFlags s =+ let fltr = if GEP_Inbounds `elem` s+ then+ -- inbounds implies nusw, but LLVM stipulates that if+ -- inbounds is present, nusw is not also printed.+ filter (/= GEP_NUSW)+ else id+ ppF = \case+ GEP_Inbounds -> "inbounds"+ GEP_NUSW -> "nusw"+ GEP_NUW -> "nuw"+ in foldl (\o f -> o <+> ppF f) empty $ fltr $ nub s+ ppConstExpr :: Fmt ConstExpr ppConstExpr = ppConstExpr' ppLabel @@ -967,7 +1058,7 @@ ppDebugInfo' :: Fmt i -> Fmt (DebugInfo' i) ppDebugInfo' pp di = case di of- DebugInfoBasicType bt -> ppDIBasicType bt+ DebugInfoBasicType bt -> ppDIBasicType' pp bt DebugInfoCompileUnit cu -> ppDICompileUnit' pp cu DebugInfoCompositeType ct -> ppDICompositeType' pp ct DebugInfoDerivedType dt -> ppDIDerivedType' pp dt@@ -989,7 +1080,69 @@ DebugInfoLabel dil -> ppDILabel' pp dil DebugInfoArgList args -> ppDIArgList' pp args DebugInfoAssignID -> "!DIAssignID()"+ -- DebugRecordDeclare drd -> ppDbgRecDeclare' pp drd +-- Prints DebugRecords (introduced in LLVM 19) which replace debug intrinsics and+-- unlike the intrinsics that follow the instruction, the debug records *precede*+-- the Instruction they affect.+ppDebugRecords :: [DebugRecord' BlockLabel] -> Fmt Doc+ppDebugRecords [] = id+ppDebugRecords drs = ((nest 2 $ vcat (ppDebugRecord' ppLabel <$> drs)) $$)++ppDebugRecord' :: Fmt lab -> Fmt (DebugRecord' lab)+ppDebugRecord' pl = \case+ DebugRecordValue drv -> ppDbgRecValue' pl drv+ DebugRecordDeclare drd -> ppDbgRecDeclare' pl drd+ DebugRecordAssign dra -> ppDbgRecAssign' pl dra+ DebugRecordValueSimple dvs -> ppDbgRecValueSimple' pl dvs+ DebugRecordLabel drl -> ppDbgRecLabel' pl drl++ppDbgRecValue' :: Fmt lab -> Fmt (DbgRecValue' lab)+ppDbgRecValue' pl dr =+ "#dbg_value"+ <> parens (commas [ ppValMd' pl $ drvValAsMetadata dr+ , ppValMd' pl $ drvLocalVariable dr+ , ppValMd' pl $ drvExpression dr+ , ppValMd' pl $ drvLocation dr+ ])++ppDbgRecDeclare' :: Fmt lab -> Fmt (DbgRecDeclare' lab)+ppDbgRecDeclare' pl dr =+ "#dbg_declare"+ <> parens (commas [ ppValMd' pl $ drdValAsMetadata dr+ , ppValMd' pl $ drdLocalVariable dr+ , ppValMd' pl $ drdExpression dr+ , ppValMd' pl $ drdLocation dr+ ])++ppDbgRecAssign' :: Fmt lab -> Fmt (DbgRecAssign' lab)+ppDbgRecAssign' pl dr =+ "#dbg_assign"+ <> parens (commas [ ppValMd' pl $ draValAsMetadata dr+ , ppValMd' pl $ draLocalVariable dr+ , ppValMd' pl $ draExpression dr+ , ppValMd' pl $ draAssignID dr+ , ppValMd' pl $ draValAsMetadataAddr dr+ , ppValMd' pl $ draExpressionAddr dr+ , ppValMd' pl $ draLocation dr+ ])++ppDbgRecValueSimple' :: Fmt lab -> Fmt (DbgRecValueSimple' lab)+ppDbgRecValueSimple' pl dr =+ "#dbg_value"+ <> parens (commas [ ppTyped (ppValue' pl) $ drvsValue dr+ , ppValMd' pl $ drvsLocalVariable dr+ , ppValMd' pl $ drvsExpression dr+ , ppValMd' pl $ drvsLocation dr+ ])++ppDbgRecLabel' :: Fmt lab -> Fmt (DbgRecLabel' lab)+ppDbgRecLabel' pl dr =+ "#dbg_label"+ <> parens (commas [ ppValMd' pl $ drlLabel dr+ , ppValMd' pl $ drlLocation dr+ ])+ ppDebugInfo :: Fmt DebugInfo ppDebugInfo = ppDebugInfo' ppLabel @@ -1008,11 +1161,17 @@ ppDILabel' :: Fmt i -> Fmt (DILabel' i) ppDILabel' pp ie = "!DILabel"- <> parens (mcommas [ (("scope:" <+>) . ppValMd' pp) <$> dilScope ie- , pure ("name:" <+> ppStringLiteral (dilName ie))- , (("file:" <+>) . ppValMd' pp) <$> dilFile ie- , pure ("line:" <+> integral (dilLine ie))- ])+ <> parens (mcommas $+ [ (("scope:" <+>) . ppValMd' pp) <$> dilScope ie+ , pure ("name:" <+> ppStringLiteral (dilName ie))+ , (("file:" <+>) . ppValMd' pp) <$> dilFile ie+ , pure ("line:" <+> integral (dilLine ie))+ ] +++ when' (llvmVer >= 21)+ [ pure ("column:" <+> integral (dilColumn ie))+ , pure ("isArtificial:" <+> ppBool (dilIsArtificial ie))+ , (("coroSuspendIdx:" <+>) . integral) <$> dilCoroSuspendIdx ie+ ]) ppDILabel :: Fmt DILabel ppDILabel = ppDILabel' ppLabel@@ -1048,18 +1207,20 @@ ppDITemplateValueParameter :: Fmt DITemplateValueParameter ppDITemplateValueParameter = ppDITemplateValueParameter' ppLabel -ppDIBasicType :: Fmt DIBasicType-ppDIBasicType bt = "!DIBasicType"- <> parens (commas [ "tag:" <+> integral (dibtTag bt)- , "name:" <+> doubleQuotes (text (dibtName bt))- , "size:" <+> integral (dibtSize bt)- , "align:" <+> integral (dibtAlign bt)- , "encoding:" <+> integral (dibtEncoding bt)- ] <> mbFlags)- where- mbFlags = case dibtFlags bt of- Just flags -> comma <+> "flags:" <+> integral flags- Nothing -> empty+ppDIBasicType' :: Fmt i -> Fmt (DIBasicType' i)+ppDIBasicType' pp bt = "!DIBasicType"+ <> parens (mcommas+ [ pure ("tag:" <+> integral (dibtTag bt))+ , pure ("name:" <+> doubleQuotes (text (dibtName bt)))+ , (("size:" <+>) . ppSizeOrOffsetValMd' pp) <$> dibtSize bt+ , pure ("align:" <+> integral (dibtAlign bt))+ , pure ("encoding:" <+> integral (dibtEncoding bt))+ , (("flags:" <+>) . integral)+ <$> dibtFlags bt+ , if dibtNumExtraInhabitants bt > 0+ then pure ("numExtraInhabitants:" <+> integral (dibtNumExtraInhabitants bt))+ else Nothing+ ]) ppDICompileUnit' :: Fmt i -> Fmt (DICompileUnit' i) ppDICompileUnit' pp cu = "!DICompileUnit"@@ -1110,9 +1271,9 @@ , (("file:" <+>) . ppValMd' pp) <$> (dictFile ct) , pure ("line:" <+> integral (dictLine ct)) , (("baseType:" <+>) . ppValMd' pp) <$> (dictBaseType ct)- , pure ("size:" <+> integral (dictSize ct))+ , (("size:" <+>) . ppSizeOrOffsetValMd' pp) <$> dictSize ct , pure ("align:" <+> integral (dictAlign ct))- , pure ("offset:" <+> integral (dictOffset ct))+ , (("offset:" <+>) . ppSizeOrOffsetValMd' pp) <$> dictOffset ct , pure ("flags:" <+> integral (dictFlags ct)) , (("elements:" <+>) . ppValMd' pp) <$> (dictElements ct) , pure ("runtimeLang:" <+> integral (dictRuntimeLang ct))@@ -1125,6 +1286,12 @@ , (("allocated:" <+>) . ppValMd' pp) <$> (dictAllocated ct) , (("rank:" <+>) . ppValMd' pp) <$> (dictRank ct) , (("annotations:" <+>) . ppValMd' pp) <$> (dictAnnotations ct)+ , if dictNumExtraInhabitants ct > 0+ then pure ("numExtraInhabitants:" <+> integral (dictNumExtraInhabitants ct))+ else Nothing+ , (("specification:" <+>) . ppValMd' pp) <$> (dictSpecification ct)+ , (("enumKind:" <+>) . integral) <$> (dictEnumKind ct)+ , (("bitStride:" <+>) . ppValMd' pp) <$> (dictBitStride ct) ]) ppDICompositeType :: Fmt DICompositeType@@ -1139,9 +1306,9 @@ , pure ("line:" <+> integral (didtLine dt)) , (("scope:" <+>) . ppValMd' pp) <$> (didtScope dt) , ("baseType:" <+>) <$> (ppValMd' pp <$> didtBaseType dt <|> Just "null")- , pure ("size:" <+> integral (didtSize dt))+ , (("size:" <+>) . ppSizeOrOffsetValMd' pp) <$> didtSize dt , pure ("align:" <+> integral (didtAlign dt))- , pure ("offset:" <+> integral (didtOffset dt))+ , (("offset:" <+>) . ppSizeOrOffsetValMd' pp) <$> didtOffset dt , pure ("flags:" <+> integral (didtFlags dt)) , (("extraData:" <+>) . ppValMd' pp) <$> (didtExtraData dt) , (("dwarfAddressSpace:" <+>) . integral) <$> didtDwarfAddressSpace dt@@ -1359,7 +1526,18 @@ -- ValMdRef _idx -> mempty -- no table here to look this up... o -> when' canFallBack $ ppValMd' pp o +-- | Print the size or offset of a type-related metadata node. This value can+-- either be an integer literal (in which case the bare literal is printed), or+-- in LLVM 21 or later, it can be a more complicated metadata expression (in+-- which case the metadata is pretty-printed).+ppSizeOrOffsetValMd' :: Fmt i -> Fmt (ValMd' i)+ppSizeOrOffsetValMd' pp = \case+ ValMdValue tv+ | ValInteger i <- typedValue tv+ -> integer i+ o -> when' (llvmVer >= 21) $ ppValMd' pp o + commas :: Fmt [Doc] commas = fsep . punctuate comma @@ -1384,3 +1562,11 @@ | llvmVer >= fromVer = id | otherwise = error $ name ++ " is supported only on LLVM >= " ++ llvmVerToString fromVer++-- | Throw an error if the @?config@ version is older than the given version. The+-- String indicates which constructor is unavailable in the error message.+droppedInLLVM :: (?config :: Config) => LLVMVer -> String -> a -> a+droppedInLLVM fromVer name+ | llvmVer >= fromVer = error $ name ++ " is supported only up to LLVM >= "+ ++ llvmVerToString fromVer+ | otherwise = id
src/Text/LLVM/Triple/AST.hs view
@@ -21,7 +21,6 @@ ) where import Data.Data (Data)-import Data.Typeable (Typeable) import GHC.Generics (Generic) -- | The constructors of this type exactly mirror the LLVM @enum ArchType@,@@ -150,7 +149,7 @@ | RenderScript64 -- | NEC SX-Aurora Vector Engine | VE- deriving (Bounded, Data, Eq, Enum, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Eq, Enum, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'UnknownArch'.@@ -216,7 +215,7 @@ | SPIRVSubArch_v13 | SPIRVSubArch_v14 | SPIRVSubArch_v15- deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'NoSubArch'.@@ -250,7 +249,7 @@ | Mesa | SUSE | OpenEmbedded- deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'UnknownVendor'.@@ -323,7 +322,7 @@ | Emscripten -- | DirectX ShaderModel | ShaderModel- deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'UnknownOS'.@@ -386,7 +385,7 @@ | Callable | Mesh | Amplification- deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'UnknownEnvironment'.@@ -414,7 +413,7 @@ | SPIRV | Wasm | XCOFF- deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show) -- | A 'First'-like semigroup instance that simply drops the RHS, unless the LHS -- is 'UnknownObjectFormat'.@@ -440,7 +439,7 @@ , ttEnv :: Environment , ttObjFmt :: ObjectFormat }- deriving (Bounded, Data, Eq, Generic, Ord, Read, Show, Typeable)+ deriving (Bounded, Data, Eq, Generic, Ord, Read, Show) -- | Combines fields pointwise. instance Semigroup TargetTriple where
+ test/DataLayout.hs view
@@ -0,0 +1,31 @@+module DataLayout ( tests ) where++import Text.LLVM.AST+import Text.LLVM.PP++import Test.Tasty+import Test.Tasty.HUnit++tests :: TestTree+tests =+ let rspDL s = Just $ "target datalayout = \"" <> s <> "\""+ ppDL = show . ppLLVM llvmVlatest ppDataLayout+ in testGroup "Test DataLayout"+ [ testCase "datalayout 0" $ ppDL <$> parseDataLayout "" @?= Just ""+ , testCase "datalayout 1"+ $ let dl = "e" in ppDL <$> parseDataLayout dl @?= rspDL dl+ , testCase "datalayout 2"+ $ let dl = "e-m:e" in ppDL <$> parseDataLayout dl @?= rspDL dl+ , testCase "datalayout 3"+ $ let dl = "e-m:e-p270:32:32"+ in ppDL <$> parseDataLayout dl @?= rspDL dl+ , testCase "datalayout 4"+ $ let dl = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-S128"+ in ppDL <$> parseDataLayout dl @?= rspDL dl+ , testCase "datalayout 5"+ $ let dl = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"+ in ppDL <$> parseDataLayout dl @?= rspDL dl+ , testCase "datalayout 6"+ $ let dl = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-ni:3:4-S128"+ in ppDL <$> parseDataLayout dl @?= rspDL dl+ ]
test/Main.hs view
@@ -2,12 +2,16 @@ import qualified Test.Tasty as Tasty -import qualified Triple+import qualified DataLayout+import qualified Metadata import qualified Output+import qualified Triple main :: IO () main = Tasty.defaultMain $ Tasty.testGroup "LLVM tests" [- Output.tests+ DataLayout.tests+ , Metadata.tests+ , Output.tests , Triple.tests ]
+ test/Metadata.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE TypeApplications #-}++-- | This module provides some testing of the metadata that can be attached to+-- Statements.++module Metadata ( tests ) where++import qualified Test.Tasty as Tasty+import Test.Tasty.HUnit++import Text.LLVM.AST+++tests :: Tasty.TestTree+tests = Tasty.testGroup "LLVM metadata tests" $+ let s1 = Effect (Load PtrOpaque (Typed Opaque ValNull) Nothing Nothing)+ mempty md1+ s2 = Result (Ident "r1")+ (Load PtrOpaque (Typed Opaque ValNull) Nothing Nothing)+ mempty md1+ md1 = [ ("foo", ValMdLoc $ DebugLoc { dlLine = 12+ , dlCol = 34+ , dlScope = ValMdRef 5+ , dlIA = Nothing+ , dlImplicit = True+ , dlAtomGroup = 0+ , dlAtomRank = 0 })+ , ("moo", ValMdString @Value "cow")+ ]+ in+ [+ testCase "stmtMetadata Effect" $ stmtMetadata s1 @?= md1+ , testCase "stmtMetadata Result" $ stmtMetadata s2 @?= md1+ ]
test/Output.hs view
@@ -32,15 +32,23 @@ -- output are seen. s1, s2 :: Stmt s1 = Effect- (GEP True (Alias (Ident "hi")) (Typed Opaque dcu) [])- []+ (GEP [GEP_Inbounds] (Alias (Ident "hi")) (Typed Opaque dcu) [])+ mempty [] s2 = Effect (Load PtrOpaque (Typed Opaque ValNull) Nothing Nothing)+ mempty [ ("location", ValMdLoc $ DebugLoc { dlLine = 12 , dlCol = 34 , dlScope = ValMdRef 5 , dlIA = Nothing- , dlImplicit = True })+ , dlImplicit = True+ , dlAtomGroup = 0+ , dlAtomRank = 0 }) ]+ s3 = Effect+ (IndirectBr+ (Typed PtrOpaque (ValIdent "addr"))+ [Named "hello", Named "world"])+ [] [] dcu :: Value dcu = ValMd $ ValMdDebugInfo@@ -75,10 +83,10 @@ } blk1 = BasicBlock { bbLabel = Just $ Named $ Ident "blk1" , bbStmts =- [ Result (Ident "r1") (Comment "insanity follows...") []- , Effect (Jump $ Named $ Ident "blk1") []- , Result (Ident "oh no") RetVoid []- , Effect (Br (Typed (PrimType Metadata) ValZeroInit) (Anon 3) (Named "oh no")) []+ [ Result (Ident "r1") (Comment "insanity follows...") mempty []+ , Effect (Jump $ Named $ Ident "blk1") mempty []+ , Result (Ident "oh no") RetVoid mempty []+ , Effect (Br (Typed (PrimType Metadata) ValZeroInit) (Anon 3) (Named "oh no")) mempty [] ] } blk2 = BasicBlock { bbLabel = Just $ Anon 123@@ -167,6 +175,51 @@ ---- |] + , testCase "Stmt 1, LLVM 18" $+ assertEqLines (ppToText $ ppLLVM 18 $ ppStmt s1) [sq|+ Significant changes occur in LLVM 19; ensure that the output is as+ expected just prior to those changes to properly capture the+ inflection point.+ ----+ getelementptr inbounds %hi, opaque !DICompileUnit(language: 12,+ producer: "llvm-pretty-test",+ isOptimized: true,+ flags: "some flags",+ runtimeVersion: 3,+ emissionKind: 1,+ enums: !DITemplateTypeParameter(name: ttp),+ dwoId: 2,+ splitDebugInlining: false,+ debugInfoForProfiling: true,+ nameTableKind: 4,+ rangesBaseAddress: true,+ sysroot: "the root",+ sdk: "SDK")+ ----+ |]++ , testCase "Stmt 1, LLVM 19" $+ assertEqLines (ppToText $ ppLLVM 19 $ ppStmt s1) [sq|+ In LLVM 19, the GEP instruction "inbounds" is no longer a boolean+ but a flag with multiple possible values (only one is checked here).+ ----+ getelementptr inbounds %hi, opaque !DICompileUnit(language: 12,+ producer: "llvm-pretty-test",+ isOptimized: true,+ flags: "some flags",+ runtimeVersion: 3,+ emissionKind: 1,+ enums: !DITemplateTypeParameter(name: ttp),+ dwoId: 2,+ splitDebugInlining: false,+ debugInfoForProfiling: true,+ nameTableKind: 4,+ rangesBaseAddress: true,+ sysroot: "the root",+ sdk: "SDK")+ ----+ |]+ ------------------------------------------------------------ , testCase "Stmt 2, LLVM 3.5" $@@ -201,6 +254,18 @@ ---- |] (ppToText $ ppLLVM 10 $ ppStmt s2)++ ------------------------------------------------------------++ , testCase "Stmt 3" $+ assertEqLines [sq|+ `indirectbr` pretty-printing works as expected (#174)+ ----+ indirectbr ptr %addr, [ label %hello,+ label %world ]+ ----+ |]+ (ppToText $ ppLLVM llvmVlatest $ ppStmt s3) ------------------------------------------------------------ -- Verify named labels and label targets are emitted correctly