brintos

brintos / llvm-project-archived public Read only

0
0
Text · 59.4 KiB · 060f45d Raw
1448 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/DebugInfo.h"10#include "../lib/IR/LLVMContextImpl.h"11#include "llvm/ADT/APSInt.h"12#include "llvm/AsmParser/Parser.h"13#include "llvm/IR/DIBuilder.h"14#include "llvm/IR/DebugInfoMetadata.h"15#include "llvm/IR/DebugProgramInstruction.h"16#include "llvm/IR/IRBuilder.h"17#include "llvm/IR/IntrinsicInst.h"18#include "llvm/IR/LLVMContext.h"19#include "llvm/IR/Metadata.h"20#include "llvm/IR/Module.h"21#include "llvm/IR/Verifier.h"22#include "llvm/Support/Compiler.h"23#include "llvm/Support/SourceMgr.h"24#include "llvm/Transforms/Utils/Local.h"25 26#include "gtest/gtest.h"27 28using namespace llvm;29 30static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {31  SMDiagnostic Err;32  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);33  if (!Mod)34    Err.print("DebugInfoTest", errs());35  return Mod;36}37 38namespace {39 40TEST(DINodeTest, getFlag) {41  // Some valid flags.42  EXPECT_EQ(DINode::FlagPublic, DINode::getFlag("DIFlagPublic"));43  EXPECT_EQ(DINode::FlagProtected, DINode::getFlag("DIFlagProtected"));44  EXPECT_EQ(DINode::FlagPrivate, DINode::getFlag("DIFlagPrivate"));45  EXPECT_EQ(DINode::FlagVector, DINode::getFlag("DIFlagVector"));46  EXPECT_EQ(DINode::FlagRValueReference,47            DINode::getFlag("DIFlagRValueReference"));48 49  // FlagAccessibility shouldn't work.50  EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));51 52  // Some other invalid strings.53  EXPECT_EQ(0u, DINode::getFlag("FlagVector"));54  EXPECT_EQ(0u, DINode::getFlag("Vector"));55  EXPECT_EQ(0u, DINode::getFlag("other things"));56  EXPECT_EQ(0u, DINode::getFlag("DIFlagOther"));57}58 59TEST(DINodeTest, getFlagString) {60  // Some valid flags.61  EXPECT_EQ(StringRef("DIFlagPublic"),62            DINode::getFlagString(DINode::FlagPublic));63  EXPECT_EQ(StringRef("DIFlagProtected"),64            DINode::getFlagString(DINode::FlagProtected));65  EXPECT_EQ(StringRef("DIFlagPrivate"),66            DINode::getFlagString(DINode::FlagPrivate));67  EXPECT_EQ(StringRef("DIFlagVector"),68            DINode::getFlagString(DINode::FlagVector));69  EXPECT_EQ(StringRef("DIFlagRValueReference"),70            DINode::getFlagString(DINode::FlagRValueReference));71 72  // FlagAccessibility actually equals FlagPublic.73  EXPECT_EQ(StringRef("DIFlagPublic"),74            DINode::getFlagString(DINode::FlagAccessibility));75 76  // Some other invalid flags.77  EXPECT_EQ(StringRef(),78            DINode::getFlagString(DINode::FlagPublic | DINode::FlagVector));79  EXPECT_EQ(StringRef(), DINode::getFlagString(DINode::FlagFwdDecl |80                                               DINode::FlagArtificial));81  EXPECT_EQ(StringRef(),82            DINode::getFlagString(static_cast<DINode::DIFlags>(0xffff)));83}84 85TEST(DINodeTest, splitFlags) {86// Some valid flags.87#define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER)                                  \88  {                                                                            \89    SmallVector<DINode::DIFlags, 8> V;                                         \90    EXPECT_EQ(REMAINDER, DINode::splitFlags(FLAGS, V));                        \91    EXPECT_TRUE(ArrayRef(V).equals(VECTOR));                                   \92  }93  CHECK_SPLIT(DINode::FlagPublic, {DINode::FlagPublic}, DINode::FlagZero);94  CHECK_SPLIT(DINode::FlagProtected, {DINode::FlagProtected}, DINode::FlagZero);95  CHECK_SPLIT(DINode::FlagPrivate, {DINode::FlagPrivate}, DINode::FlagZero);96  CHECK_SPLIT(DINode::FlagVector, {DINode::FlagVector}, DINode::FlagZero);97  CHECK_SPLIT(DINode::FlagRValueReference, {DINode::FlagRValueReference},98              DINode::FlagZero);99  DINode::DIFlags Flags[] = {DINode::FlagFwdDecl, DINode::FlagVector};100  CHECK_SPLIT(DINode::FlagFwdDecl | DINode::FlagVector, Flags,101              DINode::FlagZero);102  CHECK_SPLIT(DINode::FlagZero, {}, DINode::FlagZero);103#undef CHECK_SPLIT104}105 106TEST(StripTest, LoopMetadata) {107  LLVMContext C;108  std::unique_ptr<Module> M = parseIR(C, R"(109    define void @f() !dbg !5 {110      ret void, !dbg !10, !llvm.loop !11111    }112 113    !llvm.dbg.cu = !{!0}114    !llvm.debugify = !{!3, !3}115    !llvm.module.flags = !{!4}116 117    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)118    !1 = !DIFile(filename: "loop.ll", directory: "/")119    !2 = !{}120    !3 = !{i32 1}121    !4 = !{i32 2, !"Debug Info Version", i32 3}122    !5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)123    !6 = !DISubroutineType(types: !2)124    !7 = !{!8}125    !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9)126    !9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)127    !10 = !DILocation(line: 1, column: 1, scope: !5)128    !11 = distinct !{!11, !10, !10}129)");130 131  // Look up the debug info emission kind for the CU via the loop metadata132  // attached to the terminator. If, when stripping non-line table debug info,133  // we update the terminator's metadata correctly, we should be able to134  // observe the change in emission kind for the CU.135  auto getEmissionKind = [&]() {136    Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHIIt();137    MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop);138    return cast<DILocation>(LoopMD->getOperand(1))139        ->getScope()140        ->getSubprogram()141        ->getUnit()142        ->getEmissionKind();143  };144 145  EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug);146 147  bool Changed = stripNonLineTableDebugInfo(*M);148  EXPECT_TRUE(Changed);149 150  EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly);151 152  bool BrokenDebugInfo = false;153  bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo);154  EXPECT_FALSE(HardError);155  EXPECT_FALSE(BrokenDebugInfo);156}157 158TEST(MetadataTest, DeleteInstUsedByDbgRecord) {159  LLVMContext C;160  std::unique_ptr<Module> M = parseIR(C, R"(161    define i16 @f(i16 %a) !dbg !6 {162      %b = add i16 %a, 1, !dbg !11163      call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11164      ret i16 0, !dbg !11165    }166    declare void @llvm.dbg.value(metadata, metadata, metadata) #0167    attributes #0 = { nounwind readnone speculatable willreturn }168 169    !llvm.dbg.cu = !{!0}170    !llvm.module.flags = !{!5}171 172    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)173    !1 = !DIFile(filename: "t.ll", directory: "/")174    !2 = !{}175    !5 = !{i32 2, !"Debug Info Version", i32 3}176    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)177    !7 = !DISubroutineType(types: !2)178    !8 = !{!9}179    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)180    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)181    !11 = !DILocation(line: 1, column: 1, scope: !6)182)");183 184  // Find %b = add ...185  Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHIIt();186 187  // Find the dbg.value using %b.188  SmallVector<DbgVariableRecord *, 1> DVRs;189  findDbgValues(&I, DVRs);190 191  // Delete %b. The dbg.value should now point to undef.192  I.eraseFromParent();193  EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u);194  EXPECT_TRUE(isa<UndefValue>(DVRs[0]->getValue(0)));195}196 197TEST(MetadataTest, GlobalConstantMetadataUsedByDbgRecord) {198  LLVMContext C;199  std::unique_ptr<Module> M = parseIR(C, R"(200    @x = dso_local global i32 0, align 4201    declare void @llvm.dbg.value(metadata, metadata, metadata) #0202 203    define i16 @f(i16 %a) !dbg !6 {204      %b = add i16 %a, 1, !dbg !11205      call void @llvm.dbg.declare(metadata ptr @x, metadata !9, metadata !DIExpression()), !dbg !11206      call void @llvm.dbg.value(metadata ptr @x, metadata !9, metadata !DIExpression()), !dbg !11207      ret i16 0, !dbg !11208    }209 210    attributes #0 = { nounwind readnone speculatable willreturn }211 212    !llvm.dbg.cu = !{!0}213    !llvm.module.flags = !{!5}214 215    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)216    !1 = !DIFile(filename: "t.ll", directory: "/")217    !2 = !{}218    !5 = !{i32 2, !"Debug Info Version", i32 3}219    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)220    !7 = !DISubroutineType(types: !2)221    !8 = !{!9}222    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)223    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)224    !11 = !DILocation(line: 1, column: 1, scope: !6)225)");226 227  // Find the global @x228  Value *V = M->getNamedValue("x");229 230  // Find the dbg.value231  auto DVRs = findDVRDeclares(V);232  auto DVRVs = findDVRValues(V);233 234  EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u);235  EXPECT_TRUE(DVRVs.size() == 1);236  EXPECT_FALSE(isa<UndefValue>(DVRs[0]->getValue(0)));237}238 239TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) {240  LLVMContext Ctx;241  std::unique_ptr<Module> M = parseIR(Ctx, R"(242    define dso_local void @fun() local_unnamed_addr #0 !dbg !9 {243    entry:244      call void @llvm.dbg.declare(metadata !{}, metadata !13, metadata !DIExpression()), !dbg !16245      ret void, !dbg !16246    }247 248    declare void @llvm.dbg.declare(metadata, metadata, metadata)249 250    !llvm.dbg.cu = !{!0}251    !llvm.module.flags = !{!2, !3}252    !llvm.ident = !{!8}253 254    !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 16.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)255    !1 = !DIFile(filename: "test.c", directory: "/")256    !2 = !{i32 7, !"Dwarf Version", i32 5}257    !3 = !{i32 2, !"Debug Info Version", i32 3}258    !8 = !{!"clang version 16.0.0"}259    !9 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)260    !10 = !DISubroutineType(types: !11)261    !11 = !{null}262    !12 = !{!13}263    !13 = !DILocalVariable(name: "a", scope: !9, file: !1, line: 1, type: !14)264    !14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)265    !16 = !DILocation(line: 1, column: 21, scope: !9)266    )");267 268  bool BrokenDebugInfo = true;269  verifyModule(*M, &errs(), &BrokenDebugInfo);270  ASSERT_FALSE(BrokenDebugInfo);271 272  // Get the dbg.declare.273  Function &F = *cast<Function>(M->getNamedValue("fun"));274  DbgVariableRecord *DbgDeclare =275      cast<DbgVariableRecord>(&*F.front().front().getDbgRecordRange().begin());276  // Check that this form counts as a "no location" marker.277  EXPECT_TRUE(DbgDeclare->isKillLocation());278}279 280// Duplicate of above test, but in DbgVariableRecord representation.281TEST(MetadataTest, DeleteInstUsedByDbgVariableRecord) {282  LLVMContext C;283 284  std::unique_ptr<Module> M = parseIR(C, R"(285    define i16 @f(i16 %a) !dbg !6 {286      %b = add i16 %a, 1, !dbg !11287      call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11288      call void @llvm.dbg.value(metadata !DIArgList(i16 %a, i16 %b), metadata !9, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !11289      ret i16 0, !dbg !11290    }291    declare void @llvm.dbg.value(metadata, metadata, metadata) #0292    attributes #0 = { nounwind readnone speculatable willreturn }293 294    !llvm.dbg.cu = !{!0}295    !llvm.module.flags = !{!5}296 297    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)298    !1 = !DIFile(filename: "t.ll", directory: "/")299    !2 = !{}300    !5 = !{i32 2, !"Debug Info Version", i32 3}301    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)302    !7 = !DISubroutineType(types: !2)303    !8 = !{!9}304    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)305    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)306    !11 = !DILocation(line: 1, column: 1, scope: !6)307)");308 309  Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHIIt();310 311  // Find the DbgVariableRecords using %b.312  SmallVector<DbgVariableRecord *, 2> DVRs;313  findDbgValues(&I, DVRs);314  ASSERT_EQ(DVRs.size(), 2u);315 316  // Delete %b. The DbgVariableRecord should now point to undef.317  I.eraseFromParent();318  EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u);319  EXPECT_TRUE(isa<UndefValue>(DVRs[0]->getVariableLocationOp(0)));320  EXPECT_TRUE(DVRs[0]->isKillLocation());321  EXPECT_EQ(DVRs[1]->getNumVariableLocationOps(), 2u);322  EXPECT_TRUE(isa<UndefValue>(DVRs[1]->getVariableLocationOp(1)));323  EXPECT_TRUE(DVRs[1]->isKillLocation());324}325 326// Ensure that the order of dbg.value intrinsics returned by findDbgValues, and327// their corresponding DbgVariableRecord representation, are consistent.328TEST(MetadataTest, OrderingOfDbgVariableRecords) {329  LLVMContext C;330  std::unique_ptr<Module> M = parseIR(C, R"(331    define i16 @f(i16 %a) !dbg !6 {332      %b = add i16 %a, 1, !dbg !11333        #dbg_value(i16 %b, !9, !DIExpression(), !11)334        #dbg_value(i16 %b, !12, !DIExpression(), !11)335      ret i16 0, !dbg !11336    }337    attributes #0 = { nounwind readnone speculatable willreturn }338 339    !llvm.dbg.cu = !{!0}340    !llvm.module.flags = !{!5}341 342    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)343    !1 = !DIFile(filename: "t.ll", directory: "/")344    !2 = !{}345    !5 = !{i32 2, !"Debug Info Version", i32 3}346    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)347    !7 = !DISubroutineType(types: !2)348    !8 = !{!9}349    !9 = !DILocalVariable(name: "foo", scope: !6, file: !1, line: 1, type: !10)350    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)351    !11 = !DILocation(line: 1, column: 1, scope: !6)352    !12 = !DILocalVariable(name: "bar", scope: !6, file: !1, line: 1, type: !10)353)");354 355  Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHIIt();356 357  SmallVector<DbgVariableRecord *, 2> DVRs;358 359  findDbgValues(&I, DVRs);360  ASSERT_EQ(DVRs.size(), 2u);361 362  // The correct order of dbg.values is given by their use-list, which becomes363  // the reverse order of creation. Thus the dbg.values should come out as364  // "bar" and then "foo".365  const DILocalVariable *Var0 = DVRs[0]->getVariable();366  EXPECT_TRUE(Var0->getName() == "bar");367  const DILocalVariable *Var1 = DVRs[1]->getVariable();368  EXPECT_TRUE(Var1->getName() == "foo");369 370  M->convertFromNewDbgValues();371}372 373TEST(DIBuilder, CreateFile) {374  LLVMContext Ctx;375  std::unique_ptr<Module> M(new Module("MyModule", Ctx));376  DIBuilder DIB(*M);377 378  DIFile *F = DIB.createFile("main.c", "/");379  EXPECT_EQ(std::nullopt, F->getSource());380 381  std::optional<DIFile::ChecksumInfo<StringRef>> Checksum;382  std::optional<StringRef> Source;383  F = DIB.createFile("main.c", "/", Checksum, Source);384  EXPECT_EQ(Source, F->getSource());385 386  Source = "";387  F = DIB.createFile("main.c", "/", Checksum, Source);388  EXPECT_EQ(Source, F->getSource());389}390 391TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {392  LLVMContext Ctx;393  std::unique_ptr<Module> M(new Module("MyModule", Ctx));394  DIBuilder DIB(*M);395 396  DISubrange *Subrange = DIB.getOrCreateSubrange(1,1);397  SmallVector<Metadata*, 4> Subranges;398  Subranges.push_back(Subrange);399  DINodeArray Subscripts = DIB.getOrCreateArray(Subranges);400 401  auto getDIExpression = [&DIB](int offset) {402    SmallVector<uint64_t, 4> ops;403    ops.push_back(llvm::dwarf::DW_OP_push_object_address);404    DIExpression::appendOffset(ops, offset);405    ops.push_back(llvm::dwarf::DW_OP_deref);406 407    return DIB.createExpression(ops);408  };409 410  DIFile *F = DIB.createFile("main.c", "/");411  DICompileUnit *CU = DIB.createCompileUnit(412      DISourceLanguageName(dwarf::DW_LANG_C), DIB.createFile("main.c", "/"),413      "llvm-c", true, "", 0);414 415  DIVariable *DataLocation =416      DIB.createTempGlobalVariableFwdDecl(CU, "dl", "_dl", F, 1, nullptr, true);417  DIExpression *Associated = getDIExpression(1);418  DIExpression *Allocated = getDIExpression(2);419  DIExpression *Rank = DIB.createConstantValueExpression(3);420 421  DICompositeType *ArrayType = DIB.createArrayType(0, 0, nullptr, Subscripts,422                                                   DataLocation, Associated,423                                                   Allocated, Rank);424 425  EXPECT_TRUE(isa_and_nonnull<DICompositeType>(ArrayType));426  EXPECT_EQ(ArrayType->getRawDataLocation(), DataLocation);427  EXPECT_EQ(ArrayType->getRawAssociated(), Associated);428  EXPECT_EQ(ArrayType->getRawAllocated(), Allocated);429  EXPECT_EQ(ArrayType->getRawRank(), Rank);430 431  // Avoid memory leak.432  DIVariable::deleteTemporary(DataLocation);433}434 435TEST(DIBuilder, CreateArrayWithBitStride) {436  LLVMContext Ctx;437  std::unique_ptr<Module> M(new Module("MyModule", Ctx));438  DIBuilder DIB(*M);439 440  Type *Int32Ty = Type::getInt32Ty(Ctx);441  Constant *Ci = ConstantInt::get(Int32Ty, 7);442  Metadata *CM = ConstantAsMetadata::get(Ci);443 444  StringRef ArrayNameExp = "AnArray";445  DICompositeType *NamedArray =446      DIB.createArrayType(nullptr, ArrayNameExp, nullptr, 0, 8, 8, nullptr, {},447                          nullptr, nullptr, nullptr, nullptr, CM);448  EXPECT_EQ(NamedArray->getTag(), dwarf::DW_TAG_array_type);449  EXPECT_EQ(NamedArray->getRawBitStride(), CM);450  EXPECT_EQ(NamedArray->getBitStrideConst(), Ci);451}452 453TEST(DIBuilder, CreateSetType) {454  LLVMContext Ctx;455  std::unique_ptr<Module> M(new Module("MyModule", Ctx));456  DIBuilder DIB(*M);457  DIScope *Scope = DISubprogram::getDistinct(458      Ctx, nullptr, "", "", nullptr, 0, nullptr, 0, nullptr, 0, 0,459      DINode::FlagZero, DISubprogram::SPFlagZero, nullptr);460  DIType *Type = DIB.createBasicType("Int", 64, dwarf::DW_ATE_signed);461  DIFile *F = DIB.createFile("main.c", "/");462 463  DIDerivedType *SetType = DIB.createSetType(Scope, "set1", F, 1, 64, 64, Type);464  EXPECT_TRUE(isa_and_nonnull<DIDerivedType>(SetType));465}466 467TEST(DIBuilder, CreateStringType) {468  LLVMContext Ctx;469  std::unique_ptr<Module> M(new Module("MyModule", Ctx));470  DIBuilder DIB(*M);471  DIScope *Scope = DISubprogram::getDistinct(472      Ctx, nullptr, "", "", nullptr, 0, nullptr, 0, nullptr, 0, 0,473      DINode::FlagZero, DISubprogram::SPFlagZero, nullptr);474  DIFile *F = DIB.createFile("main.c", "/");475  StringRef StrName = "string";476  DIVariable *StringLen = DIB.createAutoVariable(Scope, StrName, F, 0, nullptr,477                                                 false, DINode::FlagZero, 0);478  auto getDIExpression = [&DIB](int offset) {479    SmallVector<uint64_t, 4> ops;480    ops.push_back(llvm::dwarf::DW_OP_push_object_address);481    DIExpression::appendOffset(ops, offset);482    ops.push_back(llvm::dwarf::DW_OP_deref);483 484    return DIB.createExpression(ops);485  };486  DIExpression *StringLocationExp = getDIExpression(1);487  DIStringType *StringType =488      DIB.createStringType(StrName, StringLen, StringLocationExp);489 490  EXPECT_TRUE(isa_and_nonnull<DIStringType>(StringType));491  EXPECT_EQ(StringType->getName(), StrName);492  EXPECT_EQ(StringType->getStringLength(), StringLen);493  EXPECT_EQ(StringType->getStringLocationExp(), StringLocationExp);494 495  StringRef StrNameExp = "stringexp";496  DIExpression *StringLengthExp = getDIExpression(2);497  DIStringType *StringTypeExp =498      DIB.createStringType(StrNameExp, StringLengthExp, StringLocationExp);499 500  EXPECT_TRUE(isa_and_nonnull<DIStringType>(StringTypeExp));501  EXPECT_EQ(StringTypeExp->getName(), StrNameExp);502  EXPECT_EQ(StringTypeExp->getStringLocationExp(), StringLocationExp);503  EXPECT_EQ(StringTypeExp->getStringLengthExp(), StringLengthExp);504}505 506TEST(DIBuilder, DIEnumerator) {507  LLVMContext Ctx;508  std::unique_ptr<Module> M(new Module("MyModule", Ctx));509  DIBuilder DIB(*M);510  APSInt I1(APInt(32, 1));511  APSInt I2(APInt(33, 1));512 513  auto *E = DIEnumerator::get(Ctx, I1, I1.isSigned(), "name");514  EXPECT_TRUE(E);515 516  auto *E1 = DIEnumerator::getIfExists(Ctx, I1, I1.isSigned(), "name");517  EXPECT_TRUE(E1);518 519  auto *E2 = DIEnumerator::getIfExists(Ctx, I2, I1.isSigned(), "name");520  EXPECT_FALSE(E2);521}522 523TEST(DIBuilder, FixedPointType) {524  LLVMContext Ctx;525  std::unique_ptr<Module> M(new Module("MyModule", Ctx));526  DIBuilder DIB(*M);527 528  DIFixedPointType *Ty = DIB.createBinaryFixedPointType(529      {}, 32, 0, dwarf::DW_ATE_signed_fixed, DINode::FlagZero, -4);530  EXPECT_TRUE(Ty);531  EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointBinary);532  EXPECT_TRUE(Ty->getFactor() == -4);533  EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_signed_fixed);534  EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);535 536  Ty = DIB.createDecimalFixedPointType({}, 32, 0, dwarf::DW_ATE_unsigned_fixed,537                                       DINode::FlagZero, -7);538  EXPECT_TRUE(Ty);539  EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointDecimal);540  EXPECT_TRUE(Ty->getFactor() == -7);541  EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_unsigned_fixed);542  EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);543 544  APSInt Num(APInt(32, 1));545  APSInt Denom(APInt(33, 72));546  Ty = DIB.createRationalFixedPointType({}, 32, 0, dwarf::DW_ATE_unsigned_fixed,547                                        DINode::FlagZero, Num, Denom);548  EXPECT_TRUE(Ty);549  EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointRational);550  EXPECT_TRUE(Ty->getFactorRaw() == 0);551  EXPECT_TRUE(Ty->getNumerator() == Num);552  EXPECT_TRUE(Ty->getDenominator() == Denom);553  EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_unsigned_fixed);554  EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);555}556 557TEST(DbgAssignRecordTest, replaceVariableLocationOp) {558  LLVMContext C;559  std::unique_ptr<Module> M = parseIR(C, R"(560    define dso_local void @fun(i32 %v1, ptr %p1, ptr %p2) !dbg !7 {561    entry:562        #dbg_assign(i32 %v1, !14, !DIExpression(), !17, ptr %p1, !DIExpression(), !16)563      ret void564    }565 566    !llvm.dbg.cu = !{!0}567    !llvm.module.flags = !{!3}568 569    !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)570    !1 = !DIFile(filename: "test.cpp", directory: "/")571    !3 = !{i32 2, !"Debug Info Version", i32 3}572    !7 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)573    !8 = !DISubroutineType(types: !9)574    !9 = !{null}575    !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)576    !11 = !{}577    !14 = !DILocalVariable(name: "Local", scope: !7, file: !1, line: 3, type: !10)578    !16 = !DILocation(line: 0, scope: !7)579    !17 = distinct !DIAssignID()580    )");581  // Check the test IR isn't malformed.582  ASSERT_TRUE(M);583 584  Function &Fun = *M->getFunction("fun");585  Value *V1 = Fun.getArg(0);586  Value *P1 = Fun.getArg(1);587  Value *P2 = Fun.getArg(2);588  DbgVariableRecord *DbgAssign = cast<DbgVariableRecord>(589      &*Fun.front().front().getDbgRecordRange().begin());590  ASSERT_TRUE(V1 == DbgAssign->getVariableLocationOp(0));591  ASSERT_TRUE(P1 == DbgAssign->getAddress());592 593#define TEST_REPLACE(Old, New, ExpectedValue, ExpectedAddr)                    \594  DbgAssign->replaceVariableLocationOp(Old, New);                              \595  EXPECT_EQ(DbgAssign->getVariableLocationOp(0), ExpectedValue);               \596  EXPECT_EQ(DbgAssign->getAddress(), ExpectedAddr);597 598  // Replace address only.599  TEST_REPLACE(/*Old*/ P1, /*New*/ P2, /*Value*/ V1, /*Address*/ P2);600  // Replace value only.601  TEST_REPLACE(/*Old*/ V1, /*New*/ P2, /*Value*/ P2, /*Address*/ P2);602  // Replace both.603  TEST_REPLACE(/*Old*/ P2, /*New*/ P1, /*Value*/ P1, /*Address*/ P1);604 605  // Replace address only, value uses a DIArgList.606  // Value = {DIArgList(V1)}, Addr = P1.607  DbgAssign->setRawLocation(DIArgList::get(C, ValueAsMetadata::get(V1)));608  DbgAssign->setExpression(DIExpression::get(609      C, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value}));610  TEST_REPLACE(/*Old*/ P1, /*New*/ P2, /*Value*/ V1, /*Address*/ P2);611#undef TEST_REPLACE612}613 614TEST(AssignmentTrackingTest, Utils) {615  // Test the assignment tracking utils defined in DebugInfo.h namespace at {}.616  // This includes:617  //     getAssignmentInsts618  //     getAssignmentMarkers619  //     RAUW620  //     deleteAll621  //622  // The input IR includes two functions, fun1 and fun2. Both contain an alloca623  // with a DIAssignID tag. fun1's alloca is linked to two llvm.dbg.assign624  // intrinsics, one of which is for an inlined variable and appears before the625  // alloca.626 627  LLVMContext C;628  std::unique_ptr<Module> M = parseIR(C, R"(629    define dso_local void @fun1() !dbg !7 {630    entry:631        #dbg_assign(i32 undef, !10, !DIExpression(), !12, i32 undef, !DIExpression(), !13)632      %local = alloca i32, align 4, !DIAssignID !12633        #dbg_assign(i32 undef, !16, !DIExpression(), !12, i32 undef, !DIExpression(), !15)634        #dbg_assign(i32 undef, !16, !DIExpression(), !25, i32 undef, !DIExpression(), !15)635        #dbg_assign(i32 undef, !16, !DIExpression(), !25, i32 undef, !DIExpression(), !15)636      ret void, !dbg !15637    }638 639    define dso_local void @fun2() !dbg !17 {640    entry:641      %local = alloca i32, align 4, !DIAssignID !20642        #dbg_assign(i32 undef, !18, !DIExpression(), !20, i32 undef, !DIExpression(), !19)643      ret void, !dbg !19644    }645 646    define dso_local void @fun3() !dbg !21 {647    entry:648      %local = alloca i32, align 4, !DIAssignID !24649        #dbg_assign(i32 undef, !22, !DIExpression(), !24, i32* undef, !DIExpression(), !23)650      ret void651    }652 653    !llvm.dbg.cu = !{!0}654    !llvm.module.flags = !{!3, !4, !5}655    !llvm.ident = !{!6}656 657    !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)658    !1 = !DIFile(filename: "test.c", directory: "/")659    !2 = !{}660    !3 = !{i32 7, !"Dwarf Version", i32 4}661    !4 = !{i32 2, !"Debug Info Version", i32 3}662    !5 = !{i32 1, !"wchar_size", i32 4}663    !6 = !{!"clang version 14.0.0"}664    !7 = distinct !DISubprogram(name: "fun1", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)665    !8 = !DISubroutineType(types: !9)666    !9 = !{null}667    !10 = !DILocalVariable(name: "local3", scope: !14, file: !1, line: 2, type: !11)668    !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)669    !12 = distinct !DIAssignID()670    !13 = !DILocation(line: 5, column: 1, scope: !14, inlinedAt: !15)671    !14 = distinct !DISubprogram(name: "inline", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)672    !15 = !DILocation(line: 3, column: 1, scope: !7)673    !16 = !DILocalVariable(name: "local1", scope: !7, file: !1, line: 2, type: !11)674    !17 = distinct !DISubprogram(name: "fun2", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)675    !18 = !DILocalVariable(name: "local2", scope: !17, file: !1, line: 2, type: !11)676    !19 = !DILocation(line: 4, column: 1, scope: !17)677    !20 = distinct !DIAssignID()678    !21 = distinct !DISubprogram(name: "fun3", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)679    !22 = !DILocalVariable(name: "local4", scope: !21, file: !1, line: 2, type: !11)680    !23 = !DILocation(line: 4, column: 1, scope: !21)681    !24 = distinct !DIAssignID()682    !25 = distinct !DIAssignID()683    )");684 685  // Check the test IR isn't malformed.686  ASSERT_TRUE(M);687 688  Function &Fun1 = *M->getFunction("fun1");689  Instruction &Alloca = *Fun1.getEntryBlock().getFirstNonPHIOrDbg();690 691  // 1. Check the Instruction <-> Intrinsic mappings work in fun1.692  //693  // Check there are two llvm.dbg.assign intrinsics linked to Alloca.694  auto CheckFun1Mapping = [&Alloca]() {695    auto Markers = at::getDVRAssignmentMarkers(&Alloca);696    EXPECT_TRUE(std::distance(Markers.begin(), Markers.end()) == 2);697    // Check those two entries are distinct.698    DbgVariableRecord *First = *Markers.begin();699    DbgVariableRecord *Second = *std::next(Markers.begin());700    EXPECT_NE(First, Second);701 702    // Check that we can get back to Alloca from each llvm.dbg.assign.703    for (auto *DAI : Markers) {704      auto Insts = at::getAssignmentInsts(DAI);705      // Check there is exactly one instruction linked to each intrinsic. Use706      // ASSERT_TRUE because we're going to dereference the begin iterator.707      ASSERT_TRUE(std::distance(Insts.begin(), Insts.end()) == 1);708      EXPECT_FALSE(Insts.empty());709      // Check the linked instruction is Alloca.710      Instruction *LinkedInst = *Insts.begin();711      EXPECT_EQ(LinkedInst, &Alloca);712    }713  };714  CheckFun1Mapping();715 716  // 2. Check DIAssignID RAUW replaces attachments and uses.717  //718  DIAssignID *Old =719      cast_or_null<DIAssignID>(Alloca.getMetadata(LLVMContext::MD_DIAssignID));720  DIAssignID *New = DIAssignID::getDistinct(C);721  ASSERT_TRUE(Old && New && New != Old);722  at::RAUW(Old, New);723  // Check fun1's alloca and intrinsics have been updated and the mapping still724  // works.725  EXPECT_EQ(New, cast_or_null<DIAssignID>(726                     Alloca.getMetadata(LLVMContext::MD_DIAssignID)));727  CheckFun1Mapping();728 729  // Check that fun2's alloca and intrinsic have not not been updated.730  Instruction &Fun2Alloca =731      *M->getFunction("fun2")->getEntryBlock().getFirstNonPHIOrDbg();732  DIAssignID *Fun2ID = cast_or_null<DIAssignID>(733      Fun2Alloca.getMetadata(LLVMContext::MD_DIAssignID));734  EXPECT_NE(New, Fun2ID);735  auto Fun2Markers = at::getDVRAssignmentMarkers(&Fun2Alloca);736  ASSERT_TRUE(std::distance(Fun2Markers.begin(), Fun2Markers.end()) == 1);737  auto Fun2Insts = at::getAssignmentInsts(*Fun2Markers.begin());738  ASSERT_TRUE(std::distance(Fun2Insts.begin(), Fun2Insts.end()) == 1);739  EXPECT_EQ(*Fun2Insts.begin(), &Fun2Alloca);740 741  // 3. Check that deleting dbg.assigns from a specific instruction works.742  Instruction &Fun3Alloca =743      *M->getFunction("fun3")->getEntryBlock().getFirstNonPHIOrDbg();744  auto Fun3Markers = at::getDVRAssignmentMarkers(&Fun3Alloca);745  ASSERT_TRUE(std::distance(Fun3Markers.begin(), Fun3Markers.end()) == 1);746  at::deleteAssignmentMarkers(&Fun3Alloca);747  Fun3Markers = at::getDVRAssignmentMarkers(&Fun3Alloca);748  EXPECT_EQ(Fun3Markers.empty(), true);749 750  // 4. Check that deleting works and applies only to the target function.751  at::deleteAll(&Fun1);752  // There should now only be the alloca and ret in fun1.753  EXPECT_EQ(Fun1.begin()->size(), 2u);754  // fun2's alloca should have the same DIAssignID and remain linked to its755  // llvm.dbg.assign.756  EXPECT_EQ(Fun2ID, cast_or_null<DIAssignID>(757                        Fun2Alloca.getMetadata(LLVMContext::MD_DIAssignID)));758  EXPECT_FALSE(at::getDVRAssignmentMarkers(&Fun2Alloca).empty());759}760 761TEST(IRBuilder, GetSetInsertionPointWithEmptyBasicBlock) {762  LLVMContext C;763  std::unique_ptr<BasicBlock> BB(BasicBlock::Create(C, "start"));764  Module *M = new Module("module", C);765  IRBuilder<> Builder(BB.get());766  Function *DbgDeclare =767      Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare);768  Value *DIV = MetadataAsValue::get(C, (Metadata *)nullptr);769  SmallVector<Value *, 3> Args = {DIV, DIV, DIV};770  Builder.CreateCall(DbgDeclare, Args);771  auto IP = BB->getFirstInsertionPt();772  Builder.SetInsertPoint(BB.get(), IP);773}774 775TEST(AssignmentTrackingTest, InstrMethods) {776  // Test the assignment tracking Instruction methods.777  // This includes:778  //     Instruction::mergeDIAssignID779 780  LLVMContext C;781  std::unique_ptr<Module> M = parseIR(C, R"(782    define dso_local void @fun() #0 !dbg !8 {783    entry:784      %Local = alloca [2 x i32], align 4, !DIAssignID !12785      call void @llvm.dbg.assign(metadata i1 undef, metadata !13, metadata !DIExpression(), metadata !12, metadata [2 x i32]* %Local, metadata !DIExpression()), !dbg !18786      %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %Local, i64 0, i64 0, !dbg !19787      store i32 5, i32* %arrayidx, align 4, !dbg !20, !DIAssignID !21788      call void @llvm.dbg.assign(metadata i32 5, metadata !13, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !21, metadata i32* %arrayidx, metadata !DIExpression()), !dbg !18789      %arrayidx1 = getelementptr inbounds [2 x i32], [2 x i32]* %Local, i64 0, i64 1, !dbg !22790      store i32 6, i32* %arrayidx1, align 4, !dbg !23, !DIAssignID !24791      call void @llvm.dbg.assign(metadata i32 6, metadata !13, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !24, metadata i32* %arrayidx1, metadata !DIExpression()), !dbg !18792      ret void, !dbg !25793    }794 795    declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #1796 797    !llvm.dbg.cu = !{!0}798    !llvm.module.flags = !{!2, !3, !4, !5, !6}799    !llvm.ident = !{!7}800 801    !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)802    !1 = !DIFile(filename: "test.cpp", directory: "/")803    !2 = !{i32 7, !"Dwarf Version", i32 5}804    !3 = !{i32 2, !"Debug Info Version", i32 3}805    !4 = !{i32 1, !"wchar_size", i32 4}806    !5 = !{i32 7, !"uwtable", i32 1}807    !6 = !{i32 7, !"frame-pointer", i32 2}808    !7 = !{!"clang version 14.0.0"}809    !8 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !11)810    !9 = !DISubroutineType(types: !10)811    !10 = !{null}812    !11 = !{}813    !12 = distinct !DIAssignID()814    !13 = !DILocalVariable(name: "Local", scope: !8, file: !1, line: 2, type: !14)815    !14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 64, elements: !16)816    !15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)817    !16 = !{!17}818    !17 = !DISubrange(count: 2)819    !18 = !DILocation(line: 0, scope: !8)820    !19 = !DILocation(line: 3, column: 3, scope: !8)821    !20 = !DILocation(line: 3, column: 12, scope: !8)822    !21 = distinct !DIAssignID()823    !22 = !DILocation(line: 4, column: 3, scope: !8)824    !23 = !DILocation(line: 4, column: 12, scope: !8)825    !24 = distinct !DIAssignID()826    !25 = !DILocation(line: 5, column: 1, scope: !8)827  )");828 829  // Check the test IR isn't malformed.830  ASSERT_TRUE(M);831  Function &Fun = *M->getFunction("fun");832  SmallVector<Instruction *> Stores;833  for (auto &BB : Fun) {834    for (auto &I : BB) {835      if (isa<StoreInst>(&I))836        Stores.push_back(&I);837    }838  }839 840  // The test requires (at least) 2 stores.841  ASSERT_TRUE(Stores.size() == 2);842  // Use SetVectors to check that the attachments and markers are unique843  // (another test requirement).844  SetVector<Metadata *> OrigIDs;845  SetVector<DbgVariableRecord *> Markers;846  for (const Instruction *SI : Stores) {847    Metadata *ID = SI->getMetadata(LLVMContext::MD_DIAssignID);848    ASSERT_TRUE(OrigIDs.insert(ID));849    ASSERT_TRUE(ID != nullptr);850    auto Range = at::getDVRAssignmentMarkers(SI);851    ASSERT_TRUE(std::distance(Range.begin(), Range.end()) == 1);852    ASSERT_TRUE(Markers.insert(*Range.begin()));853  }854 855  // Test 1 - mergeDIAssignID.856  //857  // Input            store0->mergeDIAssignID(store1)858  // -----            -------------------------859  // store0 !x        store0 !x860  // dbg.assign0 !x   dbg.assign !x861  // store1 !y        store1 !x862  // dbg.assign1 !y   dbg.assign1 !x863  {864    Stores[0]->mergeDIAssignID(Stores[1]);865    // Check that the stores share the same ID.866    Metadata *NewID0 = Stores[0]->getMetadata(LLVMContext::MD_DIAssignID);867    Metadata *NewID1 = Stores[1]->getMetadata(LLVMContext::MD_DIAssignID);868    EXPECT_NE(NewID0, nullptr);869    EXPECT_EQ(NewID0, NewID1);870    EXPECT_EQ(Markers[0]->getAssignID(), NewID0);871    EXPECT_EQ(Markers[1]->getAssignID(), NewID0);872  }873 874  // Test 2 - mergeDIAssignID.875  //876  // Input            store0->mergeDIAssignID(store1)877  // -----            -------------------------878  // store0 !x        store0 !x879  // dbg.assign0 !x   dbg.assign !x880  // store1           store1881  {882    Stores[1]->setMetadata(LLVMContext::MD_DIAssignID, nullptr);883    Stores[0]->mergeDIAssignID(Stores[1]);884    // Check that store1 doesn't get a new ID.885    Metadata *NewID0 = Stores[0]->getMetadata(LLVMContext::MD_DIAssignID);886    Metadata *NewID1 = Stores[1]->getMetadata(LLVMContext::MD_DIAssignID);887    EXPECT_NE(NewID0, nullptr);888    EXPECT_EQ(NewID1, nullptr);889    EXPECT_EQ(Markers[0]->getAssignID(), NewID0);890  }891 892  // Test 3 - mergeDIAssignID.893  //894  // Input            store1->mergeDIAssignID(store0)895  // -----            -------------------------896  // store0 !x        store0 !x897  // dbg.assign0 !x   dbg.assign !x898  // store1           store1 !x899  {900    Stores[1]->setMetadata(LLVMContext::MD_DIAssignID, nullptr);901    Stores[1]->mergeDIAssignID(Stores[0]);902    // Check that the stores share the same ID (note store1 starts with none).903    Metadata *NewID0 = Stores[0]->getMetadata(LLVMContext::MD_DIAssignID);904    Metadata *NewID1 = Stores[1]->getMetadata(LLVMContext::MD_DIAssignID);905    EXPECT_NE(NewID0, nullptr);906    EXPECT_EQ(NewID0, NewID1);907    EXPECT_EQ(Markers[0]->getAssignID(), NewID0);908  }909 910  // Test 4 - mergeDIAssignID.911  //912  // Input            store1->mergeDIAssignID(store0)913  // -----            -------------------------914  // store0 !x        store0 !x915  // dbg.assign0 !x   dbg.assign !x916  // store1 !x        store1 !x917  {918    Stores[0]->mergeDIAssignID(Stores[1]);919    // Check that the stores share the same ID.920    Metadata *NewID0 = Stores[0]->getMetadata(LLVMContext::MD_DIAssignID);921    Metadata *NewID1 = Stores[1]->getMetadata(LLVMContext::MD_DIAssignID);922    EXPECT_NE(NewID0, nullptr);923    EXPECT_EQ(NewID0, NewID1);924    EXPECT_EQ(Markers[0]->getAssignID(), NewID0);925  }926 927  // Test 5 - dropUnknownNonDebugMetadata.928  //929  // Input            store0->dropUnknownNonDebugMetadata()930  // -----            -------------------------931  // store0 !x        store0 !x932  {933    Stores[0]->dropUnknownNonDebugMetadata();934    Metadata *NewID0 = Stores[0]->getMetadata(LLVMContext::MD_DIAssignID);935    EXPECT_NE(NewID0, nullptr);936  }937}938 939// Test some very straight-forward operations on DbgVariableRecords -- these are940// dbg.values that have been converted to a non-instruction format.941TEST(MetadataTest, ConvertDbgToDbgVariableRecord) {942  LLVMContext C;943  std::unique_ptr<Module> M = parseIR(C, R"(944    define i16 @f(i16 %a) !dbg !6 {945      call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11946      %b = add i16 %a, 1, !dbg !11947      call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11948      ret i16 0, !dbg !11949 950    exit:951      %c = add i16 %b, 1, !dbg !11952      ret i16 0, !dbg !11953    }954    declare void @llvm.dbg.value(metadata, metadata, metadata) #0955    attributes #0 = { nounwind readnone speculatable willreturn }956 957    !llvm.dbg.cu = !{!0}958    !llvm.module.flags = !{!5}959 960    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)961    !1 = !DIFile(filename: "t.ll", directory: "/")962    !2 = !{}963    !5 = !{i32 2, !"Debug Info Version", i32 3}964    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)965    !7 = !DISubroutineType(types: !2)966    !8 = !{!9}967    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)968    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)969    !11 = !DILocation(line: 1, column: 1, scope: !6)970)");971 972  // The IR above will be autoupgraded to debug records: but this test is about973  // the conversion routines, so convert it back. This test will have value974  // going forwards for the purpose of testing the conversion routine, which975  // some compatibility tools (DXIL?) wish to use.976  M->convertFromNewDbgValues();977 978  // Find the first dbg.value,979  Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHIIt();980  const DILocalVariable *Var = nullptr;981  const DIExpression *Expr = nullptr;982  const DILocation *Loc = nullptr;983  const Metadata *MLoc = nullptr;984  DbgVariableRecord *DVR1 = nullptr;985  {986    DbgValueInst *DPI = dyn_cast<DbgValueInst>(&I);987    ASSERT_TRUE(DPI);988    Var = DPI->getVariable();989    Expr = DPI->getExpression();990    Loc = DPI->getDebugLoc().get();991    MLoc = DPI->getRawLocation();992 993    // Test the creation of a DbgVariableRecord and it's conversion back to a994    // dbg.value.995    DVR1 = new DbgVariableRecord(DPI);996    EXPECT_EQ(DVR1->getVariable(), Var);997    EXPECT_EQ(DVR1->getExpression(), Expr);998    EXPECT_EQ(DVR1->getDebugLoc().get(), Loc);999    EXPECT_EQ(DVR1->getRawLocation(), MLoc);1000 1001    // Erase dbg.value,1002    DPI->eraseFromParent();1003    // Re-create from DVR1, inserting at front.1004    DVR1->createDebugIntrinsic(&*M,1005                               &M->getFunction("f")->getEntryBlock().front());1006 1007    Instruction *NewDPI = &M->getFunction("f")->getEntryBlock().front();1008    DbgValueInst *DPI2 = dyn_cast<DbgValueInst>(NewDPI);1009    ASSERT_TRUE(DPI2);1010    EXPECT_EQ(DPI2->getVariable(), Var);1011    EXPECT_EQ(DPI2->getExpression(), Expr);1012    EXPECT_EQ(DPI2->getDebugLoc().get(), Loc);1013    EXPECT_EQ(DPI2->getRawLocation(), MLoc);1014  }1015 1016  // Fetch the second dbg.value, convert it to a DbgVariableRecord,1017  BasicBlock::iterator It = M->getFunction("f")->getEntryBlock().begin();1018  It = std::next(std::next(It));1019  DbgValueInst *DPI3 = dyn_cast<DbgValueInst>(It);1020  ASSERT_TRUE(DPI3);1021  DbgVariableRecord *DVR2 = new DbgVariableRecord(DPI3);1022 1023  // These dbg.values are supposed to refer to different values.1024  EXPECT_NE(DVR1->getRawLocation(), DVR2->getRawLocation());1025 1026  // Try manipulating DbgVariableRecords and markers in the exit block.1027  BasicBlock *ExitBlock = &*std::next(M->getFunction("f")->getEntryBlock().getIterator());1028  Instruction *FirstInst = &ExitBlock->front();1029  Instruction *RetInst = &*std::next(FirstInst->getIterator());1030 1031  // Set-up DbgMarkers in this block.1032  ExitBlock->createMarker(FirstInst);1033  ExitBlock->createMarker(RetInst);1034 1035  // Insert DbgRecords into markers, order should come out DVR2, DVR1.1036  FirstInst->DebugMarker->insertDbgRecord(DVR1, false);1037  FirstInst->DebugMarker->insertDbgRecord(DVR2, true);1038  unsigned int ItCount = 0;1039  for (DbgRecord &Item : FirstInst->DebugMarker->getDbgRecordRange()) {1040    EXPECT_TRUE((&Item == DVR2 && ItCount == 0) ||1041                (&Item == DVR1 && ItCount == 1));1042    EXPECT_EQ(Item.getMarker(), FirstInst->DebugMarker);1043    ++ItCount;1044  }1045 1046  // Clone them onto the second marker -- should allocate new DVRs.1047  RetInst->DebugMarker->cloneDebugInfoFrom(FirstInst->DebugMarker, std::nullopt,1048                                           false);1049  EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 2u);1050  ItCount = 0;1051  // Check these things store the same information; but that they're not the same1052  // objects.1053  for (DbgVariableRecord &Item :1054       filterDbgVars(RetInst->DebugMarker->getDbgRecordRange())) {1055    EXPECT_TRUE(1056        (Item.getRawLocation() == DVR2->getRawLocation() && ItCount == 0) ||1057        (Item.getRawLocation() == DVR1->getRawLocation() && ItCount == 1));1058 1059    EXPECT_EQ(Item.getMarker(), RetInst->DebugMarker);1060    EXPECT_NE(&Item, DVR1);1061    EXPECT_NE(&Item, DVR2);1062    ++ItCount;1063  }1064 1065  RetInst->DebugMarker->dropDbgRecords();1066  EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 0u);1067 1068  // Try cloning one single DbgVariableRecord.1069  auto DIIt = std::next(FirstInst->DebugMarker->getDbgRecordRange().begin());1070  RetInst->DebugMarker->cloneDebugInfoFrom(FirstInst->DebugMarker, DIIt, false);1071  EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 1u);1072  // The second DbgVariableRecord should have been cloned; it should have the1073  // same values as DVR1.1074  EXPECT_EQ(1075      cast<DbgVariableRecord>(RetInst->DebugMarker->StoredDbgRecords.begin())1076          ->getRawLocation(),1077      DVR1->getRawLocation());1078  // We should be able to drop individual DbgRecords.1079  RetInst->DebugMarker->dropOneDbgRecord(1080      &*RetInst->DebugMarker->StoredDbgRecords.begin());1081 1082  // "Aborb" a DbgMarker: this means pretend that the instruction it's attached1083  // to is disappearing so it needs to be transferred into "this" marker.1084  RetInst->DebugMarker->absorbDebugValues(*FirstInst->DebugMarker, true);1085  EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 2u);1086  // Should be the DVR1 and DVR2 objects.1087  ItCount = 0;1088  for (DbgRecord &Item : RetInst->DebugMarker->getDbgRecordRange()) {1089    EXPECT_TRUE((&Item == DVR2 && ItCount == 0) ||1090                (&Item == DVR1 && ItCount == 1));1091    EXPECT_EQ(Item.getMarker(), RetInst->DebugMarker);1092    ++ItCount;1093  }1094 1095  // Finally -- there are two DbgVariableRecords left over. If we remove1096  // evrything in the basic block, then they should sink down into the1097  // "TrailingDbgRecords" container for dangling debug-info. Future facilities1098  // will restore them back when a terminator is inserted.1099  FirstInst->DebugMarker->removeMarker();1100  FirstInst->eraseFromParent();1101  RetInst->DebugMarker->removeMarker();1102  RetInst->eraseFromParent();1103 1104  DbgMarker *EndMarker = ExitBlock->getTrailingDbgRecords();1105  ASSERT_NE(EndMarker, nullptr);1106  EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);1107  // Test again that it's those two DbgVariableRecords, DVR1 and DVR2.1108  ItCount = 0;1109  for (DbgRecord &Item : EndMarker->getDbgRecordRange()) {1110    EXPECT_TRUE((&Item == DVR2 && ItCount == 0) ||1111                (&Item == DVR1 && ItCount == 1));1112    EXPECT_EQ(Item.getMarker(), EndMarker);1113    ++ItCount;1114  }1115 1116  // Cleanup the trailing DbgVariableRecord records and marker.1117  EndMarker->eraseFromParent();1118 1119  // The record of those trailing DbgVariableRecords would dangle and cause an1120  // assertion failure if it lived until the end of the LLVMContext.1121  ExitBlock->deleteTrailingDbgRecords();1122}1123 1124TEST(MetadataTest, DbgVariableRecordConversionRoutines) {1125  LLVMContext C;1126 1127  std::unique_ptr<Module> M = parseIR(C, R"(1128    define i16 @f(i16 %a) !dbg !6 {1129      call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !111130      %b = add i16 %a, 1, !dbg !111131      call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !111132      ret i16 0, !dbg !111133 1134    exit:1135      %c = add i16 %b, 1, !dbg !111136      ret i16 0, !dbg !111137    }1138    declare void @llvm.dbg.value(metadata, metadata, metadata) #01139    attributes #0 = { nounwind readnone speculatable willreturn }1140 1141    !llvm.dbg.cu = !{!0}1142    !llvm.module.flags = !{!5}1143 1144    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)1145    !1 = !DIFile(filename: "t.ll", directory: "/")1146    !2 = !{}1147    !5 = !{i32 2, !"Debug Info Version", i32 3}1148    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)1149    !7 = !DISubroutineType(types: !2)1150    !8 = !{!9}1151    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)1152    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)1153    !11 = !DILocation(line: 1, column: 1, scope: !6)1154)");1155 1156  // This test exists to check we can convert back and forth between old and new1157  // debug info formats (dbg.value intrinsics versus #dbg_value records).1158  // We're ripping out support for debug intrinsics, but the conversions will1159  // live on in bitcode autoupgrade and possibly DXIL autodowngrade. Thus, this1160  // test is still valuable. Begin by starting in the intrinsic format:1161  M->convertFromNewDbgValues();1162 1163  Function *F = M->getFunction("f");1164  BasicBlock *BB1 = &F->getEntryBlock();1165  // First instruction should be a dbg.value.1166  EXPECT_TRUE(isa<DbgValueInst>(BB1->front()));1167  // Validating the block for DbgVariableRecords / DbgMarkers shouldn't fail --1168  // there's no data stored right now.1169  bool BrokenDebugInfo = false;1170  bool Error = verifyModule(*M, &errs(), &BrokenDebugInfo);1171  EXPECT_FALSE(Error);1172  EXPECT_FALSE(BrokenDebugInfo);1173 1174  // Now convert.1175  M->convertToNewDbgValues();1176 1177  // There should now be no dbg.value instructions!1178  // Ensure the first instruction exists, the test all of them.1179  EXPECT_FALSE(isa<DbgValueInst>(BB1->front()));1180  for (auto &BB : *F)1181    for (auto &I : BB)1182      EXPECT_FALSE(isa<DbgValueInst>(I));1183 1184  // There should be a DbgMarker on each of the two instructions in the entry1185  // block, each containing one DbgVariableRecord.1186  EXPECT_EQ(BB1->size(), 2u);1187  Instruction *FirstInst = &BB1->front();1188  Instruction *SecondInst = FirstInst->getNextNode();1189  ASSERT_TRUE(FirstInst->DebugMarker);1190  ASSERT_TRUE(SecondInst->DebugMarker);1191  EXPECT_NE(FirstInst->DebugMarker, SecondInst->DebugMarker);1192  EXPECT_EQ(FirstInst, FirstInst->DebugMarker->MarkedInstr);1193  EXPECT_EQ(SecondInst, SecondInst->DebugMarker->MarkedInstr);1194 1195  EXPECT_EQ(FirstInst->DebugMarker->StoredDbgRecords.size(), 1u);1196  DbgVariableRecord *DVR1 = cast<DbgVariableRecord>(1197      &*FirstInst->DebugMarker->getDbgRecordRange().begin());1198  EXPECT_EQ(DVR1->getMarker(), FirstInst->DebugMarker);1199  // Should point at %a, an argument.1200  EXPECT_TRUE(isa<Argument>(DVR1->getVariableLocationOp(0)));1201 1202  EXPECT_EQ(SecondInst->DebugMarker->StoredDbgRecords.size(), 1u);1203  DbgVariableRecord *DVR2 = cast<DbgVariableRecord>(1204      &*SecondInst->DebugMarker->getDbgRecordRange().begin());1205  EXPECT_EQ(DVR2->getMarker(), SecondInst->DebugMarker);1206  // Should point at FirstInst.1207  EXPECT_EQ(DVR2->getVariableLocationOp(0), FirstInst);1208 1209  // There should be no DbgVariableRecords / DbgMarkers in the second block, but1210  // it should be marked as being in the new format.1211  BasicBlock *BB2 = BB1->getNextNode();1212  for (auto &Inst : *BB2)1213    // Either there should be no marker, or it should be empty.1214    EXPECT_TRUE(!Inst.DebugMarker ||1215                Inst.DebugMarker->StoredDbgRecords.empty());1216 1217  // Validating the first block should continue to not be a problem,1218  Error = verifyModule(*M, &errs(), &BrokenDebugInfo);1219  EXPECT_FALSE(Error);1220  EXPECT_FALSE(BrokenDebugInfo);1221  // But if we were to break something, it should be able to fire. Don't attempt1222  // to comprehensively test the validator, it's a smoke-test rather than a1223  // "proper" verification pass.1224  DVR1->setMarker(nullptr);1225  // A marker pointing the wrong way should be an error.1226  Error = verifyModule(*M, &errs(), &BrokenDebugInfo);1227  EXPECT_FALSE(Error);1228  EXPECT_TRUE(BrokenDebugInfo);1229  DVR1->setMarker(FirstInst->DebugMarker);1230 1231  DILocalVariable *DLV1 = DVR1->getVariable();1232  DIExpression *Expr1 = DVR1->getExpression();1233  DILocalVariable *DLV2 = DVR2->getVariable();1234  DIExpression *Expr2 = DVR2->getExpression();1235 1236  // Convert everything back to the "old" format and ensure it's right.1237  M->convertFromNewDbgValues();1238 1239  EXPECT_EQ(BB1->size(), 4u);1240  ASSERT_TRUE(isa<DbgValueInst>(BB1->front()));1241  DbgValueInst *DVI1 = cast<DbgValueInst>(&BB1->front());1242  // These dbg.values should still point at the same places.1243  EXPECT_TRUE(isa<Argument>(DVI1->getVariableLocationOp(0)));1244  DbgValueInst *DVI2 = cast<DbgValueInst>(DVI1->getNextNode()->getNextNode());1245  EXPECT_EQ(DVI2->getVariableLocationOp(0), FirstInst);1246 1247  // Check a few fields too,1248  EXPECT_EQ(DVI1->getVariable(), DLV1);1249  EXPECT_EQ(DVI1->getExpression(), Expr1);1250  EXPECT_EQ(DVI2->getVariable(), DLV2);1251  EXPECT_EQ(DVI2->getExpression(), Expr2);1252}1253 1254TEST(MetadataTest, InlinedAtMethodsWithMultipleLevels) {1255  LLVMContext C;1256 1257  // Create IR with 3 levels of inlining:1258  // main() calls inline1() which calls inline2() which calls inline3()1259  // We'll test from the perspective of code in inline3()1260  std::unique_ptr<Module> M = parseIR(C, R"(1261    define void @main() !dbg !10 {1262      ret void, !dbg !201263    }1264 1265    !llvm.dbg.cu = !{!0}1266    !llvm.module.flags = !{!2}1267 1268    !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)1269    !1 = !DIFile(filename: "test.c", directory: "/test")1270    !2 = !{i32 2, !"Debug Info Version", i32 3}1271 1272    ; Subprograms for each function in the call chain1273    !10 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 100, unit: !0)1274    !11 = distinct !DISubprogram(name: "inline1", scope: !1, file: !1, line: 200, unit: !0)1275    !12 = distinct !DISubprogram(name: "inline2", scope: !1, file: !1, line: 300, unit: !0)1276    !13 = distinct !DISubprogram(name: "inline3", scope: !1, file: !1, line: 400, unit: !0)1277 1278    ; Location in inline3 (line 401), inlined at location !211279    !20 = !DILocation(line: 401, column: 5, scope: !13, inlinedAt: !21)1280 1281    ; Location in inline2 (line 301) where inline3 was called, inlined at !221282    !21 = !DILocation(line: 301, column: 10, scope: !12, inlinedAt: !22)1283 1284    ; Location in inline1 (line 201) where inline2 was called, inlined at !231285    !22 = !DILocation(line: 201, column: 15, scope: !11, inlinedAt: !23)1286 1287    ; Location in main (line 101) where inline1 was called (no more inlinedAt)1288    !23 = !DILocation(line: 101, column: 3, scope: !10)1289  )");1290 1291  ASSERT_TRUE(M);1292 1293  Function *MainFunc = M->getFunction("main");1294  ASSERT_TRUE(MainFunc);1295  Instruction &RetInst = MainFunc->getEntryBlock().front();1296 1297  // Use getDebugLoc() to get the location from the ret instruction.1298  const DILocation *InnermostLoc = RetInst.getDebugLoc().get();1299  ASSERT_TRUE(InnermostLoc);1300 1301  // Test getScope() - should return the immediate scope (inline3).1302  DILocalScope *ImmediateScope = InnermostLoc->getScope();1303  ASSERT_TRUE(ImmediateScope);1304  EXPECT_TRUE(isa<DISubprogram>(ImmediateScope));1305  EXPECT_EQ(cast<DISubprogram>(ImmediateScope)->getName(), "inline3");1306 1307  // Test getInlinedAt() - should return the next level in the inlining chain.1308  const DILocation *NextLevel = InnermostLoc->getInlinedAt();1309  ASSERT_TRUE(NextLevel);1310  EXPECT_EQ(NextLevel->getLine(), 301u);1311  EXPECT_EQ(cast<DISubprogram>(NextLevel->getScope())->getName(), "inline2");1312 1313  // Test getInlinedAtLocation() - should return the outermost location.1314  const DILocation *OutermostLoc = InnermostLoc->getInlinedAtLocation();1315  ASSERT_TRUE(OutermostLoc);1316  EXPECT_EQ(OutermostLoc->getLine(), 101u);1317  EXPECT_EQ(OutermostLoc->getColumn(), 3u);1318  EXPECT_EQ(OutermostLoc->getInlinedAt(), nullptr);1319  EXPECT_EQ(cast<DISubprogram>(OutermostLoc->getScope())->getName(), "main");1320 1321  // Test getInlinedAtScope() - should return the scope of the outermost1322  // location.1323  DILocalScope *InlinedAtScope = InnermostLoc->getInlinedAtScope();1324  ASSERT_TRUE(InlinedAtScope);1325  EXPECT_TRUE(isa<DISubprogram>(InlinedAtScope));1326  EXPECT_EQ(cast<DISubprogram>(InlinedAtScope)->getName(), "main");1327  EXPECT_EQ(InlinedAtScope, OutermostLoc->getScope());1328}1329 1330// Test that the hashing function for DISubprograms representing methods produce1331// the same result after replacing their scope (the type containing the1332// subprogram) from a temporary DIType with the permanent one.1333TEST(DIBuilder, HashingDISubprogram) {1334  LLVMContext Ctx;1335  std::unique_ptr<Module> M = std::make_unique<Module>("MyModule", Ctx);1336  DIBuilder DIB(*M);1337 1338  DIFile *F = DIB.createFile("main.c", "/");1339  DICompileUnit *CU = DIB.createCompileUnit(1340      DISourceLanguageName(dwarf::DW_LANG_C), F, "Test", false, "", 0);1341 1342  llvm::TempDIType ForwardDeclaredType =1343      llvm::TempDIType(DIB.createReplaceableCompositeType(1344          llvm::dwarf::DW_TAG_structure_type, "MyType", CU, F, 0, 0, 8, 8, {},1345          "UniqueIdentifier"));1346 1347  // The hashing function is different for declarations and definitions, so1348  // create one of each.1349  DISubprogram *Declaration =1350      DIB.createMethod(ForwardDeclaredType.get(), "MethodName", "LinkageName",1351                       F, 0, DIB.createSubroutineType({}));1352 1353  DISubprogram *Definition = DIB.createFunction(1354      ForwardDeclaredType.get(), "MethodName", "LinkageName", F, 0,1355      DIB.createSubroutineType({}), 0, DINode::FlagZero,1356      llvm::DISubprogram::SPFlagDefinition, nullptr, Declaration);1357 1358  // Produce the hash with the temporary scope.1359  unsigned HashDeclaration =1360      MDNodeKeyImpl<DISubprogram>(Declaration).getHashValue();1361  unsigned HashDefinition =1362      MDNodeKeyImpl<DISubprogram>(Definition).getHashValue();1363 1364  // Instantiate the real scope and replace the temporary one with it.1365  DICompositeType *Type = DIB.createStructType(CU, "MyType", F, 0, 8, 8, {}, {},1366                                               {}, 0, {}, "UniqueIdentifier");1367  DIB.replaceTemporary(std::move(ForwardDeclaredType), Type);1368 1369  // Now make sure the hashing is consistent.1370  unsigned HashDeclarationAfter =1371      MDNodeKeyImpl<DISubprogram>(Declaration).getHashValue();1372  unsigned HashDefinitionAfter =1373      MDNodeKeyImpl<DISubprogram>(Definition).getHashValue();1374 1375  EXPECT_EQ(HashDeclaration, HashDeclarationAfter);1376  EXPECT_EQ(HashDefinition, HashDefinitionAfter);1377}1378 1379TEST(DIBuilder, CompositeTypes) {1380  LLVMContext Ctx;1381  std::unique_ptr<Module> M = std::make_unique<Module>("MyModule", Ctx);1382  DIBuilder DIB(*M);1383 1384  DIFile *F = DIB.createFile("main.c", "/");1385  DICompileUnit *CU = DIB.createCompileUnit(1386      DISourceLanguageName(dwarf::DW_LANG_C), F, "Test", false, "", 0);1387 1388  DICompositeType *Class =1389      DIB.createClassType(CU, "MyClass", F, 0, 8, 8, 0, {}, nullptr, {}, 0,1390                          nullptr, nullptr, "ClassUniqueIdentifier");1391  EXPECT_EQ(Class->getTag(), dwarf::DW_TAG_class_type);1392 1393  DICompositeType *Struct = DIB.createStructType(1394      CU, "MyStruct", F, 0, 8, 8, {}, {}, {}, 0, {}, "StructUniqueIdentifier");1395  EXPECT_EQ(Struct->getTag(), dwarf::DW_TAG_structure_type);1396 1397  DICompositeType *Union = DIB.createUnionType(CU, "MyUnion", F, 0, 8, 8, {},1398                                               {}, 0, "UnionUniqueIdentifier");1399  EXPECT_EQ(Union->getTag(), dwarf::DW_TAG_union_type);1400 1401  DICompositeType *Array = DIB.createArrayType(8, 8, nullptr, {});1402  EXPECT_EQ(Array->getTag(), dwarf::DW_TAG_array_type);1403 1404  StringRef ArrayNameExp = "AnArray";1405  DICompositeType *NamedArray =1406      DIB.createArrayType(nullptr, ArrayNameExp, nullptr, 0, 8, 8, nullptr, {});1407  EXPECT_EQ(NamedArray->getTag(), dwarf::DW_TAG_array_type);1408  EXPECT_EQ(NamedArray->getName(), ArrayNameExp);1409 1410  DICompositeType *Vector = DIB.createVectorType(8, 8, nullptr, {});1411  EXPECT_EQ(Vector->getTag(), dwarf::DW_TAG_array_type);1412 1413  DICompositeType *Enum = DIB.createEnumerationType(1414      CU, "MyEnum", F, 0, 8, 8, {}, nullptr, 0, "EnumUniqueIdentifier");1415  EXPECT_EQ(Enum->getTag(), dwarf::DW_TAG_enumeration_type);1416}1417 1418TEST(DIBuilder, DynamicOffsetAndSize) {1419  LLVMContext Ctx;1420  auto M = std::make_unique<Module>("MyModule", Ctx);1421  DIBuilder DIB(*M);1422  DIScope *Scope = DISubprogram::getDistinct(1423      Ctx, nullptr, "", "", nullptr, 0, nullptr, 0, nullptr, 0, 0,1424      DINode::FlagZero, DISubprogram::SPFlagZero, nullptr);1425  DIFile *F = DIB.createFile("main.adb", "/");1426 1427  DIVariable *Len = DIB.createAutoVariable(Scope, "length", F, 0, nullptr,1428                                           false, DINode::FlagZero, 0);1429 1430  DICompositeType *Struct = DIB.createStructType(1431      Scope, "some_record", F, 18, Len, 8, DINode::FlagZero, nullptr, {});1432  EXPECT_EQ(Struct->getTag(), dwarf::DW_TAG_structure_type);1433 1434  SmallVector<uint64_t, 4> ops;1435  ops.push_back(llvm::dwarf::DW_OP_push_object_address);1436  DIExpression::appendOffset(ops, 3);1437  ops.push_back(llvm::dwarf::DW_OP_deref);1438  DIExpression *Expr = DIB.createExpression(ops);1439 1440  DIDerivedType *Field = DIB.createMemberType(Scope, "field", F, 23, Len, 0,1441                                              Expr, DINode::FlagZero, Struct);1442 1443  EXPECT_EQ(Field->getRawOffsetInBits(), Expr);1444  EXPECT_EQ(Field->getRawSizeInBits(), Len);1445}1446 1447} // end namespace1448