1 /*===-- debuginfo.c - tool for testing libLLVM and llvm-c API -------------===*\
3 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
5 |* See https://llvm.org/LICENSE.txt for license information. *|
6 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
8 |*===----------------------------------------------------------------------===*|
10 |* Tests for the LLVM C DebugInfo API *|
12 \*===----------------------------------------------------------------------===*/
14 #include "llvm-c/DebugInfo.h"
15 #include "llvm-c-test.h"
16 #include "llvm-c/Core.h"
17 #include "llvm-c/Types.h"
23 static LLVMMetadataRef
24 declare_objc_class(LLVMDIBuilderRef DIB
, LLVMMetadataRef File
) {
25 LLVMMetadataRef Decl
= LLVMDIBuilderCreateStructType(DIB
, File
, "TestClass", 9, File
, 42, 64, 0, LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
26 LLVMMetadataRef SuperDecl
= LLVMDIBuilderCreateStructType(DIB
, File
, "TestSuperClass", 14, File
, 42, 64, 0, LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
27 LLVMDIBuilderCreateInheritance(DIB
, Decl
, SuperDecl
, 0, 0, 0);
28 LLVMMetadataRef TestProperty
=
29 LLVMDIBuilderCreateObjCProperty(DIB
, "test", 4, File
, 42, "getTest", 7, "setTest", 7, 0x20 /*copy*/ | 0x40 /*nonatomic*/, SuperDecl
);
30 LLVMDIBuilderCreateObjCIVar(DIB
, "_test", 5, File
, 42, 64, 0, 64, LLVMDIFlagPublic
, SuperDecl
, TestProperty
);
34 int llvm_test_dibuilder(void) {
35 const char *Filename
= "debuginfo.c";
36 LLVMModuleRef M
= LLVMModuleCreateWithName(Filename
);
38 LLVMSetIsNewDbgInfoFormat(M
, true);
39 assert(LLVMIsNewDbgInfoFormat(M
));
41 LLVMDIBuilderRef DIB
= LLVMCreateDIBuilder(M
);
43 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(DIB
, Filename
,
44 strlen(Filename
), ".", 1);
46 LLVMMetadataRef CompileUnit
= LLVMDIBuilderCreateCompileUnit(
47 DIB
, LLVMDWARFSourceLanguageC
, File
, "llvm-c-test", 11, 0, NULL
, 0, 0,
48 NULL
, 0, LLVMDWARFEmissionFull
, 0, 0, 0, "/", 1, "", 0);
50 LLVMMetadataRef Module
=
51 LLVMDIBuilderCreateModule(DIB
, CompileUnit
,
54 "/test/include/llvm-c-test.h", 27,
57 LLVMMetadataRef OtherModule
=
58 LLVMDIBuilderCreateModule(DIB
, CompileUnit
,
59 "llvm-c-test-import", 18,
61 "/test/include/llvm-c-test-import.h", 34,
63 LLVMMetadataRef ImportedModule
= LLVMDIBuilderCreateImportedModuleFromModule(
64 DIB
, Module
, OtherModule
, File
, 42, NULL
, 0);
65 LLVMDIBuilderCreateImportedModuleFromAlias(DIB
, Module
, ImportedModule
, File
,
68 LLVMMetadataRef ClassTy
= declare_objc_class(DIB
, File
);
69 LLVMMetadataRef GlobalClassValueExpr
=
70 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
71 LLVMDIBuilderCreateGlobalVariableExpression(
72 DIB
, Module
, "globalClass", 11, "", 0, File
, 1, ClassTy
, true,
73 GlobalClassValueExpr
, NULL
, 0);
75 LLVMMetadataRef Int64Ty
=
76 LLVMDIBuilderCreateBasicType(DIB
, "Int64", 5, 64, 0, LLVMDIFlagZero
);
77 LLVMMetadataRef Int64TypeDef
=
78 LLVMDIBuilderCreateTypedef(DIB
, Int64Ty
, "int64_t", 7, File
, 42, File
, 0);
80 LLVMMetadataRef GlobalVarValueExpr
=
81 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
82 LLVMDIBuilderCreateGlobalVariableExpression(
83 DIB
, Module
, "global", 6, "", 0, File
, 1, Int64TypeDef
, true,
84 GlobalVarValueExpr
, NULL
, 0);
86 LLVMMetadataRef NameSpace
=
87 LLVMDIBuilderCreateNameSpace(DIB
, Module
, "NameSpace", 9, false);
89 LLVMMetadataRef StructDbgElts
[] = {Int64Ty
, Int64Ty
, Int64Ty
};
90 LLVMMetadataRef StructDbgTy
=
91 LLVMDIBuilderCreateStructType(DIB
, NameSpace
, "MyStruct",
92 8, File
, 0, 192, 0, 0, NULL
, StructDbgElts
, 3,
93 LLVMDWARFSourceLanguageC
, NULL
, "MyStruct", 8);
95 LLVMMetadataRef StructDbgPtrTy
=
96 LLVMDIBuilderCreatePointerType(DIB
, StructDbgTy
, 192, 0, 0, "", 0);
98 LLVMAddNamedMetadataOperand(M
, "FooType",
99 LLVMMetadataAsValue(LLVMGetModuleContext(M
), StructDbgPtrTy
));
102 LLVMTypeRef FooParamTys
[] = {
105 LLVMVectorType(LLVMInt64Type(), 10),
107 LLVMTypeRef FooFuncTy
= LLVMFunctionType(LLVMInt64Type(), FooParamTys
, 3, 0);
108 LLVMValueRef FooFunction
= LLVMAddFunction(M
, "foo", FooFuncTy
);
109 LLVMBasicBlockRef FooEntryBlock
= LLVMAppendBasicBlock(FooFunction
, "entry");
111 LLVMMetadataRef Subscripts
[] = {
112 LLVMDIBuilderGetOrCreateSubrange(DIB
, 0, 10),
114 LLVMMetadataRef VectorTy
=
115 LLVMDIBuilderCreateVectorType(DIB
, 64 * 10, 0,
116 Int64Ty
, Subscripts
, 1);
119 LLVMMetadataRef ParamTypes
[] = {Int64Ty
, Int64Ty
, VectorTy
};
120 LLVMMetadataRef FunctionTy
=
121 LLVMDIBuilderCreateSubroutineType(DIB
, File
, ParamTypes
, 3, 0);
123 LLVMMetadataRef ReplaceableFunctionMetadata
=
124 LLVMDIBuilderCreateReplaceableCompositeType(DIB
, 0x15, "foo", 3,
130 LLVMMetadataRef FooParamLocation
=
131 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 42, 0,
132 ReplaceableFunctionMetadata
, NULL
);
133 LLVMMetadataRef FunctionMetadata
=
134 LLVMDIBuilderCreateFunction(DIB
, File
, "foo", 3, "foo", 3,
135 File
, 42, FunctionTy
, true, true,
137 LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata
, FunctionMetadata
);
139 LLVMMetadataRef FooParamExpression
=
140 LLVMDIBuilderCreateExpression(DIB
, NULL
, 0);
141 LLVMMetadataRef FooParamVar1
=
142 LLVMDIBuilderCreateParameterVariable(DIB
, FunctionMetadata
, "a", 1, 1, File
,
143 42, Int64Ty
, true, 0);
145 LLVMDIBuilderInsertDeclareRecordAtEnd(
146 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1
,
147 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
149 LLVMMetadataRef FooParamVar2
=
150 LLVMDIBuilderCreateParameterVariable(DIB
, FunctionMetadata
, "b", 1, 2, File
,
151 42, Int64Ty
, true, 0);
153 LLVMDIBuilderInsertDeclareRecordAtEnd(
154 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2
,
155 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
157 LLVMMetadataRef FooParamVar3
= LLVMDIBuilderCreateParameterVariable(
158 DIB
, FunctionMetadata
, "c", 1, 3, File
, 42, VectorTy
, true, 0);
160 LLVMDIBuilderInsertDeclareRecordAtEnd(
161 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3
,
162 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
164 LLVMSetSubprogram(FooFunction
, FunctionMetadata
);
166 LLVMMetadataRef FooLabel1
= LLVMDIBuilderCreateLabel(DIB
, FunctionMetadata
,
167 "label1", 6, File
, 42, false);
168 LLVMDIBuilderInsertLabelAtEnd(DIB
, FooLabel1
, FooParamLocation
,
171 LLVMMetadataRef FooLexicalBlock
=
172 LLVMDIBuilderCreateLexicalBlock(DIB
, FunctionMetadata
, File
, 42, 0);
174 LLVMBasicBlockRef FooVarBlock
= LLVMAppendBasicBlock(FooFunction
, "vars");
175 LLVMMetadataRef FooVarsLocation
=
176 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 43, 0,
177 FunctionMetadata
, NULL
);
178 LLVMMetadataRef FooVar1
=
179 LLVMDIBuilderCreateAutoVariable(DIB
, FooLexicalBlock
, "d", 1, File
,
180 43, Int64Ty
, true, 0, 0);
181 LLVMValueRef FooVal1
= LLVMConstInt(LLVMInt64Type(), 0, false);
182 LLVMMetadataRef FooVarValueExpr1
=
183 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
185 LLVMDIBuilderInsertDbgValueRecordAtEnd(
186 DIB
, FooVal1
, FooVar1
, FooVarValueExpr1
, FooVarsLocation
, FooVarBlock
);
188 LLVMMetadataRef FooVar2
= LLVMDIBuilderCreateAutoVariable(
189 DIB
, FooLexicalBlock
, "e", 1, File
, 44, Int64Ty
, true, 0, 0);
190 LLVMValueRef FooVal2
= LLVMConstInt(LLVMInt64Type(), 1, false);
191 LLVMMetadataRef FooVarValueExpr2
=
192 LLVMDIBuilderCreateConstantValueExpression(DIB
, 1);
194 LLVMDIBuilderInsertDbgValueRecordAtEnd(
195 DIB
, FooVal2
, FooVar2
, FooVarValueExpr2
, FooVarsLocation
, FooVarBlock
);
197 LLVMMetadataRef MacroFile
=
198 LLVMDIBuilderCreateTempMacroFile(DIB
, NULL
, 0, File
);
199 LLVMDIBuilderCreateMacro(DIB
, MacroFile
, 0, LLVMDWARFMacinfoRecordTypeDefine
,
200 "SIMPLE_DEFINE", 13, NULL
, 0);
201 LLVMDIBuilderCreateMacro(DIB
, MacroFile
, 0, LLVMDWARFMacinfoRecordTypeDefine
,
202 "VALUE_DEFINE", 12, "1", 1);
204 LLVMMetadataRef EnumeratorTestA
=
205 LLVMDIBuilderCreateEnumerator(DIB
, "Test_A", strlen("Test_A"), 0, true);
206 LLVMMetadataRef EnumeratorTestB
=
207 LLVMDIBuilderCreateEnumerator(DIB
, "Test_B", strlen("Test_B"), 1, true);
208 LLVMMetadataRef EnumeratorTestC
=
209 LLVMDIBuilderCreateEnumerator(DIB
, "Test_B", strlen("Test_C"), 2, true);
210 LLVMMetadataRef EnumeratorsTest
[] = {EnumeratorTestA
, EnumeratorTestB
,
212 LLVMMetadataRef EnumTest
= LLVMDIBuilderCreateEnumerationType(
213 DIB
, NameSpace
, "EnumTest", strlen("EnumTest"), File
, 0, 64, 0,
214 EnumeratorsTest
, 3, Int64Ty
);
215 LLVMAddNamedMetadataOperand(
216 M
, "EnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M
), EnumTest
));
218 // Using the new debug format, debug records get attached to instructions.
219 // Insert a `br` and `ret` now to absorb the debug records which are
220 // currently "trailing", meaning that they're associated with a block
221 // but no particular instruction, which is only valid as a transient state.
222 LLVMContextRef Ctx
= LLVMGetModuleContext(M
);
223 LLVMBuilderRef Builder
= LLVMCreateBuilderInContext(Ctx
);
224 LLVMPositionBuilderAtEnd(Builder
, FooEntryBlock
);
225 // Build `br label %vars` in entry.
226 LLVMBuildBr(Builder
, FooVarBlock
);
228 // Build another br for the sake of testing labels.
229 LLVMMetadataRef FooLabel2
= LLVMDIBuilderCreateLabel(DIB
, FunctionMetadata
,
230 "label2", 6, File
, 42, false);
231 LLVMDIBuilderInsertLabelBefore(DIB
, FooLabel2
, FooParamLocation
,
232 LLVMBuildBr(Builder
, FooVarBlock
));
233 // label3 will be emitted, but label4 won't be emitted
234 // because label3 is AlwaysPreserve and label4 is not.
235 LLVMDIBuilderCreateLabel(DIB
, FunctionMetadata
,
236 "label3", 6, File
, 42, true);
237 LLVMDIBuilderCreateLabel(DIB
, FunctionMetadata
,
238 "label4", 6, File
, 42, false);
239 LLVMDIBuilderFinalize(DIB
);
241 // Build `ret i64 0` in vars.
242 LLVMPositionBuilderAtEnd(Builder
, FooVarBlock
);
243 LLVMTypeRef I64
= LLVMInt64TypeInContext(Ctx
);
244 LLVMValueRef Zero
= LLVMConstInt(I64
, 0, false);
245 LLVMValueRef Ret
= LLVMBuildRet(Builder
, Zero
);
247 // Insert a `phi` before the `ret`. In the new debug info mode we need to
248 // be careful to insert before debug records too, else the debug records
249 // will come before the `phi` (and be absorbed onto it) which is an invalid
251 LLVMValueRef InsertPos
= LLVMGetFirstInstruction(FooVarBlock
);
252 LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder
, InsertPos
);
253 LLVMValueRef Phi1
= LLVMBuildPhi(Builder
, I64
, "p1");
254 LLVMAddIncoming(Phi1
, &Zero
, &FooEntryBlock
, 1);
256 // Do the same again using the other position-setting function.
257 LLVMPositionBuilderBeforeDbgRecords(Builder
, FooVarBlock
, InsertPos
);
258 LLVMValueRef Phi2
= LLVMBuildPhi(Builder
, I64
, "p2");
259 LLVMAddIncoming(Phi2
, &Zero
, &FooEntryBlock
, 1);
261 // Insert a non-phi before the `ret` but not before the debug records to
262 // test that works as expected.
263 LLVMPositionBuilder(Builder
, FooVarBlock
, Ret
);
264 LLVMValueRef Add
= LLVMBuildAdd(Builder
, Phi1
, Phi2
, "a");
266 // Iterate over debug records in the add instruction. There should be two.
267 LLVMDbgRecordRef AddDbgRecordFirst
= LLVMGetFirstDbgRecord(Add
);
268 assert(AddDbgRecordFirst
!= NULL
);
269 LLVMDbgRecordRef AddDbgRecordSecond
= LLVMGetNextDbgRecord(AddDbgRecordFirst
);
270 assert(AddDbgRecordSecond
!= NULL
);
271 LLVMDbgRecordRef AddDbgRecordLast
= LLVMGetLastDbgRecord(Add
);
272 assert(AddDbgRecordLast
!= NULL
);
273 (void)AddDbgRecordLast
;
274 assert(AddDbgRecordSecond
== AddDbgRecordLast
);
275 LLVMDbgRecordRef AddDbgRecordOverTheRange
=
276 LLVMGetNextDbgRecord(AddDbgRecordSecond
);
277 assert(AddDbgRecordOverTheRange
== NULL
);
278 (void)AddDbgRecordOverTheRange
;
279 LLVMDbgRecordRef AddDbgRecordFirstPrev
=
280 LLVMGetPreviousDbgRecord(AddDbgRecordSecond
);
281 assert(AddDbgRecordFirstPrev
!= NULL
);
282 assert(AddDbgRecordFirst
== AddDbgRecordFirstPrev
);
283 LLVMDbgRecordRef AddDbgRecordUnderTheRange
=
284 LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev
);
285 assert(AddDbgRecordUnderTheRange
== NULL
);
286 (void)AddDbgRecordUnderTheRange
;
288 char *MStr
= LLVMPrintModuleToString(M
);
290 LLVMDisposeMessage(MStr
);
292 LLVMDisposeBuilder(Builder
);
293 LLVMDisposeDIBuilder(DIB
);
294 LLVMDisposeModule(M
);
299 int llvm_get_di_tag(void) {
300 LLVMModuleRef M
= LLVMModuleCreateWithName("Mod");
301 LLVMContextRef Context
= LLVMGetModuleContext(M
);
303 const char String
[] = "foo";
304 LLVMMetadataRef StringMD
=
305 LLVMMDStringInContext2(Context
, String
, strlen(String
));
306 LLVMMetadataRef NodeMD
= LLVMMDNodeInContext2(Context
, &StringMD
, 1);
307 assert(LLVMGetDINodeTag(NodeMD
) == 0);
310 LLVMDIBuilderRef Builder
= LLVMCreateDIBuilder(M
);
311 const char Filename
[] = "metadata.c";
312 const char Directory
[] = ".";
313 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(
314 Builder
, Filename
, strlen(Filename
), Directory
, strlen(Directory
));
315 const char Name
[] = "TestClass";
316 LLVMMetadataRef Struct
= LLVMDIBuilderCreateStructType(
317 Builder
, File
, Name
, strlen(Name
), File
, 42, 64, 0,
318 LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
319 assert(LLVMGetDINodeTag(Struct
) == 0x13);
322 LLVMDisposeDIBuilder(Builder
);
323 LLVMDisposeModule(M
);
328 int llvm_di_type_get_name(void) {
329 LLVMModuleRef M
= LLVMModuleCreateWithName("Mod");
331 LLVMDIBuilderRef Builder
= LLVMCreateDIBuilder(M
);
332 const char Filename
[] = "metadata.c";
333 const char Directory
[] = ".";
334 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(
335 Builder
, Filename
, strlen(Filename
), Directory
, strlen(Directory
));
336 const char Name
[] = "TestClass";
337 LLVMMetadataRef Struct
= LLVMDIBuilderCreateStructType(
338 Builder
, File
, Name
, strlen(Name
), File
, 42, 64, 0,
339 LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
342 const char *TypeName
= LLVMDITypeGetName(Struct
, &Len
);
343 assert(Len
== strlen(Name
));
344 assert(strncmp(TypeName
, Name
, Len
) == 0);
347 LLVMDisposeDIBuilder(Builder
);
348 LLVMDisposeModule(M
);