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-test.h"
15 #include "llvm-c/DebugInfo.h"
21 static LLVMMetadataRef
22 declare_objc_class(LLVMDIBuilderRef DIB
, LLVMMetadataRef File
) {
23 LLVMMetadataRef Decl
= LLVMDIBuilderCreateStructType(DIB
, File
, "TestClass", 9, File
, 42, 64, 0, LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
24 LLVMMetadataRef SuperDecl
= LLVMDIBuilderCreateStructType(DIB
, File
, "TestSuperClass", 14, File
, 42, 64, 0, LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
25 LLVMDIBuilderCreateInheritance(DIB
, Decl
, SuperDecl
, 0, 0, 0);
26 LLVMMetadataRef TestProperty
=
27 LLVMDIBuilderCreateObjCProperty(DIB
, "test", 4, File
, 42, "getTest", 7, "setTest", 7, 0x20 /*copy*/ | 0x40 /*nonatomic*/, SuperDecl
);
28 LLVMDIBuilderCreateObjCIVar(DIB
, "_test", 5, File
, 42, 64, 0, 64, LLVMDIFlagPublic
, SuperDecl
, TestProperty
);
32 int llvm_test_dibuilder(void) {
33 const char *Filename
= "debuginfo.c";
34 LLVMModuleRef M
= LLVMModuleCreateWithName(Filename
);
36 LLVMSetIsNewDbgInfoFormat(M
, true);
37 assert(LLVMIsNewDbgInfoFormat(M
));
39 LLVMDIBuilderRef DIB
= LLVMCreateDIBuilder(M
);
41 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(DIB
, Filename
,
42 strlen(Filename
), ".", 1);
44 LLVMMetadataRef CompileUnit
= LLVMDIBuilderCreateCompileUnit(
45 DIB
, LLVMDWARFSourceLanguageC
, File
, "llvm-c-test", 11, 0, NULL
, 0, 0,
46 NULL
, 0, LLVMDWARFEmissionFull
, 0, 0, 0, "/", 1, "", 0);
48 LLVMMetadataRef Module
=
49 LLVMDIBuilderCreateModule(DIB
, CompileUnit
,
52 "/test/include/llvm-c-test.h", 27,
55 LLVMMetadataRef OtherModule
=
56 LLVMDIBuilderCreateModule(DIB
, CompileUnit
,
57 "llvm-c-test-import", 18,
59 "/test/include/llvm-c-test-import.h", 34,
61 LLVMMetadataRef ImportedModule
= LLVMDIBuilderCreateImportedModuleFromModule(
62 DIB
, Module
, OtherModule
, File
, 42, NULL
, 0);
63 LLVMDIBuilderCreateImportedModuleFromAlias(DIB
, Module
, ImportedModule
, File
,
66 LLVMMetadataRef ClassTy
= declare_objc_class(DIB
, File
);
67 LLVMMetadataRef GlobalClassValueExpr
=
68 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
69 LLVMDIBuilderCreateGlobalVariableExpression(
70 DIB
, Module
, "globalClass", 11, "", 0, File
, 1, ClassTy
, true,
71 GlobalClassValueExpr
, NULL
, 0);
73 LLVMMetadataRef Int64Ty
=
74 LLVMDIBuilderCreateBasicType(DIB
, "Int64", 5, 64, 0, LLVMDIFlagZero
);
75 LLVMMetadataRef Int64TypeDef
=
76 LLVMDIBuilderCreateTypedef(DIB
, Int64Ty
, "int64_t", 7, File
, 42, File
, 0);
78 LLVMMetadataRef GlobalVarValueExpr
=
79 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
80 LLVMDIBuilderCreateGlobalVariableExpression(
81 DIB
, Module
, "global", 6, "", 0, File
, 1, Int64TypeDef
, true,
82 GlobalVarValueExpr
, NULL
, 0);
84 LLVMMetadataRef NameSpace
=
85 LLVMDIBuilderCreateNameSpace(DIB
, Module
, "NameSpace", 9, false);
87 LLVMMetadataRef StructDbgElts
[] = {Int64Ty
, Int64Ty
, Int64Ty
};
88 LLVMMetadataRef StructDbgTy
=
89 LLVMDIBuilderCreateStructType(DIB
, NameSpace
, "MyStruct",
90 8, File
, 0, 192, 0, 0, NULL
, StructDbgElts
, 3,
91 LLVMDWARFSourceLanguageC
, NULL
, "MyStruct", 8);
93 LLVMMetadataRef StructDbgPtrTy
=
94 LLVMDIBuilderCreatePointerType(DIB
, StructDbgTy
, 192, 0, 0, "", 0);
96 LLVMAddNamedMetadataOperand(M
, "FooType",
97 LLVMMetadataAsValue(LLVMGetModuleContext(M
), StructDbgPtrTy
));
100 LLVMTypeRef FooParamTys
[] = {
103 LLVMVectorType(LLVMInt64Type(), 10),
105 LLVMTypeRef FooFuncTy
= LLVMFunctionType(LLVMInt64Type(), FooParamTys
, 3, 0);
106 LLVMValueRef FooFunction
= LLVMAddFunction(M
, "foo", FooFuncTy
);
107 LLVMBasicBlockRef FooEntryBlock
= LLVMAppendBasicBlock(FooFunction
, "entry");
109 LLVMMetadataRef Subscripts
[] = {
110 LLVMDIBuilderGetOrCreateSubrange(DIB
, 0, 10),
112 LLVMMetadataRef VectorTy
=
113 LLVMDIBuilderCreateVectorType(DIB
, 64 * 10, 0,
114 Int64Ty
, Subscripts
, 1);
117 LLVMMetadataRef ParamTypes
[] = {Int64Ty
, Int64Ty
, VectorTy
};
118 LLVMMetadataRef FunctionTy
=
119 LLVMDIBuilderCreateSubroutineType(DIB
, File
, ParamTypes
, 3, 0);
121 LLVMMetadataRef ReplaceableFunctionMetadata
=
122 LLVMDIBuilderCreateReplaceableCompositeType(DIB
, 0x15, "foo", 3,
128 LLVMMetadataRef FooParamLocation
=
129 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 42, 0,
130 ReplaceableFunctionMetadata
, NULL
);
131 LLVMMetadataRef FunctionMetadata
=
132 LLVMDIBuilderCreateFunction(DIB
, File
, "foo", 3, "foo", 3,
133 File
, 42, FunctionTy
, true, true,
135 LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata
, FunctionMetadata
);
137 LLVMMetadataRef FooParamExpression
=
138 LLVMDIBuilderCreateExpression(DIB
, NULL
, 0);
139 LLVMMetadataRef FooParamVar1
=
140 LLVMDIBuilderCreateParameterVariable(DIB
, FunctionMetadata
, "a", 1, 1, File
,
141 42, Int64Ty
, true, 0);
143 LLVMDIBuilderInsertDeclareRecordAtEnd(
144 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1
,
145 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
147 LLVMMetadataRef FooParamVar2
=
148 LLVMDIBuilderCreateParameterVariable(DIB
, FunctionMetadata
, "b", 1, 2, File
,
149 42, Int64Ty
, true, 0);
151 LLVMDIBuilderInsertDeclareRecordAtEnd(
152 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2
,
153 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
155 LLVMMetadataRef FooParamVar3
= LLVMDIBuilderCreateParameterVariable(
156 DIB
, FunctionMetadata
, "c", 1, 3, File
, 42, VectorTy
, true, 0);
158 LLVMDIBuilderInsertDeclareRecordAtEnd(
159 DIB
, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3
,
160 FooParamExpression
, FooParamLocation
, FooEntryBlock
);
162 LLVMSetSubprogram(FooFunction
, FunctionMetadata
);
164 LLVMMetadataRef FooLexicalBlock
=
165 LLVMDIBuilderCreateLexicalBlock(DIB
, FunctionMetadata
, File
, 42, 0);
167 LLVMBasicBlockRef FooVarBlock
= LLVMAppendBasicBlock(FooFunction
, "vars");
168 LLVMMetadataRef FooVarsLocation
=
169 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 43, 0,
170 FunctionMetadata
, NULL
);
171 LLVMMetadataRef FooVar1
=
172 LLVMDIBuilderCreateAutoVariable(DIB
, FooLexicalBlock
, "d", 1, File
,
173 43, Int64Ty
, true, 0, 0);
174 LLVMValueRef FooVal1
= LLVMConstInt(LLVMInt64Type(), 0, false);
175 LLVMMetadataRef FooVarValueExpr
=
176 LLVMDIBuilderCreateConstantValueExpression(DIB
, 0);
178 LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB
, FooVal1
, FooVar1
, FooVarValueExpr
,
179 FooVarsLocation
, FooVarBlock
);
181 LLVMMetadataRef MacroFile
=
182 LLVMDIBuilderCreateTempMacroFile(DIB
, NULL
, 0, File
);
183 LLVMDIBuilderCreateMacro(DIB
, MacroFile
, 0, LLVMDWARFMacinfoRecordTypeDefine
,
184 "SIMPLE_DEFINE", 13, NULL
, 0);
185 LLVMDIBuilderCreateMacro(DIB
, MacroFile
, 0, LLVMDWARFMacinfoRecordTypeDefine
,
186 "VALUE_DEFINE", 12, "1", 1);
188 LLVMMetadataRef EnumeratorTestA
=
189 LLVMDIBuilderCreateEnumerator(DIB
, "Test_A", strlen("Test_A"), 0, true);
190 LLVMMetadataRef EnumeratorTestB
=
191 LLVMDIBuilderCreateEnumerator(DIB
, "Test_B", strlen("Test_B"), 1, true);
192 LLVMMetadataRef EnumeratorTestC
=
193 LLVMDIBuilderCreateEnumerator(DIB
, "Test_B", strlen("Test_C"), 2, true);
194 LLVMMetadataRef EnumeratorsTest
[] = {EnumeratorTestA
, EnumeratorTestB
,
196 LLVMMetadataRef EnumTest
= LLVMDIBuilderCreateEnumerationType(
197 DIB
, NameSpace
, "EnumTest", strlen("EnumTest"), File
, 0, 64, 0,
198 EnumeratorsTest
, 3, Int64Ty
);
199 LLVMAddNamedMetadataOperand(
200 M
, "EnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M
), EnumTest
));
202 LLVMDIBuilderFinalize(DIB
);
204 // Using the new debug format, debug records get attached to instructions.
205 // Insert a `br` and `ret` now to absorb the debug records which are
206 // currently "trailing", meaning that they're associated with a block
207 // but no particular instruction, which is only valid as a transient state.
208 LLVMContextRef Ctx
= LLVMGetModuleContext(M
);
209 LLVMBuilderRef Builder
= LLVMCreateBuilderInContext(Ctx
);
210 LLVMPositionBuilderAtEnd(Builder
, FooEntryBlock
);
211 // Build `br label %vars` in entry.
212 LLVMBuildBr(Builder
, FooVarBlock
);
213 // Build `ret i64 0` in vars.
214 LLVMPositionBuilderAtEnd(Builder
, FooVarBlock
);
215 LLVMTypeRef I64
= LLVMInt64TypeInContext(Ctx
);
216 LLVMValueRef Zero
= LLVMConstInt(I64
, 0, false);
217 LLVMValueRef Ret
= LLVMBuildRet(Builder
, Zero
);
219 // Insert a `phi` before the `ret`. In the new debug info mode we need to
220 // be careful to insert before debug records too, else the debug records
221 // will come before the `phi` (and be absorbed onto it) which is an invalid
223 LLVMValueRef InsertPos
= LLVMGetFirstInstruction(FooVarBlock
);
224 LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder
, InsertPos
);
225 LLVMValueRef Phi1
= LLVMBuildPhi(Builder
, I64
, "p1");
226 LLVMAddIncoming(Phi1
, &Zero
, &FooEntryBlock
, 1);
227 // Do the same again using the other position-setting function.
228 LLVMPositionBuilderBeforeDbgRecords(Builder
, FooVarBlock
, InsertPos
);
229 LLVMValueRef Phi2
= LLVMBuildPhi(Builder
, I64
, "p2");
230 LLVMAddIncoming(Phi2
, &Zero
, &FooEntryBlock
, 1);
231 // Insert a non-phi before the `ret` but not before the debug records to
232 // test that works as expected.
233 LLVMPositionBuilder(Builder
, FooVarBlock
, Ret
);
234 LLVMBuildAdd(Builder
, Phi1
, Phi2
, "a");
236 char *MStr
= LLVMPrintModuleToString(M
);
238 LLVMDisposeMessage(MStr
);
240 LLVMDisposeBuilder(Builder
);
241 LLVMDisposeDIBuilder(DIB
);
242 LLVMDisposeModule(M
);
247 int llvm_get_di_tag(void) {
248 LLVMModuleRef M
= LLVMModuleCreateWithName("Mod");
249 LLVMContextRef Context
= LLVMGetModuleContext(M
);
251 const char String
[] = "foo";
252 LLVMMetadataRef StringMD
=
253 LLVMMDStringInContext2(Context
, String
, strlen(String
));
254 LLVMMetadataRef NodeMD
= LLVMMDNodeInContext2(Context
, &StringMD
, 1);
255 assert(LLVMGetDINodeTag(NodeMD
) == 0);
258 LLVMDIBuilderRef Builder
= LLVMCreateDIBuilder(M
);
259 const char Filename
[] = "metadata.c";
260 const char Directory
[] = ".";
261 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(
262 Builder
, Filename
, strlen(Filename
), Directory
, strlen(Directory
));
263 const char Name
[] = "TestClass";
264 LLVMMetadataRef Struct
= LLVMDIBuilderCreateStructType(
265 Builder
, File
, Name
, strlen(Name
), File
, 42, 64, 0,
266 LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
267 assert(LLVMGetDINodeTag(Struct
) == 0x13);
270 LLVMDisposeDIBuilder(Builder
);
271 LLVMDisposeModule(M
);
276 int llvm_di_type_get_name(void) {
277 LLVMModuleRef M
= LLVMModuleCreateWithName("Mod");
279 LLVMDIBuilderRef Builder
= LLVMCreateDIBuilder(M
);
280 const char Filename
[] = "metadata.c";
281 const char Directory
[] = ".";
282 LLVMMetadataRef File
= LLVMDIBuilderCreateFile(
283 Builder
, Filename
, strlen(Filename
), Directory
, strlen(Directory
));
284 const char Name
[] = "TestClass";
285 LLVMMetadataRef Struct
= LLVMDIBuilderCreateStructType(
286 Builder
, File
, Name
, strlen(Name
), File
, 42, 64, 0,
287 LLVMDIFlagObjcClassComplete
, NULL
, NULL
, 0, 0, NULL
, NULL
, 0);
290 const char *TypeName
= LLVMDITypeGetName(Struct
, &Len
);
291 assert(Len
== strlen(Name
));
292 assert(strncmp(TypeName
, Name
, Len
) == 0);
295 LLVMDisposeDIBuilder(Builder
);
296 LLVMDisposeModule(M
);