| 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 | LLVMModuleRef M = LLVMModuleCreateWithName(ModuleID: Filename); |
| 37 | |
| 38 | LLVMSetIsNewDbgInfoFormat(M, true); |
| 39 | assert(LLVMIsNewDbgInfoFormat(M)); |
| 40 | |
| 41 | LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M); |
| 42 | |
| 43 | LLVMMetadataRef File = LLVMDIBuilderCreateFile(Builder: DIB, Filename, |
| 44 | FilenameLen: strlen(s: Filename), Directory: "." , DirectoryLen: 1); |
| 45 | |
| 46 | LLVMMetadataRef CompileUnit = LLVMDIBuilderCreateCompileUnit( |
| 47 | Builder: DIB, Lang: LLVMDWARFSourceLanguageC, FileRef: File, Producer: "llvm-c-test" , ProducerLen: 11, isOptimized: 0, NULL, FlagsLen: 0, RuntimeVer: 0, |
| 48 | NULL, SplitNameLen: 0, Kind: LLVMDWARFEmissionFull, DWOId: 0, SplitDebugInlining: 0, DebugInfoForProfiling: 0, SysRoot: "/" , SysRootLen: 1, SDK: "" , SDKLen: 0); |
| 49 | |
| 50 | LLVMMetadataRef Module = |
| 51 | LLVMDIBuilderCreateModule(Builder: DIB, ParentScope: CompileUnit, |
| 52 | Name: "llvm-c-test" , NameLen: 11, |
| 53 | ConfigMacros: "" , ConfigMacrosLen: 0, |
| 54 | IncludePath: "/test/include/llvm-c-test.h" , IncludePathLen: 27, |
| 55 | APINotesFile: "" , APINotesFileLen: 0); |
| 56 | |
| 57 | LLVMMetadataRef OtherModule = |
| 58 | LLVMDIBuilderCreateModule(Builder: DIB, ParentScope: CompileUnit, |
| 59 | Name: "llvm-c-test-import" , NameLen: 18, |
| 60 | ConfigMacros: "" , ConfigMacrosLen: 0, |
| 61 | IncludePath: "/test/include/llvm-c-test-import.h" , IncludePathLen: 34, |
| 62 | APINotesFile: "" , APINotesFileLen: 0); |
| 63 | LLVMMetadataRef ImportedModule = LLVMDIBuilderCreateImportedModuleFromModule( |
| 64 | Builder: DIB, Scope: Module, M: OtherModule, File, Line: 42, NULL, NumElements: 0); |
| 65 | LLVMDIBuilderCreateImportedModuleFromAlias(Builder: DIB, Scope: Module, ImportedEntity: ImportedModule, File, |
| 66 | Line: 42, NULL, NumElements: 0); |
| 67 | |
| 68 | LLVMMetadataRef ClassTy = declare_objc_class(DIB, File); |
| 69 | LLVMMetadataRef GlobalClassValueExpr = |
| 70 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 71 | LLVMDIBuilderCreateGlobalVariableExpression( |
| 72 | Builder: DIB, Scope: Module, Name: "globalClass" , NameLen: 11, Linkage: "" , LinkLen: 0, File, LineNo: 1, Ty: ClassTy, true, |
| 73 | Expr: GlobalClassValueExpr, NULL, AlignInBits: 0); |
| 74 | |
| 75 | LLVMMetadataRef Int64Ty = |
| 76 | LLVMDIBuilderCreateBasicType(Builder: DIB, Name: "Int64" , NameLen: 5, SizeInBits: 64, Encoding: 0, Flags: LLVMDIFlagZero); |
| 77 | LLVMMetadataRef Int64TypeDef = |
| 78 | LLVMDIBuilderCreateTypedef(Builder: DIB, Type: Int64Ty, Name: "int64_t" , NameLen: 7, File, LineNo: 42, Scope: File, AlignInBits: 0); |
| 79 | |
| 80 | LLVMMetadataRef GlobalVarValueExpr = |
| 81 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 82 | LLVMDIBuilderCreateGlobalVariableExpression( |
| 83 | Builder: DIB, Scope: Module, Name: "global" , NameLen: 6, Linkage: "" , LinkLen: 0, File, LineNo: 1, Ty: Int64TypeDef, true, |
| 84 | Expr: GlobalVarValueExpr, NULL, AlignInBits: 0); |
| 85 | |
| 86 | LLVMMetadataRef NameSpace = |
| 87 | LLVMDIBuilderCreateNameSpace(Builder: DIB, ParentScope: Module, Name: "NameSpace" , NameLen: 9, false); |
| 88 | |
| 89 | LLVMMetadataRef StructDbgElts[] = {Int64Ty, Int64Ty, Int64Ty}; |
| 90 | LLVMMetadataRef StructDbgTy = |
| 91 | LLVMDIBuilderCreateStructType(Builder: DIB, Scope: NameSpace, Name: "MyStruct" , |
| 92 | NameLen: 8, File, LineNumber: 0, SizeInBits: 192, AlignInBits: 0, Flags: 0, NULL, Elements: StructDbgElts, NumElements: 3, |
| 93 | RunTimeLang: LLVMDWARFSourceLanguageC, NULL, UniqueId: "MyStruct" , UniqueIdLen: 8); |
| 94 | |
| 95 | LLVMMetadataRef StructDbgPtrTy = |
| 96 | LLVMDIBuilderCreatePointerType(Builder: DIB, PointeeTy: StructDbgTy, SizeInBits: 192, AlignInBits: 0, AddressSpace: 0, Name: "" , NameLen: 0); |
| 97 | |
| 98 | LLVMAddNamedMetadataOperand(M, Name: "FooType" , |
| 99 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: StructDbgPtrTy)); |
| 100 | |
| 101 | |
| 102 | LLVMTypeRef FooParamTys[] = { |
| 103 | LLVMInt64Type(), |
| 104 | LLVMInt64Type(), |
| 105 | LLVMVectorType(ElementType: LLVMInt64Type(), ElementCount: 10), |
| 106 | }; |
| 107 | LLVMTypeRef FooFuncTy = LLVMFunctionType(ReturnType: LLVMInt64Type(), ParamTypes: FooParamTys, ParamCount: 3, IsVarArg: 0); |
| 108 | LLVMValueRef FooFunction = LLVMAddFunction(M, Name: "foo" , FunctionTy: FooFuncTy); |
| 109 | LLVMBasicBlockRef FooEntryBlock = LLVMAppendBasicBlock(Fn: FooFunction, Name: "entry" ); |
| 110 | |
| 111 | LLVMMetadataRef Subscripts[] = { |
| 112 | LLVMDIBuilderGetOrCreateSubrange(Builder: DIB, LowerBound: 0, Count: 10), |
| 113 | }; |
| 114 | LLVMMetadataRef VectorTy = |
| 115 | LLVMDIBuilderCreateVectorType(Builder: DIB, Size: 64 * 10, AlignInBits: 0, |
| 116 | Ty: Int64Ty, Subscripts, NumSubscripts: 1); |
| 117 | |
| 118 | |
| 119 | LLVMMetadataRef ParamTypes[] = {Int64Ty, Int64Ty, VectorTy}; |
| 120 | LLVMMetadataRef FunctionTy = |
| 121 | LLVMDIBuilderCreateSubroutineType(Builder: DIB, File, ParameterTypes: ParamTypes, NumParameterTypes: 3, Flags: 0); |
| 122 | |
| 123 | LLVMMetadataRef ReplaceableFunctionMetadata = |
| 124 | LLVMDIBuilderCreateReplaceableCompositeType(Builder: DIB, Tag: 0x15, Name: "foo" , NameLen: 3, |
| 125 | Scope: File, File, Line: 42, |
| 126 | RuntimeLang: 0, SizeInBits: 0, AlignInBits: 0, |
| 127 | Flags: LLVMDIFlagFwdDecl, |
| 128 | UniqueIdentifier: "" , UniqueIdentifierLen: 0); |
| 129 | |
| 130 | LLVMMetadataRef FooParamLocation = |
| 131 | LLVMDIBuilderCreateDebugLocation(Ctx: LLVMGetGlobalContext(), Line: 42, Column: 0, |
| 132 | Scope: ReplaceableFunctionMetadata, NULL); |
| 133 | LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction( |
| 134 | Builder: DIB, Scope: File, Name: "foo" , NameLen: 3, LinkageName: "foo" , LinkageNameLen: 3, File, LineNo: 42, NULL, true, true, ScopeLine: 42, Flags: 0, false); |
| 135 | LLVMMetadataReplaceAllUsesWith(TempTargetMetadata: ReplaceableFunctionMetadata, Replacement: FunctionMetadata); |
| 136 | |
| 137 | LLVMDISubprogramReplaceType(Subprogram: FunctionMetadata, SubroutineType: FunctionTy); |
| 138 | |
| 139 | LLVMMetadataRef FooParamExpression = |
| 140 | LLVMDIBuilderCreateExpression(Builder: DIB, NULL, Length: 0); |
| 141 | LLVMMetadataRef FooParamVar1 = |
| 142 | LLVMDIBuilderCreateParameterVariable(Builder: DIB, Scope: FunctionMetadata, Name: "a" , NameLen: 1, ArgNo: 1, File, |
| 143 | LineNo: 42, Ty: Int64Ty, true, Flags: 0); |
| 144 | |
| 145 | LLVMDIBuilderInsertDeclareRecordAtEnd( |
| 146 | Builder: DIB, Storage: LLVMConstInt(IntTy: LLVMInt64Type(), N: 0, false), VarInfo: FooParamVar1, |
| 147 | Expr: FooParamExpression, DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 148 | |
| 149 | LLVMMetadataRef FooParamVar2 = |
| 150 | LLVMDIBuilderCreateParameterVariable(Builder: DIB, Scope: FunctionMetadata, Name: "b" , NameLen: 1, ArgNo: 2, File, |
| 151 | LineNo: 42, Ty: Int64Ty, true, Flags: 0); |
| 152 | |
| 153 | LLVMDIBuilderInsertDeclareRecordAtEnd( |
| 154 | Builder: DIB, Storage: LLVMConstInt(IntTy: LLVMInt64Type(), N: 0, false), VarInfo: FooParamVar2, |
| 155 | Expr: FooParamExpression, DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 156 | |
| 157 | LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable( |
| 158 | Builder: DIB, Scope: FunctionMetadata, Name: "c" , NameLen: 1, ArgNo: 3, File, LineNo: 42, Ty: VectorTy, true, Flags: 0); |
| 159 | |
| 160 | LLVMDIBuilderInsertDeclareRecordAtEnd( |
| 161 | Builder: DIB, Storage: LLVMConstInt(IntTy: LLVMInt64Type(), N: 0, false), VarInfo: FooParamVar3, |
| 162 | Expr: FooParamExpression, DebugLoc: FooParamLocation, Block: FooEntryBlock); |
| 163 | |
| 164 | LLVMSetSubprogram(Func: FooFunction, SP: FunctionMetadata); |
| 165 | |
| 166 | LLVMMetadataRef FooLabel1 = LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 167 | Name: "label1" , NameLen: 6, File, LineNo: 42, false); |
| 168 | LLVMDIBuilderInsertLabelAtEnd(Builder: DIB, LabelInfo: FooLabel1, Location: FooParamLocation, |
| 169 | InsertAtEnd: FooEntryBlock); |
| 170 | |
| 171 | LLVMMetadataRef FooLexicalBlock = |
| 172 | LLVMDIBuilderCreateLexicalBlock(Builder: DIB, Scope: FunctionMetadata, File, Line: 42, Column: 0); |
| 173 | |
| 174 | LLVMBasicBlockRef FooVarBlock = LLVMAppendBasicBlock(Fn: FooFunction, Name: "vars" ); |
| 175 | LLVMMetadataRef FooVarsLocation = |
| 176 | LLVMDIBuilderCreateDebugLocation(Ctx: LLVMGetGlobalContext(), Line: 43, Column: 0, |
| 177 | Scope: FunctionMetadata, NULL); |
| 178 | LLVMMetadataRef FooVar1 = |
| 179 | LLVMDIBuilderCreateAutoVariable(Builder: DIB, Scope: FooLexicalBlock, Name: "d" , NameLen: 1, File, |
| 180 | LineNo: 43, Ty: Int64Ty, true, Flags: 0, AlignInBits: 0); |
| 181 | LLVMValueRef FooVal1 = LLVMConstInt(IntTy: LLVMInt64Type(), N: 0, false); |
| 182 | LLVMMetadataRef FooVarValueExpr1 = |
| 183 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 0); |
| 184 | |
| 185 | LLVMDIBuilderInsertDbgValueRecordAtEnd( |
| 186 | Builder: DIB, Val: FooVal1, VarInfo: FooVar1, Expr: FooVarValueExpr1, DebugLoc: FooVarsLocation, Block: FooVarBlock); |
| 187 | |
| 188 | LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable( |
| 189 | Builder: DIB, Scope: FooLexicalBlock, Name: "e" , NameLen: 1, File, LineNo: 44, Ty: Int64Ty, true, Flags: 0, AlignInBits: 0); |
| 190 | LLVMValueRef FooVal2 = LLVMConstInt(IntTy: LLVMInt64Type(), N: 1, false); |
| 191 | LLVMMetadataRef FooVarValueExpr2 = |
| 192 | LLVMDIBuilderCreateConstantValueExpression(Builder: DIB, Value: 1); |
| 193 | |
| 194 | LLVMDIBuilderInsertDbgValueRecordAtEnd( |
| 195 | Builder: DIB, Val: FooVal2, VarInfo: FooVar2, Expr: FooVarValueExpr2, DebugLoc: FooVarsLocation, Block: FooVarBlock); |
| 196 | |
| 197 | LLVMMetadataRef MacroFile = |
| 198 | LLVMDIBuilderCreateTempMacroFile(Builder: DIB, NULL, Line: 0, File); |
| 199 | LLVMDIBuilderCreateMacro(Builder: DIB, ParentMacroFile: MacroFile, Line: 0, RecordType: LLVMDWARFMacinfoRecordTypeDefine, |
| 200 | Name: "SIMPLE_DEFINE" , NameLen: 13, NULL, ValueLen: 0); |
| 201 | LLVMDIBuilderCreateMacro(Builder: DIB, ParentMacroFile: MacroFile, Line: 0, RecordType: LLVMDWARFMacinfoRecordTypeDefine, |
| 202 | Name: "VALUE_DEFINE" , NameLen: 12, Value: "1" , ValueLen: 1); |
| 203 | |
| 204 | LLVMMetadataRef EnumeratorTestA = |
| 205 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_A" , NameLen: strlen(s: "Test_A" ), Value: 0, true); |
| 206 | LLVMMetadataRef EnumeratorTestB = |
| 207 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_B" , NameLen: strlen(s: "Test_B" ), Value: 1, true); |
| 208 | LLVMMetadataRef EnumeratorTestC = |
| 209 | LLVMDIBuilderCreateEnumerator(Builder: DIB, Name: "Test_B" , NameLen: strlen(s: "Test_C" ), Value: 2, true); |
| 210 | LLVMMetadataRef EnumeratorsTest[] = {EnumeratorTestA, EnumeratorTestB, |
| 211 | EnumeratorTestC}; |
| 212 | LLVMMetadataRef EnumTest = LLVMDIBuilderCreateEnumerationType( |
| 213 | Builder: DIB, Scope: NameSpace, Name: "EnumTest" , NameLen: strlen(s: "EnumTest" ), File, LineNumber: 0, SizeInBits: 64, AlignInBits: 0, |
| 214 | Elements: EnumeratorsTest, NumElements: 3, ClassTy: Int64Ty); |
| 215 | LLVMAddNamedMetadataOperand( |
| 216 | M, Name: "EnumTest" , Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: EnumTest)); |
| 217 | |
| 218 | LLVMMetadataRef UInt128Ty = LLVMDIBuilderCreateBasicType( |
| 219 | Builder: DIB, Name: "UInt128" , NameLen: strlen(s: "UInt128" ), SizeInBits: 128, Encoding: 0, Flags: LLVMDIFlagZero); |
| 220 | const uint64_t WordsTestD[] = {0x098a224000000000ull, 0x4b3b4ca85a86c47aull}; |
| 221 | const uint64_t WordsTestE[] = {0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull}; |
| 222 | |
| 223 | LLVMMetadataRef LargeEnumeratorTestD = |
| 224 | LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision( |
| 225 | Builder: DIB, Name: "Test_D" , NameLen: strlen(s: "Test_D" ), SizeInBits: 128, Words: WordsTestD, false); |
| 226 | LLVMMetadataRef LargeEnumeratorTestE = |
| 227 | LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision( |
| 228 | Builder: DIB, Name: "Test_E" , NameLen: strlen(s: "Test_E" ), SizeInBits: 128, Words: WordsTestE, false); |
| 229 | LLVMMetadataRef LargeEnumeratorsTest[] = {LargeEnumeratorTestD, |
| 230 | LargeEnumeratorTestE}; |
| 231 | LLVMMetadataRef LargeEnumTest = LLVMDIBuilderCreateEnumerationType( |
| 232 | Builder: DIB, Scope: NameSpace, Name: "LargeEnumTest" , NameLen: strlen(s: "LargeEnumTest" ), File, LineNumber: 0, SizeInBits: 128, AlignInBits: 0, |
| 233 | Elements: LargeEnumeratorsTest, NumElements: 2, ClassTy: UInt128Ty); |
| 234 | LLVMAddNamedMetadataOperand( |
| 235 | M, Name: "LargeEnumTest" , |
| 236 | Val: LLVMMetadataAsValue(C: LLVMGetModuleContext(M), MD: LargeEnumTest)); |
| 237 | |
| 238 | // Using the new debug format, debug records get attached to instructions. |
| 239 | // Insert a `br` and `ret` now to absorb the debug records which are |
| 240 | // currently "trailing", meaning that they're associated with a block |
| 241 | // but no particular instruction, which is only valid as a transient state. |
| 242 | LLVMContextRef Ctx = LLVMGetModuleContext(M); |
| 243 | LLVMBuilderRef Builder = LLVMCreateBuilderInContext(C: Ctx); |
| 244 | LLVMPositionBuilderAtEnd(Builder, Block: FooEntryBlock); |
| 245 | // Build `br label %vars` in entry. |
| 246 | LLVMBuildBr(Builder, Dest: FooVarBlock); |
| 247 | |
| 248 | // Build another br for the sake of testing labels. |
| 249 | LLVMMetadataRef FooLabel2 = LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 250 | Name: "label2" , NameLen: 6, File, LineNo: 42, false); |
| 251 | LLVMDIBuilderInsertLabelBefore(Builder: DIB, LabelInfo: FooLabel2, Location: FooParamLocation, |
| 252 | InsertBefore: LLVMBuildBr(Builder, Dest: FooVarBlock)); |
| 253 | // label3 will be emitted, but label4 won't be emitted |
| 254 | // because label3 is AlwaysPreserve and label4 is not. |
| 255 | LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 256 | Name: "label3" , NameLen: 6, File, LineNo: 42, true); |
| 257 | LLVMDIBuilderCreateLabel(Builder: DIB, Context: FunctionMetadata, |
| 258 | Name: "label4" , NameLen: 6, File, LineNo: 42, false); |
| 259 | LLVMDIBuilderFinalize(Builder: DIB); |
| 260 | |
| 261 | // Build `ret i64 0` in vars. |
| 262 | LLVMPositionBuilderAtEnd(Builder, Block: FooVarBlock); |
| 263 | LLVMTypeRef I64 = LLVMInt64TypeInContext(C: Ctx); |
| 264 | LLVMValueRef Zero = LLVMConstInt(IntTy: I64, N: 0, false); |
| 265 | LLVMValueRef Ret = LLVMBuildRet(Builder, V: Zero); |
| 266 | |
| 267 | // Insert a `phi` before the `ret`. In the new debug info mode we need to |
| 268 | // be careful to insert before debug records too, else the debug records |
| 269 | // will come before the `phi` (and be absorbed onto it) which is an invalid |
| 270 | // state. |
| 271 | LLVMValueRef InsertPos = LLVMGetFirstInstruction(BB: FooVarBlock); |
| 272 | LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, Instr: InsertPos); |
| 273 | LLVMValueRef Phi1 = LLVMBuildPhi(Builder, Ty: I64, Name: "p1" ); |
| 274 | LLVMAddIncoming(PhiNode: Phi1, IncomingValues: &Zero, IncomingBlocks: &FooEntryBlock, Count: 1); |
| 275 | |
| 276 | // Do the same again using the other position-setting function. |
| 277 | LLVMPositionBuilderBeforeDbgRecords(Builder, Block: FooVarBlock, Inst: InsertPos); |
| 278 | LLVMValueRef Phi2 = LLVMBuildPhi(Builder, Ty: I64, Name: "p2" ); |
| 279 | LLVMAddIncoming(PhiNode: Phi2, IncomingValues: &Zero, IncomingBlocks: &FooEntryBlock, Count: 1); |
| 280 | |
| 281 | // Insert a non-phi before the `ret` but not before the debug records to |
| 282 | // test that works as expected. |
| 283 | LLVMPositionBuilder(Builder, Block: FooVarBlock, Instr: Ret); |
| 284 | LLVMValueRef Add = LLVMBuildAdd(Builder, LHS: Phi1, RHS: Phi2, Name: "a" ); |
| 285 | |
| 286 | // Iterate over debug records in the add instruction. There should be two. |
| 287 | LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Inst: Add); |
| 288 | assert(AddDbgRecordFirst != NULL); |
| 289 | LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(DbgRecord: AddDbgRecordFirst); |
| 290 | assert(AddDbgRecordSecond != NULL); |
| 291 | LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Inst: Add); |
| 292 | assert(AddDbgRecordLast != NULL); |
| 293 | (void)AddDbgRecordLast; |
| 294 | assert(AddDbgRecordSecond == AddDbgRecordLast); |
| 295 | LLVMDbgRecordRef AddDbgRecordOverTheRange = |
| 296 | LLVMGetNextDbgRecord(DbgRecord: AddDbgRecordSecond); |
| 297 | assert(AddDbgRecordOverTheRange == NULL); |
| 298 | (void)AddDbgRecordOverTheRange; |
| 299 | LLVMDbgRecordRef AddDbgRecordFirstPrev = |
| 300 | LLVMGetPreviousDbgRecord(DbgRecord: AddDbgRecordSecond); |
| 301 | assert(AddDbgRecordFirstPrev != NULL); |
| 302 | assert(AddDbgRecordFirst == AddDbgRecordFirstPrev); |
| 303 | LLVMDbgRecordRef AddDbgRecordUnderTheRange = |
| 304 | LLVMGetPreviousDbgRecord(DbgRecord: AddDbgRecordFirstPrev); |
| 305 | assert(AddDbgRecordUnderTheRange == NULL); |
| 306 | (void)AddDbgRecordUnderTheRange; |
| 307 | |
| 308 | char *MStr = LLVMPrintModuleToString(M); |
| 309 | puts(s: MStr); |
| 310 | LLVMDisposeMessage(Message: MStr); |
| 311 | |
| 312 | LLVMDisposeBuilder(Builder); |
| 313 | LLVMDisposeDIBuilder(Builder: DIB); |
| 314 | LLVMDisposeModule(M); |
| 315 | |
| 316 | return 0; |
| 317 | } |
| 318 | |
| 319 | int llvm_get_di_tag(void) { |
| 320 | LLVMModuleRef M = LLVMModuleCreateWithName(ModuleID: "Mod" ); |
| 321 | LLVMContextRef Context = LLVMGetModuleContext(M); |
| 322 | |
| 323 | const char String[] = "foo" ; |
| 324 | LLVMMetadataRef StringMD = |
| 325 | LLVMMDStringInContext2(C: Context, Str: String, SLen: strlen(s: String)); |
| 326 | LLVMMetadataRef NodeMD = LLVMMDNodeInContext2(C: Context, MDs: &StringMD, Count: 1); |
| 327 | assert(LLVMGetDINodeTag(NodeMD) == 0); |
| 328 | (void)NodeMD; |
| 329 | |
| 330 | LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); |
| 331 | const char Filename[] = "metadata.c" ; |
| 332 | const char Directory[] = "." ; |
| 333 | LLVMMetadataRef File = LLVMDIBuilderCreateFile( |
| 334 | Builder, Filename, FilenameLen: strlen(s: Filename), Directory, DirectoryLen: strlen(s: Directory)); |
| 335 | const char Name[] = "TestClass" ; |
| 336 | LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( |
| 337 | Builder, Scope: File, Name, NameLen: strlen(s: Name), File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, |
| 338 | Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 339 | assert(LLVMGetDINodeTag(Struct) == 0x13); |
| 340 | (void)Struct; |
| 341 | |
| 342 | LLVMDisposeDIBuilder(Builder); |
| 343 | LLVMDisposeModule(M); |
| 344 | |
| 345 | return 0; |
| 346 | } |
| 347 | |
| 348 | int llvm_di_type_get_name(void) { |
| 349 | LLVMModuleRef M = LLVMModuleCreateWithName(ModuleID: "Mod" ); |
| 350 | |
| 351 | LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); |
| 352 | const char Filename[] = "metadata.c" ; |
| 353 | const char Directory[] = "." ; |
| 354 | LLVMMetadataRef File = LLVMDIBuilderCreateFile( |
| 355 | Builder, Filename, FilenameLen: strlen(s: Filename), Directory, DirectoryLen: strlen(s: Directory)); |
| 356 | const char Name[] = "TestClass" ; |
| 357 | LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( |
| 358 | Builder, Scope: File, Name, NameLen: strlen(s: Name), File, LineNumber: 42, SizeInBits: 64, AlignInBits: 0, |
| 359 | Flags: LLVMDIFlagObjcClassComplete, NULL, NULL, NumElements: 0, RunTimeLang: 0, NULL, NULL, UniqueIdLen: 0); |
| 360 | |
| 361 | size_t Len; |
| 362 | const char *TypeName = LLVMDITypeGetName(DType: Struct, Length: &Len); |
| 363 | assert(Len == strlen(Name)); |
| 364 | assert(strncmp(TypeName, Name, Len) == 0); |
| 365 | (void)TypeName; |
| 366 | |
| 367 | LLVMDisposeDIBuilder(Builder); |
| 368 | LLVMDisposeModule(M); |
| 369 | |
| 370 | return 0; |
| 371 | } |
| 372 | |