[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / IR / DebugInfoTest.cpp
blob524752168b091093906ff954e1ebaa8bb160f0b8
1 //===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/DebugInfo.h"
10 #include "llvm/ADT/APSInt.h"
11 #include "llvm/AsmParser/Parser.h"
12 #include "llvm/IR/DIBuilder.h"
13 #include "llvm/IR/DebugInfoMetadata.h"
14 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Metadata.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/Verifier.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Transforms/Utils/Local.h"
22 #include "gtest/gtest.h"
24 using namespace llvm;
26 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
27 SMDiagnostic Err;
28 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
29 if (!Mod)
30 Err.print("DebugInfoTest", errs());
31 return Mod;
34 namespace {
36 TEST(DINodeTest, getFlag) {
37 // Some valid flags.
38 EXPECT_EQ(DINode::FlagPublic, DINode::getFlag("DIFlagPublic"));
39 EXPECT_EQ(DINode::FlagProtected, DINode::getFlag("DIFlagProtected"));
40 EXPECT_EQ(DINode::FlagPrivate, DINode::getFlag("DIFlagPrivate"));
41 EXPECT_EQ(DINode::FlagVector, DINode::getFlag("DIFlagVector"));
42 EXPECT_EQ(DINode::FlagRValueReference,
43 DINode::getFlag("DIFlagRValueReference"));
45 // FlagAccessibility shouldn't work.
46 EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));
48 // Some other invalid strings.
49 EXPECT_EQ(0u, DINode::getFlag("FlagVector"));
50 EXPECT_EQ(0u, DINode::getFlag("Vector"));
51 EXPECT_EQ(0u, DINode::getFlag("other things"));
52 EXPECT_EQ(0u, DINode::getFlag("DIFlagOther"));
55 TEST(DINodeTest, getFlagString) {
56 // Some valid flags.
57 EXPECT_EQ(StringRef("DIFlagPublic"),
58 DINode::getFlagString(DINode::FlagPublic));
59 EXPECT_EQ(StringRef("DIFlagProtected"),
60 DINode::getFlagString(DINode::FlagProtected));
61 EXPECT_EQ(StringRef("DIFlagPrivate"),
62 DINode::getFlagString(DINode::FlagPrivate));
63 EXPECT_EQ(StringRef("DIFlagVector"),
64 DINode::getFlagString(DINode::FlagVector));
65 EXPECT_EQ(StringRef("DIFlagRValueReference"),
66 DINode::getFlagString(DINode::FlagRValueReference));
68 // FlagAccessibility actually equals FlagPublic.
69 EXPECT_EQ(StringRef("DIFlagPublic"),
70 DINode::getFlagString(DINode::FlagAccessibility));
72 // Some other invalid flags.
73 EXPECT_EQ(StringRef(),
74 DINode::getFlagString(DINode::FlagPublic | DINode::FlagVector));
75 EXPECT_EQ(StringRef(), DINode::getFlagString(DINode::FlagFwdDecl |
76 DINode::FlagArtificial));
77 EXPECT_EQ(StringRef(),
78 DINode::getFlagString(static_cast<DINode::DIFlags>(0xffff)));
81 TEST(DINodeTest, splitFlags) {
82 // Some valid flags.
83 #define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER) \
84 { \
85 SmallVector<DINode::DIFlags, 8> V; \
86 EXPECT_EQ(REMAINDER, DINode::splitFlags(FLAGS, V)); \
87 EXPECT_TRUE(makeArrayRef(V).equals(VECTOR)); \
89 CHECK_SPLIT(DINode::FlagPublic, {DINode::FlagPublic}, DINode::FlagZero);
90 CHECK_SPLIT(DINode::FlagProtected, {DINode::FlagProtected}, DINode::FlagZero);
91 CHECK_SPLIT(DINode::FlagPrivate, {DINode::FlagPrivate}, DINode::FlagZero);
92 CHECK_SPLIT(DINode::FlagVector, {DINode::FlagVector}, DINode::FlagZero);
93 CHECK_SPLIT(DINode::FlagRValueReference, {DINode::FlagRValueReference},
94 DINode::FlagZero);
95 DINode::DIFlags Flags[] = {DINode::FlagFwdDecl, DINode::FlagVector};
96 CHECK_SPLIT(DINode::FlagFwdDecl | DINode::FlagVector, Flags,
97 DINode::FlagZero);
98 CHECK_SPLIT(DINode::FlagZero, {}, DINode::FlagZero);
99 #undef CHECK_SPLIT
102 TEST(StripTest, LoopMetadata) {
103 LLVMContext C;
104 std::unique_ptr<Module> M = parseIR(C, R"(
105 define void @f() !dbg !5 {
106 ret void, !dbg !10, !llvm.loop !11
109 !llvm.dbg.cu = !{!0}
110 !llvm.debugify = !{!3, !3}
111 !llvm.module.flags = !{!4}
113 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
114 !1 = !DIFile(filename: "loop.ll", directory: "/")
115 !2 = !{}
116 !3 = !{i32 1}
117 !4 = !{i32 2, !"Debug Info Version", i32 3}
118 !5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
119 !6 = !DISubroutineType(types: !2)
120 !7 = !{!8}
121 !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9)
122 !9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
123 !10 = !DILocation(line: 1, column: 1, scope: !5)
124 !11 = distinct !{!11, !10, !10}
125 )");
127 // Look up the debug info emission kind for the CU via the loop metadata
128 // attached to the terminator. If, when stripping non-line table debug info,
129 // we update the terminator's metadata correctly, we should be able to
130 // observe the change in emission kind for the CU.
131 auto getEmissionKind = [&]() {
132 Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
133 MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop);
134 return cast<DILocation>(LoopMD->getOperand(1))
135 ->getScope()
136 ->getSubprogram()
137 ->getUnit()
138 ->getEmissionKind();
141 EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug);
143 bool Changed = stripNonLineTableDebugInfo(*M);
144 EXPECT_TRUE(Changed);
146 EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly);
148 bool BrokenDebugInfo = false;
149 bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo);
150 EXPECT_FALSE(HardError);
151 EXPECT_FALSE(BrokenDebugInfo);
154 TEST(MetadataTest, DeleteInstUsedByDbgValue) {
155 LLVMContext C;
156 std::unique_ptr<Module> M = parseIR(C, R"(
157 define i16 @f(i16 %a) !dbg !6 {
158 %b = add i16 %a, 1, !dbg !11
159 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
160 ret i16 0, !dbg !11
162 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
163 attributes #0 = { nounwind readnone speculatable willreturn }
165 !llvm.dbg.cu = !{!0}
166 !llvm.module.flags = !{!5}
168 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
169 !1 = !DIFile(filename: "t.ll", directory: "/")
170 !2 = !{}
171 !5 = !{i32 2, !"Debug Info Version", i32 3}
172 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
173 !7 = !DISubroutineType(types: !2)
174 !8 = !{!9}
175 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
176 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
177 !11 = !DILocation(line: 1, column: 1, scope: !6)
178 )");
180 // Find %b = add ...
181 Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
183 // Find the dbg.value using %b.
184 SmallVector<DbgValueInst *, 1> DVIs;
185 findDbgValues(DVIs, &I);
187 // Delete %b. The dbg.value should now point to undef.
188 I.eraseFromParent();
189 EXPECT_EQ(DVIs[0]->getNumVariableLocationOps(), 1u);
190 EXPECT_TRUE(isa<UndefValue>(DVIs[0]->getValue(0)));
193 TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
194 LLVMContext Ctx;
195 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
196 DIBuilder DIB(*M);
198 DISubrange *Subrange = DIB.getOrCreateSubrange(1,1);
199 SmallVector<Metadata*, 4> Subranges;
200 Subranges.push_back(Subrange);
201 DINodeArray Subscripts = DIB.getOrCreateArray(Subranges);
203 auto getDIExpression = [&DIB](int offset) {
204 SmallVector<uint64_t, 4> ops;
205 ops.push_back(llvm::dwarf::DW_OP_push_object_address);
206 DIExpression::appendOffset(ops, offset);
207 ops.push_back(llvm::dwarf::DW_OP_deref);
209 return DIB.createExpression(ops);
212 DIFile *F = DIB.createFile("main.c", "/");
213 DICompileUnit *CU = DIB.createCompileUnit(
214 dwarf::DW_LANG_C, DIB.createFile("main.c", "/"), "llvm-c", true, "", 0);
216 DIVariable *DataLocation =
217 DIB.createTempGlobalVariableFwdDecl(CU, "dl", "_dl", F, 1, nullptr, true);
218 DIExpression *Associated = getDIExpression(1);
219 DIExpression *Allocated = getDIExpression(2);
220 DIExpression *Rank = DIB.createConstantValueExpression(3);
222 DICompositeType *ArrayType = DIB.createArrayType(0, 0, nullptr, Subscripts,
223 DataLocation, Associated,
224 Allocated, Rank);
226 EXPECT_TRUE(isa_and_nonnull<DICompositeType>(ArrayType));
227 EXPECT_EQ(ArrayType->getRawDataLocation(), DataLocation);
228 EXPECT_EQ(ArrayType->getRawAssociated(), Associated);
229 EXPECT_EQ(ArrayType->getRawAllocated(), Allocated);
230 EXPECT_EQ(ArrayType->getRawRank(), Rank);
232 // Avoid memory leak.
233 DIVariable::deleteTemporary(DataLocation);
236 TEST(DIBuilder, CreateSetType) {
237 LLVMContext Ctx;
238 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
239 DIBuilder DIB(*M);
240 DIScope *Scope = DISubprogram::getDistinct(
241 Ctx, nullptr, "", "", nullptr, 0, nullptr, 0, nullptr, 0, 0,
242 DINode::FlagZero, DISubprogram::SPFlagZero, nullptr);
243 DIType *Type = DIB.createBasicType("Int", 64, dwarf::DW_ATE_signed);
244 DIFile *F = DIB.createFile("main.c", "/");
246 DIDerivedType *SetType = DIB.createSetType(Scope, "set1", F, 1, 64, 64, Type);
247 EXPECT_TRUE(isa_and_nonnull<DIDerivedType>(SetType));
250 TEST(DIBuilder, CreateStringType) {
251 LLVMContext Ctx;
252 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
253 DIBuilder DIB(*M);
254 DIScope *Scope = DISubprogram::getDistinct(
255 Ctx, nullptr, "", "", nullptr, 0, nullptr, 0, nullptr, 0, 0,
256 DINode::FlagZero, DISubprogram::SPFlagZero, nullptr);
257 DIFile *F = DIB.createFile("main.c", "/");
258 StringRef StrName = "string";
259 DIVariable *StringLen = DIB.createAutoVariable(Scope, StrName, F, 0, nullptr,
260 false, DINode::FlagZero, 0);
261 auto getDIExpression = [&DIB](int offset) {
262 SmallVector<uint64_t, 4> ops;
263 ops.push_back(llvm::dwarf::DW_OP_push_object_address);
264 DIExpression::appendOffset(ops, offset);
265 ops.push_back(llvm::dwarf::DW_OP_deref);
267 return DIB.createExpression(ops);
269 DIExpression *StringLocationExp = getDIExpression(1);
270 DIStringType *StringType =
271 DIB.createStringType(StrName, StringLen, StringLocationExp);
273 EXPECT_TRUE(isa_and_nonnull<DIStringType>(StringType));
274 EXPECT_EQ(StringType->getName(), StrName);
275 EXPECT_EQ(StringType->getStringLength(), StringLen);
276 EXPECT_EQ(StringType->getStringLocationExp(), StringLocationExp);
278 StringRef StrNameExp = "stringexp";
279 DIExpression *StringLengthExp = getDIExpression(2);
280 DIStringType *StringTypeExp =
281 DIB.createStringType(StrNameExp, StringLengthExp, StringLocationExp);
283 EXPECT_TRUE(isa_and_nonnull<DIStringType>(StringTypeExp));
284 EXPECT_EQ(StringTypeExp->getName(), StrNameExp);
285 EXPECT_EQ(StringTypeExp->getStringLocationExp(), StringLocationExp);
286 EXPECT_EQ(StringTypeExp->getStringLengthExp(), StringLengthExp);
289 TEST(DIBuilder, DIEnumerator) {
290 LLVMContext Ctx;
291 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
292 DIBuilder DIB(*M);
293 APSInt I1(APInt(32, 1));
294 APSInt I2(APInt(33, 1));
296 auto *E = DIEnumerator::get(Ctx, I1, I1.isSigned(), "name");
297 EXPECT_TRUE(E);
299 auto *E1 = DIEnumerator::getIfExists(Ctx, I1, I1.isSigned(), "name");
300 EXPECT_TRUE(E1);
302 auto *E2 = DIEnumerator::getIfExists(Ctx, I2, I1.isSigned(), "name");
303 EXPECT_FALSE(E2);
306 TEST(DIBuilder, createDbgAddr) {
307 LLVMContext C;
308 std::unique_ptr<Module> M = parseIR(C, R"(
309 define void @f() !dbg !6 {
310 %a = alloca i16, align 8
311 ;; It is important that we put the debug marker on the return.
312 ;; We take advantage of that to conjure up a debug loc without
313 ;; having to synthesize one programatically.
314 ret void, !dbg !11
316 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
317 attributes #0 = { nounwind readnone speculatable willreturn }
319 !llvm.dbg.cu = !{!0}
320 !llvm.module.flags = !{!5}
322 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
323 !1 = !DIFile(filename: "t.ll", directory: "/")
324 !2 = !{}
325 !5 = !{i32 2, !"Debug Info Version", i32 3}
326 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
327 !7 = !DISubroutineType(types: !2)
328 !8 = !{!9}
329 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
330 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
331 !11 = !DILocation(line: 1, column: 1, scope: !6)
332 )");
333 auto *F = M->getFunction("f");
334 auto *EntryBlock = &F->getEntryBlock();
336 auto *CU =
337 cast<DICompileUnit>(M->getNamedMetadata("llvm.dbg.cu")->getOperand(0));
338 auto *Alloca = &*EntryBlock->begin();
339 auto *Ret = EntryBlock->getTerminator();
341 auto *SP = cast<DISubprogram>(F->getMetadata(LLVMContext::MD_dbg));
342 auto *File = SP->getFile();
343 std::string Name = "myName";
344 const auto *Loc = Ret->getDebugLoc().get();
346 IRBuilder<> Builder(EntryBlock);
347 DIBuilder DIB(*M, true, CU);
348 DIType *DT = DIB.createBasicType("ty16", 16, dwarf::DW_ATE_unsigned);
350 DILocalVariable *LocalVar =
351 DIB.createAutoVariable(SP, Name, File, 5 /*line*/, DT,
352 /*AlwaysPreserve=*/true);
354 auto *Inst = DIB.insertDbgAddrIntrinsic(Alloca, LocalVar,
355 DIB.createExpression(), Loc, Ret);
357 DIB.finalize();
359 EXPECT_EQ(Inst->getDebugLoc().get(), Loc);
361 auto *MD0 = cast<MetadataAsValue>(Inst->getOperand(0))->getMetadata();
362 auto *MD0Local = cast<LocalAsMetadata>(MD0);
363 EXPECT_EQ(MD0Local->getValue(), Alloca);
364 auto *MD1 = cast<MetadataAsValue>(Inst->getOperand(1))->getMetadata();
365 EXPECT_EQ(MD1->getMetadataID(), Metadata::MetadataKind::DILocalVariableKind);
366 auto *MD2 = cast<MetadataAsValue>(Inst->getOperand(2))->getMetadata();
367 auto *MDExp = cast<DIExpression>(MD2);
368 EXPECT_EQ(MDExp->getNumElements(), 0u);
371 } // end namespace