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 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 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 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 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 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 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 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 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 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 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 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