| 1 | /*===-- debuginfo.c - tool for testing libLLVM and llvm-c API -------------===*\ |
| 2 | |* *| |
| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| |
| 4 | |* Exceptions. *| |
| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| |
| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |
| 7 | |* *| |
| 8 | |*===----------------------------------------------------------------------===*| |
| 9 | |* *| |
| 10 | |* Tests for the LLVM C DebugInfo API *| |
| 11 | |* *| |
| 12 | \*===----------------------------------------------------------------------===*/ |
| 13 | |
| 14 | #include "llvm-c/DebugInfo.h" |
| 15 | #include "llvm-c-test.h" |
| 16 | #include "llvm-c/Core.h" |
| 17 | #include "llvm-c/Types.h" |
| 18 | |
| 19 | #include <assert.h> |
| 20 | #include <stdio.h> |
| 21 | #include <string.h> |
| 22 | |
| 23 | static LLVMMetadataRef |
| 24 | declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) { |
| 25 | LLVMMetadataRef Decl = LLVMDIBuilderCreateStructType(Builder: DIB, Scope: File, Name: "TestClass" , NameLen: 9, File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 26 | LLVMMetadataRef SuperDecl = LLVMDIBuilderCreateStructType(Builder: DIB, Scope: File, Name: "TestSuperClass" , NameLen: 14, File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 27 | LLVMDIBuilderCreateInheritance(Builder: DIB, Ty: Decl, BaseTy: SuperDecl, BaseOffset: 0, VBPtrOffset: 0, Flags: 0); |
| 28 | LLVMMetadataRef TestProperty = |
| 29 | LLVMDIBuilderCreateObjCProperty(Builder: DIB, Name: "test" , NameLen: 4, File, LineNo: 42, GetterName: "getTest" , GetterNameLen: 7, SetterName: "setTest" , SetterNameLen: 7, PropertyAttributes: 0x20 /*copy*/ | 0x40 /*nonatomic*/, Ty: SuperDecl); |
| 30 | LLVMDIBuilderCreateObjCIVar(Builder: DIB, Name: "_test" , NameLen: 5, File, LineNo: 42, SizeInBits: 64, AlignInBits: 0, OffsetInBits: 64, Flags: LLVMDIFlagPublic, Ty: SuperDecl, PropertyNode: TestProperty); |
| 31 | return Decl; |
| 32 | } |
| 33 | |
| 34 | int llvm_test_dibuilder(void) { |
| 35 | const char *Filename = "debuginfo.c" ; |
| 36 | LLVMContextRef C = LLVMContextCreate(); |
| 37 | LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleID: Filename, C); |
| 38 | |
| 39 | LLVMSetIsNewDbgInfoFormat(M, true); |
| 40 | assert(LLVMIsNewDbgInfoFormat(M)); |
| 41 | |
| 42 | LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M); |
| 43 | |
| 44 | LLVMMetadataRef File = LLVMDIBuilderCreateFile(Builder: DIB, Filename, |
| 45 | FilenameLen: strlen(s: Filename), Directory: "." , DirectoryLen: 1); |
| 46 | |
| 47 | LLVMMetadataRef FileCS = LLVMDIBuilderCreateFileWithChecksum( |
| 48 | Builder: DIB, Filename, FilenameLen: strlen(s: Filename), Directory: "." , DirectoryLen: 1, ChecksumKind: CSK_MD5, Checksum: "1234" , ChecksumLen: 4, Source: "source" , SourceLen: 6); |
| 49 | |
| 50 | LLVMMetadataRef CompileUnit = LLVMDIBuilderCreateCompileUnit( |
| 51 | Builder: DIB, Lang: LLVMDWARFSourceLanguageC, FileRef: File, Producer: "llvm-c-test" , ProducerLen: 11, isOptimized: 0, NULL, FlagsLen: 0, RuntimeVer: 0, |
| 52 | NULL, SplitNameLen: 0, Kind: LLVMDWARFEmissionFull, DWOId: 0, SplitDebugInlining: 0, DebugInfoForProfiling: 0, SysRoot: "/" , SysRootLen: 1, SDK: "" , SDKLen: 0); |
| 53 | |
| 54 | LLVMMetadataRef Module = |
| 55 | LLVMDIBuilderCreateModule(Builder: DIB, ParentScope: CompileUnit, |
| 56 | Name: "llvm-c-test" , NameLen: 11, |
| 57 | ConfigMacros: "" , ConfigMacrosLen: 0, |
| 58 | IncludePath: "/test/include/llvm-c-test.h" , IncludePathLen: 27, |
| 59 | APINotesFile: "" , APINotesFileLen: 0); |
| 60 | |
| 61 | LLVMMetadataRef OtherModule = |
| 62 | LLVMDIBuilderCreateModule(Builder: DIB, ParentScope: CompileUnit, |
| 63 | Name: "llvm-c-test-import" , NameLen: 18, |
| 64 | ConfigMacros: "" , ConfigMacrosLen: 0, |
| 65 | IncludePath: "/test/include/llvm-c-test-import.h" , IncludePathLen: 34, |
| 66 | APINotesFile: "" , APINotesFileLen: 0); |
| 67 | LLVMMetadataRef ImportedModule = LLVMDIBuilderCreateImportedModuleFromModule( |
| 68 | Builder: DIB, Scope: Module, M: OtherModule, File: FileCS, Line: 42, NULL, NumElements: 0); |
| 69 | LLVMDIBuilderCreateImportedModuleFromAlias(Builder: DIB, Scope: Module, ImportedEntity: ImportedModule, File, |
| 70 | Line: 42, NULL, NumElements: 0); |
| 71 | |
| 72 | LLVMMetadataRef ClassTy = declare_objc_class(DIB, File); |
| 73 | LLVMMetadataRef GlobalClassValueExpr = |
| 74 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 75 | LLVMDIBuilderCreateGlobalVariableExpression( |
| 76 | Builder: DIB, Scope: Module, Name: "globalClass" , NameLen: 11, Linkage: "" , LinkLen: 0, File, LineNo: 1, Ty: ClassTy, true, |
| 77 | Expr: GlobalClassValueExpr, NULL, AlignInBits: 0); |
| 78 | |
| 79 | LLVMMetadataRef Int64Ty = |
| 80 | LLVMDIBuilderCreateBasicType(Builder: DIB, Name: "Int64" , NameLen: 5, SizeInBits: 64, Encoding: 0, Flags: LLVMDIFlagZero); |
| 81 | LLVMMetadataRef Int64TypeDef = |
| 82 | LLVMDIBuilderCreateTypedef(Builder: DIB, Type: Int64Ty, Name: "int64_t" , NameLen: 7, File, LineNo: 42, Scope: File, AlignInBits: 0); |
| 83 | |
| 84 | LLVMMetadataRef GlobalVarValueExpr = |
| 85 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 86 | LLVMDIBuilderCreateGlobalVariableExpression( |
| 87 | Builder: DIB, Scope: Module, Name: "global" , NameLen: 6, Linkage: "" , LinkLen: 0, File, LineNo: 1, Ty: Int64TypeDef, true, |
| 88 | Expr: GlobalVarValueExpr, NULL, AlignInBits: 0); |
| 89 | |
| 90 | LLVMMetadataRef NameSpace = |
| 91 | LLVMDIBuilderCreateNameSpace(Builder: DIB, ParentScope: Module, Name: "NameSpace" , NameLen: 9, false); |
| 92 | |
| 93 | LLVMMetadataRef StructDbgElts[] = {Int64Ty, Int64Ty, Int64Ty}; |
| 94 | LLVMMetadataRef StructDbgTy = |
| 95 | LLVMDIBuilderCreateStructType(Builder: DIB, Scope: NameSpace, Name: "MyStruct" , |
| 96 | NameLen: 8, File, LineNumber: 0, SizeInBits: 192, AlignInBits: 0, Flags: 0, NULL, Elements: StructDbgElts, NumElements: 3, |
| 97 | RunTimeLang: LLVMDWARFSourceLanguageC, NULL, UniqueId: "MyStruct" , UniqueIdLen: 8); |
| 98 | |
| 99 | LLVMMetadataRef StructDbgPtrTy = |
| 100 | LLVMDIBuilderCreatePointerType(Builder: DIB, PointeeTy: StructDbgTy, SizeInBits: 192, AlignInBits: 0, AddressSpace: 0, Name: "" , NameLen: 0); |
| 101 | |
| 102 | LLVMAddNamedMetadataOperand(M, Name: "FooType" , |
| 103 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: StructDbgPtrTy)); |
| 104 | |
| 105 | LLVMTypeRef I64Ty = LLVMInt64TypeInContext(C); |
| 106 | LLVMTypeRef FooParamTys[] = { |
| 107 | I64Ty, |
| 108 | I64Ty, |
| 109 | LLVMVectorType(ElementType: I64Ty, ElementCount: 10), |
| 110 | }; |
| 111 | LLVMTypeRef FooFuncTy = LLVMFunctionType(ReturnType: I64Ty, ParamTypes: FooParamTys, ParamCount: 3, IsVarArg: 0); |
| 112 | LLVMValueRef FooFunction = LLVMAddFunction(M, Name: "foo" , FunctionTy: FooFuncTy); |
| 113 | LLVMBasicBlockRef FooEntryBlock = |
| 114 | LLVMAppendBasicBlockInContext(C, Fn: FooFunction, Name: "entry" ); |
| 115 | |
| 116 | LLVMMetadataRef Subscripts[] = { |
| 117 | LLVMDIBuilderGetOrCreateSubrange(Builder: DIB, LowerBound: 0, Count: 10), |
| 118 | }; |
| 119 | LLVMMetadataRef VectorTy = |
| 120 | LLVMDIBuilderCreateVectorType(Builder: DIB, Size: 64 * 10, AlignInBits: 0, |
| 121 | Ty: Int64Ty, Subscripts, NumSubscripts: 1); |
| 122 | |
| 123 | |
| 124 | LLVMMetadataRef ParamTypes[] = {Int64Ty, Int64Ty, VectorTy}; |
| 125 | LLVMMetadataRef FunctionTy = |
| 126 | LLVMDIBuilderCreateSubroutineType(Builder: DIB, File, ParameterTypes: ParamTypes, NumParameterTypes: 3, Flags: 0); |
| 127 | |
| 128 | LLVMMetadataRef ReplaceableFunctionMetadata = |
| 129 | LLVMDIBuilderCreateReplaceableCompositeType(Builder: DIB, Tag: 0x15, Name: "foo" , NameLen: 3, |
| 130 | Scope: File, File, Line: 42, |
| 131 | RuntimeLang: 0, SizeInBits: 0, AlignInBits: 0, |
| 132 | Flags: LLVMDIFlagFwdDecl, |
| 133 | UniqueIdentifier: "" , UniqueIdentifierLen: 0); |
| 134 | |
| 135 | LLVMMetadataRef FooParamLocation = LLVMDIBuilderCreateDebugLocation( |
| 136 | Ctx: C, Line: 42, Column: 0, Scope: ReplaceableFunctionMetadata, NULL); |
| 137 | LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction( |
| 138 | Builder: DIB, Scope: File, Name: "foo" , NameLen: 3, LinkageName: "foo" , LinkageNameLen: 3, File, LineNo: 42, NULL, true, true, ScopeLine: 42, Flags: 0, false); |
| 139 | LLVMMetadataReplaceAllUsesWith(TempTargetMetadata: ReplaceableFunctionMetadata, Replacement: FunctionMetadata); |
| 140 | |
| 141 | LLVMDISubprogramReplaceType(Subprogram: FunctionMetadata, SubroutineType: FunctionTy); |
| 142 | |
| 143 | LLVMMetadataRef FooParamExpression = |
| 144 | LLVMDIBuilderCreateExpression(Builder: DIB, NULL, Length: 0); |
| 145 | LLVMMetadataRef FooParamVar1 = |
| 146 | LLVMDIBuilderCreateParameterVariable(Builder: DIB, Scope: FunctionMetadata, Name: "a" , NameLen: 1, ArgNo: 1, File, |
| 147 | LineNo: 42, Ty: Int64Ty, true, Flags: 0); |
| 148 | |
| 149 | LLVMDIBuilderInsertDeclareRecordAtEnd(Builder: DIB, Storage: LLVMConstInt(IntTy: I64Ty, N: 0, false), |
| 150 | VarInfo: FooParamVar1, Expr: FooParamExpression, |
| 151 | DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 152 | |
| 153 | LLVMMetadataRef FooParamVar2 = |
| 154 | LLVMDIBuilderCreateParameterVariable(Builder: DIB, Scope: FunctionMetadata, Name: "b" , NameLen: 1, ArgNo: 2, File, |
| 155 | LineNo: 42, Ty: Int64Ty, true, Flags: 0); |
| 156 | |
| 157 | LLVMDIBuilderInsertDeclareRecordAtEnd(Builder: DIB, Storage: LLVMConstInt(IntTy: I64Ty, N: 0, false), |
| 158 | VarInfo: FooParamVar2, Expr: FooParamExpression, |
| 159 | DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 160 | |
| 161 | LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable( |
| 162 | Builder: DIB, Scope: FunctionMetadata, Name: "c" , NameLen: 1, ArgNo: 3, File, LineNo: 42, Ty: VectorTy, true, Flags: 0); |
| 163 | |
| 164 | LLVMDIBuilderInsertDeclareRecordAtEnd(Builder: DIB, Storage: LLVMConstInt(IntTy: I64Ty, N: 0, false), |
| 165 | VarInfo: FooParamVar3, Expr: FooParamExpression, |
| 166 | DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 167 | |
| 168 | LLVMSetSubprogram(Func: FooFunction, SP: FunctionMetadata); |
| 169 | |
| 170 | LLVMMetadataRef FooLabel1 = LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 171 | Name: "label1" , NameLen: 6, File, LineNo: 42, false); |
| 172 | LLVMDIBuilderInsertLabelAtEnd(Builder: DIB, LabelInfo: FooLabel1, Location: FooParamLocation, |
| 173 | InsertAtEnd: FooEntryBlock); |
| 174 | |
| 175 | LLVMMetadataRef FooLexicalBlock = |
| 176 | LLVMDIBuilderCreateLexicalBlock(Builder: DIB, Scope: FunctionMetadata, File, Line: 42, Column: 0); |
| 177 | |
| 178 | LLVMBasicBlockRef FooVarBlock = |
| 179 | LLVMAppendBasicBlockInContext(C, Fn: FooFunction, Name: "vars" ); |
| 180 | LLVMMetadataRef FooVarsLocation = |
| 181 | LLVMDIBuilderCreateDebugLocation(Ctx: C, Line: 43, Column: 0, Scope: FunctionMetadata, NULL); |
| 182 | LLVMMetadataRef FooVar1 = |
| 183 | LLVMDIBuilderCreateAutoVariable(Builder: DIB, Scope: FooLexicalBlock, Name: "d" , NameLen: 1, File, |
| 184 | LineNo: 43, Ty: Int64Ty, true, Flags: 0, AlignInBits: 0); |
| 185 | LLVMValueRef FooVal1 = LLVMConstInt(IntTy: I64Ty, N: 0, false); |
| 186 | LLVMMetadataRef FooVarValueExpr1 = |
| 187 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 188 | |
| 189 | LLVMDIBuilderInsertDbgValueRecordAtEnd( |
| 190 | Builder: DIB, Val: FooVal1, VarInfo: FooVar1, Expr: FooVarValueExpr1, DebugLoc: FooVarsLocation, Block: FooVarBlock); |
| 191 | |
| 192 | LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable( |
| 193 | Builder: DIB, Scope: FooLexicalBlock, Name: "e" , NameLen: 1, File, LineNo: 44, Ty: Int64Ty, true, Flags: 0, AlignInBits: 0); |
| 194 | LLVMValueRef FooVal2 = LLVMConstInt(IntTy: I64Ty, N: 1, false); |
| 195 | LLVMMetadataRef FooVarValueExpr2 = |
| 196 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 1); |
| 197 | |
| 198 | LLVMDIBuilderInsertDbgValueRecordAtEnd( |
| 199 | Builder: DIB, Val: FooVal2, VarInfo: FooVar2, Expr: FooVarValueExpr2, DebugLoc: FooVarsLocation, Block: FooVarBlock); |
| 200 | |
| 201 | LLVMMetadataRef MacroFile = |
| 202 | LLVMDIBuilderCreateTempMacroFile(Builder: DIB, NULL, Line: 0, File); |
| 203 | LLVMDIBuilderCreateMacro(Builder: DIB, ParentMacroFile: MacroFile, Line: 0, RecordType: LLVMDWARFMacinfoRecordTypeDefine, |
| 204 | Name: "SIMPLE_DEFINE" , NameLen: 13, NULL, ValueLen: 0); |
| 205 | LLVMDIBuilderCreateMacro(Builder: DIB, ParentMacroFile: MacroFile, Line: 0, RecordType: LLVMDWARFMacinfoRecordTypeDefine, |
| 206 | Name: "VALUE_DEFINE" , NameLen: 12, Value: "1" , ValueLen: 1); |
| 207 | |
| 208 | LLVMMetadataRef EnumeratorTestA = |
| 209 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_A" , NameLen: strlen(s: "Test_A" ), Value: 0, true); |
| 210 | LLVMMetadataRef EnumeratorTestB = |
| 211 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_B" , NameLen: strlen(s: "Test_B" ), Value: 1, true); |
| 212 | LLVMMetadataRef EnumeratorTestC = |
| 213 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_B" , NameLen: strlen(s: "Test_C" ), Value: 2, true); |
| 214 | LLVMMetadataRef EnumeratorsTest[] = {EnumeratorTestA, EnumeratorTestB, |
| 215 | EnumeratorTestC}; |
| 216 | LLVMMetadataRef EnumTest = LLVMDIBuilderCreateEnumerationType( |
| 217 | Builder: DIB, Scope: NameSpace, Name: "EnumTest" , NameLen: strlen(s: "EnumTest" ), File, LineNumber: 0, SizeInBits: 64, AlignInBits: 0, |
| 218 | Elements: EnumeratorsTest, NumElements: 3, ClassTy: Int64Ty); |
| 219 | LLVMAddNamedMetadataOperand( |
| 220 | M, Name: "EnumTest" , Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: EnumTest)); |
| 221 | |
| 222 | LLVMMetadataRef UInt128Ty = LLVMDIBuilderCreateBasicType( |
| 223 | Builder: DIB, Name: "UInt128" , NameLen: strlen(s: "UInt128" ), SizeInBits: 128, Encoding: 0, Flags: LLVMDIFlagZero); |
| 224 | const uint64_t WordsTestD[] = {0x098a224000000000ull, 0x4b3b4ca85a86c47aull}; |
| 225 | const uint64_t WordsTestE[] = {0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull}; |
| 226 | |
| 227 | LLVMMetadataRef LargeEnumeratorTestD = |
| 228 | LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision( |
| 229 | Builder: DIB, Name: "Test_D" , NameLen: strlen(s: "Test_D" ), SizeInBits: 128, Words: WordsTestD, false); |
| 230 | LLVMMetadataRef LargeEnumeratorTestE = |
| 231 | LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision( |
| 232 | Builder: DIB, Name: "Test_E" , NameLen: strlen(s: "Test_E" ), SizeInBits: 128, Words: WordsTestE, false); |
| 233 | LLVMMetadataRef LargeEnumeratorsTest[] = {LargeEnumeratorTestD, |
| 234 | LargeEnumeratorTestE}; |
| 235 | LLVMMetadataRef LargeEnumTest = LLVMDIBuilderCreateEnumerationType( |
| 236 | Builder: DIB, Scope: NameSpace, Name: "LargeEnumTest" , NameLen: strlen(s: "LargeEnumTest" ), File, LineNumber: 0, SizeInBits: 128, AlignInBits: 0, |
| 237 | Elements: LargeEnumeratorsTest, NumElements: 2, ClassTy: UInt128Ty); |
| 238 | LLVMAddNamedMetadataOperand( |
| 239 | M, Name: "LargeEnumTest" , |
| 240 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: LargeEnumTest)); |
| 241 | |
| 242 | LLVMValueRef FooVal3 = LLVMConstInt(IntTy: I64Ty, N: 8, false); |
| 243 | LLVMValueRef FooVal4 = LLVMConstInt(IntTy: I64Ty, N: 4, false); |
| 244 | LLVMMetadataRef lo = LLVMValueAsMetadata(Val: FooVal1); |
| 245 | LLVMMetadataRef hi = LLVMValueAsMetadata(Val: FooVal2); |
| 246 | LLVMMetadataRef strd = LLVMValueAsMetadata(Val: FooVal3); |
| 247 | LLVMMetadataRef bias = LLVMValueAsMetadata(Val: FooVal4); |
| 248 | LLVMMetadataRef SubrangeMetadataTy = LLVMDIBuilderCreateSubrangeType( |
| 249 | Builder: DIB, Scope: File, Name: "foo" , NameLen: 3, LineNo: 42, File, SizeInBits: 64, AlignInBits: 0, Flags: 0, BaseTy: Int64Ty, LowerBound: lo, UpperBound: hi, Stride: strd, Bias: bias); |
| 250 | LLVMAddNamedMetadataOperand( |
| 251 | M, Name: "SubrangeType" , |
| 252 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: SubrangeMetadataTy)); |
| 253 | |
| 254 | LLVMMetadataRef SetMetadataTy1 = LLVMDIBuilderCreateSetType( |
| 255 | Builder: DIB, Scope: File, Name: "enumset" , NameLen: 7, File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, BaseTy: EnumTest); |
| 256 | LLVMMetadataRef SetMetadataTy2 = LLVMDIBuilderCreateSetType( |
| 257 | Builder: DIB, Scope: File, Name: "subrangeset" , NameLen: 11, File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, BaseTy: SubrangeMetadataTy); |
| 258 | LLVMAddNamedMetadataOperand( |
| 259 | M, Name: "SetType1" , |
| 260 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: SetMetadataTy1)); |
| 261 | LLVMAddNamedMetadataOperand( |
| 262 | M, Name: "SetType2" , |
| 263 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: SetMetadataTy2)); |
| 264 | |
| 265 | LLVMMetadataRef DynSubscripts[] = { |
| 266 | LLVMDIBuilderGetOrCreateSubrange(Builder: DIB, LowerBound: 0, Count: 10), |
| 267 | }; |
| 268 | LLVMMetadataRef Loc = LLVMDIBuilderCreateExpression(Builder: DIB, NULL, Length: 0); |
| 269 | LLVMMetadataRef Rank = LLVMDIBuilderCreateExpression(Builder: DIB, NULL, Length: 0); |
| 270 | LLVMMetadataRef DynamicArrayMetadataTy = LLVMDIBuilderCreateDynamicArrayType( |
| 271 | Builder: DIB, Scope: File, Name: "foo" , NameLen: 3, LineNo: 42, File, Size: 64 * 10, AlignInBits: 0, Ty: Int64Ty, Subscripts: DynSubscripts, NumSubscripts: 1, DataLocation: Loc, |
| 272 | Associated: FooVar1, NULL, Rank, NULL); |
| 273 | LLVMAddNamedMetadataOperand( |
| 274 | M, Name: "DynType" , |
| 275 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: DynamicArrayMetadataTy)); |
| 276 | |
| 277 | LLVMMetadataRef StructPTy = LLVMDIBuilderCreateForwardDecl( |
| 278 | Builder: DIB, Tag: 2 /*DW_TAG_class_type*/, Name: "Class1" , NameLen: 5, Scope: NameSpace, File, Line: 0, RuntimeLang: 0, SizeInBits: 192, AlignInBits: 0, |
| 279 | UniqueIdentifier: "FooClass" , UniqueIdentifierLen: 8); |
| 280 | |
| 281 | LLVMMetadataRef Int32Ty = |
| 282 | LLVMDIBuilderCreateBasicType(Builder: DIB, Name: "Int32" , NameLen: 5, SizeInBits: 32, Encoding: 0, Flags: LLVMDIFlagZero); |
| 283 | LLVMMetadataRef StructElts[] = {Int64Ty, Int64Ty, Int32Ty}; |
| 284 | LLVMMetadataRef ClassArr = LLVMDIBuilderGetOrCreateArray(Builder: DIB, Data: StructElts, NumElements: 3); |
| 285 | LLVMReplaceArrays(Builder: DIB, T: &StructPTy, Elements: &ClassArr, NumElements: 1); |
| 286 | LLVMAddNamedMetadataOperand( |
| 287 | M, Name: "ClassType" , Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: StructPTy)); |
| 288 | |
| 289 | // Using the new debug format, debug records get attached to instructions. |
| 290 | // Insert a `br` and `ret` now to absorb the debug records which are |
| 291 | // currently "trailing", meaning that they're associated with a block |
| 292 | // but no particular instruction, which is only valid as a transient state. |
| 293 | LLVMContextRef Ctx = LLVMGetModuleContext(M); |
| 294 | LLVMBuilderRef Builder = LLVMCreateBuilderInContext(C: Ctx); |
| 295 | LLVMPositionBuilderAtEnd(Builder, Block: FooEntryBlock); |
| 296 | // Build `br label %vars` in entry. |
| 297 | LLVMBuildBr(Builder, Dest: FooVarBlock); |
| 298 | |
| 299 | // Build another br for the sake of testing labels. |
| 300 | LLVMMetadataRef FooLabel2 = LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 301 | Name: "label2" , NameLen: 6, File, LineNo: 42, false); |
| 302 | LLVMDIBuilderInsertLabelBefore(Builder: DIB, LabelInfo: FooLabel2, Location: FooParamLocation, |
| 303 | InsertBefore: LLVMBuildBr(Builder, Dest: FooVarBlock)); |
| 304 | // label3 will be emitted, but label4 won't be emitted |
| 305 | // because label3 is AlwaysPreserve and label4 is not. |
| 306 | LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 307 | Name: "label3" , NameLen: 6, File, LineNo: 42, true); |
| 308 | LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 309 | Name: "label4" , NameLen: 6, File, LineNo: 42, false); |
| 310 | LLVMDIBuilderFinalize(Builder: DIB); |
| 311 | |
| 312 | // Build `ret i64 0` in vars. |
| 313 | LLVMPositionBuilderAtEnd(Builder, Block: FooVarBlock); |
| 314 | LLVMTypeRef I64 = LLVMInt64TypeInContext(C: Ctx); |
| 315 | LLVMValueRef Zero = LLVMConstInt(IntTy: I64, N: 0, false); |
| 316 | LLVMValueRef Ret = LLVMBuildRet(Builder, V: Zero); |
| 317 | |
| 318 | // Insert a `phi` before the `ret`. In the new debug info mode we need to |
| 319 | // be careful to insert before debug records too, else the debug records |
| 320 | // will come before the `phi` (and be absorbed onto it) which is an invalid |
| 321 | // state. |
| 322 | LLVMValueRef InsertPos = LLVMGetFirstInstruction(BB: FooVarBlock); |
| 323 | LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, Instr: InsertPos); |
| 324 | LLVMValueRef Phi1 = LLVMBuildPhi(Builder, Ty: I64, Name: "p1" ); |
| 325 | LLVMAddIncoming(PhiNode: Phi1, IncomingValues: &Zero, IncomingBlocks: &FooEntryBlock, Count: 1); |
| 326 | |
| 327 | // Do the same again using the other position-setting function. |
| 328 | LLVMPositionBuilderBeforeDbgRecords(Builder, Block: FooVarBlock, Inst: InsertPos); |
| 329 | LLVMValueRef Phi2 = LLVMBuildPhi(Builder, Ty: I64, Name: "p2" ); |
| 330 | LLVMAddIncoming(PhiNode: Phi2, IncomingValues: &Zero, IncomingBlocks: &FooEntryBlock, Count: 1); |
| 331 | |
| 332 | // Test that LLVMGetFirstDbgRecord and LLVMGetLastDbgRecord return NULL for |
| 333 | // instructions without debug info. |
| 334 | LLVMDbgRecordRef Phi1FirstDbgRecord = LLVMGetFirstDbgRecord(Inst: Phi1); |
| 335 | (void)Phi1FirstDbgRecord; |
| 336 | assert(Phi1FirstDbgRecord == NULL); |
| 337 | LLVMDbgRecordRef Phi1LastDbgRecord = LLVMGetLastDbgRecord(Inst: Phi1); |
| 338 | (void)Phi1LastDbgRecord; |
| 339 | assert(Phi1LastDbgRecord == NULL); |
| 340 | |
| 341 | // Insert a non-phi before the `ret` but not before the debug records to |
| 342 | // test that works as expected. |
| 343 | LLVMPositionBuilder(Builder, Block: FooVarBlock, Instr: Ret); |
| 344 | LLVMValueRef Add = LLVMBuildAdd(Builder, LHS: Phi1, RHS: Phi2, Name: "a" ); |
| 345 | |
| 346 | // Iterate over debug records in the add instruction. There should be two. |
| 347 | LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Inst: Add); |
| 348 | assert(AddDbgRecordFirst != NULL); |
| 349 | LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(DbgRecord: AddDbgRecordFirst); |
| 350 | assert(AddDbgRecordSecond != NULL); |
| 351 | LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Inst: Add); |
| 352 | assert(AddDbgRecordLast != NULL); |
| 353 | (void)AddDbgRecordLast; |
| 354 | assert(AddDbgRecordSecond == AddDbgRecordLast); |
| 355 | LLVMDbgRecordRef AddDbgRecordOverTheRange = |
| 356 | LLVMGetNextDbgRecord(DbgRecord: AddDbgRecordSecond); |
| 357 | assert(AddDbgRecordOverTheRange == NULL); |
| 358 | (void)AddDbgRecordOverTheRange; |
| 359 | LLVMDbgRecordRef AddDbgRecordFirstPrev = |
| 360 | LLVMGetPreviousDbgRecord(DbgRecord: AddDbgRecordSecond); |
| 361 | assert(AddDbgRecordFirstPrev != NULL); |
| 362 | assert(AddDbgRecordFirst == AddDbgRecordFirstPrev); |
| 363 | LLVMDbgRecordRef AddDbgRecordUnderTheRange = |
| 364 | LLVMGetPreviousDbgRecord(DbgRecord: AddDbgRecordFirstPrev); |
| 365 | assert(AddDbgRecordUnderTheRange == NULL); |
| 366 | (void)AddDbgRecordUnderTheRange; |
| 367 | |
| 368 | // Test that we can read the first debug record. |
| 369 | LLVMMetadataRef AddDbgRecordFirstDebugLoc = |
| 370 | LLVMDbgRecordGetDebugLoc(Rec: AddDbgRecordFirst); |
| 371 | (void)AddDbgRecordFirstDebugLoc; |
| 372 | assert(LLVMDILocationGetLine(AddDbgRecordFirstDebugLoc) == 43); |
| 373 | assert(LLVMDbgRecordGetKind(AddDbgRecordFirst) == LLVMDbgRecordValue); |
| 374 | LLVMValueRef AddDbgRecordFirstValue = |
| 375 | LLVMDbgVariableRecordGetValue(Rec: AddDbgRecordFirst, OpIdx: 0); |
| 376 | (void)AddDbgRecordFirstValue; |
| 377 | assert(LLVMGetValueKind(AddDbgRecordFirstValue) == LLVMConstantIntValueKind); |
| 378 | assert(LLVMConstIntGetZExtValue(AddDbgRecordFirstValue) == 0); |
| 379 | LLVMMetadataRef AddDbgRecordFirstVariable = |
| 380 | LLVMDbgVariableRecordGetVariable(Rec: AddDbgRecordFirst); |
| 381 | (void)AddDbgRecordFirstVariable; |
| 382 | assert(LLVMGetMetadataKind(AddDbgRecordFirstVariable) == |
| 383 | LLVMDILocalVariableMetadataKind); |
| 384 | // TODO: For now, there is no way to get the name. |
| 385 | LLVMMetadataRef AddDbgRecordFirstVariableScope = |
| 386 | LLVMDIVariableGetScope(Var: AddDbgRecordFirstVariable); |
| 387 | (void)AddDbgRecordFirstVariableScope; |
| 388 | assert(LLVMGetMetadataKind(AddDbgRecordFirstVariableScope) == |
| 389 | LLVMDILexicalBlockMetadataKind); |
| 390 | LLVMMetadataRef AddDbgRecordFirstVariableFile = |
| 391 | LLVMDIScopeGetFile(Scope: AddDbgRecordFirstVariableScope); |
| 392 | (void)AddDbgRecordFirstVariableFile; |
| 393 | assert(LLVMGetMetadataKind(AddDbgRecordFirstVariableFile) == |
| 394 | LLVMDIFileMetadataKind); |
| 395 | unsigned FileLen = 0; |
| 396 | assert(strcmp(LLVMDIFileGetFilename(AddDbgRecordFirstVariableFile, &FileLen), |
| 397 | "debuginfo.c" ) == 0); |
| 398 | (void)FileLen; |
| 399 | LLVMMetadataRef AddDbgRecordFirstExpr = |
| 400 | LLVMDbgVariableRecordGetExpression(Rec: AddDbgRecordFirst); |
| 401 | assert(LLVMGetMetadataKind(AddDbgRecordFirstExpr) == |
| 402 | LLVMDIExpressionMetadataKind); |
| 403 | (void)AddDbgRecordFirstExpr; |
| 404 | |
| 405 | char *MStr = LLVMPrintModuleToString(M); |
| 406 | puts(s: MStr); |
| 407 | LLVMDisposeMessage(Message: MStr); |
| 408 | |
| 409 | LLVMDisposeBuilder(Builder); |
| 410 | LLVMDisposeDIBuilder(Builder: DIB); |
| 411 | LLVMDisposeModule(M); |
| 412 | LLVMContextDispose(C); |
| 413 | |
| 414 | return 0; |
| 415 | } |
| 416 | |
| 417 | int llvm_get_di_tag(void) { |
| 418 | LLVMContextRef Context = LLVMContextCreate(); |
| 419 | LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleID: "Mod" , C: Context); |
| 420 | |
| 421 | const char String[] = "foo" ; |
| 422 | LLVMMetadataRef StringMD = |
| 423 | LLVMMDStringInContext2(C: Context, Str: String, SLen: strlen(s: String)); |
| 424 | LLVMMetadataRef NodeMD = LLVMMDNodeInContext2(C: Context, MDs: &StringMD, Count: 1); |
| 425 | assert(LLVMGetDINodeTag(NodeMD) == 0); |
| 426 | (void)NodeMD; |
| 427 | |
| 428 | LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); |
| 429 | const char Filename[] = "metadata.c" ; |
| 430 | const char Directory[] = "." ; |
| 431 | LLVMMetadataRef File = LLVMDIBuilderCreateFile( |
| 432 | Builder, Filename, FilenameLen: strlen(s: Filename), Directory, DirectoryLen: strlen(s: Directory)); |
| 433 | const char Name[] = "TestClass" ; |
| 434 | LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( |
| 435 | Builder, Scope: File, Name, NameLen: strlen(s: Name), File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, |
| 436 | Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 437 | assert(LLVMGetDINodeTag(Struct) == 0x13); |
| 438 | (void)Struct; |
| 439 | |
| 440 | LLVMDisposeDIBuilder(Builder); |
| 441 | LLVMDisposeModule(M); |
| 442 | LLVMContextDispose(C: Context); |
| 443 | |
| 444 | return 0; |
| 445 | } |
| 446 | |
| 447 | int llvm_di_type_get_name(void) { |
| 448 | LLVMContextRef C = LLVMContextCreate(); |
| 449 | LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleID: "Mod" , C); |
| 450 | |
| 451 | LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); |
| 452 | const char Filename[] = "metadata.c" ; |
| 453 | const char Directory[] = "." ; |
| 454 | LLVMMetadataRef File = LLVMDIBuilderCreateFile( |
| 455 | Builder, Filename, FilenameLen: strlen(s: Filename), Directory, DirectoryLen: strlen(s: Directory)); |
| 456 | const char Name[] = "TestClass" ; |
| 457 | LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( |
| 458 | Builder, Scope: File, Name, NameLen: strlen(s: Name), File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, |
| 459 | Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 460 | |
| 461 | size_t Len; |
| 462 | const char *TypeName = LLVMDITypeGetName(DType: Struct, Length: &Len); |
| 463 | assert(Len == strlen(Name)); |
| 464 | assert(strncmp(TypeName, Name, Len) == 0); |
| 465 | (void)TypeName; |
| 466 | |
| 467 | LLVMDisposeDIBuilder(Builder); |
| 468 | LLVMDisposeModule(M); |
| 469 | LLVMContextDispose(C); |
| 470 | |
| 471 | return 0; |
| 472 | } |
| 473 | |
| 474 | int llvm_add_globaldebuginfo(void) { |
| 475 | const char *Filename = "debuginfo.c" ; |
| 476 | LLVMContextRef C = LLVMContextCreate(); |
| 477 | LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleID: Filename, C); |
| 478 | LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); |
| 479 | LLVMMetadataRef File = |
| 480 | LLVMDIBuilderCreateFile(Builder, Filename, FilenameLen: strlen(s: Filename), Directory: "." , DirectoryLen: 1); |
| 481 | |
| 482 | LLVMMetadataRef GlobalVarValueExpr = |
| 483 | LLVMDIBuilderCreateConstantValueExpression(Builder, Value: 0); |
| 484 | LLVMMetadataRef Int64Ty = |
| 485 | LLVMDIBuilderCreateBasicType(Builder, Name: "Int64" , NameLen: 5, SizeInBits: 64, Encoding: 0, Flags: LLVMDIFlagZero); |
| 486 | LLVMMetadataRef Int64TypeDef = LLVMDIBuilderCreateTypedef( |
| 487 | Builder, Type: Int64Ty, Name: "int64_t" , NameLen: 7, File, LineNo: 42, Scope: File, AlignInBits: 0); |
| 488 | |
| 489 | LLVMMetadataRef GVE = LLVMDIBuilderCreateGlobalVariableExpression( |
| 490 | Builder, Scope: File, Name: "global" , NameLen: 6, Linkage: "" , LinkLen: 0, File, LineNo: 1, Ty: Int64TypeDef, true, |
| 491 | Expr: GlobalVarValueExpr, NULL, AlignInBits: 0); |
| 492 | |
| 493 | LLVMTypeRef RecType = LLVMStructCreateNamed(C, Name: "struct" ); |
| 494 | LLVMValueRef Global = LLVMAddGlobal(M, Ty: RecType, Name: "global" ); |
| 495 | |
| 496 | LLVMGlobalAddDebugInfo(Global, GVE); |
| 497 | // use AddMetadata to add twice |
| 498 | int kindId = LLVMGetMDKindIDInContext(C, Name: "dbg" , SLen: 3); |
| 499 | LLVMGlobalAddMetadata(Global, Kind: kindId, MD: GVE); |
| 500 | size_t numEntries; |
| 501 | LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Value: Global, NumEntries: &numEntries); |
| 502 | assert(ME != NULL); |
| 503 | assert(numEntries == 2); |
| 504 | |
| 505 | LLVMDisposeValueMetadataEntries(Entries: ME); |
| 506 | LLVMDisposeDIBuilder(Builder); |
| 507 | LLVMDisposeModule(M); |
| 508 | LLVMContextDispose(C); |
| 509 | |
| 510 | return 0; |
| 511 | } |
| 512 | |