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 //===----------------------------------------------------------------------===//
8 
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"
23 
24 using namespace llvm;
25 
parseIR(LLVMContext & C,const char * IR)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;
32 }
33 
34 namespace {
35 
TEST(DINodeTest,getFlag)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"));
44 
45   // FlagAccessibility shouldn't work.
46   EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));
47 
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"));
53 }
54 
TEST(DINodeTest,getFlagString)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));
67 
68   // FlagAccessibility actually equals FlagPublic.
69   EXPECT_EQ(StringRef("DIFlagPublic"),
70             DINode::getFlagString(DINode::FlagAccessibility));
71 
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)));
79 }
80 
TEST(DINodeTest,splitFlags)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));                               \
88   }
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
100 }
101 
TEST(StripTest,LoopMetadata)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
107     }
108 
109     !llvm.dbg.cu = !{!0}
110     !llvm.debugify = !{!3, !3}
111     !llvm.module.flags = !{!4}
112 
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 )");
126 
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();
139   };
140 
141   EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug);
142 
143   bool Changed = stripNonLineTableDebugInfo(*M);
144   EXPECT_TRUE(Changed);
145 
146   EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly);
147 
148   bool BrokenDebugInfo = false;
149   bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo);
150   EXPECT_FALSE(HardError);
151   EXPECT_FALSE(BrokenDebugInfo);
152 }
153 
TEST(MetadataTest,DeleteInstUsedByDbgValue)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
161     }
162     declare void @llvm.dbg.value(metadata, metadata, metadata) #0
163     attributes #0 = { nounwind readnone speculatable willreturn }
164 
165     !llvm.dbg.cu = !{!0}
166     !llvm.module.flags = !{!5}
167 
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 )");
179 
180   // Find %b = add ...
181   Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
182 
183   // Find the dbg.value using %b.
184   SmallVector<DbgValueInst *, 1> DVIs;
185   findDbgValues(DVIs, &I);
186 
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)));
191 }
192 
TEST(DIBuilder,CreateFortranArrayTypeWithAttributes)193 TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
194   LLVMContext Ctx;
195   std::unique_ptr<Module> M(new Module("MyModule", Ctx));
196   DIBuilder DIB(*M);
197 
198   DISubrange *Subrange = DIB.getOrCreateSubrange(1,1);
199   SmallVector<Metadata*, 4> Subranges;
200   Subranges.push_back(Subrange);
201   DINodeArray Subscripts = DIB.getOrCreateArray(Subranges);
202 
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);
208 
209     return DIB.createExpression(ops);
210   };
211 
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);
215 
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);
221 
222   DICompositeType *ArrayType = DIB.createArrayType(0, 0, nullptr, Subscripts,
223                                                    DataLocation, Associated,
224                                                    Allocated, Rank);
225 
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);
231 
232   // Avoid memory leak.
233   DIVariable::deleteTemporary(DataLocation);
234 }
235 
TEST(DIBuilder,CreateSetType)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", "/");
245 
246   DIDerivedType *SetType = DIB.createSetType(Scope, "set1", F, 1, 64, 64, Type);
247   EXPECT_TRUE(isa_and_nonnull<DIDerivedType>(SetType));
248 }
249 
TEST(DIBuilder,CreateStringType)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);
266 
267     return DIB.createExpression(ops);
268   };
269   DIExpression *StringLocationExp = getDIExpression(1);
270   DIStringType *StringType =
271       DIB.createStringType(StrName, StringLen, StringLocationExp);
272 
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);
277 
278   StringRef StrNameExp = "stringexp";
279   DIExpression *StringLengthExp = getDIExpression(2);
280   DIStringType *StringTypeExp =
281       DIB.createStringType(StrNameExp, StringLengthExp, StringLocationExp);
282 
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);
287 }
288 
TEST(DIBuilder,DIEnumerator)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));
295 
296   auto *E = DIEnumerator::get(Ctx, I1, I1.isSigned(), "name");
297   EXPECT_TRUE(E);
298 
299   auto *E1 = DIEnumerator::getIfExists(Ctx, I1, I1.isSigned(), "name");
300   EXPECT_TRUE(E1);
301 
302   auto *E2 = DIEnumerator::getIfExists(Ctx, I2, I1.isSigned(), "name");
303   EXPECT_FALSE(E2);
304 }
305 
TEST(DIBuilder,createDbgAddr)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
315     }
316     declare void @llvm.dbg.value(metadata, metadata, metadata) #0
317     attributes #0 = { nounwind readnone speculatable willreturn }
318 
319     !llvm.dbg.cu = !{!0}
320     !llvm.module.flags = !{!5}
321 
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();
335 
336   auto *CU =
337       cast<DICompileUnit>(M->getNamedMetadata("llvm.dbg.cu")->getOperand(0));
338   auto *Alloca = &*EntryBlock->begin();
339   auto *Ret = EntryBlock->getTerminator();
340 
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();
345 
346   IRBuilder<> Builder(EntryBlock);
347   DIBuilder DIB(*M, true, CU);
348   DIType *DT = DIB.createBasicType("ty16", 16, dwarf::DW_ATE_unsigned);
349 
350   DILocalVariable *LocalVar =
351       DIB.createAutoVariable(SP, Name, File, 5 /*line*/, DT,
352                              /*AlwaysPreserve=*/true);
353 
354   auto *Inst = DIB.insertDbgAddrIntrinsic(Alloca, LocalVar,
355                                           DIB.createExpression(), Loc, Ret);
356 
357   DIB.finalize();
358 
359   EXPECT_EQ(Inst->getDebugLoc().get(), Loc);
360 
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);
369 }
370 
371 } // end namespace
372