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/IR/DIBuilder.h"
11 #include "llvm/AsmParser/Parser.h"
12 #include "llvm/IR/DebugInfoMetadata.h"
13 #include "llvm/IR/IntrinsicInst.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/IR/Verifier.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Transforms/Utils/Local.h"
19 #include "gtest/gtest.h"
20 
21 using namespace llvm;
22 
parseIR(LLVMContext & C,const char * IR)23 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
24   SMDiagnostic Err;
25   std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
26   if (!Mod)
27     Err.print("DebugInfoTest", errs());
28   return Mod;
29 }
30 
31 namespace {
32 
TEST(DINodeTest,getFlag)33 TEST(DINodeTest, getFlag) {
34   // Some valid flags.
35   EXPECT_EQ(DINode::FlagPublic, DINode::getFlag("DIFlagPublic"));
36   EXPECT_EQ(DINode::FlagProtected, DINode::getFlag("DIFlagProtected"));
37   EXPECT_EQ(DINode::FlagPrivate, DINode::getFlag("DIFlagPrivate"));
38   EXPECT_EQ(DINode::FlagVector, DINode::getFlag("DIFlagVector"));
39   EXPECT_EQ(DINode::FlagRValueReference,
40             DINode::getFlag("DIFlagRValueReference"));
41 
42   // FlagAccessibility shouldn't work.
43   EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));
44 
45   // Some other invalid strings.
46   EXPECT_EQ(0u, DINode::getFlag("FlagVector"));
47   EXPECT_EQ(0u, DINode::getFlag("Vector"));
48   EXPECT_EQ(0u, DINode::getFlag("other things"));
49   EXPECT_EQ(0u, DINode::getFlag("DIFlagOther"));
50 }
51 
TEST(DINodeTest,getFlagString)52 TEST(DINodeTest, getFlagString) {
53   // Some valid flags.
54   EXPECT_EQ(StringRef("DIFlagPublic"),
55             DINode::getFlagString(DINode::FlagPublic));
56   EXPECT_EQ(StringRef("DIFlagProtected"),
57             DINode::getFlagString(DINode::FlagProtected));
58   EXPECT_EQ(StringRef("DIFlagPrivate"),
59             DINode::getFlagString(DINode::FlagPrivate));
60   EXPECT_EQ(StringRef("DIFlagVector"),
61             DINode::getFlagString(DINode::FlagVector));
62   EXPECT_EQ(StringRef("DIFlagRValueReference"),
63             DINode::getFlagString(DINode::FlagRValueReference));
64 
65   // FlagAccessibility actually equals FlagPublic.
66   EXPECT_EQ(StringRef("DIFlagPublic"),
67             DINode::getFlagString(DINode::FlagAccessibility));
68 
69   // Some other invalid flags.
70   EXPECT_EQ(StringRef(),
71             DINode::getFlagString(DINode::FlagPublic | DINode::FlagVector));
72   EXPECT_EQ(StringRef(), DINode::getFlagString(DINode::FlagFwdDecl |
73                                                DINode::FlagArtificial));
74   EXPECT_EQ(StringRef(),
75             DINode::getFlagString(static_cast<DINode::DIFlags>(0xffff)));
76 }
77 
TEST(DINodeTest,splitFlags)78 TEST(DINodeTest, splitFlags) {
79 // Some valid flags.
80 #define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER)                                  \
81   {                                                                            \
82     SmallVector<DINode::DIFlags, 8> V;                                         \
83     EXPECT_EQ(REMAINDER, DINode::splitFlags(FLAGS, V));                        \
84     EXPECT_TRUE(makeArrayRef(V).equals(VECTOR));                               \
85   }
86   CHECK_SPLIT(DINode::FlagPublic, {DINode::FlagPublic}, DINode::FlagZero);
87   CHECK_SPLIT(DINode::FlagProtected, {DINode::FlagProtected}, DINode::FlagZero);
88   CHECK_SPLIT(DINode::FlagPrivate, {DINode::FlagPrivate}, DINode::FlagZero);
89   CHECK_SPLIT(DINode::FlagVector, {DINode::FlagVector}, DINode::FlagZero);
90   CHECK_SPLIT(DINode::FlagRValueReference, {DINode::FlagRValueReference},
91               DINode::FlagZero);
92   DINode::DIFlags Flags[] = {DINode::FlagFwdDecl, DINode::FlagVector};
93   CHECK_SPLIT(DINode::FlagFwdDecl | DINode::FlagVector, Flags,
94               DINode::FlagZero);
95   CHECK_SPLIT(DINode::FlagZero, {}, DINode::FlagZero);
96 #undef CHECK_SPLIT
97 }
98 
TEST(StripTest,LoopMetadata)99 TEST(StripTest, LoopMetadata) {
100   LLVMContext C;
101   std::unique_ptr<Module> M = parseIR(C, R"(
102     define void @f() !dbg !5 {
103       ret void, !dbg !10, !llvm.loop !11
104     }
105 
106     !llvm.dbg.cu = !{!0}
107     !llvm.debugify = !{!3, !3}
108     !llvm.module.flags = !{!4}
109 
110     !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
111     !1 = !DIFile(filename: "loop.ll", directory: "/")
112     !2 = !{}
113     !3 = !{i32 1}
114     !4 = !{i32 2, !"Debug Info Version", i32 3}
115     !5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
116     !6 = !DISubroutineType(types: !2)
117     !7 = !{!8}
118     !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9)
119     !9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
120     !10 = !DILocation(line: 1, column: 1, scope: !5)
121     !11 = distinct !{!11, !10, !10}
122 )");
123 
124   // Look up the debug info emission kind for the CU via the loop metadata
125   // attached to the terminator. If, when stripping non-line table debug info,
126   // we update the terminator's metadata correctly, we should be able to
127   // observe the change in emission kind for the CU.
128   auto getEmissionKind = [&]() {
129     Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
130     MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop);
131     return cast<DILocation>(LoopMD->getOperand(1))
132         ->getScope()
133         ->getSubprogram()
134         ->getUnit()
135         ->getEmissionKind();
136   };
137 
138   EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug);
139 
140   bool Changed = stripNonLineTableDebugInfo(*M);
141   EXPECT_TRUE(Changed);
142 
143   EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly);
144 
145   bool BrokenDebugInfo = false;
146   bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo);
147   EXPECT_FALSE(HardError);
148   EXPECT_FALSE(BrokenDebugInfo);
149 }
150 
TEST(MetadataTest,DeleteInstUsedByDbgValue)151 TEST(MetadataTest, DeleteInstUsedByDbgValue) {
152   LLVMContext C;
153   std::unique_ptr<Module> M = parseIR(C, R"(
154     define i16 @f(i16 %a) !dbg !6 {
155       %b = add i16 %a, 1, !dbg !11
156       call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
157       ret i16 0, !dbg !11
158     }
159     declare void @llvm.dbg.value(metadata, metadata, metadata) #0
160     attributes #0 = { nounwind readnone speculatable willreturn }
161 
162     !llvm.dbg.cu = !{!0}
163     !llvm.module.flags = !{!5}
164 
165     !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
166     !1 = !DIFile(filename: "t.ll", directory: "/")
167     !2 = !{}
168     !5 = !{i32 2, !"Debug Info Version", i32 3}
169     !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
170     !7 = !DISubroutineType(types: !2)
171     !8 = !{!9}
172     !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
173     !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
174     !11 = !DILocation(line: 1, column: 1, scope: !6)
175 )");
176 
177   // Find %b = add ...
178   Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
179 
180   // Find the dbg.value using %b.
181   SmallVector<DbgValueInst *, 1> DVIs;
182   findDbgValues(DVIs, &I);
183 
184   // Delete %b. The dbg.value should now point to undef.
185   I.eraseFromParent();
186   EXPECT_TRUE(isa<UndefValue>(DVIs[0]->getValue()));
187 }
188 
TEST(DIBuilder,CreateFortranArrayTypeWithAttributes)189 TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
190   LLVMContext Ctx;
191   std::unique_ptr<Module> M(new Module("MyModule", Ctx));
192   DIBuilder DIB(*M);
193 
194   DISubrange *Subrange = DIB.getOrCreateSubrange(1,1);
195   SmallVector<Metadata*, 4> Subranges;
196   Subranges.push_back(Subrange);
197   DINodeArray Subscripts = DIB.getOrCreateArray(Subranges);
198 
199   auto getDIExpression = [&DIB](int offset) {
200     SmallVector<uint64_t, 4> ops;
201     ops.push_back(llvm::dwarf::DW_OP_push_object_address);
202     DIExpression::appendOffset(ops, offset);
203     ops.push_back(llvm::dwarf::DW_OP_deref);
204 
205     return DIB.createExpression(ops);
206   };
207 
208   DIFile *F = DIB.createFile("main.c", "/");
209   DICompileUnit *CU = DIB.createCompileUnit(
210       dwarf::DW_LANG_C, DIB.createFile("main.c", "/"), "llvm-c", true, "", 0);
211 
212   DIVariable *DataLocation =
213       DIB.createTempGlobalVariableFwdDecl(CU, "dl", "_dl", F, 1, nullptr, true);
214   DIExpression *Associated = getDIExpression(1);
215   DIExpression *Allocated = getDIExpression(2);
216   DIExpression *Rank = DIB.createConstantValueExpression(3);
217 
218   DICompositeType *ArrayType = DIB.createArrayType(0, 0, nullptr, Subscripts,
219                                                    DataLocation, Associated,
220                                                    Allocated, Rank);
221 
222   EXPECT_TRUE(isa_and_nonnull<DICompositeType>(ArrayType));
223   EXPECT_EQ(ArrayType->getRawDataLocation(), DataLocation);
224   EXPECT_EQ(ArrayType->getRawAssociated(), Associated);
225   EXPECT_EQ(ArrayType->getRawAllocated(), Allocated);
226   EXPECT_EQ(ArrayType->getRawRank(), Rank);
227 
228   // Avoid memory leak.
229   DIVariable::deleteTemporary(DataLocation);
230 }
231 
232 } // end namespace
233