5488 lines · cpp
1//===- unittests/IR/MetadataTest.cpp - Metadata unit 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/Metadata.h"10#include "../lib/IR/LLVMContextImpl.h"11#include "llvm/ADT/DenseMap.h"12#include "llvm/ADT/STLExtras.h"13#include "llvm/IR/Constants.h"14#include "llvm/IR/DIBuilder.h"15#include "llvm/IR/DebugInfo.h"16#include "llvm/IR/DebugInfoMetadata.h"17#include "llvm/IR/Function.h"18#include "llvm/IR/Instructions.h"19#include "llvm/IR/LLVMContext.h"20#include "llvm/IR/Module.h"21#include "llvm/IR/ModuleSlotTracker.h"22#include "llvm/IR/Type.h"23#include "llvm/IR/Verifier.h"24#include "llvm/Support/Compiler.h"25#include "llvm/Support/raw_ostream.h"26#include "gtest/gtest.h"27#include <optional>28using namespace llvm;29 30namespace llvm {31LLVM_ABI extern cl::opt<bool> PickMergedSourceLocations;32} // namespace llvm33 34namespace {35 36TEST(ContextAndReplaceableUsesTest, FromContext) {37 LLVMContext Context;38 ContextAndReplaceableUses CRU(Context);39 EXPECT_EQ(&Context, &CRU.getContext());40 EXPECT_FALSE(CRU.hasReplaceableUses());41 EXPECT_FALSE(CRU.getReplaceableUses());42}43 44TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {45 LLVMContext Context;46 ContextAndReplaceableUses CRU(std::make_unique<ReplaceableMetadataImpl>(Context));47 EXPECT_EQ(&Context, &CRU.getContext());48 EXPECT_TRUE(CRU.hasReplaceableUses());49 EXPECT_TRUE(CRU.getReplaceableUses());50}51 52TEST(ContextAndReplaceableUsesTest, makeReplaceable) {53 LLVMContext Context;54 ContextAndReplaceableUses CRU(Context);55 CRU.makeReplaceable(std::make_unique<ReplaceableMetadataImpl>(Context));56 EXPECT_EQ(&Context, &CRU.getContext());57 EXPECT_TRUE(CRU.hasReplaceableUses());58 EXPECT_TRUE(CRU.getReplaceableUses());59}60 61TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) {62 LLVMContext Context;63 auto ReplaceableUses = std::make_unique<ReplaceableMetadataImpl>(Context);64 auto *Ptr = ReplaceableUses.get();65 ContextAndReplaceableUses CRU(std::move(ReplaceableUses));66 ReplaceableUses = CRU.takeReplaceableUses();67 EXPECT_EQ(&Context, &CRU.getContext());68 EXPECT_FALSE(CRU.hasReplaceableUses());69 EXPECT_FALSE(CRU.getReplaceableUses());70 EXPECT_EQ(Ptr, ReplaceableUses.get());71}72 73class MetadataTest : public testing::Test {74public:75 MetadataTest() : M("test", Context), Counter(0) {}76 77protected:78 LLVMContext Context;79 Module M;80 int Counter;81 82 MDNode *getNode() { return MDNode::get(Context, {}); }83 MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); }84 MDNode *getNode(Metadata *MD1, Metadata *MD2) {85 Metadata *MDs[] = {MD1, MD2};86 return MDNode::get(Context, MDs);87 }88 89 MDTuple *getTuple() { return MDTuple::getDistinct(Context, {}); }90 DISubroutineType *getSubroutineType() {91 return DISubroutineType::getDistinct(Context, DINode::FlagZero, 0,92 getNode(nullptr));93 }94 DISubprogram *getSubprogram(DIFile *F = nullptr) {95 return DISubprogram::getDistinct(Context, nullptr, "", "", F, 0, nullptr, 0,96 nullptr, 0, 0, DINode::FlagZero,97 DISubprogram::SPFlagZero, nullptr);98 }99 DIFile *getFile() {100 return DIFile::getDistinct(Context, "file.c", "/path/to/dir");101 }102 DICompileUnit *getUnit() {103 return DICompileUnit::getDistinct(104 Context, DISourceLanguageName(1), getFile(), "clang", false, "-g", 2,105 "", DICompileUnit::FullDebug, getTuple(), getTuple(), getTuple(),106 getTuple(), getTuple(), 0, true, false,107 DICompileUnit::DebugNameTableKind::Default, false, "/", "");108 }109 DIType *getBasicType(StringRef Name) {110 return DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, Name);111 }112 DIType *getDerivedType() {113 return DIDerivedType::getDistinct(114 Context, dwarf::DW_TAG_pointer_type, "", nullptr, 0, nullptr,115 getBasicType("basictype"), 1, 2, 0, std::nullopt, {}, DINode::FlagZero);116 }117 Constant *getConstant() {118 return ConstantInt::get(Type::getInt32Ty(Context), Counter++);119 }120 ConstantAsMetadata *getConstantAsMetadata() {121 return ConstantAsMetadata::get(getConstant());122 }123 DIType *getCompositeType() {124 return DICompositeType::getDistinct(Context, dwarf::DW_TAG_structure_type,125 "", nullptr, 0, nullptr, nullptr, 32,126 32, 0, DINode::FlagZero, nullptr, 0,127 std::nullopt, nullptr, nullptr, "");128 }129 Function *getFunction(StringRef Name) {130 return Function::Create(131 FunctionType::get(Type::getVoidTy(Context), {}, false),132 Function::ExternalLinkage, Name, M);133 }134};135typedef MetadataTest MDStringTest;136 137// Test that construction of MDString with different value produces different138// MDString objects, even with the same string pointer and nulls in the string.139TEST_F(MDStringTest, CreateDifferent) {140 char x[3] = { 'f', 0, 'A' };141 MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));142 x[2] = 'B';143 MDString *s2 = MDString::get(Context, StringRef(&x[0], 3));144 EXPECT_NE(s1, s2);145}146 147// Test that creation of MDStrings with the same string contents produces the148// same MDString object, even with different pointers.149TEST_F(MDStringTest, CreateSame) {150 char x[4] = { 'a', 'b', 'c', 'X' };151 char y[4] = { 'a', 'b', 'c', 'Y' };152 153 MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));154 MDString *s2 = MDString::get(Context, StringRef(&y[0], 3));155 EXPECT_EQ(s1, s2);156}157 158// Test that MDString prints out the string we fed it.159TEST_F(MDStringTest, PrintingSimple) {160 char str[14] = "testing 1 2 3";161 MDString *s = MDString::get(Context, StringRef(&str[0], 13));162 strncpy(str, "aaaaaaaaaaaaa", 14);163 164 std::string Str;165 raw_string_ostream oss(Str);166 s->print(oss);167 EXPECT_STREQ("!\"testing 1 2 3\"", Str.c_str());168}169 170// Test printing of MDString with non-printable characters.171TEST_F(MDStringTest, PrintingComplex) {172 char str[5] = {0, '\n', '"', '\\', (char)-1};173 MDString *s = MDString::get(Context, StringRef(str+0, 5));174 std::string Str;175 raw_string_ostream oss(Str);176 s->print(oss);177 EXPECT_STREQ("!\"\\00\\0A\\22\\\\\\FF\"", Str.c_str());178}179 180typedef MetadataTest MDNodeTest;181 182// Test the two constructors, and containing other Constants.183TEST_F(MDNodeTest, Simple) {184 char x[3] = { 'a', 'b', 'c' };185 char y[3] = { '1', '2', '3' };186 187 MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));188 MDString *s2 = MDString::get(Context, StringRef(&y[0], 3));189 ConstantAsMetadata *CI =190 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(8, 0)));191 192 std::vector<Metadata *> V;193 V.push_back(s1);194 V.push_back(CI);195 V.push_back(s2);196 197 MDNode *n1 = MDNode::get(Context, V);198 Metadata *const c1 = n1;199 MDNode *n2 = MDNode::get(Context, c1);200 Metadata *const c2 = n2;201 MDNode *n3 = MDNode::get(Context, V);202 MDNode *n4 = MDNode::getIfExists(Context, V);203 MDNode *n5 = MDNode::getIfExists(Context, c1);204 MDNode *n6 = MDNode::getIfExists(Context, c2);205 EXPECT_NE(n1, n2);206 EXPECT_EQ(n1, n3);207 EXPECT_EQ(n4, n1);208 EXPECT_EQ(n5, n2);209 EXPECT_EQ(n6, (Metadata *)nullptr);210 211 EXPECT_EQ(3u, n1->getNumOperands());212 EXPECT_EQ(s1, n1->getOperand(0));213 EXPECT_EQ(CI, n1->getOperand(1));214 EXPECT_EQ(s2, n1->getOperand(2));215 216 EXPECT_EQ(1u, n2->getNumOperands());217 EXPECT_EQ(n1, n2->getOperand(0));218}219 220TEST_F(MDNodeTest, Delete) {221 Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1);222 Instruction *I = new BitCastInst(C, Type::getInt32Ty(Context));223 224 Metadata *const V = LocalAsMetadata::get(I);225 MDNode *n = MDNode::get(Context, V);226 TrackingMDRef wvh(n);227 228 EXPECT_EQ(n, wvh);229 230 I->deleteValue();231}232 233TEST_F(MDNodeTest, SelfReference) {234 // !0 = !{!0}235 // !1 = !{!0}236 {237 auto Temp = MDNode::getTemporary(Context, {});238 Metadata *Args[] = {Temp.get()};239 MDNode *Self = MDNode::get(Context, Args);240 Self->replaceOperandWith(0, Self);241 ASSERT_EQ(Self, Self->getOperand(0));242 243 // Self-references should be distinct, so MDNode::get() should grab a244 // uniqued node that references Self, not Self.245 Args[0] = Self;246 MDNode *Ref1 = MDNode::get(Context, Args);247 MDNode *Ref2 = MDNode::get(Context, Args);248 EXPECT_NE(Self, Ref1);249 EXPECT_EQ(Ref1, Ref2);250 }251 252 // !0 = !{!0, !{}}253 // !1 = !{!0, !{}}254 {255 auto Temp = MDNode::getTemporary(Context, {});256 Metadata *Args[] = {Temp.get(), MDNode::get(Context, {})};257 MDNode *Self = MDNode::get(Context, Args);258 Self->replaceOperandWith(0, Self);259 ASSERT_EQ(Self, Self->getOperand(0));260 261 // Self-references should be distinct, so MDNode::get() should grab a262 // uniqued node that references Self, not Self itself.263 Args[0] = Self;264 MDNode *Ref1 = MDNode::get(Context, Args);265 MDNode *Ref2 = MDNode::get(Context, Args);266 EXPECT_NE(Self, Ref1);267 EXPECT_EQ(Ref1, Ref2);268 }269}270 271TEST_F(MDNodeTest, Print) {272 Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7);273 MDString *S = MDString::get(Context, "foo");274 MDNode *N0 = getNode();275 MDNode *N1 = getNode(N0);276 MDNode *N2 = getNode(N0, N1);277 278 Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};279 MDNode *N = MDNode::get(Context, Args);280 281 std::string Expected;282 {283 raw_string_ostream OS(Expected);284 OS << "<" << (void *)N << "> = !{";285 C->printAsOperand(OS);286 OS << ", ";287 S->printAsOperand(OS);288 OS << ", null";289 MDNode *Nodes[] = {N0, N1, N2};290 for (auto *Node : Nodes)291 OS << ", <" << (void *)Node << ">";292 OS << "}";293 }294 295 std::string Actual;296 {297 raw_string_ostream OS(Actual);298 N->print(OS);299 }300 301 EXPECT_EQ(Expected, Actual);302}303 304#define EXPECT_PRINTER_EQ(EXPECTED, PRINT) \305 do { \306 std::string Actual_; \307 raw_string_ostream OS(Actual_); \308 PRINT; \309 std::string Expected_(EXPECTED); \310 EXPECT_EQ(Expected_, Actual_); \311 } while (false)312 313TEST_F(MDNodeTest, PrintTemporary) {314 MDNode *Arg = getNode();315 TempMDNode Temp = MDNode::getTemporary(Context, Arg);316 MDNode *N = getNode(Temp.get());317 Module M("test", Context);318 NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");319 NMD->addOperand(N);320 321 EXPECT_PRINTER_EQ("!0 = !{!1}", N->print(OS, &M));322 EXPECT_PRINTER_EQ("!1 = <temporary!> !{!2}", Temp->print(OS, &M));323 EXPECT_PRINTER_EQ("!2 = !{}", Arg->print(OS, &M));324 325 // Cleanup.326 Temp->replaceAllUsesWith(Arg);327}328 329TEST_F(MDNodeTest, PrintFromModule) {330 Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7);331 MDString *S = MDString::get(Context, "foo");332 MDNode *N0 = getNode();333 MDNode *N1 = getNode(N0);334 MDNode *N2 = getNode(N0, N1);335 336 Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};337 MDNode *N = MDNode::get(Context, Args);338 Module M("test", Context);339 NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");340 NMD->addOperand(N);341 342 std::string Expected;343 {344 raw_string_ostream OS(Expected);345 OS << "!0 = !{";346 C->printAsOperand(OS);347 OS << ", ";348 S->printAsOperand(OS);349 OS << ", null, !1, !2, !3}";350 }351 352 EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));353}354 355TEST_F(MDNodeTest, PrintFromFunction) {356 Module M("test", Context);357 auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);358 auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);359 auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);360 auto *BB0 = BasicBlock::Create(Context, "entry", F0);361 auto *BB1 = BasicBlock::Create(Context, "entry", F1);362 auto *R0 = ReturnInst::Create(Context, BB0);363 auto *R1 = ReturnInst::Create(Context, BB1);364 auto *N0 = MDNode::getDistinct(Context, {});365 auto *N1 = MDNode::getDistinct(Context, {});366 R0->setMetadata("md", N0);367 R1->setMetadata("md", N1);368 369 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, &M));370 EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, &M));371 372 ModuleSlotTracker MST(&M);373 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, MST));374 EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, MST));375}376 377TEST_F(MDNodeTest, PrintFromMetadataAsValue) {378 Module M("test", Context);379 380 auto *Intrinsic =381 Function::Create(FunctionType::get(Type::getVoidTy(Context),382 Type::getMetadataTy(Context), false),383 GlobalValue::ExternalLinkage, "llvm.intrinsic", &M);384 385 auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);386 auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);387 auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);388 auto *BB0 = BasicBlock::Create(Context, "entry", F0);389 auto *BB1 = BasicBlock::Create(Context, "entry", F1);390 auto *N0 = MDNode::getDistinct(Context, {});391 auto *N1 = MDNode::getDistinct(Context, {});392 auto *MAV0 = MetadataAsValue::get(Context, N0);393 auto *MAV1 = MetadataAsValue::get(Context, N1);394 CallInst::Create(Intrinsic, MAV0, "", BB0);395 CallInst::Create(Intrinsic, MAV1, "", BB1);396 397 EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS));398 EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS));399 EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false));400 EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false));401 EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true));402 EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true));403 404 ModuleSlotTracker MST(&M);405 EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS, MST));406 EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS, MST));407 EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false, MST));408 EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false, MST));409 EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true, MST));410 EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true, MST));411}412 413TEST_F(MDNodeTest, PrintWithDroppedCallOperand) {414 Module M("test", Context);415 416 auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);417 auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);418 auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);419 auto *BB0 = BasicBlock::Create(Context, "entry", F0);420 421 CallInst *CI0 = CallInst::Create(F1, "", BB0);422 CI0->dropAllReferences();423 424 auto *R0 = ReturnInst::Create(Context, BB0);425 auto *N0 = MDNode::getDistinct(Context, {});426 R0->setMetadata("md", N0);427 428 // Printing the metadata node would previously result in a failed assertion429 // due to the call instruction's dropped function operand.430 ModuleSlotTracker MST(&M);431 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, MST));432}433 434TEST_F(MDNodeTest, PrintTree) {435 DILocalScope *Scope = getSubprogram();436 DIFile *File = getFile();437 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);438 {439 DIType *Type = getDerivedType();440 auto *Var = DILocalVariable::get(Context, Scope, "foo", File,441 /*LineNo=*/8, Type, /*ArgNo=*/2, Flags,442 /*Align=*/8, nullptr);443 std::string Expected;444 {445 raw_string_ostream SS(Expected);446 Var->print(SS);447 // indent level 1448 Scope->print((SS << "\n").indent(2));449 File->print((SS << "\n").indent(2));450 Type->print((SS << "\n").indent(2));451 // indent level 2452 auto *BaseType = cast<DIDerivedType>(Type)->getBaseType();453 BaseType->print((SS << "\n").indent(4));454 }455 456 EXPECT_PRINTER_EQ(Expected, Var->printTree(OS));457 }458 459 {460 // Test if printTree works correctly when there is461 // a cycle in the MDNode and its dependencies.462 //463 // We're trying to create type like this:464 // struct LinkedList {465 // LinkedList *Head;466 // };467 auto *StructTy = cast<DICompositeType>(getCompositeType());468 DIType *PointerTy = DIDerivedType::getDistinct(469 Context, dwarf::DW_TAG_pointer_type, "", nullptr, 0, nullptr, StructTy,470 1, 2, 0, std::nullopt, {}, DINode::FlagZero);471 StructTy->replaceElements(MDTuple::get(Context, PointerTy));472 473 auto *Var = DILocalVariable::get(Context, Scope, "foo", File,474 /*LineNo=*/8, StructTy, /*ArgNo=*/2, Flags,475 /*Align=*/8, nullptr);476 std::string Expected;477 {478 raw_string_ostream SS(Expected);479 Var->print(SS);480 // indent level 1481 Scope->print((SS << "\n").indent(2));482 File->print((SS << "\n").indent(2));483 StructTy->print((SS << "\n").indent(2));484 // indent level 2485 StructTy->getRawElements()->print((SS << "\n").indent(4));486 // indent level 3487 auto Elements = StructTy->getElements();488 Elements[0]->print((SS << "\n").indent(6));489 }490 491 EXPECT_PRINTER_EQ(Expected, Var->printTree(OS));492 }493}494#undef EXPECT_PRINTER_EQ495 496TEST_F(MDNodeTest, NullOperand) {497 // metadata !{}498 MDNode *Empty = MDNode::get(Context, {});499 500 // metadata !{metadata !{}}501 Metadata *Ops[] = {Empty};502 MDNode *N = MDNode::get(Context, Ops);503 ASSERT_EQ(Empty, N->getOperand(0));504 505 // metadata !{metadata !{}} => metadata !{null}506 N->replaceOperandWith(0, nullptr);507 ASSERT_EQ(nullptr, N->getOperand(0));508 509 // metadata !{null}510 Ops[0] = nullptr;511 MDNode *NullOp = MDNode::get(Context, Ops);512 ASSERT_EQ(nullptr, NullOp->getOperand(0));513 EXPECT_EQ(N, NullOp);514}515 516TEST_F(MDNodeTest, DistinctOnUniquingCollision) {517 // !{}518 MDNode *Empty = MDNode::get(Context, {});519 ASSERT_TRUE(Empty->isResolved());520 EXPECT_FALSE(Empty->isDistinct());521 522 // !{!{}}523 Metadata *Wrapped1Ops[] = {Empty};524 MDNode *Wrapped1 = MDNode::get(Context, Wrapped1Ops);525 ASSERT_EQ(Empty, Wrapped1->getOperand(0));526 ASSERT_TRUE(Wrapped1->isResolved());527 EXPECT_FALSE(Wrapped1->isDistinct());528 529 // !{!{!{}}}530 Metadata *Wrapped2Ops[] = {Wrapped1};531 MDNode *Wrapped2 = MDNode::get(Context, Wrapped2Ops);532 ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0));533 ASSERT_TRUE(Wrapped2->isResolved());534 EXPECT_FALSE(Wrapped2->isDistinct());535 536 // !{!{!{}}} => !{!{}}537 Wrapped2->replaceOperandWith(0, Empty);538 ASSERT_EQ(Empty, Wrapped2->getOperand(0));539 EXPECT_TRUE(Wrapped2->isDistinct());540 EXPECT_FALSE(Wrapped1->isDistinct());541}542 543TEST_F(MDNodeTest, UniquedOnDeletedOperand) {544 // temp !{}545 TempMDTuple T = MDTuple::getTemporary(Context, {});546 547 // !{temp !{}}548 Metadata *Ops[] = {T.get()};549 MDTuple *N = MDTuple::get(Context, Ops);550 551 // !{temp !{}} => !{null}552 T.reset();553 ASSERT_TRUE(N->isUniqued());554 Metadata *NullOps[] = {nullptr};555 ASSERT_EQ(N, MDTuple::get(Context, NullOps));556}557 558TEST_F(MDNodeTest, DistinctOnDeletedValueOperand) {559 // i1* @GV560 Type *Ty = PointerType::getUnqual(Context);561 std::unique_ptr<GlobalVariable> GV(562 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));563 ConstantAsMetadata *Op = ConstantAsMetadata::get(GV.get());564 565 // !{i1* @GV}566 Metadata *Ops[] = {Op};567 MDTuple *N = MDTuple::get(Context, Ops);568 569 // !{i1* @GV} => !{null}570 GV.reset();571 ASSERT_TRUE(N->isDistinct());572 ASSERT_EQ(nullptr, N->getOperand(0));573 Metadata *NullOps[] = {nullptr};574 ASSERT_NE(N, MDTuple::get(Context, NullOps));575}576 577TEST_F(MDNodeTest, getDistinct) {578 // !{}579 MDNode *Empty = MDNode::get(Context, {});580 ASSERT_TRUE(Empty->isResolved());581 ASSERT_FALSE(Empty->isDistinct());582 ASSERT_EQ(Empty, MDNode::get(Context, {}));583 584 // distinct !{}585 MDNode *Distinct1 = MDNode::getDistinct(Context, {});586 MDNode *Distinct2 = MDNode::getDistinct(Context, {});587 EXPECT_TRUE(Distinct1->isResolved());588 EXPECT_TRUE(Distinct2->isDistinct());589 EXPECT_NE(Empty, Distinct1);590 EXPECT_NE(Empty, Distinct2);591 EXPECT_NE(Distinct1, Distinct2);592 593 // !{}594 ASSERT_EQ(Empty, MDNode::get(Context, {}));595}596 597TEST_F(MDNodeTest, isUniqued) {598 MDNode *U = MDTuple::get(Context, {});599 MDNode *D = MDTuple::getDistinct(Context, {});600 auto T = MDTuple::getTemporary(Context, {});601 EXPECT_TRUE(U->isUniqued());602 EXPECT_FALSE(D->isUniqued());603 EXPECT_FALSE(T->isUniqued());604}605 606TEST_F(MDNodeTest, isDistinct) {607 MDNode *U = MDTuple::get(Context, {});608 MDNode *D = MDTuple::getDistinct(Context, {});609 auto T = MDTuple::getTemporary(Context, {});610 EXPECT_FALSE(U->isDistinct());611 EXPECT_TRUE(D->isDistinct());612 EXPECT_FALSE(T->isDistinct());613}614 615TEST_F(MDNodeTest, isTemporary) {616 MDNode *U = MDTuple::get(Context, {});617 MDNode *D = MDTuple::getDistinct(Context, {});618 auto T = MDTuple::getTemporary(Context, {});619 EXPECT_FALSE(U->isTemporary());620 EXPECT_FALSE(D->isTemporary());621 EXPECT_TRUE(T->isTemporary());622}623 624TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {625 // temporary !{}626 auto Temp = MDTuple::getTemporary(Context, {});627 ASSERT_FALSE(Temp->isResolved());628 629 // distinct !{temporary !{}}630 Metadata *Ops[] = {Temp.get()};631 MDNode *Distinct = MDNode::getDistinct(Context, Ops);632 EXPECT_TRUE(Distinct->isResolved());633 EXPECT_EQ(Temp.get(), Distinct->getOperand(0));634 635 // temporary !{} => !{}636 MDNode *Empty = MDNode::get(Context, {});637 Temp->replaceAllUsesWith(Empty);638 EXPECT_EQ(Empty, Distinct->getOperand(0));639}640 641TEST_F(MDNodeTest, handleChangedOperandRecursion) {642 // !0 = !{}643 MDNode *N0 = MDNode::get(Context, {});644 645 // !1 = !{!3, null}646 auto Temp3 = MDTuple::getTemporary(Context, {});647 Metadata *Ops1[] = {Temp3.get(), nullptr};648 MDNode *N1 = MDNode::get(Context, Ops1);649 650 // !2 = !{!3, !0}651 Metadata *Ops2[] = {Temp3.get(), N0};652 MDNode *N2 = MDNode::get(Context, Ops2);653 654 // !3 = !{!2}655 Metadata *Ops3[] = {N2};656 MDNode *N3 = MDNode::get(Context, Ops3);657 Temp3->replaceAllUsesWith(N3);658 659 // !4 = !{!1}660 Metadata *Ops4[] = {N1};661 MDNode *N4 = MDNode::get(Context, Ops4);662 663 // Confirm that the cycle prevented RAUW from getting dropped.664 EXPECT_TRUE(N0->isResolved());665 EXPECT_FALSE(N1->isResolved());666 EXPECT_FALSE(N2->isResolved());667 EXPECT_FALSE(N3->isResolved());668 EXPECT_FALSE(N4->isResolved());669 670 // Create a couple of distinct nodes to observe what's going on.671 //672 // !5 = distinct !{!2}673 // !6 = distinct !{!3}674 Metadata *Ops5[] = {N2};675 MDNode *N5 = MDNode::getDistinct(Context, Ops5);676 Metadata *Ops6[] = {N3};677 MDNode *N6 = MDNode::getDistinct(Context, Ops6);678 679 // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW).680 // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2681 // references !3, this can cause a re-entry of handleChangedOperand() when !3682 // is not ready for it.683 //684 // !2->replaceOperandWith(1, nullptr)685 // !2: !{!3, !0} => !{!3, null}686 // !2->replaceAllUsesWith(!1)687 // !3: !{!2] => !{!1}688 // !3->replaceAllUsesWith(!4)689 N2->replaceOperandWith(1, nullptr);690 691 // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from692 // under us. Just check that the other nodes are sane.693 //694 // !1 = !{!4, null}695 // !4 = !{!1}696 // !5 = distinct !{!1}697 // !6 = distinct !{!4}698 EXPECT_EQ(N4, N1->getOperand(0));699 EXPECT_EQ(N1, N4->getOperand(0));700 EXPECT_EQ(N1, N5->getOperand(0));701 EXPECT_EQ(N4, N6->getOperand(0));702}703 704TEST_F(MDNodeTest, replaceResolvedOperand) {705 // Check code for replacing one resolved operand with another. If doing this706 // directly (via replaceOperandWith()) becomes illegal, change the operand to707 // a global value that gets RAUW'ed.708 //709 // Use a temporary node to keep N from being resolved.710 auto Temp = MDTuple::getTemporary(Context, {});711 Metadata *Ops[] = {nullptr, Temp.get()};712 713 MDNode *Empty = MDTuple::get(Context, ArrayRef<Metadata *>());714 MDNode *N = MDTuple::get(Context, Ops);715 EXPECT_EQ(nullptr, N->getOperand(0));716 ASSERT_FALSE(N->isResolved());717 718 // Check code for replacing resolved nodes.719 N->replaceOperandWith(0, Empty);720 EXPECT_EQ(Empty, N->getOperand(0));721 722 // Check code for adding another unresolved operand.723 N->replaceOperandWith(0, Temp.get());724 EXPECT_EQ(Temp.get(), N->getOperand(0));725 726 // Remove the references to Temp; required for teardown.727 Temp->replaceAllUsesWith(nullptr);728}729 730TEST_F(MDNodeTest, replaceWithUniqued) {731 auto *Empty = MDTuple::get(Context, {});732 MDTuple *FirstUniqued;733 {734 Metadata *Ops[] = {Empty};735 auto Temp = MDTuple::getTemporary(Context, Ops);736 EXPECT_TRUE(Temp->isTemporary());737 738 // Don't expect a collision.739 auto *Current = Temp.get();740 FirstUniqued = MDNode::replaceWithUniqued(std::move(Temp));741 EXPECT_TRUE(FirstUniqued->isUniqued());742 EXPECT_TRUE(FirstUniqued->isResolved());743 EXPECT_EQ(Current, FirstUniqued);744 }745 {746 Metadata *Ops[] = {Empty};747 auto Temp = MDTuple::getTemporary(Context, Ops);748 EXPECT_TRUE(Temp->isTemporary());749 750 // Should collide with Uniqued above this time.751 auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));752 EXPECT_TRUE(Uniqued->isUniqued());753 EXPECT_TRUE(Uniqued->isResolved());754 EXPECT_EQ(FirstUniqued, Uniqued);755 }756 {757 auto Unresolved = MDTuple::getTemporary(Context, {});758 Metadata *Ops[] = {Unresolved.get()};759 auto Temp = MDTuple::getTemporary(Context, Ops);760 EXPECT_TRUE(Temp->isTemporary());761 762 // Shouldn't be resolved.763 auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));764 EXPECT_TRUE(Uniqued->isUniqued());765 EXPECT_FALSE(Uniqued->isResolved());766 767 // Should be a different node.768 EXPECT_NE(FirstUniqued, Uniqued);769 770 // Should resolve when we update its node (note: be careful to avoid a771 // collision with any other nodes above).772 Uniqued->replaceOperandWith(0, nullptr);773 EXPECT_TRUE(Uniqued->isResolved());774 }775}776 777TEST_F(MDNodeTest, replaceWithUniquedResolvingOperand) {778 // temp !{}779 MDTuple *Op = MDTuple::getTemporary(Context, {}).release();780 EXPECT_FALSE(Op->isResolved());781 782 // temp !{temp !{}}783 Metadata *Ops[] = {Op};784 MDTuple *N = MDTuple::getTemporary(Context, Ops).release();785 EXPECT_FALSE(N->isResolved());786 787 // temp !{temp !{}} => !{temp !{}}788 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));789 EXPECT_FALSE(N->isResolved());790 791 // !{temp !{}} => !{!{}}792 ASSERT_EQ(Op, MDNode::replaceWithUniqued(TempMDTuple(Op)));793 EXPECT_TRUE(Op->isResolved());794 EXPECT_TRUE(N->isResolved());795}796 797TEST_F(MDNodeTest, replaceWithUniquedDeletedOperand) {798 // i1* @GV799 Type *Ty = PointerType::getUnqual(Context);800 std::unique_ptr<GlobalVariable> GV(801 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));802 ConstantAsMetadata *Op = ConstantAsMetadata::get(GV.get());803 804 // temp !{i1* @GV}805 Metadata *Ops[] = {Op};806 MDTuple *N = MDTuple::getTemporary(Context, Ops).release();807 808 // temp !{i1* @GV} => !{i1* @GV}809 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));810 ASSERT_TRUE(N->isUniqued());811 812 // !{i1* @GV} => !{null}813 GV.reset();814 ASSERT_TRUE(N->isDistinct());815 ASSERT_EQ(nullptr, N->getOperand(0));816 Metadata *NullOps[] = {nullptr};817 ASSERT_NE(N, MDTuple::get(Context, NullOps));818}819 820TEST_F(MDNodeTest, replaceWithUniquedChangedOperand) {821 // i1* @GV822 Type *Ty = PointerType::getUnqual(Context);823 std::unique_ptr<GlobalVariable> GV(824 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));825 ConstantAsMetadata *Op = ConstantAsMetadata::get(GV.get());826 827 // temp !{i1* @GV}828 Metadata *Ops[] = {Op};829 MDTuple *N = MDTuple::getTemporary(Context, Ops).release();830 831 // temp !{i1* @GV} => !{i1* @GV}832 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));833 ASSERT_TRUE(N->isUniqued());834 835 // !{i1* @GV} => !{i1* @GV2}836 std::unique_ptr<GlobalVariable> GV2(837 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));838 GV->replaceAllUsesWith(GV2.get());839 ASSERT_TRUE(N->isUniqued());840 Metadata *NullOps[] = {ConstantAsMetadata::get(GV2.get())};841 ASSERT_EQ(N, MDTuple::get(Context, NullOps));842}843 844TEST_F(MDNodeTest, replaceWithDistinct) {845 {846 auto *Empty = MDTuple::get(Context, {});847 Metadata *Ops[] = {Empty};848 auto Temp = MDTuple::getTemporary(Context, Ops);849 EXPECT_TRUE(Temp->isTemporary());850 851 // Don't expect a collision.852 auto *Current = Temp.get();853 auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));854 EXPECT_TRUE(Distinct->isDistinct());855 EXPECT_TRUE(Distinct->isResolved());856 EXPECT_EQ(Current, Distinct);857 }858 {859 auto Unresolved = MDTuple::getTemporary(Context, {});860 Metadata *Ops[] = {Unresolved.get()};861 auto Temp = MDTuple::getTemporary(Context, Ops);862 EXPECT_TRUE(Temp->isTemporary());863 864 // Don't expect a collision.865 auto *Current = Temp.get();866 auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));867 EXPECT_TRUE(Distinct->isDistinct());868 EXPECT_TRUE(Distinct->isResolved());869 EXPECT_EQ(Current, Distinct);870 871 // Cleanup; required for teardown.872 Unresolved->replaceAllUsesWith(nullptr);873 }874}875 876TEST_F(MDNodeTest, replaceWithPermanent) {877 Metadata *Ops[] = {nullptr};878 auto Temp = MDTuple::getTemporary(Context, Ops);879 auto *T = Temp.get();880 881 // U is a normal, uniqued node that references T.882 auto *U = MDTuple::get(Context, T);883 EXPECT_TRUE(U->isUniqued());884 885 // Make Temp self-referencing.886 Temp->replaceOperandWith(0, T);887 888 // Try to uniquify Temp. This should, despite the name in the API, give a889 // 'distinct' node, since self-references aren't allowed to be uniqued.890 //891 // Since it's distinct, N should have the same address as when it was a892 // temporary (i.e., be equal to T not U).893 auto *N = MDNode::replaceWithPermanent(std::move(Temp));894 EXPECT_EQ(N, T);895 EXPECT_TRUE(N->isDistinct());896 897 // U should be the canonical unique node with N as the argument.898 EXPECT_EQ(U, MDTuple::get(Context, N));899 EXPECT_TRUE(U->isUniqued());900 901 // This temporary should collide with U when replaced, but it should still be902 // uniqued.903 EXPECT_EQ(U, MDNode::replaceWithPermanent(MDTuple::getTemporary(Context, N)));904 EXPECT_TRUE(U->isUniqued());905 906 // This temporary should become a new uniqued node.907 auto Temp2 = MDTuple::getTemporary(Context, U);908 auto *V = Temp2.get();909 EXPECT_EQ(V, MDNode::replaceWithPermanent(std::move(Temp2)));910 EXPECT_TRUE(V->isUniqued());911 EXPECT_EQ(U, V->getOperand(0));912}913 914TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) {915 TrackingMDRef Ref;916 EXPECT_EQ(nullptr, Ref.get());917 {918 auto Temp = MDTuple::getTemporary(Context, {});919 Ref.reset(Temp.get());920 EXPECT_EQ(Temp.get(), Ref.get());921 }922 EXPECT_EQ(nullptr, Ref.get());923}924 925typedef MetadataTest DILocationTest;926 927TEST_F(DILocationTest, Merge) {928 DIFile *F = getFile();929 DISubprogram *N = getSubprogram(F);930 DIScope *S = DILexicalBlock::get(Context, N, F, 3, 4);931 932 {933 // Identical.934 auto *A = DILocation::get(Context, 2, 7, N);935 auto *B = DILocation::get(Context, 2, 7, N);936 auto *M = DILocation::getMergedLocation(A, B);937 EXPECT_EQ(2u, M->getLine());938 EXPECT_EQ(7u, M->getColumn());939 EXPECT_EQ(N, M->getScope());940 }941 942 {943 // Identical, inside DILexicalBlockFile.944 auto *OtherF = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");945 auto *LBF = DILexicalBlockFile::get(Context, S, OtherF, 0);946 auto *A = DILocation::get(Context, 2, 7, LBF);947 auto *B = DILocation::get(Context, 2, 7, LBF);948 auto *M = DILocation::getMergedLocation(A, B);949 EXPECT_EQ(2u, M->getLine());950 EXPECT_EQ(7u, M->getColumn());951 EXPECT_EQ(LBF, M->getScope());952 }953 954 {955 // Identical, different scopes.956 auto *A = DILocation::get(Context, 2, 7, N);957 auto *B = DILocation::get(Context, 2, 7, S);958 auto *M = DILocation::getMergedLocation(A, B);959 EXPECT_EQ(2u, M->getLine());960 EXPECT_EQ(7u, M->getColumn());961 EXPECT_EQ(N, M->getScope());962 }963 964 {965 // Same line, different column.966 auto *A = DILocation::get(Context, 2, 7, N);967 auto *B = DILocation::get(Context, 2, 10, S);968 auto *M0 = DILocation::getMergedLocation(A, B);969 auto *M1 = DILocation::getMergedLocation(B, A);970 for (auto *M : {M0, M1}) {971 EXPECT_EQ(2u, M->getLine());972 EXPECT_EQ(0u, M->getColumn());973 EXPECT_EQ(N, M->getScope());974 }975 }976 977 {978 // Same line, different column, same DILexicalBlockFile scope.979 auto *OtherF = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");980 auto *LBF = DILexicalBlockFile::get(Context, S, OtherF, 0);981 auto *A = DILocation::get(Context, 2, 7, LBF);982 auto *B = DILocation::get(Context, 2, 10, LBF);983 auto *M0 = DILocation::getMergedLocation(A, B);984 auto *M1 = DILocation::getMergedLocation(B, A);985 for (auto *M : {M0, M1}) {986 EXPECT_EQ(2u, M->getLine());987 EXPECT_EQ(0u, M->getColumn());988 EXPECT_EQ(LBF, M->getScope());989 }990 }991 992 {993 // Different lines, same DISubprogram scopes.994 auto *A = DILocation::get(Context, 1, 6, N);995 auto *B = DILocation::get(Context, 2, 7, N);996 auto *M = DILocation::getMergedLocation(A, B);997 EXPECT_EQ(0u, M->getLine());998 EXPECT_EQ(0u, M->getColumn());999 EXPECT_EQ(N, M->getScope());1000 }1001 1002 {1003 // Different lines, same DILexicalBlockFile scopes.1004 auto *OtherF = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1005 auto *LBF = DILexicalBlockFile::get(Context, S, OtherF, 0);1006 auto *A = DILocation::get(Context, 1, 6, LBF);1007 auto *B = DILocation::get(Context, 2, 7, LBF);1008 auto *M = DILocation::getMergedLocation(A, B);1009 EXPECT_EQ(0u, M->getLine());1010 EXPECT_EQ(0u, M->getColumn());1011 EXPECT_EQ(LBF, M->getScope());1012 }1013 1014 {1015 // Different lines, same DILexicalBlock scopes.1016 auto *A = DILocation::get(Context, 1, 6, S);1017 auto *B = DILocation::get(Context, 2, 7, S);1018 auto *M = DILocation::getMergedLocation(A, B);1019 EXPECT_EQ(0u, M->getLine());1020 EXPECT_EQ(0u, M->getColumn());1021 EXPECT_EQ(S, M->getScope());1022 }1023 1024 {1025 // Twisty locations, all different, same function.1026 auto *A = DILocation::get(Context, 1, 6, N);1027 auto *B = DILocation::get(Context, 2, 7, S);1028 auto *M = DILocation::getMergedLocation(A, B);1029 EXPECT_EQ(0u, M->getLine());1030 EXPECT_EQ(0u, M->getColumn());1031 EXPECT_EQ(N, M->getScope());1032 }1033 1034 {1035 // Different files, same line numbers, same subprogram.1036 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1037 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1038 DISubprogram *N = getSubprogram(F1);1039 auto *LBF = DILexicalBlockFile::get(Context, N, F2, 0);1040 auto *A = DILocation::get(Context, 1, 6, N);1041 auto *B = DILocation::get(Context, 1, 6, LBF);1042 auto *M = DILocation::getMergedLocation(A, B);1043 EXPECT_EQ(0u, M->getLine());1044 EXPECT_EQ(0u, M->getColumn());1045 EXPECT_EQ(N, M->getScope());1046 }1047 1048 {1049 // Different files, same line numbers.1050 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1051 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1052 DISubprogram *N = getSubprogram(F1);1053 auto *LB = DILexicalBlock::getDistinct(Context, N, F1, 4, 9);1054 auto *LBF = DILexicalBlockFile::get(Context, LB, F2, 0);1055 auto *A = DILocation::get(Context, 1, 6, LB);1056 auto *B = DILocation::get(Context, 1, 6, LBF);1057 auto *M = DILocation::getMergedLocation(A, B);1058 EXPECT_EQ(4u, M->getLine());1059 EXPECT_EQ(9u, M->getColumn());1060 EXPECT_EQ(LB, M->getScope());1061 }1062 1063 {1064 // Different files, same line numbers,1065 // both locations have DILexicalBlockFile scopes.1066 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1067 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1068 auto *F3 = DIFile::getDistinct(Context, "file3.c", "/path/to/dir");1069 DISubprogram *N = getSubprogram(F1);1070 auto *LB = DILexicalBlock::getDistinct(Context, N, F1, 4, 9);1071 auto *LBF1 = DILexicalBlockFile::get(Context, LB, F2, 0);1072 auto *LBF2 = DILexicalBlockFile::get(Context, LB, F3, 0);1073 auto *A = DILocation::get(Context, 1, 6, LBF1);1074 auto *B = DILocation::get(Context, 1, 6, LBF2);1075 auto *M = DILocation::getMergedLocation(A, B);1076 EXPECT_EQ(4u, M->getLine());1077 EXPECT_EQ(9u, M->getColumn());1078 EXPECT_EQ(LB, M->getScope());1079 }1080 1081 {1082 // Same file, same line numbers, but different LBF objects.1083 // both locations have DILexicalBlockFile scope.1084 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1085 DISubprogram *N = getSubprogram(F1);1086 auto *LB1 = DILexicalBlock::getDistinct(Context, N, F1, 4, 9);1087 auto *LB2 = DILexicalBlock::getDistinct(Context, N, F1, 5, 9);1088 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1089 auto *LBF1 = DILexicalBlockFile::get(Context, LB1, F2, 0);1090 auto *LBF2 = DILexicalBlockFile::get(Context, LB2, F2, 0);1091 auto *A = DILocation::get(Context, 1, 6, LBF1);1092 auto *B = DILocation::get(Context, 1, 6, LBF2);1093 auto *M = DILocation::getMergedLocation(A, B);1094 EXPECT_EQ(1u, M->getLine());1095 EXPECT_EQ(6u, M->getColumn());1096 EXPECT_EQ(LBF1->getFile(), M->getScope()->getFile());1097 EXPECT_EQ(N, M->getScope()->getScope());1098 }1099 1100 {1101 // Merge locations A and B, where B is included in A's file1102 // at the same position as A's position.1103 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1104 DISubprogram *N = getSubprogram(F1);1105 auto *LB = DILexicalBlock::getDistinct(Context, N, F1, 4, 9);1106 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1107 auto *LBF = DILexicalBlockFile::get(Context, LB, F2, 0);1108 auto *A = DILocation::get(Context, 4, 9, LB);1109 auto *B = DILocation::get(Context, 1, 6, LBF);1110 auto *M = DILocation::getMergedLocation(A, B);1111 EXPECT_EQ(4u, M->getLine());1112 EXPECT_EQ(9u, M->getColumn());1113 EXPECT_EQ(LB, M->getScope());1114 }1115 1116 {1117 // Different locations from different files included from the same block.1118 auto *F1 = DIFile::getDistinct(Context, "file1.c", "/path/to/dir");1119 DISubprogram *N = getSubprogram(F1);1120 1121 auto *LBCommon = DILexicalBlock::getDistinct(Context, N, F1, 4, 9);1122 1123 auto *F2 = DIFile::getDistinct(Context, "file2.c", "/path/to/dir");1124 LBCommon = DILexicalBlock::getDistinct(Context, LBCommon, F2, 5, 9);1125 1126 auto *F3 = DIFile::getDistinct(Context, "file3.c", "/path/to/dir");1127 auto *LB1 = DILexicalBlock::getDistinct(Context, LBCommon, F3, 6, 9);1128 1129 auto *F4 = DIFile::getDistinct(Context, "file4.c", "/path/to/dir");1130 auto *LB2 = DILexicalBlock::getDistinct(Context, LBCommon, F4, 7, 9);1131 1132 auto *F5 = DIFile::getDistinct(Context, "file5.c", "/path/to/dir");1133 auto *LBF1 = DILexicalBlockFile::get(Context, LB1, F5, 0);1134 1135 auto *A = DILocation::get(Context, 8, 9, LB2);1136 auto *B = DILocation::get(Context, 9, 6, LBF1);1137 auto *M = DILocation::getMergedLocation(A, B);1138 EXPECT_EQ(5u, M->getLine());1139 EXPECT_EQ(9u, M->getColumn());1140 EXPECT_EQ(LBCommon, M->getScope());1141 }1142 1143 {1144 // Different locations from different files having common include parent.1145 auto *LBCommon = DILexicalBlock::getDistinct(Context, N, F, 4, 1);1146 1147 // Different scopes.1148 DILexicalBlock *Block[2] = {};1149 Block[0] = DILexicalBlock::get(Context, LBCommon, F, 10, 2);1150 Block[1] = DILexicalBlock::get(Context, LBCommon, F, 20, 3);1151 1152 // Includes of the same file.1153 auto *F1 = DIFile::getDistinct(Context, "file1.inc", "/path/to/dir");1154 DILexicalBlock *Block1[2] = {};1155 Block1[0] = DILexicalBlock::get(1156 Context, DILexicalBlockFile::get(Context, Block[0], F1, 0), F1, 30, 4);1157 Block1[1] = DILexicalBlock::get(1158 Context, DILexicalBlockFile::get(Context, Block[1], F1, 0), F1, 30, 4);1159 1160 // Different sub-includes.1161 DIFile *F2[2] = {};1162 DILexicalBlock *Block2[2] = {};1163 1164 F2[0] = DIFile::getDistinct(Context, "file2_a.inc", "/path/to/dir");1165 Block2[0] = DILexicalBlock::get(1166 Context, DILexicalBlockFile::get(Context, Block1[0], F2[0], 0), F2[0],1167 40, 5);1168 1169 F2[1] = DIFile::getDistinct(Context, "file2_b.inc", "/path/to/dir");1170 Block2[1] = DILexicalBlock::get(1171 Context, DILexicalBlockFile::get(Context, Block1[1], F2[1], 0), F2[1],1172 50, 6);1173 1174 auto *A = DILocation::get(Context, 41, 7, Block2[0]);1175 auto *B = DILocation::get(Context, 51, 8, Block2[1]);1176 auto *M = DILocation::getMergedLocation(A, B);1177 auto *MScope = dyn_cast<DILexicalBlock>(M->getScope());1178 EXPECT_EQ(30u, M->getLine());1179 EXPECT_EQ(4u, M->getColumn());1180 EXPECT_EQ(Block1[0]->getFile(), MScope->getFile());1181 EXPECT_EQ(Block1[0]->getLine(), MScope->getLine());1182 EXPECT_EQ(Block1[0]->getColumn(), MScope->getColumn());1183 EXPECT_EQ(LBCommon, MScope->getScope());1184 }1185 1186 {1187 // Different function, same inlined-at.1188 auto *F = getFile();1189 auto *SP1 = DISubprogram::getDistinct(Context, F, "a", "a", F, 0, nullptr,1190 0, nullptr, 0, 0, DINode::FlagZero,1191 DISubprogram::SPFlagZero, nullptr);1192 auto *SP2 = DISubprogram::getDistinct(Context, F, "b", "b", F, 0, nullptr,1193 0, nullptr, 0, 0, DINode::FlagZero,1194 DISubprogram::SPFlagZero, nullptr);1195 1196 auto *I = DILocation::get(Context, 2, 7, N);1197 auto *A = DILocation::get(Context, 1, 6, SP1, I);1198 auto *B = DILocation::get(Context, 3, 8, SP2, I);1199 auto *M = DILocation::getMergedLocation(A, B);1200 EXPECT_EQ(2u, M->getLine());1201 EXPECT_EQ(7u, M->getColumn());1202 EXPECT_EQ(N, M->getScope());1203 EXPECT_EQ(nullptr, M->getInlinedAt());1204 }1205 1206 {1207 // Different function, inlined-at same line, but different column.1208 auto *F = getFile();1209 auto *SP1 = DISubprogram::getDistinct(Context, F, "a", "a", F, 0, nullptr,1210 0, nullptr, 0, 0, DINode::FlagZero,1211 DISubprogram::SPFlagZero, nullptr);1212 auto *SP2 = DISubprogram::getDistinct(Context, F, "b", "b", F, 0, nullptr,1213 0, nullptr, 0, 0, DINode::FlagZero,1214 DISubprogram::SPFlagZero, nullptr);1215 1216 auto *IA = DILocation::get(Context, 2, 7, N);1217 auto *IB = DILocation::get(Context, 2, 8, N);1218 auto *A = DILocation::get(Context, 1, 6, SP1, IA);1219 auto *B = DILocation::get(Context, 3, 8, SP2, IB);1220 auto *M = DILocation::getMergedLocation(A, B);1221 EXPECT_EQ(2u, M->getLine());1222 EXPECT_EQ(0u, M->getColumn());1223 EXPECT_EQ(N, M->getScope());1224 EXPECT_EQ(nullptr, M->getInlinedAt());1225 }1226 1227 {1228 // Completely different.1229 auto *I = DILocation::get(Context, 2, 7, N);1230 auto *A = DILocation::get(Context, 1, 6, S, I);1231 auto *B = DILocation::get(Context, 2, 7, getSubprogram());1232 auto *M = DILocation::getMergedLocation(A, B);1233 EXPECT_EQ(0u, M->getLine());1234 EXPECT_EQ(0u, M->getColumn());1235 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1236 EXPECT_EQ(S, M->getScope());1237 EXPECT_EQ(nullptr, M->getInlinedAt());1238 }1239 1240 // Two locations, same line/column different file, inlined at the same place.1241 {1242 auto *FA = getFile();1243 auto *FB = getFile();1244 auto *FI = getFile();1245 1246 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1247 0, nullptr, 0, 0, DINode::FlagZero,1248 DISubprogram::SPFlagZero, nullptr);1249 1250 auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,1251 0, nullptr, 0, 0, DINode::FlagZero,1252 DISubprogram::SPFlagZero, nullptr);1253 1254 auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,1255 0, nullptr, 0, 0, DINode::FlagZero,1256 DISubprogram::SPFlagZero, nullptr);1257 1258 auto *I = DILocation::get(Context, 3, 8, SPI);1259 auto *A = DILocation::get(Context, 2, 7, SPA, I);1260 auto *B = DILocation::get(Context, 2, 7, SPB, I);1261 auto *M = DILocation::getMergedLocation(A, B);1262 EXPECT_EQ(3u, M->getLine());1263 EXPECT_EQ(8u, M->getColumn());1264 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1265 EXPECT_EQ(SPI, M->getScope());1266 EXPECT_EQ(nullptr, M->getInlinedAt());1267 }1268 1269 // Two locations, same line/column different file, one location with 2 scopes,1270 // inlined at the same place.1271 {1272 auto *FA = getFile();1273 auto *FB = getFile();1274 auto *FI = getFile();1275 1276 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1277 0, nullptr, 0, 0, DINode::FlagZero,1278 DISubprogram::SPFlagZero, nullptr);1279 1280 auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,1281 0, nullptr, 0, 0, DINode::FlagZero,1282 DISubprogram::SPFlagZero, nullptr);1283 1284 auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,1285 0, nullptr, 0, 0, DINode::FlagZero,1286 DISubprogram::SPFlagZero, nullptr);1287 1288 auto *SPAScope = DILexicalBlock::getDistinct(Context, SPA, FA, 4, 9);1289 1290 auto *I = DILocation::get(Context, 3, 8, SPI);1291 auto *A = DILocation::get(Context, 2, 7, SPAScope, I);1292 auto *B = DILocation::get(Context, 2, 7, SPB, I);1293 auto *M = DILocation::getMergedLocation(A, B);1294 EXPECT_EQ(3u, M->getLine());1295 EXPECT_EQ(8u, M->getColumn());1296 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1297 EXPECT_EQ(SPI, M->getScope());1298 EXPECT_EQ(nullptr, M->getInlinedAt());1299 }1300 1301 // Merge a location in C, which is inlined-at in B that is inlined in A,1302 // with a location in A that has the same scope, line and column as B's1303 // inlined-at location.1304 {1305 auto *FA = getFile();1306 auto *FB = getFile();1307 auto *FC = getFile();1308 1309 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1310 0, nullptr, 0, 0, DINode::FlagZero,1311 DISubprogram::SPFlagZero, nullptr);1312 1313 auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,1314 0, nullptr, 0, 0, DINode::FlagZero,1315 DISubprogram::SPFlagZero, nullptr);1316 1317 auto *SPC = DISubprogram::getDistinct(Context, FC, "c", "c", FC, 0, nullptr,1318 0, nullptr, 0, 0, DINode::FlagZero,1319 DISubprogram::SPFlagZero, nullptr);1320 1321 auto *A = DILocation::get(Context, 3, 2, SPA);1322 auto *B = DILocation::get(Context, 2, 4, SPB, A);1323 auto *C = DILocation::get(Context, 13, 2, SPC, B);1324 auto *M = DILocation::getMergedLocation(A, C);1325 EXPECT_EQ(3u, M->getLine());1326 EXPECT_EQ(2u, M->getColumn());1327 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1328 EXPECT_EQ(SPA, M->getScope());1329 EXPECT_EQ(nullptr, M->getInlinedAt());1330 }1331 1332 // Two inlined locations with the same scope, line and column1333 // in the same inlined-at function at different line and column.1334 {1335 auto *FA = getFile();1336 auto *FB = getFile();1337 auto *FC = getFile();1338 1339 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1340 0, nullptr, 0, 0, DINode::FlagZero,1341 DISubprogram::SPFlagZero, nullptr);1342 1343 auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,1344 0, nullptr, 0, 0, DINode::FlagZero,1345 DISubprogram::SPFlagZero, nullptr);1346 1347 auto *SPC = DISubprogram::getDistinct(Context, FC, "c", "c", FC, 0, nullptr,1348 0, nullptr, 0, 0, DINode::FlagZero,1349 DISubprogram::SPFlagZero, nullptr);1350 1351 auto *A = DILocation::get(Context, 10, 20, SPA);1352 auto *B1 = DILocation::get(Context, 3, 2, SPB, A);1353 auto *B2 = DILocation::get(Context, 4, 5, SPB, A);1354 auto *C1 = DILocation::get(Context, 2, 4, SPC, B1);1355 auto *C2 = DILocation::get(Context, 2, 4, SPC, B2);1356 1357 auto *M = DILocation::getMergedLocation(C1, C2);1358 EXPECT_EQ(2u, M->getLine());1359 EXPECT_EQ(4u, M->getColumn());1360 EXPECT_EQ(SPC, M->getScope());1361 ASSERT_NE(nullptr, M->getInlinedAt());1362 1363 auto *I1 = M->getInlinedAt();1364 EXPECT_EQ(0u, I1->getLine());1365 EXPECT_EQ(0u, I1->getColumn());1366 EXPECT_EQ(SPB, I1->getScope());1367 EXPECT_EQ(A, I1->getInlinedAt());1368 }1369 1370 // Two locations, different line/column and scope in the same subprogram,1371 // inlined at the same place. This should result in a 0:0 location with1372 // the nearest common scope in the inlined function.1373 {1374 auto *FA = getFile();1375 auto *FI = getFile();1376 1377 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1378 0, nullptr, 0, 0, DINode::FlagZero,1379 DISubprogram::SPFlagZero, nullptr);1380 1381 auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,1382 0, nullptr, 0, 0, DINode::FlagZero,1383 DISubprogram::SPFlagZero, nullptr);1384 1385 // Nearest common scope for the two locations in a.1386 auto *SPAScope1 = DILexicalBlock::getDistinct(Context, SPA, FA, 4, 9);1387 1388 // Scope for the first location in a.1389 auto *SPAScope2 =1390 DILexicalBlock::getDistinct(Context, SPAScope1, FA, 10, 12);1391 1392 // Scope for the second location in a.1393 auto *SPAScope3 =1394 DILexicalBlock::getDistinct(Context, SPAScope1, FA, 20, 8);1395 auto *SPAScope4 =1396 DILexicalBlock::getDistinct(Context, SPAScope3, FA, 21, 12);1397 1398 auto *I = DILocation::get(Context, 3, 8, SPI);1399 auto *A1 = DILocation::get(Context, 12, 7, SPAScope2, I);1400 auto *A2 = DILocation::get(Context, 21, 15, SPAScope4, I);1401 auto *M = DILocation::getMergedLocation(A1, A2);1402 EXPECT_EQ(0u, M->getLine());1403 EXPECT_EQ(0u, M->getColumn());1404 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1405 EXPECT_EQ(SPAScope1, M->getScope());1406 EXPECT_EQ(I, M->getInlinedAt());1407 }1408 1409 // Regression test to catch a case where an iterator was invalidated due to1410 // handling the chain of inlined-at locations after the nearest common1411 // location for the two arguments were found.1412 {1413 auto *FA = getFile();1414 auto *FB = getFile();1415 auto *FI = getFile();1416 1417 auto *SPA = DISubprogram::getDistinct(Context, FA, "a", "a", FA, 0, nullptr,1418 0, nullptr, 0, 0, DINode::FlagZero,1419 DISubprogram::SPFlagZero, nullptr);1420 1421 auto *SPB = DISubprogram::getDistinct(Context, FB, "b", "b", FB, 0, nullptr,1422 0, nullptr, 0, 0, DINode::FlagZero,1423 DISubprogram::SPFlagZero, nullptr);1424 1425 auto *SPI = DISubprogram::getDistinct(Context, FI, "i", "i", FI, 0, nullptr,1426 0, nullptr, 0, 0, DINode::FlagZero,1427 DISubprogram::SPFlagZero, nullptr);1428 1429 auto *SPAScope1 = DILexicalBlock::getDistinct(Context, SPA, FA, 4, 9);1430 auto *SPAScope2 = DILexicalBlock::getDistinct(Context, SPA, FA, 8, 3);1431 1432 DILocation *InlinedAt = nullptr;1433 1434 // Create a chain of inlined-at locations.1435 for (int i = 0; i < 256; i++) {1436 InlinedAt = DILocation::get(Context, 3 + i, 8 + i, SPI, InlinedAt);1437 }1438 1439 auto *A1 = DILocation::get(Context, 5, 9, SPAScope1, InlinedAt);1440 auto *A2 = DILocation::get(Context, 9, 8, SPAScope2, InlinedAt);1441 auto *B = DILocation::get(Context, 10, 3, SPB, A1);1442 auto *M1 = DILocation::getMergedLocation(B, A2);1443 EXPECT_EQ(0u, M1->getLine());1444 EXPECT_EQ(0u, M1->getColumn());1445 EXPECT_TRUE(isa<DILocalScope>(M1->getScope()));1446 EXPECT_EQ(SPA, M1->getScope());1447 EXPECT_EQ(InlinedAt, M1->getInlinedAt());1448 1449 // Test the other argument order for good measure.1450 auto *M2 = DILocation::getMergedLocation(A2, B);1451 EXPECT_EQ(M1, M2);1452 }1453 1454 {1455 // If PickMergedSourceLocation is enabled, when one source location is null1456 // we should return the valid location.1457 PickMergedSourceLocations = true;1458 auto *A = DILocation::get(Context, 2, 7, N);1459 auto *M1 = DILocation::getMergedLocation(A, nullptr);1460 ASSERT_NE(nullptr, M1);1461 EXPECT_EQ(2u, M1->getLine());1462 EXPECT_EQ(7u, M1->getColumn());1463 EXPECT_EQ(N, M1->getScope());1464 1465 auto *M2 = DILocation::getMergedLocation(nullptr, A);1466 ASSERT_NE(nullptr, M2);1467 EXPECT_EQ(2u, M2->getLine());1468 EXPECT_EQ(7u, M2->getColumn());1469 EXPECT_EQ(N, M2->getScope());1470 PickMergedSourceLocations = false;1471 }1472 1473#define EXPECT_ATOM(Loc, Group, Rank) \1474 EXPECT_EQ(Group, M->getAtomGroup()); \1475 EXPECT_EQ(Rank, M->getAtomRank());1476 1477 // Identical, including source atom numbers.1478 {1479 auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1480 /*AtomRank*/ 1);1481 auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1482 /*AtomRank*/ 1);1483 auto *M = DILocation::getMergedLocation(A, B);1484 EXPECT_ATOM(M, /*AtomGroup*/ 1u, 1u);1485 // DILocations are uniqued, so we can check equality by ptr.1486 EXPECT_EQ(M, DILocation::getMergedLocation(A, B));1487 }1488 1489 // Identical but different atom ranks (same atom) - choose the lowest nonzero1490 // rank.1491 {1492 auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1493 /*AtomRank*/ 1);1494 auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1495 /*AtomRank*/ 2);1496 auto *M = DILocation::getMergedLocation(A, B);1497 EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 1u);1498 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1499 1500 A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1501 /*AtomRank*/ 0);1502 B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1503 /*AtomRank*/ 2);1504 M = DILocation::getMergedLocation(A, B);1505 EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 2u);1506 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1507 }1508 1509 // Identical but different atom ranks (different atom) - choose the lowest1510 // nonzero rank.1511 {1512 auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1513 /*AtomRank*/ 1);1514 auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 2,1515 /*AtomRank*/ 2);1516 auto *M = DILocation::getMergedLocation(A, B);1517 EXPECT_ATOM(M, 1u, 1u);1518 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1519 1520 A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1521 /*AtomRank*/ 0);1522 B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 2,1523 /*AtomRank*/ 2);1524 M = DILocation::getMergedLocation(A, B);1525 EXPECT_ATOM(M, /*AtomGroup*/ 2u, /*AtomRank*/ 2u);1526 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1527 }1528 1529 // Identical but equal atom rank (different atom) - choose the lowest non-zero1530 // group (arbitrary choice for deterministic behaviour).1531 {1532 auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 1,1533 /*AtomRank*/ 1);1534 auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 2,1535 /*AtomRank*/ 1);1536 auto *M = DILocation::getMergedLocation(A, B);1537 EXPECT_ATOM(M, 1u, 1u);1538 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1539 1540 A = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 0,1541 /*AtomRank*/ 1);1542 B = DILocation::get(Context, 2, 7, N, nullptr, false, /*AtomGroup*/ 2,1543 /*AtomRank*/ 1);1544 M = DILocation::getMergedLocation(A, B);1545 EXPECT_ATOM(M, /*AtomGroup*/ 2u, /*AtomRank*/ 1u);1546 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1547 }1548 1549 // Completely different except same atom numbers. Zero out the atoms.1550 {1551 auto *I = DILocation::get(Context, 2, 7, N);1552 auto *A = DILocation::get(Context, 1, 6, S, I, false, /*AtomGroup*/ 1,1553 /*AtomRank*/ 1);1554 auto *B = DILocation::get(Context, 2, 7, getSubprogram(), nullptr, false,1555 /*AtomGroup*/ 1, /*AtomRank*/ 1);1556 auto *M = DILocation::getMergedLocation(A, B);1557 EXPECT_EQ(0u, M->getLine());1558 EXPECT_EQ(0u, M->getColumn());1559 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));1560 EXPECT_EQ(S, M->getScope());1561 EXPECT_EQ(nullptr, M->getInlinedAt());1562 }1563 1564 // Same inlined-at chain but different atoms. Choose the lowest1565 // non-zero group (arbitrary choice for deterministic behaviour).1566 {1567 auto *I = DILocation::get(Context, 1, 7, N);1568 auto *F = getSubprogram();1569 auto *A = DILocation::get(Context, 1, 1, F, I, false, /*AtomGroup*/ 1,1570 /*AtomRank*/ 2);1571 auto *B = DILocation::get(Context, 1, 1, F, I, false, /*AtomGroup*/ 2,1572 /*AtomRank*/ 2);1573 auto *M = DILocation::getMergedLocation(A, B);1574 EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 2u);1575 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1576 1577 A = DILocation::get(Context, 1, 1, F, I, false, /*AtomGroup*/ 1,1578 /*AtomRank*/ 2);1579 B = DILocation::get(Context, 1, 1, F, I, false, /*AtomGroup*/ 2,1580 /*AtomRank*/ 0);1581 M = DILocation::getMergedLocation(A, B);1582 EXPECT_ATOM(M, /*AtomGroup*/ 1u, /*AtomRank*/ 2u);1583 EXPECT_EQ(M, DILocation::getMergedLocation(B, A));1584 }1585 1586 // Partially equal inlined-at chain but different atoms. Generate a new atom1587 // group (if either have a group number). This configuration seems unlikely1588 // to occur as line numbers must match, but isn't impossible.1589 {1590 // Reset global counter to ensure EXPECT numbers line up.1591 Context.pImpl->NextAtomGroup = 1;1592 // x1 -> y2 -> z41593 // y3 -> z41594 auto *FX = getSubprogram();1595 auto *FY = getSubprogram();1596 auto *FZ = getSubprogram();1597 auto *Z4 = DILocation::get(Context, 1, 4, FZ);1598 auto *Y3IntoZ4 = DILocation::get(Context, 1, 3, FY, Z4, false,1599 /*AtomGroup*/ 1, /*AtomRank*/ 1);1600 auto *Y2IntoZ4 = DILocation::get(Context, 1, 2, FY, Z4);1601 auto *X1IntoY2 = DILocation::get(Context, 1, 1, FX, Y2IntoZ4);1602 auto *M = DILocation::getMergedLocation(X1IntoY2, Y3IntoZ4);1603 EXPECT_EQ(M->getScope(), FY);1604 EXPECT_EQ(M->getInlinedAt()->getScope(), FZ);1605 EXPECT_ATOM(M, /*AtomGroup*/ 2u, /*AtomRank*/ 1u);1606 1607 // This swapped merge will produce a new atom group too.1608 M = DILocation::getMergedLocation(Y3IntoZ4, X1IntoY2);1609 1610 // Same again, even if the atom numbers match.1611 auto *X1IntoY2SameAtom = DILocation::get(Context, 1, 1, FX, Y2IntoZ4, false,1612 /*AtomGroup*/ 1, /*AtomRank*/ 1);1613 M = DILocation::getMergedLocation(X1IntoY2SameAtom, Y3IntoZ4);1614 EXPECT_ATOM(M, /*AtomGroup*/ 4u, /*AtomRank*/ 1u);1615 M = DILocation::getMergedLocation(Y3IntoZ4, X1IntoY2SameAtom);1616 EXPECT_ATOM(M, /*AtomGroup*/ 5u, /*AtomRank*/ 1u);1617 }1618#undef EXPECT_ATOM1619}1620 1621TEST_F(DILocationTest, getDistinct) {1622 MDNode *N = getSubprogram();1623 DILocation *L0 = DILocation::getDistinct(Context, 2, 7, N);1624 EXPECT_TRUE(L0->isDistinct());1625 DILocation *L1 = DILocation::get(Context, 2, 7, N);1626 EXPECT_FALSE(L1->isDistinct());1627 EXPECT_EQ(L1, DILocation::get(Context, 2, 7, N));1628}1629 1630TEST_F(DILocationTest, getTemporary) {1631 MDNode *N = MDNode::get(Context, {});1632 auto L = DILocation::getTemporary(Context, 2, 7, N);1633 EXPECT_TRUE(L->isTemporary());1634 EXPECT_FALSE(L->isResolved());1635}1636 1637TEST_F(DILocationTest, cloneTemporary) {1638 MDNode *N = MDNode::get(Context, {});1639 auto L = DILocation::getTemporary(Context, 2, 7, N);1640 EXPECT_TRUE(L->isTemporary());1641 auto L2 = L->clone();1642 EXPECT_TRUE(L2->isTemporary());1643}1644 1645TEST_F(DILocationTest, discriminatorEncoding) {1646 EXPECT_EQ(0U, *DILocation::encodeDiscriminator(0, 0, 0));1647 1648 // Encode base discriminator as a component: lsb is 0, then the value.1649 // The other components are all absent, so we leave all the other bits 0.1650 EXPECT_EQ(2U, *DILocation::encodeDiscriminator(1, 0, 0));1651 1652 // Base discriminator component is empty, so lsb is 1. Next component is not1653 // empty, so its lsb is 0, then its value (1). Next component is empty.1654 // So the bit pattern is 101.1655 EXPECT_EQ(5U, *DILocation::encodeDiscriminator(0, 1, 0));1656 1657 // First 2 components are empty, so the bit pattern is 11. Then the1658 // next component - ending up with 1011.1659 EXPECT_EQ(0xbU, *DILocation::encodeDiscriminator(0, 0, 1));1660 1661 // The bit pattern for the first 2 components is 11. The next bit is 0,1662 // because the last component is not empty. We have 29 bits usable for1663 // encoding, but we cap it at 12 bits uniformously for all components. We1664 // encode the last component over 14 bits.1665 EXPECT_EQ(0xfffbU, *DILocation::encodeDiscriminator(0, 0, 0xfff));1666 1667 EXPECT_EQ(0x102U, *DILocation::encodeDiscriminator(1, 1, 0));1668 1669 EXPECT_EQ(0x13eU, *DILocation::encodeDiscriminator(0x1f, 1, 0));1670 1671 EXPECT_EQ(0x87feU, *DILocation::encodeDiscriminator(0x1ff, 1, 0));1672 1673 EXPECT_EQ(0x1f3eU, *DILocation::encodeDiscriminator(0x1f, 0x1f, 0));1674 1675 EXPECT_EQ(0x3ff3eU, *DILocation::encodeDiscriminator(0x1f, 0x1ff, 0));1676 1677 EXPECT_EQ(0x1ff87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1ff, 0));1678 1679 EXPECT_EQ(0xfff9f3eU, *DILocation::encodeDiscriminator(0x1f, 0x1f, 0xfff));1680 1681 EXPECT_EQ(0xffc3ff3eU, *DILocation::encodeDiscriminator(0x1f, 0x1ff, 0x1ff));1682 1683 EXPECT_EQ(0xffcf87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1f, 0x1ff));1684 1685 EXPECT_EQ(0xe1ff87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1ff, 7));1686}1687 1688TEST_F(DILocationTest, discriminatorEncodingNegativeTests) {1689 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0, 0x1000));1690 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0x1000, 0, 0));1691 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0x1000, 0));1692 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0, 0x1000));1693 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0x1ff, 0x1ff, 8));1694 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(1695 std::numeric_limits<uint32_t>::max(),1696 std::numeric_limits<uint32_t>::max(), 0));1697}1698 1699TEST_F(DILocationTest, discriminatorSpecialCases) {1700 // We don't test getCopyIdentifier here because the only way1701 // to set it is by constructing an encoded discriminator using1702 // encodeDiscriminator, which is already tested.1703 auto L1 = DILocation::get(Context, 1, 2, getSubprogram());1704 EXPECT_EQ(0U, L1->getBaseDiscriminator());1705 EXPECT_EQ(1U, L1->getDuplicationFactor());1706 1707 EXPECT_EQ(L1, *L1->cloneWithBaseDiscriminator(0));1708 EXPECT_EQ(L1, *L1->cloneByMultiplyingDuplicationFactor(0));1709 EXPECT_EQ(L1, *L1->cloneByMultiplyingDuplicationFactor(1));1710 1711 auto L2 = *L1->cloneWithBaseDiscriminator(1);1712 EXPECT_EQ(0U, L1->getBaseDiscriminator());1713 EXPECT_EQ(1U, L1->getDuplicationFactor());1714 1715 EXPECT_EQ(1U, L2->getBaseDiscriminator());1716 EXPECT_EQ(1U, L2->getDuplicationFactor());1717 1718 auto L3 = *L2->cloneByMultiplyingDuplicationFactor(2);1719 EXPECT_EQ(1U, L3->getBaseDiscriminator());1720 EXPECT_EQ(2U, L3->getDuplicationFactor());1721 1722 EXPECT_EQ(L2, *L2->cloneByMultiplyingDuplicationFactor(1));1723 1724 auto L4 = *L3->cloneByMultiplyingDuplicationFactor(4);1725 EXPECT_EQ(1U, L4->getBaseDiscriminator());1726 EXPECT_EQ(8U, L4->getDuplicationFactor());1727 1728 auto L5 = *L4->cloneWithBaseDiscriminator(2);1729 EXPECT_EQ(2U, L5->getBaseDiscriminator());1730 EXPECT_EQ(8U, L5->getDuplicationFactor());1731 1732 // Check extreme cases1733 auto L6 = *L1->cloneWithBaseDiscriminator(0xfff);1734 EXPECT_EQ(0xfffU, L6->getBaseDiscriminator());1735 EXPECT_EQ(0xfffU, (*L6->cloneByMultiplyingDuplicationFactor(0xfff))1736 ->getDuplicationFactor());1737 1738 // Check we return std::nullopt for unencodable cases.1739 EXPECT_EQ(std::nullopt, L4->cloneWithBaseDiscriminator(0x1000));1740 EXPECT_EQ(std::nullopt, L4->cloneByMultiplyingDuplicationFactor(0x1000));1741}1742 1743TEST_F(DILocationTest, KeyInstructions) {1744 Context.pImpl->NextAtomGroup = 1;1745 1746 EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u);1747 DILocation *A1 =1748 DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);1749 EXPECT_EQ(A1->getAtomGroup(), 1u);1750 EXPECT_EQ(A1->getAtomRank(), 2u);1751 1752 // Group number 1 has been "used" so next available is 2.1753 EXPECT_EQ(Context.pImpl->NextAtomGroup, 2u);1754 1755 // Set a group number higher than current + 1, then check the waterline.1756 DILocation::get(Context, 2, 0, getSubprogram(), nullptr, false, 5, 1);1757 EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);1758 1759 // The waterline should be unchanged (group <= next).1760 DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 4, 1);1761 EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);1762 DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 5, 1);1763 EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);1764 1765 // Check the waterline gets incremented by 1.1766 EXPECT_EQ(Context.incNextDILocationAtomGroup(), 6u);1767 EXPECT_EQ(Context.pImpl->NextAtomGroup, 7u);1768 1769 Context.updateDILocationAtomGroupWaterline(8);1770 EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);1771 Context.updateDILocationAtomGroupWaterline(7);1772 EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);1773}1774 1775typedef MetadataTest GenericDINodeTest;1776 1777TEST_F(GenericDINodeTest, get) {1778 StringRef Header = "header";1779 auto *Empty = MDNode::get(Context, {});1780 Metadata *Ops1[] = {Empty};1781 auto *N = GenericDINode::get(Context, 15, Header, Ops1);1782 EXPECT_EQ(15u, N->getTag());1783 EXPECT_EQ(2u, N->getNumOperands());1784 EXPECT_EQ(Header, N->getHeader());1785 EXPECT_EQ(MDString::get(Context, Header), N->getOperand(0));1786 EXPECT_EQ(1u, N->getNumDwarfOperands());1787 EXPECT_EQ(Empty, N->getDwarfOperand(0));1788 EXPECT_EQ(Empty, N->getOperand(1));1789 ASSERT_TRUE(N->isUniqued());1790 1791 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));1792 1793 N->replaceOperandWith(1, nullptr);1794 EXPECT_EQ(15u, N->getTag());1795 EXPECT_EQ(Header, N->getHeader());1796 EXPECT_EQ(nullptr, N->getDwarfOperand(0));1797 ASSERT_TRUE(N->isUniqued());1798 1799 Metadata *Ops2[] = {nullptr};1800 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops2));1801 1802 N->replaceDwarfOperandWith(0, Empty);1803 EXPECT_EQ(15u, N->getTag());1804 EXPECT_EQ(Header, N->getHeader());1805 EXPECT_EQ(Empty, N->getDwarfOperand(0));1806 ASSERT_TRUE(N->isUniqued());1807 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));1808 1809 TempGenericDINode Temp = N->clone();1810 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));1811}1812 1813TEST_F(GenericDINodeTest, getEmptyHeader) {1814 // Canonicalize !"" to null.1815 auto *N = GenericDINode::get(Context, 15, StringRef(), {});1816 EXPECT_EQ(StringRef(), N->getHeader());1817 EXPECT_EQ(nullptr, N->getOperand(0));1818}1819 1820typedef MetadataTest DISubrangeTest;1821 1822TEST_F(DISubrangeTest, get) {1823 auto *N = DISubrange::get(Context, 5, 7);1824 auto Count = N->getCount();1825 auto Lower = N->getLowerBound();1826 EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());1827 ASSERT_TRUE(Count);1828 ASSERT_TRUE(isa<ConstantInt *>(Count));1829 EXPECT_EQ(5, cast<ConstantInt *>(Count)->getSExtValue());1830 EXPECT_EQ(7, cast<ConstantInt *>(Lower)->getSExtValue());1831 EXPECT_EQ(N, DISubrange::get(Context, 5, 7));1832 EXPECT_EQ(DISubrange::get(Context, 5, 0), DISubrange::get(Context, 5));1833 1834 TempDISubrange Temp = N->clone();1835 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));1836}1837 1838TEST_F(DISubrangeTest, getEmptyArray) {1839 auto *N = DISubrange::get(Context, -1, 0);1840 auto Count = N->getCount();1841 auto Lower = N->getLowerBound();1842 EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());1843 ASSERT_TRUE(Count);1844 ASSERT_TRUE(isa<ConstantInt *>(Count));1845 EXPECT_EQ(-1, cast<ConstantInt *>(Count)->getSExtValue());1846 EXPECT_EQ(0, cast<ConstantInt *>(Lower)->getSExtValue());1847 EXPECT_EQ(N, DISubrange::get(Context, -1, 0));1848}1849 1850TEST_F(DISubrangeTest, getVariableCount) {1851 DILocalScope *Scope = getSubprogram();1852 DIFile *File = getFile();1853 DIType *Type = getDerivedType();1854 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);1855 auto *VlaExpr = DILocalVariable::get(Context, Scope, "vla_expr", File, 8,1856 Type, 2, Flags, 8, nullptr);1857 1858 auto *N = DISubrange::get(Context, VlaExpr, 0);1859 auto Count = N->getCount();1860 auto Lower = N->getLowerBound();1861 ASSERT_TRUE(Count);1862 ASSERT_TRUE(isa<DIVariable *>(Count));1863 EXPECT_EQ(VlaExpr, cast<DIVariable *>(Count));1864 ASSERT_TRUE(isa<DIVariable>(N->getRawCountNode()));1865 EXPECT_EQ(0, cast<ConstantInt *>(Lower)->getSExtValue());1866 EXPECT_EQ("vla_expr", cast<DIVariable *>(Count)->getName());1867 EXPECT_EQ(N, DISubrange::get(Context, VlaExpr, 0));1868}1869 1870TEST_F(DISubrangeTest, fortranAllocatableInt) {1871 DILocalScope *Scope = getSubprogram();1872 DIFile *File = getFile();1873 DIType *Type = getDerivedType();1874 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);1875 auto *LI = ConstantAsMetadata::get(1876 ConstantInt::getSigned(Type::getInt64Ty(Context), -10));1877 auto *UI = ConstantAsMetadata::get(1878 ConstantInt::getSigned(Type::getInt64Ty(Context), 10));1879 auto *SI = ConstantAsMetadata::get(1880 ConstantInt::getSigned(Type::getInt64Ty(Context), 4));1881 auto *UIother = ConstantAsMetadata::get(1882 ConstantInt::getSigned(Type::getInt64Ty(Context), 20));1883 auto *UVother = DILocalVariable::get(Context, Scope, "ubother", File, 8, Type,1884 2, Flags, 8, nullptr);1885 auto *UEother = DIExpression::get(Context, {5, 6});1886 auto *LIZero = ConstantAsMetadata::get(1887 ConstantInt::getSigned(Type::getInt64Ty(Context), 0));1888 auto *UIZero = ConstantAsMetadata::get(1889 ConstantInt::getSigned(Type::getInt64Ty(Context), 0));1890 1891 auto *N = DISubrange::get(Context, nullptr, LI, UI, SI);1892 1893 auto Lower = N->getLowerBound();1894 ASSERT_TRUE(Lower);1895 ASSERT_TRUE(isa<ConstantInt *>(Lower));1896 EXPECT_EQ(cast<ConstantInt>(LI->getValue()), cast<ConstantInt *>(Lower));1897 1898 auto Upper = N->getUpperBound();1899 ASSERT_TRUE(Upper);1900 ASSERT_TRUE(isa<ConstantInt *>(Upper));1901 EXPECT_EQ(cast<ConstantInt>(UI->getValue()), cast<ConstantInt *>(Upper));1902 1903 auto Stride = N->getStride();1904 ASSERT_TRUE(Stride);1905 ASSERT_TRUE(isa<ConstantInt *>(Stride));1906 EXPECT_EQ(cast<ConstantInt>(SI->getValue()), cast<ConstantInt *>(Stride));1907 1908 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LI, UI, SI));1909 1910 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UIother, SI));1911 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UEother, SI));1912 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UVother, SI));1913 1914 auto *NZeroLower = DISubrange::get(Context, nullptr, LIZero, UI, SI);1915 EXPECT_NE(NZeroLower, DISubrange::get(Context, nullptr, nullptr, UI, SI));1916 1917 auto *NZeroUpper = DISubrange::get(Context, nullptr, LI, UIZero, SI);1918 EXPECT_NE(NZeroUpper, DISubrange::get(Context, nullptr, LI, nullptr, SI));1919}1920 1921TEST_F(DISubrangeTest, fortranAllocatableVar) {1922 DILocalScope *Scope = getSubprogram();1923 DIFile *File = getFile();1924 DIType *Type = getDerivedType();1925 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);1926 auto *LV =1927 DILocalVariable::get(Context, Scope, "lb", File, 8, Type, 2, Flags, 8,1928 nullptr);1929 auto *UV =1930 DILocalVariable::get(Context, Scope, "ub", File, 8, Type, 2, Flags, 8,1931 nullptr);1932 auto *SV =1933 DILocalVariable::get(Context, Scope, "st", File, 8, Type, 2, Flags, 8,1934 nullptr);1935 auto *SVother = DILocalVariable::get(Context, Scope, "stother", File, 8, Type,1936 2, Flags, 8, nullptr);1937 auto *SIother = ConstantAsMetadata::get(1938 ConstantInt::getSigned(Type::getInt64Ty(Context), 20));1939 auto *SEother = DIExpression::get(Context, {5, 6});1940 1941 auto *N = DISubrange::get(Context, nullptr, LV, UV, SV);1942 1943 auto Lower = N->getLowerBound();1944 ASSERT_TRUE(Lower);1945 ASSERT_TRUE(isa<DIVariable *>(Lower));1946 EXPECT_EQ(LV, cast<DIVariable *>(Lower));1947 1948 auto Upper = N->getUpperBound();1949 ASSERT_TRUE(Upper);1950 ASSERT_TRUE(isa<DIVariable *>(Upper));1951 EXPECT_EQ(UV, cast<DIVariable *>(Upper));1952 1953 auto Stride = N->getStride();1954 ASSERT_TRUE(Stride);1955 ASSERT_TRUE(isa<DIVariable *>(Stride));1956 EXPECT_EQ(SV, cast<DIVariable *>(Stride));1957 1958 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LV, UV, SV));1959 1960 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SVother));1961 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SEother));1962 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SIother));1963}1964 1965TEST_F(DISubrangeTest, fortranAllocatableExpr) {1966 DILocalScope *Scope = getSubprogram();1967 DIFile *File = getFile();1968 DIType *Type = getDerivedType();1969 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);1970 auto *LE = DIExpression::get(Context, {1, 2});1971 auto *UE = DIExpression::get(Context, {2, 3});1972 auto *SE = DIExpression::get(Context, {3, 4});1973 auto *LEother = DIExpression::get(Context, {5, 6});1974 auto *LIother = ConstantAsMetadata::get(1975 ConstantInt::getSigned(Type::getInt64Ty(Context), 20));1976 auto *LVother = DILocalVariable::get(Context, Scope, "lbother", File, 8, Type,1977 2, Flags, 8, nullptr);1978 1979 auto *N = DISubrange::get(Context, nullptr, LE, UE, SE);1980 1981 auto Lower = N->getLowerBound();1982 ASSERT_TRUE(Lower);1983 ASSERT_TRUE(isa<DIExpression *>(Lower));1984 EXPECT_EQ(LE, cast<DIExpression *>(Lower));1985 1986 auto Upper = N->getUpperBound();1987 ASSERT_TRUE(Upper);1988 ASSERT_TRUE(isa<DIExpression *>(Upper));1989 EXPECT_EQ(UE, cast<DIExpression *>(Upper));1990 1991 auto Stride = N->getStride();1992 ASSERT_TRUE(Stride);1993 ASSERT_TRUE(isa<DIExpression *>(Stride));1994 EXPECT_EQ(SE, cast<DIExpression *>(Stride));1995 1996 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LE, UE, SE));1997 1998 EXPECT_NE(N, DISubrange::get(Context, nullptr, LEother, UE, SE));1999 EXPECT_NE(N, DISubrange::get(Context, nullptr, LIother, UE, SE));2000 EXPECT_NE(N, DISubrange::get(Context, nullptr, LVother, UE, SE));2001}2002 2003typedef MetadataTest DISubrangeTypeTest;2004 2005TEST_F(DISubrangeTypeTest, get) {2006 auto *Base =2007 DIBasicType::get(Context, dwarf::DW_TAG_base_type, "test_integer", 32, 0,2008 dwarf::DW_ATE_signed, 100, DINode::FlagZero);2009 2010 DILocalScope *Scope = getSubprogram();2011 DIFile *File = getFile();2012 2013 ConstantInt *Lower = ConstantInt::get(Context, APInt(32, -7, true));2014 ConstantAsMetadata *LowerConst = ConstantAsMetadata::get(Lower);2015 ConstantInt *Upper = ConstantInt::get(Context, APInt(32, 23, true));2016 ConstantAsMetadata *UpperConst = ConstantAsMetadata::get(Upper);2017 2018 auto *N = DISubrangeType::get(Context, StringRef(), File, 101, Scope, 32, 0,2019 DINode::FlagZero, Base, LowerConst, UpperConst,2020 nullptr, LowerConst);2021 EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());2022 2023 auto L = N->getLowerBound();2024 EXPECT_EQ(-7, cast<ConstantInt *>(L)->getSExtValue());2025 2026 auto U = N->getUpperBound();2027 EXPECT_EQ(23, cast<ConstantInt *>(U)->getSExtValue());2028 2029 EXPECT_EQ(101u, N->getLine());2030 EXPECT_EQ(32u, N->getSizeInBits());2031 2032 TempDISubrangeType Temp = N->clone();2033 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2034}2035 2036typedef MetadataTest DIGenericSubrangeTest;2037 2038TEST_F(DIGenericSubrangeTest, fortranAssumedRankInt) {2039 DILocalScope *Scope = getSubprogram();2040 DIFile *File = getFile();2041 DIType *Type = getDerivedType();2042 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);2043 auto *LI = DIExpression::get(2044 Context, {dwarf::DW_OP_consts, static_cast<uint64_t>(-10)});2045 auto *UI = DIExpression::get(Context, {dwarf::DW_OP_consts, 10});2046 auto *SI = DIExpression::get(Context, {dwarf::DW_OP_consts, 4});2047 auto *UIother = DIExpression::get(Context, {dwarf::DW_OP_consts, 20});2048 auto *UVother = DILocalVariable::get(Context, Scope, "ubother", File, 8, Type,2049 2, Flags, 8, nullptr);2050 auto *UEother = DIExpression::get(Context, {5, 6});2051 auto *LIZero = DIExpression::get(Context, {dwarf::DW_OP_consts, 0});2052 auto *UIZero = DIExpression::get(Context, {dwarf::DW_OP_consts, 0});2053 2054 auto *N = DIGenericSubrange::get(Context, nullptr, LI, UI, SI);2055 2056 auto Lower = N->getLowerBound();2057 ASSERT_TRUE(Lower);2058 ASSERT_TRUE(isa<DIExpression *>(Lower));2059 EXPECT_EQ(dyn_cast_or_null<DIExpression>(LI), cast<DIExpression *>(Lower));2060 2061 auto Upper = N->getUpperBound();2062 ASSERT_TRUE(Upper);2063 ASSERT_TRUE(isa<DIExpression *>(Upper));2064 EXPECT_EQ(dyn_cast_or_null<DIExpression>(UI), cast<DIExpression *>(Upper));2065 2066 auto Stride = N->getStride();2067 ASSERT_TRUE(Stride);2068 ASSERT_TRUE(isa<DIExpression *>(Stride));2069 EXPECT_EQ(dyn_cast_or_null<DIExpression>(SI), cast<DIExpression *>(Stride));2070 2071 EXPECT_EQ(N, DIGenericSubrange::get(Context, nullptr, LI, UI, SI));2072 2073 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UIother, SI));2074 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UEother, SI));2075 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UVother, SI));2076 2077 auto *NZeroLower = DIGenericSubrange::get(Context, nullptr, LIZero, UI, SI);2078 EXPECT_NE(NZeroLower,2079 DIGenericSubrange::get(Context, nullptr, nullptr, UI, SI));2080 2081 auto *NZeroUpper = DIGenericSubrange::get(Context, nullptr, LI, UIZero, SI);2082 EXPECT_NE(NZeroUpper,2083 DIGenericSubrange::get(Context, nullptr, LI, nullptr, SI));2084}2085 2086TEST_F(DIGenericSubrangeTest, fortranAssumedRankVar) {2087 DILocalScope *Scope = getSubprogram();2088 DIFile *File = getFile();2089 DIType *Type = getDerivedType();2090 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);2091 auto *LV =2092 DILocalVariable::get(Context, Scope, "lb", File, 8, Type, 2, Flags, 8,2093 nullptr);2094 auto *UV =2095 DILocalVariable::get(Context, Scope, "ub", File, 8, Type, 2, Flags, 8,2096 nullptr);2097 auto *SV =2098 DILocalVariable::get(Context, Scope, "st", File, 8, Type, 2, Flags, 8,2099 nullptr);2100 auto *SVother = DILocalVariable::get(Context, Scope, "stother", File, 8, Type,2101 2, Flags, 8, nullptr);2102 auto *SIother = DIExpression::get(2103 Context, {dwarf::DW_OP_consts, static_cast<uint64_t>(-1)});2104 auto *SEother = DIExpression::get(Context, {5, 6});2105 2106 auto *N = DIGenericSubrange::get(Context, nullptr, LV, UV, SV);2107 2108 auto Lower = N->getLowerBound();2109 ASSERT_TRUE(Lower);2110 ASSERT_TRUE(isa<DIVariable *>(Lower));2111 EXPECT_EQ(LV, cast<DIVariable *>(Lower));2112 2113 auto Upper = N->getUpperBound();2114 ASSERT_TRUE(Upper);2115 ASSERT_TRUE(isa<DIVariable *>(Upper));2116 EXPECT_EQ(UV, cast<DIVariable *>(Upper));2117 2118 auto Stride = N->getStride();2119 ASSERT_TRUE(Stride);2120 ASSERT_TRUE(isa<DIVariable *>(Stride));2121 EXPECT_EQ(SV, cast<DIVariable *>(Stride));2122 2123 EXPECT_EQ(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SV));2124 2125 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SVother));2126 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SEother));2127 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SIother));2128}2129 2130TEST_F(DIGenericSubrangeTest, useDIBuilder) {2131 DILocalScope *Scope = getSubprogram();2132 DIFile *File = getFile();2133 DIType *Type = getDerivedType();2134 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);2135 auto *LV =2136 DILocalVariable::get(Context, Scope, "lb", File, 8, Type, 2, Flags, 8, nullptr);2137 auto *UE = DIExpression::get(Context, {2, 3});2138 auto *SE = DIExpression::get(Context, {3, 4});2139 2140 auto *LVother = DILocalVariable::get(Context, Scope, "lbother", File, 8, Type,2141 2, Flags, 8, nullptr);2142 auto *LIother = DIExpression::get(2143 Context, {dwarf::DW_OP_consts, static_cast<uint64_t>(-1)});2144 2145 Module M("M", Context);2146 DIBuilder DIB(M);2147 2148 auto *N = DIB.getOrCreateGenericSubrange(2149 DIGenericSubrange::BoundType(nullptr), DIGenericSubrange::BoundType(LV),2150 DIGenericSubrange::BoundType(UE), DIGenericSubrange::BoundType(SE));2151 2152 auto Lower = N->getLowerBound();2153 ASSERT_TRUE(Lower);2154 ASSERT_TRUE(isa<DIVariable *>(Lower));2155 EXPECT_EQ(LV, cast<DIVariable *>(Lower));2156 2157 auto Upper = N->getUpperBound();2158 ASSERT_TRUE(Upper);2159 ASSERT_TRUE(isa<DIExpression *>(Upper));2160 EXPECT_EQ(UE, cast<DIExpression *>(Upper));2161 2162 auto Stride = N->getStride();2163 ASSERT_TRUE(Stride);2164 ASSERT_TRUE(isa<DIExpression *>(Stride));2165 EXPECT_EQ(SE, cast<DIExpression *>(Stride));2166 2167 EXPECT_EQ(2168 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),2169 DIGenericSubrange::BoundType(LV),2170 DIGenericSubrange::BoundType(UE),2171 DIGenericSubrange::BoundType(SE)));2172 2173 EXPECT_NE(2174 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),2175 DIGenericSubrange::BoundType(LVother),2176 DIGenericSubrange::BoundType(UE),2177 DIGenericSubrange::BoundType(SE)));2178 EXPECT_NE(2179 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),2180 DIGenericSubrange::BoundType(LIother),2181 DIGenericSubrange::BoundType(UE),2182 DIGenericSubrange::BoundType(SE)));2183}2184typedef MetadataTest DIEnumeratorTest;2185 2186TEST_F(DIEnumeratorTest, get) {2187 auto *N = DIEnumerator::get(Context, 7, false, "name");2188 EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());2189 EXPECT_EQ(7, N->getValue().getSExtValue());2190 EXPECT_FALSE(N->isUnsigned());2191 EXPECT_EQ("name", N->getName());2192 EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name"));2193 2194 EXPECT_NE(N, DIEnumerator::get(Context, 7, true, "name"));2195 EXPECT_NE(N, DIEnumerator::get(Context, 8, false, "name"));2196 EXPECT_NE(N, DIEnumerator::get(Context, 7, false, "nam"));2197 2198 TempDIEnumerator Temp = N->clone();2199 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2200}2201 2202TEST_F(DIEnumeratorTest, getWithLargeValues) {2203 auto *N = DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val");2204 EXPECT_EQ(128U, N->getValue().popcount());2205 EXPECT_EQ(N,2206 DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val"));2207 EXPECT_NE(N,2208 DIEnumerator::get(Context, APInt::getMinValue(128), false, "val"));2209}2210 2211typedef MetadataTest DIBasicTypeTest;2212 2213TEST_F(DIBasicTypeTest, get) {2214 auto *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2215 26, 7, 100, DINode::FlagZero);2216 EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag());2217 EXPECT_EQ("special", N->getName());2218 EXPECT_EQ(33u, N->getSizeInBits());2219 EXPECT_EQ(26u, N->getAlignInBits());2220 EXPECT_EQ(7u, N->getEncoding());2221 EXPECT_EQ(0u, N->getLine());2222 EXPECT_EQ(100u, N->getNumExtraInhabitants());2223 EXPECT_EQ(DINode::FlagZero, N->getFlags());2224 EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2225 26, 7, 100, DINode::FlagZero));2226 2227 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type,2228 "special", 33, 26, 7, 100, DINode::FlagZero));2229 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26,2230 7, 100, DINode::FlagZero));2231 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32,2232 26, 7, 100, DINode::FlagZero));2233 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2234 25, 7, 100, DINode::FlagZero));2235 2236 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2237 26, 7, 99, DINode::FlagZero));2238 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2239 26, 6, 100, DINode::FlagZero));2240 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2241 26, 7, 100, DINode::FlagBigEndian));2242 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,2243 26, 7, 100, DINode::FlagLittleEndian));2244 2245 TempDIBasicType Temp = N->clone();2246 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2247}2248 2249TEST_F(DIBasicTypeTest, getWithLargeValues) {2250 auto *N =2251 DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", UINT64_MAX,2252 UINT32_MAX - 1, 7, UINT32_MAX, DINode::FlagZero);2253 EXPECT_EQ(UINT64_MAX, N->getSizeInBits());2254 EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits());2255 EXPECT_EQ(UINT32_MAX, N->getNumExtraInhabitants());2256}2257 2258TEST_F(DIBasicTypeTest, getUnspecified) {2259 auto *N =2260 DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, "unspecified");2261 EXPECT_EQ(dwarf::DW_TAG_unspecified_type, N->getTag());2262 EXPECT_EQ("unspecified", N->getName());2263 EXPECT_EQ(0u, N->getSizeInBits());2264 EXPECT_EQ(0u, N->getAlignInBits());2265 EXPECT_EQ(0u, N->getEncoding());2266 EXPECT_EQ(0u, N->getLine());2267 EXPECT_EQ(DINode::FlagZero, N->getFlags());2268}2269 2270typedef MetadataTest DITypeTest;2271 2272TEST_F(DITypeTest, clone) {2273 // Check that DIType has a specialized clone that returns TempDIType.2274 DIType *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "int", 32, 32,2275 0, dwarf::DW_ATE_signed, DINode::FlagZero);2276 2277 TempDIType Temp = N->clone();2278 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2279}2280 2281TEST_F(DITypeTest, cloneWithFlags) {2282 // void (void)2283 Metadata *TypesOps[] = {nullptr};2284 Metadata *Types = MDTuple::get(Context, TypesOps);2285 2286 DIType *D =2287 DISubroutineType::getDistinct(Context, DINode::FlagZero, 0, Types);2288 EXPECT_EQ(DINode::FlagZero, D->getFlags());2289 TempDIType D2 = D->cloneWithFlags(DINode::FlagRValueReference);2290 EXPECT_EQ(DINode::FlagRValueReference, D2->getFlags());2291 EXPECT_EQ(DINode::FlagZero, D->getFlags());2292 2293 TempDIType T =2294 DISubroutineType::getTemporary(Context, DINode::FlagZero, 0, Types);2295 EXPECT_EQ(DINode::FlagZero, T->getFlags());2296 TempDIType T2 = T->cloneWithFlags(DINode::FlagRValueReference);2297 EXPECT_EQ(DINode::FlagRValueReference, T2->getFlags());2298 EXPECT_EQ(DINode::FlagZero, T->getFlags());2299}2300 2301typedef MetadataTest DIDerivedTypeTest;2302 2303TEST_F(DIDerivedTypeTest, get) {2304 DIFile *File = getFile();2305 DIScope *Scope = getSubprogram();2306 DIType *BaseType = getBasicType("basic");2307 MDTuple *ExtraData = getTuple();2308 unsigned DWARFAddressSpace = 8;2309 DIDerivedType::PtrAuthData PtrAuthData(1, false, 1234, true, true);2310 DIDerivedType::PtrAuthData PtrAuthData2(1, false, 1234, true, false);2311 DINode::DIFlags Flags5 = static_cast<DINode::DIFlags>(5);2312 DINode::DIFlags Flags4 = static_cast<DINode::DIFlags>(4);2313 2314 auto *N = DIDerivedType::get(2315 Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope,2316 BaseType, 2, 3, 4, DWARFAddressSpace, std::nullopt, Flags5, ExtraData);2317 auto *N1 = DIDerivedType::get(Context, dwarf::DW_TAG_LLVM_ptrauth_type, "",2318 File, 1, Scope, N, 2, 3, 4, DWARFAddressSpace,2319 PtrAuthData, Flags5, ExtraData);2320 EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag());2321 EXPECT_EQ("something", N->getName());2322 EXPECT_EQ(File, N->getFile());2323 EXPECT_EQ(1u, N->getLine());2324 EXPECT_EQ(Scope, N->getScope());2325 EXPECT_EQ(BaseType, N->getBaseType());2326 EXPECT_EQ(2u, N->getSizeInBits());2327 EXPECT_EQ(3u, N->getAlignInBits());2328 EXPECT_EQ(4u, N->getOffsetInBits());2329 EXPECT_EQ(DWARFAddressSpace, *N->getDWARFAddressSpace());2330 EXPECT_EQ(std::nullopt, N->getPtrAuthData());2331 EXPECT_EQ(PtrAuthData, N1->getPtrAuthData());2332 EXPECT_NE(PtrAuthData2, N1->getPtrAuthData());2333 EXPECT_EQ(5u, N->getFlags());2334 EXPECT_EQ(ExtraData, N->getExtraData());2335 EXPECT_EQ(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2336 "something", File, 1, Scope, BaseType, 2, 3,2337 4, DWARFAddressSpace, std::nullopt, Flags5,2338 ExtraData));2339 2340 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_reference_type,2341 "something", File, 1, Scope, BaseType, 2, 3,2342 4, DWARFAddressSpace, std::nullopt, Flags5,2343 ExtraData));2344 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else",2345 File, 1, Scope, BaseType, 2, 3, 4,2346 DWARFAddressSpace, std::nullopt, Flags5,2347 ExtraData));2348 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2349 "something", getFile(), 1, Scope, BaseType, 2,2350 3, 4, DWARFAddressSpace, std::nullopt, Flags5,2351 ExtraData));2352 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2353 "something", File, 2, Scope, BaseType, 2, 3,2354 4, DWARFAddressSpace, std::nullopt, Flags5,2355 ExtraData));2356 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2357 "something", File, 1, getSubprogram(),2358 BaseType, 2, 3, 4, DWARFAddressSpace,2359 std::nullopt, Flags5, ExtraData));2360 EXPECT_NE(N, DIDerivedType::get(2361 Context, dwarf::DW_TAG_pointer_type, "something", File, 1,2362 Scope, getBasicType("basic2"), 2, 3, 4, DWARFAddressSpace,2363 std::nullopt, Flags5, ExtraData));2364 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2365 "something", File, 1, Scope, BaseType, 3, 3,2366 4, DWARFAddressSpace, std::nullopt, Flags5,2367 ExtraData));2368 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2369 "something", File, 1, Scope, BaseType, 2, 2,2370 4, DWARFAddressSpace, std::nullopt, Flags5,2371 ExtraData));2372 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2373 "something", File, 1, Scope, BaseType, 2, 3,2374 5, DWARFAddressSpace, std::nullopt, Flags5,2375 ExtraData));2376 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2377 "something", File, 1, Scope, BaseType, 2, 3,2378 4, DWARFAddressSpace + 1, std::nullopt,2379 Flags5, ExtraData));2380 EXPECT_NE(N1,2381 DIDerivedType::get(Context, dwarf::DW_TAG_LLVM_ptrauth_type, "",2382 File, 1, Scope, N, 2, 3, 4, DWARFAddressSpace,2383 std::nullopt, Flags5, ExtraData));2384 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2385 "something", File, 1, Scope, BaseType, 2, 3,2386 4, DWARFAddressSpace, std::nullopt, Flags4,2387 ExtraData));2388 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,2389 "something", File, 1, Scope, BaseType, 2, 3,2390 4, DWARFAddressSpace, std::nullopt, Flags5,2391 getTuple()));2392 2393 TempDIDerivedType Temp = N->clone();2394 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2395 TempDIDerivedType Temp1 = N1->clone();2396 EXPECT_EQ(N1, MDNode::replaceWithUniqued(std::move(Temp1)));2397}2398 2399TEST_F(DIDerivedTypeTest, getWithLargeValues) {2400 DIFile *File = getFile();2401 DIScope *Scope = getSubprogram();2402 DIType *BaseType = getBasicType("basic");2403 MDTuple *ExtraData = getTuple();2404 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);2405 2406 auto *N = DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",2407 File, 1, Scope, BaseType, UINT64_MAX,2408 UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3,2409 std::nullopt, Flags, ExtraData);2410 EXPECT_EQ(UINT64_MAX, N->getSizeInBits());2411 EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits());2412 EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits());2413 EXPECT_EQ(UINT32_MAX - 3, *N->getDWARFAddressSpace());2414 2415 auto *N1 = DIDerivedType::get(2416 Context, dwarf::DW_TAG_LLVM_ptrauth_type, "", File, 1, Scope, N,2417 UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3,2418 DIDerivedType::PtrAuthData(7, true, 0xffff, true, false), Flags,2419 ExtraData);2420 EXPECT_EQ(7U, N1->getPtrAuthData()->key());2421 EXPECT_EQ(true, N1->getPtrAuthData()->isAddressDiscriminated());2422 EXPECT_EQ(0xffffU, N1->getPtrAuthData()->extraDiscriminator());2423}2424 2425typedef MetadataTest DICompositeTypeTest;2426 2427TEST_F(DICompositeTypeTest, get) {2428 unsigned Tag = dwarf::DW_TAG_structure_type;2429 StringRef Name = "some name";2430 DIFile *File = getFile();2431 unsigned Line = 1;2432 DIScope *Scope = getSubprogram();2433 DIType *BaseType = getCompositeType();2434 uint64_t SizeInBits = 2;2435 uint32_t AlignInBits = 3;2436 uint64_t OffsetInBits = 4;2437 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);2438 MDTuple *Elements = getTuple();2439 unsigned RuntimeLang = 6;2440 DIType *VTableHolder = getCompositeType();2441 MDTuple *TemplateParams = getTuple();2442 StringRef Identifier = "some id";2443 std::optional<uint32_t> EnumKind = 1;2444 2445 auto *N = DICompositeType::get(2446 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2447 OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder,2448 TemplateParams, Identifier);2449 EXPECT_EQ(Tag, N->getTag());2450 EXPECT_EQ(Name, N->getName());2451 EXPECT_EQ(File, N->getFile());2452 EXPECT_EQ(Line, N->getLine());2453 EXPECT_EQ(Scope, N->getScope());2454 EXPECT_EQ(BaseType, N->getBaseType());2455 EXPECT_EQ(SizeInBits, N->getSizeInBits());2456 EXPECT_EQ(AlignInBits, N->getAlignInBits());2457 EXPECT_EQ(OffsetInBits, N->getOffsetInBits());2458 EXPECT_EQ(Flags, N->getFlags());2459 EXPECT_EQ(Elements, N->getElements().get());2460 EXPECT_EQ(RuntimeLang, N->getRuntimeLang());2461 EXPECT_EQ(VTableHolder, N->getVTableHolder());2462 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());2463 EXPECT_EQ(Identifier, N->getIdentifier());2464 EXPECT_EQ(EnumKind, N->getEnumKind());2465 2466 EXPECT_EQ(N, DICompositeType::get(2467 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2468 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,2469 EnumKind, VTableHolder, TemplateParams, Identifier));2470 2471 EXPECT_NE(N, DICompositeType::get(Context, Tag + 1, Name, File, Line, Scope,2472 BaseType, SizeInBits, AlignInBits,2473 OffsetInBits, Flags, Elements, RuntimeLang,2474 EnumKind, VTableHolder, TemplateParams,2475 Identifier));2476 EXPECT_NE(N, DICompositeType::get(2477 Context, Tag, "abc", File, Line, Scope, BaseType, SizeInBits,2478 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,2479 EnumKind, VTableHolder, TemplateParams, Identifier));2480 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, getFile(), Line, Scope,2481 BaseType, SizeInBits, AlignInBits,2482 OffsetInBits, Flags, Elements, RuntimeLang,2483 EnumKind, VTableHolder, TemplateParams,2484 Identifier));2485 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line + 1, Scope,2486 BaseType, SizeInBits, AlignInBits,2487 OffsetInBits, Flags, Elements, RuntimeLang,2488 EnumKind, VTableHolder, TemplateParams,2489 Identifier));2490 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line,2491 getSubprogram(), BaseType, SizeInBits,2492 AlignInBits, OffsetInBits, Flags, Elements,2493 RuntimeLang, EnumKind, VTableHolder,2494 TemplateParams, Identifier));2495 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,2496 getBasicType("other"), SizeInBits,2497 AlignInBits, OffsetInBits, Flags, Elements,2498 RuntimeLang, EnumKind, VTableHolder,2499 TemplateParams, Identifier));2500 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,2501 BaseType, SizeInBits + 1, AlignInBits,2502 OffsetInBits, Flags, Elements, RuntimeLang,2503 EnumKind, VTableHolder, TemplateParams,2504 Identifier));2505 EXPECT_NE(N, DICompositeType::get(2506 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2507 AlignInBits + 1, OffsetInBits, Flags, Elements, RuntimeLang,2508 EnumKind, VTableHolder, TemplateParams, Identifier));2509 EXPECT_NE(N, DICompositeType::get(2510 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2511 AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang,2512 EnumKind, VTableHolder, TemplateParams, Identifier));2513 DINode::DIFlags FlagsPOne = static_cast<DINode::DIFlags>(Flags + 1);2514 EXPECT_NE(N, DICompositeType::get(2515 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2516 AlignInBits, OffsetInBits, FlagsPOne, Elements, RuntimeLang,2517 EnumKind, VTableHolder, TemplateParams, Identifier));2518 EXPECT_NE(N, DICompositeType::get(2519 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2520 AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang,2521 EnumKind, VTableHolder, TemplateParams, Identifier));2522 EXPECT_NE(N, DICompositeType::get(2523 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2524 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1,2525 EnumKind, VTableHolder, TemplateParams, Identifier));2526 EXPECT_NE(N, DICompositeType::get(2527 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2528 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,2529 EnumKind, getCompositeType(), TemplateParams, Identifier));2530 EXPECT_NE(N, DICompositeType::get(2531 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2532 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,2533 EnumKind, VTableHolder, getTuple(), Identifier));2534 EXPECT_NE(N, DICompositeType::get(2535 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,2536 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,2537 EnumKind, VTableHolder, TemplateParams, "other"));2538 2539 // Be sure that missing identifiers get null pointers.2540 EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,2541 BaseType, SizeInBits, AlignInBits,2542 OffsetInBits, Flags, Elements, RuntimeLang,2543 EnumKind, VTableHolder, TemplateParams, "")2544 ->getRawIdentifier());2545 EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,2546 BaseType, SizeInBits, AlignInBits,2547 OffsetInBits, Flags, Elements, RuntimeLang,2548 EnumKind, VTableHolder, TemplateParams)2549 ->getRawIdentifier());2550 2551 TempDICompositeType Temp = N->clone();2552 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2553}2554 2555TEST_F(DICompositeTypeTest, getWithLargeValues) {2556 unsigned Tag = dwarf::DW_TAG_structure_type;2557 StringRef Name = "some name";2558 DIFile *File = getFile();2559 unsigned Line = 1;2560 DIScope *Scope = getSubprogram();2561 DIType *BaseType = getCompositeType();2562 uint64_t SizeInBits = UINT64_MAX;2563 uint32_t AlignInBits = UINT32_MAX - 1;2564 uint64_t OffsetInBits = UINT64_MAX - 2;2565 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);2566 MDTuple *Elements = getTuple();2567 unsigned RuntimeLang = 6;2568 std::optional<uint32_t> EnumKind = 1;2569 DIType *VTableHolder = getCompositeType();2570 MDTuple *TemplateParams = getTuple();2571 StringRef Identifier = "some id";2572 2573 auto *N = DICompositeType::get(2574 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2575 OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder,2576 TemplateParams, Identifier);2577 EXPECT_EQ(SizeInBits, N->getSizeInBits());2578 EXPECT_EQ(AlignInBits, N->getAlignInBits());2579 EXPECT_EQ(OffsetInBits, N->getOffsetInBits());2580}2581 2582TEST_F(DICompositeTypeTest, replaceOperands) {2583 unsigned Tag = dwarf::DW_TAG_structure_type;2584 StringRef Name = "some name";2585 DIFile *File = getFile();2586 unsigned Line = 1;2587 DIScope *Scope = getSubprogram();2588 DIType *BaseType = getCompositeType();2589 uint64_t SizeInBits = 2;2590 uint32_t AlignInBits = 3;2591 uint64_t OffsetInBits = 4;2592 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);2593 unsigned RuntimeLang = 6;2594 std::optional<uint32_t> EnumKind = 1;2595 StringRef Identifier = "some id";2596 2597 auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,2598 BaseType, SizeInBits, AlignInBits,2599 OffsetInBits, Flags, nullptr, RuntimeLang,2600 EnumKind, nullptr, nullptr, Identifier);2601 2602 auto *Elements = MDTuple::getDistinct(Context, {});2603 EXPECT_EQ(nullptr, N->getElements().get());2604 N->replaceElements(Elements);2605 EXPECT_EQ(Elements, N->getElements().get());2606 N->replaceElements(nullptr);2607 EXPECT_EQ(nullptr, N->getElements().get());2608 2609 DIType *VTableHolder = getCompositeType();2610 EXPECT_EQ(nullptr, N->getVTableHolder());2611 N->replaceVTableHolder(VTableHolder);2612 EXPECT_EQ(VTableHolder, N->getVTableHolder());2613 // As an extension, the containing type can be anything. This is2614 // used by Rust to associate vtables with their concrete type.2615 DIType *BasicType = getBasicType("basic");2616 N->replaceVTableHolder(BasicType);2617 EXPECT_EQ(BasicType, N->getVTableHolder());2618 N->replaceVTableHolder(nullptr);2619 EXPECT_EQ(nullptr, N->getVTableHolder());2620 2621 auto *TemplateParams = MDTuple::getDistinct(Context, {});2622 EXPECT_EQ(nullptr, N->getTemplateParams().get());2623 N->replaceTemplateParams(TemplateParams);2624 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());2625 N->replaceTemplateParams(nullptr);2626 EXPECT_EQ(nullptr, N->getTemplateParams().get());2627}2628 2629TEST_F(DICompositeTypeTest, variant_part) {2630 unsigned Tag = dwarf::DW_TAG_variant_part;2631 StringRef Name = "some name";2632 DIFile *File = getFile();2633 unsigned Line = 1;2634 DIScope *Scope = getSubprogram();2635 DIType *BaseType = getCompositeType();2636 uint64_t SizeInBits = 2;2637 uint32_t AlignInBits = 3;2638 uint64_t OffsetInBits = 4;2639 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);2640 unsigned RuntimeLang = 6;2641 std::optional<uint32_t> EnumKind = 1;2642 StringRef Identifier = "some id";2643 DIDerivedType *Discriminator = cast<DIDerivedType>(getDerivedType());2644 DIDerivedType *Discriminator2 = cast<DIDerivedType>(getDerivedType());2645 2646 EXPECT_NE(Discriminator, Discriminator2);2647 2648 auto *N = DICompositeType::get(2649 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2650 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2651 Identifier, Discriminator);2652 2653 // Test the hashing.2654 auto *Same = DICompositeType::get(2655 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2656 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2657 Identifier, Discriminator);2658 auto *Other = DICompositeType::get(2659 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2660 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2661 Identifier, Discriminator2);2662 auto *NoDisc = DICompositeType::get(2663 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2664 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2665 Identifier, nullptr);2666 2667 EXPECT_EQ(N, Same);2668 EXPECT_NE(Same, Other);2669 EXPECT_NE(Same, NoDisc);2670 EXPECT_NE(Other, NoDisc);2671 2672 EXPECT_EQ(N->getDiscriminator(), Discriminator);2673}2674 2675TEST_F(DICompositeTypeTest, dynamicArray) {2676 unsigned Tag = dwarf::DW_TAG_array_type;2677 StringRef Name = "some name";2678 DIFile *File = getFile();2679 unsigned Line = 1;2680 DILocalScope *Scope = getSubprogram();2681 DIType *BaseType = getCompositeType();2682 uint64_t SizeInBits = 32;2683 uint32_t AlignInBits = 32;2684 uint64_t OffsetInBits = 4;2685 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(3);2686 unsigned RuntimeLang = 6;2687 std::optional<uint32_t> EnumKind = 1;2688 StringRef Identifier = "some id";2689 DIType *Type = getDerivedType();2690 Metadata *DlVar1 = DILocalVariable::get(Context, Scope, "dl_var1", File, 8,2691 Type, 2, Flags, 8, nullptr);2692 Metadata *DlVar2 = DILocalVariable::get(Context, Scope, "dl_var2", File, 8,2693 Type, 2, Flags, 8, nullptr);2694 uint64_t Elements1[] = {dwarf::DW_OP_push_object_address, dwarf::DW_OP_deref};2695 Metadata *DataLocation1 = DIExpression::get(Context, Elements1);2696 2697 uint64_t Elements2[] = {dwarf::DW_OP_constu, 0};2698 Metadata *DataLocation2 = DIExpression::get(Context, Elements2);2699 2700 uint64_t Elements3[] = {dwarf::DW_OP_constu, 3};2701 Metadata *Rank1 = DIExpression::get(Context, Elements3);2702 2703 uint64_t Elements4[] = {dwarf::DW_OP_constu, 4};2704 Metadata *Rank2 = DIExpression::get(Context, Elements4);2705 2706 ConstantInt *RankInt1 = ConstantInt::get(Context, APInt(7, 0));2707 ConstantAsMetadata *RankConst1 = ConstantAsMetadata::get(RankInt1);2708 ConstantInt *RankInt2 = ConstantInt::get(Context, APInt(6, 0));2709 ConstantAsMetadata *RankConst2 = ConstantAsMetadata::get(RankInt2);2710 auto *N1 = DICompositeType::get(2711 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2712 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2713 Identifier, nullptr, DlVar1);2714 2715 auto *Same1 = DICompositeType::get(2716 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2717 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2718 Identifier, nullptr, DlVar1);2719 2720 auto *Other1 = DICompositeType::get(2721 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2722 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2723 Identifier, nullptr, DlVar2);2724 2725 EXPECT_EQ(N1, Same1);2726 EXPECT_NE(Same1, Other1);2727 EXPECT_EQ(N1->getDataLocation(), DlVar1);2728 2729 auto *N2 = DICompositeType::get(2730 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2731 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2732 Identifier, nullptr, DataLocation1);2733 2734 auto *Same2 = DICompositeType::get(2735 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2736 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2737 Identifier, nullptr, DataLocation1);2738 2739 auto *Other2 = DICompositeType::get(2740 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2741 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2742 Identifier, nullptr, DataLocation2);2743 2744 EXPECT_EQ(N2, Same2);2745 EXPECT_NE(Same2, Other2);2746 EXPECT_EQ(N2->getDataLocationExp(), DataLocation1);2747 2748 auto *N3 = DICompositeType::get(2749 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2750 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2751 Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank1);2752 2753 auto *Same3 = DICompositeType::get(2754 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2755 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2756 Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank1);2757 2758 auto *Other3 = DICompositeType::get(2759 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2760 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2761 Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank2);2762 2763 EXPECT_EQ(N3, Same3);2764 EXPECT_NE(Same3, Other3);2765 EXPECT_EQ(N3->getRankExp(), Rank1);2766 2767 auto *N4 = DICompositeType::get(2768 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2769 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2770 Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst1);2771 2772 auto *Same4 = DICompositeType::get(2773 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2774 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2775 Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst1);2776 2777 auto *Other4 = DICompositeType::get(2778 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,2779 OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,2780 Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst2);2781 2782 EXPECT_EQ(N4, Same4);2783 EXPECT_NE(Same4, Other4);2784 EXPECT_EQ(N4->getRankConst(), RankInt1);2785}2786 2787typedef MetadataTest DISubroutineTypeTest;2788 2789TEST_F(DISubroutineTypeTest, get) {2790 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(1);2791 DINode::DIFlags FlagsPOne = static_cast<DINode::DIFlags>(Flags + 1);2792 MDTuple *TypeArray = getTuple();2793 2794 auto *N = DISubroutineType::get(Context, Flags, 0, TypeArray);2795 EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());2796 EXPECT_EQ(Flags, N->getFlags());2797 EXPECT_EQ(TypeArray, N->getTypeArray().get());2798 EXPECT_EQ(N, DISubroutineType::get(Context, Flags, 0, TypeArray));2799 2800 EXPECT_NE(N, DISubroutineType::get(Context, FlagsPOne, 0, TypeArray));2801 EXPECT_NE(N, DISubroutineType::get(Context, Flags, 0, getTuple()));2802 2803 // Test the hashing of calling conventions.2804 auto *Fast = DISubroutineType::get(2805 Context, Flags, dwarf::DW_CC_BORLAND_msfastcall, TypeArray);2806 auto *Std = DISubroutineType::get(Context, Flags,2807 dwarf::DW_CC_BORLAND_stdcall, TypeArray);2808 EXPECT_EQ(Fast,2809 DISubroutineType::get(Context, Flags,2810 dwarf::DW_CC_BORLAND_msfastcall, TypeArray));2811 EXPECT_EQ(Std, DISubroutineType::get(2812 Context, Flags, dwarf::DW_CC_BORLAND_stdcall, TypeArray));2813 2814 EXPECT_NE(N, Fast);2815 EXPECT_NE(N, Std);2816 EXPECT_NE(Fast, Std);2817 2818 TempDISubroutineType Temp = N->clone();2819 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2820 2821 // Test always-empty operands.2822 EXPECT_EQ(nullptr, N->getScope());2823 EXPECT_EQ(nullptr, N->getFile());2824 EXPECT_EQ("", N->getName());2825}2826 2827typedef MetadataTest DIFileTest;2828 2829TEST_F(DIFileTest, get) {2830 StringRef Filename = "file";2831 StringRef Directory = "dir";2832 DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_MD5;2833 StringRef ChecksumString = "000102030405060708090a0b0c0d0e0f";2834 DIFile::ChecksumInfo<StringRef> Checksum(CSKind, ChecksumString);2835 StringRef Source = "source";2836 auto *N = DIFile::get(Context, Filename, Directory, Checksum, Source);2837 2838 EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());2839 EXPECT_EQ(Filename, N->getFilename());2840 EXPECT_EQ(Directory, N->getDirectory());2841 EXPECT_EQ(Checksum, N->getChecksum());2842 EXPECT_EQ(Source, N->getSource());2843 EXPECT_EQ(N, DIFile::get(Context, Filename, Directory, Checksum, Source));2844 2845 EXPECT_NE(N, DIFile::get(Context, "other", Directory, Checksum, Source));2846 EXPECT_NE(N, DIFile::get(Context, Filename, "other", Checksum, Source));2847 DIFile::ChecksumInfo<StringRef> OtherChecksum(DIFile::ChecksumKind::CSK_SHA1, ChecksumString);2848 EXPECT_NE(2849 N, DIFile::get(Context, Filename, Directory, OtherChecksum));2850 StringRef OtherSource = "other";2851 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum, OtherSource));2852 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum));2853 EXPECT_NE(N, DIFile::get(Context, Filename, Directory));2854 2855 TempDIFile Temp = N->clone();2856 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));2857}2858 2859TEST_F(DIFileTest, EmptySource) {2860 DIFile *N = DIFile::get(Context, "file", "dir");2861 EXPECT_EQ(std::nullopt, N->getSource());2862 2863 std::optional<DIFile::ChecksumInfo<StringRef>> Checksum;2864 std::optional<StringRef> Source;2865 N = DIFile::get(Context, "file", "dir", Checksum, Source);2866 EXPECT_EQ(Source, N->getSource());2867 2868 Source = "";2869 N = DIFile::get(Context, "file", "dir", Checksum, Source);2870 EXPECT_EQ(Source, N->getSource());2871}2872 2873TEST_F(DIFileTest, ScopeGetFile) {2874 // Ensure that DIScope::getFile() returns itself.2875 DIScope *N = DIFile::get(Context, "file", "dir");2876 EXPECT_EQ(N, N->getFile());2877}2878 2879typedef MetadataTest DICompileUnitTest;2880 2881TEST_F(DICompileUnitTest, get) {2882 unsigned SourceLanguage = 1;2883 DIFile *File = getFile();2884 StringRef Producer = "some producer";2885 bool IsOptimized = false;2886 StringRef Flags = "flag after flag";2887 unsigned RuntimeVersion = 2;2888 StringRef SplitDebugFilename = "another/file";2889 auto EmissionKind = DICompileUnit::FullDebug;2890 MDTuple *EnumTypes = getTuple();2891 MDTuple *RetainedTypes = getTuple();2892 MDTuple *GlobalVariables = getTuple();2893 MDTuple *ImportedEntities = getTuple();2894 uint64_t DWOId = 0x10000000c0ffee;2895 MDTuple *Macros = getTuple();2896 StringRef SysRoot = "/";2897 StringRef SDK = "MacOSX.sdk";2898 auto *N = DICompileUnit::getDistinct(2899 Context, DISourceLanguageName(SourceLanguage), File, Producer,2900 IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind,2901 EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros,2902 DWOId, true, false, DICompileUnit::DebugNameTableKind::Default, false,2903 SysRoot, SDK);2904 2905 EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag());2906 EXPECT_EQ(SourceLanguage, N->getSourceLanguage().getUnversionedName());2907 EXPECT_EQ(File, N->getFile());2908 EXPECT_EQ(Producer, N->getProducer());2909 EXPECT_EQ(IsOptimized, N->isOptimized());2910 EXPECT_EQ(Flags, N->getFlags());2911 EXPECT_EQ(RuntimeVersion, N->getRuntimeVersion());2912 EXPECT_EQ(SplitDebugFilename, N->getSplitDebugFilename());2913 EXPECT_EQ(EmissionKind, N->getEmissionKind());2914 EXPECT_EQ(EnumTypes, N->getEnumTypes().get());2915 EXPECT_EQ(RetainedTypes, N->getRetainedTypes().get());2916 EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());2917 EXPECT_EQ(ImportedEntities, N->getImportedEntities().get());2918 EXPECT_EQ(Macros, N->getMacros().get());2919 EXPECT_EQ(DWOId, N->getDWOId());2920 EXPECT_EQ(SysRoot, N->getSysRoot());2921 EXPECT_EQ(SDK, N->getSDK());2922 2923 TempDICompileUnit Temp = N->clone();2924 EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag());2925 EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage().getUnversionedName());2926 EXPECT_EQ(File, Temp->getFile());2927 EXPECT_EQ(Producer, Temp->getProducer());2928 EXPECT_EQ(IsOptimized, Temp->isOptimized());2929 EXPECT_EQ(Flags, Temp->getFlags());2930 EXPECT_EQ(RuntimeVersion, Temp->getRuntimeVersion());2931 EXPECT_EQ(SplitDebugFilename, Temp->getSplitDebugFilename());2932 EXPECT_EQ(EmissionKind, Temp->getEmissionKind());2933 EXPECT_EQ(EnumTypes, Temp->getEnumTypes().get());2934 EXPECT_EQ(RetainedTypes, Temp->getRetainedTypes().get());2935 EXPECT_EQ(GlobalVariables, Temp->getGlobalVariables().get());2936 EXPECT_EQ(ImportedEntities, Temp->getImportedEntities().get());2937 EXPECT_EQ(Macros, Temp->getMacros().get());2938 EXPECT_EQ(SysRoot, Temp->getSysRoot());2939 EXPECT_EQ(SDK, Temp->getSDK());2940 2941 auto *TempAddress = Temp.get();2942 auto *Clone = MDNode::replaceWithPermanent(std::move(Temp));2943 EXPECT_TRUE(Clone->isDistinct());2944 EXPECT_EQ(TempAddress, Clone);2945}2946 2947TEST_F(DICompileUnitTest, replaceArrays) {2948 unsigned SourceLanguage = 1;2949 DIFile *File = getFile();2950 StringRef Producer = "some producer";2951 bool IsOptimized = false;2952 StringRef Flags = "flag after flag";2953 unsigned RuntimeVersion = 2;2954 StringRef SplitDebugFilename = "another/file";2955 auto EmissionKind = DICompileUnit::FullDebug;2956 MDTuple *EnumTypes = MDTuple::getDistinct(Context, {});2957 MDTuple *RetainedTypes = MDTuple::getDistinct(Context, {});2958 MDTuple *ImportedEntities = MDTuple::getDistinct(Context, {});2959 uint64_t DWOId = 0xc0ffee;2960 StringRef SysRoot = "/";2961 StringRef SDK = "MacOSX.sdk";2962 auto *N = DICompileUnit::getDistinct(2963 Context, DISourceLanguageName(SourceLanguage), File, Producer,2964 IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind,2965 EnumTypes, RetainedTypes, nullptr, ImportedEntities, nullptr, DWOId, true,2966 false, DICompileUnit::DebugNameTableKind::Default, false, SysRoot, SDK);2967 2968 auto *GlobalVariables = MDTuple::getDistinct(Context, {});2969 EXPECT_EQ(nullptr, N->getGlobalVariables().get());2970 N->replaceGlobalVariables(GlobalVariables);2971 EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());2972 N->replaceGlobalVariables(nullptr);2973 EXPECT_EQ(nullptr, N->getGlobalVariables().get());2974 2975 auto *Macros = MDTuple::getDistinct(Context, {});2976 EXPECT_EQ(nullptr, N->getMacros().get());2977 N->replaceMacros(Macros);2978 EXPECT_EQ(Macros, N->getMacros().get());2979 N->replaceMacros(nullptr);2980 EXPECT_EQ(nullptr, N->getMacros().get());2981}2982 2983typedef MetadataTest DISubprogramTest;2984 2985TEST_F(DISubprogramTest, get) {2986 DIScope *Scope = getCompositeType();2987 StringRef Name = "name";2988 StringRef LinkageName = "linkage";2989 DIFile *File = getFile();2990 unsigned Line = 2;2991 DISubroutineType *Type = getSubroutineType();2992 bool IsLocalToUnit = false;2993 bool IsDefinition = true;2994 unsigned ScopeLine = 3;2995 DIType *ContainingType = getCompositeType();2996 unsigned Virtuality = 2;2997 unsigned VirtualIndex = 5;2998 int ThisAdjustment = -3;2999 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(6);3000 bool IsOptimized = false;3001 MDTuple *TemplateParams = getTuple();3002 DISubprogram *Declaration = getSubprogram();3003 MDTuple *RetainedNodes = getTuple();3004 MDTuple *ThrownTypes = getTuple();3005 MDTuple *Annotations = getTuple();3006 StringRef TargetFuncName = "target";3007 DICompileUnit *Unit = getUnit();3008 DISubprogram::DISPFlags SPFlags =3009 static_cast<DISubprogram::DISPFlags>(Virtuality);3010 assert(!IsLocalToUnit && IsDefinition && !IsOptimized &&3011 "bools and SPFlags have to match");3012 SPFlags |= DISubprogram::SPFlagDefinition;3013 bool KeyInstructions = false;3014 3015 auto *N = DISubprogram::get(3016 Context, Scope, Name, LinkageName, File, Line, Type, ScopeLine,3017 ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit,3018 TemplateParams, Declaration, RetainedNodes, ThrownTypes, Annotations,3019 TargetFuncName, KeyInstructions);3020 3021 EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag());3022 EXPECT_EQ(Scope, N->getScope());3023 EXPECT_EQ(Name, N->getName());3024 EXPECT_EQ(LinkageName, N->getLinkageName());3025 EXPECT_EQ(File, N->getFile());3026 EXPECT_EQ(Line, N->getLine());3027 EXPECT_EQ(Type, N->getType());3028 EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());3029 EXPECT_EQ(IsDefinition, N->isDefinition());3030 EXPECT_EQ(ScopeLine, N->getScopeLine());3031 EXPECT_EQ(ContainingType, N->getContainingType());3032 EXPECT_EQ(Virtuality, N->getVirtuality());3033 EXPECT_EQ(VirtualIndex, N->getVirtualIndex());3034 EXPECT_EQ(ThisAdjustment, N->getThisAdjustment());3035 EXPECT_EQ(Flags, N->getFlags());3036 EXPECT_EQ(IsOptimized, N->isOptimized());3037 EXPECT_EQ(Unit, N->getUnit());3038 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());3039 EXPECT_EQ(Declaration, N->getDeclaration());3040 EXPECT_EQ(RetainedNodes, N->getRetainedNodes().get());3041 EXPECT_EQ(ThrownTypes, N->getThrownTypes().get());3042 EXPECT_EQ(Annotations, N->getAnnotations().get());3043 EXPECT_EQ(TargetFuncName, N->getTargetFuncName());3044 EXPECT_EQ(KeyInstructions, N->getKeyInstructionsEnabled());3045 EXPECT_EQ(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3046 Type, ScopeLine, ContainingType, VirtualIndex,3047 ThisAdjustment, Flags, SPFlags, Unit,3048 TemplateParams, Declaration, RetainedNodes,3049 ThrownTypes, Annotations, TargetFuncName,3050 KeyInstructions));3051 3052 EXPECT_NE(N, DISubprogram::get(Context, getCompositeType(), Name, LinkageName,3053 File, Line, Type, ScopeLine, ContainingType,3054 VirtualIndex, ThisAdjustment, Flags, SPFlags,3055 Unit, TemplateParams, Declaration,3056 RetainedNodes, ThrownTypes, Annotations,3057 TargetFuncName, KeyInstructions));3058 EXPECT_NE(N, DISubprogram::get(Context, Scope, "other", LinkageName, File,3059 Line, Type, ScopeLine, ContainingType,3060 VirtualIndex, ThisAdjustment, Flags, SPFlags,3061 Unit, TemplateParams, Declaration,3062 RetainedNodes, ThrownTypes, Annotations,3063 TargetFuncName, KeyInstructions));3064 EXPECT_NE(N, DISubprogram::get(3065 Context, Scope, Name, "other", File, Line, Type, ScopeLine,3066 ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags,3067 Unit, TemplateParams, Declaration, RetainedNodes,3068 ThrownTypes, Annotations, TargetFuncName, KeyInstructions));3069 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, getFile(),3070 Line, Type, ScopeLine, ContainingType,3071 VirtualIndex, ThisAdjustment, Flags, SPFlags,3072 Unit, TemplateParams, Declaration,3073 RetainedNodes, ThrownTypes, Annotations,3074 TargetFuncName, KeyInstructions));3075 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File,3076 Line + 1, Type, ScopeLine, ContainingType,3077 VirtualIndex, ThisAdjustment, Flags, SPFlags,3078 Unit, TemplateParams, Declaration,3079 RetainedNodes, ThrownTypes, Annotations,3080 TargetFuncName, KeyInstructions));3081 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3082 getSubroutineType(), ScopeLine, ContainingType,3083 VirtualIndex, ThisAdjustment, Flags, SPFlags,3084 Unit, TemplateParams, Declaration,3085 RetainedNodes, ThrownTypes, Annotations,3086 TargetFuncName, KeyInstructions));3087 EXPECT_NE(N, DISubprogram::get(3088 Context, Scope, Name, LinkageName, File, Line, Type,3089 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,3090 Flags, SPFlags ^ DISubprogram::SPFlagLocalToUnit, Unit,3091 TemplateParams, Declaration, RetainedNodes, ThrownTypes,3092 Annotations, TargetFuncName, KeyInstructions));3093 EXPECT_NE(N, DISubprogram::get(3094 Context, Scope, Name, LinkageName, File, Line, Type,3095 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,3096 Flags, SPFlags ^ DISubprogram::SPFlagDefinition, Unit,3097 TemplateParams, Declaration, RetainedNodes, ThrownTypes,3098 Annotations, TargetFuncName, KeyInstructions));3099 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3100 Type, ScopeLine + 1, ContainingType,3101 VirtualIndex, ThisAdjustment, Flags, SPFlags,3102 Unit, TemplateParams, Declaration,3103 RetainedNodes, ThrownTypes, Annotations,3104 TargetFuncName, KeyInstructions));3105 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3106 Type, ScopeLine, getCompositeType(),3107 VirtualIndex, ThisAdjustment, Flags, SPFlags,3108 Unit, TemplateParams, Declaration,3109 RetainedNodes, ThrownTypes, Annotations,3110 TargetFuncName, KeyInstructions));3111 EXPECT_NE(N, DISubprogram::get(3112 Context, Scope, Name, LinkageName, File, Line, Type,3113 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,3114 Flags, SPFlags ^ DISubprogram::SPFlagVirtual, Unit,3115 TemplateParams, Declaration, RetainedNodes, ThrownTypes,3116 Annotations, TargetFuncName, KeyInstructions));3117 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3118 Type, ScopeLine, ContainingType,3119 VirtualIndex + 1, ThisAdjustment, Flags,3120 SPFlags, Unit, TemplateParams, Declaration,3121 RetainedNodes, ThrownTypes, Annotations,3122 TargetFuncName, KeyInstructions));3123 EXPECT_NE(N, DISubprogram::get(3124 Context, Scope, Name, LinkageName, File, Line, Type,3125 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,3126 Flags, SPFlags ^ DISubprogram::SPFlagOptimized, Unit,3127 TemplateParams, Declaration, RetainedNodes, ThrownTypes,3128 Annotations, TargetFuncName, KeyInstructions));3129 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3130 Type, ScopeLine, ContainingType, VirtualIndex,3131 ThisAdjustment, Flags, SPFlags, nullptr,3132 TemplateParams, Declaration, RetainedNodes,3133 ThrownTypes, Annotations, TargetFuncName,3134 KeyInstructions));3135 EXPECT_NE(N, DISubprogram::get(3136 Context, Scope, Name, LinkageName, File, Line, Type,3137 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,3138 Flags, SPFlags, Unit, getTuple(), Declaration, RetainedNodes,3139 ThrownTypes, Annotations, TargetFuncName, KeyInstructions));3140 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3141 Type, ScopeLine, ContainingType, VirtualIndex,3142 ThisAdjustment, Flags, SPFlags, Unit,3143 TemplateParams, getSubprogram(), RetainedNodes,3144 ThrownTypes, Annotations, TargetFuncName,3145 KeyInstructions));3146 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3147 Type, ScopeLine, ContainingType, VirtualIndex,3148 ThisAdjustment, Flags, SPFlags, Unit,3149 TemplateParams, Declaration, getTuple(),3150 ThrownTypes, Annotations, TargetFuncName,3151 KeyInstructions));3152 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3153 Type, ScopeLine, ContainingType, VirtualIndex,3154 ThisAdjustment, Flags, SPFlags, Unit,3155 TemplateParams, Declaration, RetainedNodes,3156 getTuple(), Annotations, TargetFuncName,3157 KeyInstructions));3158 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3159 Type, ScopeLine, ContainingType, VirtualIndex,3160 ThisAdjustment, Flags, SPFlags, Unit,3161 TemplateParams, Declaration, RetainedNodes,3162 ThrownTypes, getTuple(), TargetFuncName,3163 KeyInstructions));3164 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3165 Type, ScopeLine, ContainingType, VirtualIndex,3166 ThisAdjustment, Flags, SPFlags, Unit,3167 TemplateParams, Declaration, RetainedNodes,3168 ThrownTypes, Annotations, "other",3169 KeyInstructions));3170 EXPECT_NE(N,3171 DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,3172 Type, ScopeLine, ContainingType, VirtualIndex,3173 ThisAdjustment, Flags, SPFlags, Unit,3174 TemplateParams, Declaration, RetainedNodes,3175 ThrownTypes, Annotations, TargetFuncName, true));3176 3177 TempDISubprogram Temp = N->clone();3178 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3179}3180 3181typedef MetadataTest DILexicalBlockTest;3182 3183TEST_F(DILexicalBlockTest, get) {3184 DILocalScope *Scope = getSubprogram();3185 DIFile *File = getFile();3186 unsigned Line = 5;3187 unsigned Column = 8;3188 3189 auto *N = DILexicalBlock::get(Context, Scope, File, Line, Column);3190 3191 EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());3192 EXPECT_EQ(Scope, N->getScope());3193 EXPECT_EQ(File, N->getFile());3194 EXPECT_EQ(Line, N->getLine());3195 EXPECT_EQ(Column, N->getColumn());3196 EXPECT_EQ(N, DILexicalBlock::get(Context, Scope, File, Line, Column));3197 3198 EXPECT_NE(N,3199 DILexicalBlock::get(Context, getSubprogram(), File, Line, Column));3200 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, getFile(), Line, Column));3201 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line + 1, Column));3202 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line, Column + 1));3203 3204 TempDILexicalBlock Temp = N->clone();3205 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3206}3207 3208TEST_F(DILexicalBlockTest, Overflow) {3209 DISubprogram *SP = getSubprogram();3210 DIFile *F = getFile();3211 {3212 auto *LB = DILexicalBlock::get(Context, SP, F, 2, 7);3213 EXPECT_EQ(2u, LB->getLine());3214 EXPECT_EQ(7u, LB->getColumn());3215 }3216 unsigned U16 = 1u << 16;3217 {3218 auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16 - 1);3219 EXPECT_EQ(UINT32_MAX, LB->getLine());3220 EXPECT_EQ(U16 - 1, LB->getColumn());3221 }3222 {3223 auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16);3224 EXPECT_EQ(UINT32_MAX, LB->getLine());3225 EXPECT_EQ(0u, LB->getColumn());3226 }3227 {3228 auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16 + 1);3229 EXPECT_EQ(UINT32_MAX, LB->getLine());3230 EXPECT_EQ(0u, LB->getColumn());3231 }3232}3233 3234typedef MetadataTest DILexicalBlockFileTest;3235 3236TEST_F(DILexicalBlockFileTest, get) {3237 DILocalScope *Scope = getSubprogram();3238 DIFile *File = getFile();3239 unsigned Discriminator = 5;3240 3241 auto *N = DILexicalBlockFile::get(Context, Scope, File, Discriminator);3242 3243 EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());3244 EXPECT_EQ(Scope, N->getScope());3245 EXPECT_EQ(File, N->getFile());3246 EXPECT_EQ(Discriminator, N->getDiscriminator());3247 EXPECT_EQ(N, DILexicalBlockFile::get(Context, Scope, File, Discriminator));3248 3249 EXPECT_NE(N, DILexicalBlockFile::get(Context, getSubprogram(), File,3250 Discriminator));3251 EXPECT_NE(N,3252 DILexicalBlockFile::get(Context, Scope, getFile(), Discriminator));3253 EXPECT_NE(N,3254 DILexicalBlockFile::get(Context, Scope, File, Discriminator + 1));3255 3256 TempDILexicalBlockFile Temp = N->clone();3257 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3258}3259 3260typedef MetadataTest DINamespaceTest;3261 3262TEST_F(DINamespaceTest, get) {3263 DIScope *Scope = getFile();3264 StringRef Name = "namespace";3265 bool ExportSymbols = true;3266 3267 auto *N = DINamespace::get(Context, Scope, Name, ExportSymbols);3268 3269 EXPECT_EQ(dwarf::DW_TAG_namespace, N->getTag());3270 EXPECT_EQ(Scope, N->getScope());3271 EXPECT_EQ(Name, N->getName());3272 EXPECT_EQ(N, DINamespace::get(Context, Scope, Name, ExportSymbols));3273 EXPECT_NE(N, DINamespace::get(Context, getFile(), Name, ExportSymbols));3274 EXPECT_NE(N, DINamespace::get(Context, Scope, "other", ExportSymbols));3275 EXPECT_NE(N, DINamespace::get(Context, Scope, Name, !ExportSymbols));3276 3277 TempDINamespace Temp = N->clone();3278 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3279}3280 3281typedef MetadataTest DIModuleTest;3282 3283TEST_F(DIModuleTest, get) {3284 DIFile *File = getFile();3285 DIScope *Scope = getFile();3286 StringRef Name = "module";3287 StringRef ConfigMacro = "-DNDEBUG";3288 StringRef Includes = "-I.";3289 StringRef APINotes = "/tmp/m.apinotes";3290 unsigned LineNo = 4;3291 bool IsDecl = true;3292 3293 auto *N = DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,3294 APINotes, LineNo, IsDecl);3295 3296 EXPECT_EQ(dwarf::DW_TAG_module, N->getTag());3297 EXPECT_EQ(File, N->getFile());3298 EXPECT_EQ(Scope, N->getScope());3299 EXPECT_EQ(Name, N->getName());3300 EXPECT_EQ(ConfigMacro, N->getConfigurationMacros());3301 EXPECT_EQ(Includes, N->getIncludePath());3302 EXPECT_EQ(APINotes, N->getAPINotesFile());3303 EXPECT_EQ(LineNo, N->getLineNo());3304 EXPECT_EQ(IsDecl, N->getIsDecl());3305 EXPECT_EQ(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,3306 APINotes, LineNo, IsDecl));3307 EXPECT_NE(N, DIModule::get(Context, getFile(), getFile(), Name, ConfigMacro,3308 Includes, APINotes, LineNo, IsDecl));3309 EXPECT_NE(N, DIModule::get(Context, File, Scope, "other", ConfigMacro,3310 Includes, APINotes, LineNo, IsDecl));3311 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, "other", Includes,3312 APINotes, LineNo, IsDecl));3313 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, "other",3314 APINotes, LineNo, IsDecl));3315 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,3316 "other", LineNo, IsDecl));3317 EXPECT_NE(N, DIModule::get(Context, getFile(), Scope, Name, ConfigMacro,3318 Includes, APINotes, LineNo, IsDecl));3319 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,3320 APINotes, 5, IsDecl));3321 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,3322 APINotes, LineNo, false));3323 3324 TempDIModule Temp = N->clone();3325 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3326}3327 3328typedef MetadataTest DITemplateTypeParameterTest;3329 3330TEST_F(DITemplateTypeParameterTest, get) {3331 StringRef Name = "template";3332 DIType *Type = getBasicType("basic");3333 bool defaulted = false;3334 3335 auto *N = DITemplateTypeParameter::get(Context, Name, Type, defaulted);3336 3337 EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());3338 EXPECT_EQ(Name, N->getName());3339 EXPECT_EQ(Type, N->getType());3340 EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type, defaulted));3341 3342 EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type, defaulted));3343 EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name,3344 getBasicType("other"), defaulted));3345 EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name, Type, true));3346 3347 TempDITemplateTypeParameter Temp = N->clone();3348 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3349}3350 3351typedef MetadataTest DITemplateValueParameterTest;3352 3353TEST_F(DITemplateValueParameterTest, get) {3354 unsigned Tag = dwarf::DW_TAG_template_value_parameter;3355 StringRef Name = "template";3356 DIType *Type = getBasicType("basic");3357 bool defaulted = false;3358 Metadata *Value = getConstantAsMetadata();3359 3360 auto *N =3361 DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted, Value);3362 EXPECT_EQ(Tag, N->getTag());3363 EXPECT_EQ(Name, N->getName());3364 EXPECT_EQ(Type, N->getType());3365 EXPECT_EQ(Value, N->getValue());3366 EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type,3367 defaulted, Value));3368 3369 EXPECT_NE(N, DITemplateValueParameter::get(3370 Context, dwarf::DW_TAG_GNU_template_template_param, Name,3371 Type, defaulted, Value));3372 EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, "other", Type,3373 defaulted, Value));3374 EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name,3375 getBasicType("other"), defaulted,3376 Value));3377 EXPECT_NE(N,3378 DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted,3379 getConstantAsMetadata()));3380 EXPECT_NE(3381 N, DITemplateValueParameter::get(Context, Tag, Name, Type, true, Value));3382 3383 TempDITemplateValueParameter Temp = N->clone();3384 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3385}3386 3387typedef MetadataTest DIGlobalVariableTest;3388 3389TEST_F(DIGlobalVariableTest, get) {3390 DIScope *Scope = getSubprogram();3391 StringRef Name = "name";3392 StringRef LinkageName = "linkage";3393 DIFile *File = getFile();3394 unsigned Line = 5;3395 DIType *Type = getDerivedType();3396 bool IsLocalToUnit = false;3397 bool IsDefinition = true;3398 MDTuple *templateParams = getTuple();3399 DIDerivedType *StaticDataMemberDeclaration =3400 cast<DIDerivedType>(getDerivedType());3401 3402 uint32_t AlignInBits = 8;3403 3404 auto *N = DIGlobalVariable::get(3405 Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,3406 IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits,3407 nullptr);3408 3409 EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag());3410 EXPECT_EQ(Scope, N->getScope());3411 EXPECT_EQ(Name, N->getName());3412 EXPECT_EQ(LinkageName, N->getLinkageName());3413 EXPECT_EQ(File, N->getFile());3414 EXPECT_EQ(Line, N->getLine());3415 EXPECT_EQ(Type, N->getType());3416 EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());3417 EXPECT_EQ(IsDefinition, N->isDefinition());3418 EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration());3419 EXPECT_EQ(templateParams, N->getTemplateParams());3420 EXPECT_EQ(AlignInBits, N->getAlignInBits());3421 EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3422 Line, Type, IsLocalToUnit, IsDefinition,3423 StaticDataMemberDeclaration,3424 templateParams, AlignInBits, nullptr));3425 3426 EXPECT_NE(N, DIGlobalVariable::get(3427 Context, getSubprogram(), Name, LinkageName, File, Line,3428 Type, IsLocalToUnit, IsDefinition,3429 StaticDataMemberDeclaration, templateParams, AlignInBits,3430 nullptr));3431 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File,3432 Line, Type, IsLocalToUnit, IsDefinition,3433 StaticDataMemberDeclaration,3434 templateParams, AlignInBits, nullptr));3435 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line,3436 Type, IsLocalToUnit, IsDefinition,3437 StaticDataMemberDeclaration,3438 templateParams, AlignInBits, nullptr));3439 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName,3440 getFile(), Line, Type, IsLocalToUnit,3441 IsDefinition, StaticDataMemberDeclaration,3442 templateParams, AlignInBits, nullptr));3443 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3444 Line + 1, Type, IsLocalToUnit,3445 IsDefinition, StaticDataMemberDeclaration,3446 templateParams, AlignInBits, nullptr));3447 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3448 Line, getDerivedType(), IsLocalToUnit,3449 IsDefinition, StaticDataMemberDeclaration,3450 templateParams, AlignInBits, nullptr));3451 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3452 Line, Type, !IsLocalToUnit, IsDefinition,3453 StaticDataMemberDeclaration,3454 templateParams, AlignInBits, nullptr));3455 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3456 Line, Type, IsLocalToUnit, !IsDefinition,3457 StaticDataMemberDeclaration,3458 templateParams, AlignInBits, nullptr));3459 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3460 Line, Type, IsLocalToUnit, IsDefinition,3461 cast<DIDerivedType>(getDerivedType()),3462 templateParams, AlignInBits, nullptr));3463 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3464 Line, Type, IsLocalToUnit, IsDefinition,3465 StaticDataMemberDeclaration, nullptr,3466 AlignInBits, nullptr));3467 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,3468 Line, Type, IsLocalToUnit, IsDefinition,3469 StaticDataMemberDeclaration,3470 templateParams, (AlignInBits << 1),3471 nullptr));3472 3473 TempDIGlobalVariable Temp = N->clone();3474 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3475}3476 3477typedef MetadataTest DIGlobalVariableExpressionTest;3478 3479TEST_F(DIGlobalVariableExpressionTest, get) {3480 DIScope *Scope = getSubprogram();3481 StringRef Name = "name";3482 StringRef LinkageName = "linkage";3483 DIFile *File = getFile();3484 unsigned Line = 5;3485 DIType *Type = getDerivedType();3486 bool IsLocalToUnit = false;3487 bool IsDefinition = true;3488 MDTuple *templateParams = getTuple();3489 auto *Expr = DIExpression::get(Context, {1, 2});3490 auto *Expr2 = DIExpression::get(Context, {1, 2, 3});3491 DIDerivedType *StaticDataMemberDeclaration =3492 cast<DIDerivedType>(getDerivedType());3493 uint32_t AlignInBits = 8;3494 3495 auto *Var = DIGlobalVariable::get(3496 Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,3497 IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits,3498 nullptr);3499 auto *Var2 = DIGlobalVariable::get(3500 Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit,3501 IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits,3502 nullptr);3503 auto *N = DIGlobalVariableExpression::get(Context, Var, Expr);3504 3505 EXPECT_EQ(Var, N->getVariable());3506 EXPECT_EQ(Expr, N->getExpression());3507 EXPECT_EQ(N, DIGlobalVariableExpression::get(Context, Var, Expr));3508 EXPECT_NE(N, DIGlobalVariableExpression::get(Context, Var2, Expr));3509 EXPECT_NE(N, DIGlobalVariableExpression::get(Context, Var, Expr2));3510 3511 TempDIGlobalVariableExpression Temp = N->clone();3512 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3513}3514 3515typedef MetadataTest DILocalVariableTest;3516 3517TEST_F(DILocalVariableTest, get) {3518 DILocalScope *Scope = getSubprogram();3519 StringRef Name = "name";3520 DIFile *File = getFile();3521 unsigned Line = 5;3522 DIType *Type = getDerivedType();3523 unsigned Arg = 6;3524 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);3525 uint32_t AlignInBits = 8;3526 3527 auto *N =3528 DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, Flags,3529 AlignInBits, nullptr);3530 EXPECT_TRUE(N->isParameter());3531 EXPECT_EQ(Scope, N->getScope());3532 EXPECT_EQ(Name, N->getName());3533 EXPECT_EQ(File, N->getFile());3534 EXPECT_EQ(Line, N->getLine());3535 EXPECT_EQ(Type, N->getType());3536 EXPECT_EQ(Arg, N->getArg());3537 EXPECT_EQ(Flags, N->getFlags());3538 EXPECT_EQ(AlignInBits, N->getAlignInBits());3539 EXPECT_EQ(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg,3540 Flags, AlignInBits, nullptr));3541 3542 EXPECT_FALSE(3543 DILocalVariable::get(Context, Scope, Name, File, Line, Type, 0, Flags,3544 AlignInBits, nullptr)->isParameter());3545 EXPECT_NE(N, DILocalVariable::get(Context, getSubprogram(), Name, File, Line,3546 Type, Arg, Flags, AlignInBits, nullptr));3547 EXPECT_NE(N, DILocalVariable::get(Context, Scope, "other", File, Line, Type,3548 Arg, Flags, AlignInBits, nullptr));3549 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, getFile(), Line, Type,3550 Arg, Flags, AlignInBits, nullptr));3551 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line + 1, Type,3552 Arg, Flags, AlignInBits, nullptr));3553 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line,3554 getDerivedType(), Arg, Flags, AlignInBits,3555 nullptr));3556 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type,3557 Arg + 1, Flags, AlignInBits, nullptr));3558 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type,3559 Arg, Flags, (AlignInBits << 1), nullptr));3560 3561 TempDILocalVariable Temp = N->clone();3562 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3563}3564 3565TEST_F(DILocalVariableTest, getArg256) {3566 EXPECT_EQ(255u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),3567 0, nullptr, 255, DINode::FlagZero, 0,3568 nullptr)3569 ->getArg());3570 EXPECT_EQ(256u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),3571 0, nullptr, 256, DINode::FlagZero, 0,3572 nullptr)3573 ->getArg());3574 EXPECT_EQ(257u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),3575 0, nullptr, 257, DINode::FlagZero, 0,3576 nullptr)3577 ->getArg());3578 unsigned Max = UINT16_MAX;3579 EXPECT_EQ(Max, DILocalVariable::get(Context, getSubprogram(), "", getFile(),3580 0, nullptr, Max, DINode::FlagZero, 0,3581 nullptr)3582 ->getArg());3583}3584 3585typedef MetadataTest DIExpressionTest;3586 3587TEST_F(DIExpressionTest, get) {3588 uint64_t Elements[] = {2, 6, 9, 78, 0};3589 auto *N = DIExpression::get(Context, Elements);3590 EXPECT_EQ(ArrayRef(Elements), N->getElements());3591 EXPECT_EQ(N, DIExpression::get(Context, Elements));3592 3593 EXPECT_EQ(5u, N->getNumElements());3594 EXPECT_EQ(2u, N->getElement(0));3595 EXPECT_EQ(6u, N->getElement(1));3596 EXPECT_EQ(9u, N->getElement(2));3597 EXPECT_EQ(78u, N->getElement(3));3598 EXPECT_EQ(0u, N->getElement(4));3599 3600 TempDIExpression Temp = N->clone();3601 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));3602 3603 // Test DIExpression::prepend().3604 uint64_t Elts0[] = {dwarf::DW_OP_LLVM_fragment, 0, 32};3605 auto *N0 = DIExpression::get(Context, Elts0);3606 uint8_t DIExprFlags = DIExpression::ApplyOffset;3607 DIExprFlags |= DIExpression::DerefBefore;3608 DIExprFlags |= DIExpression::DerefAfter;3609 DIExprFlags |= DIExpression::StackValue;3610 auto *N0WithPrependedOps = DIExpression::prepend(N0, DIExprFlags, 64);3611 uint64_t Elts1[] = {dwarf::DW_OP_deref,3612 dwarf::DW_OP_plus_uconst, 64,3613 dwarf::DW_OP_deref,3614 dwarf::DW_OP_stack_value,3615 dwarf::DW_OP_LLVM_fragment, 0, 32};3616 auto *N1 = DIExpression::get(Context, Elts1);3617 EXPECT_EQ(N0WithPrependedOps, N1);3618 3619 // Test DIExpression::append().3620 uint64_t Elts2[] = {dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 64,3621 dwarf::DW_OP_deref, dwarf::DW_OP_stack_value};3622 auto *N2 = DIExpression::append(N0, Elts2);3623 EXPECT_EQ(N0WithPrependedOps, N2);3624}3625 3626TEST_F(DIExpressionTest, Fold) {3627 3628 // Remove a No-op DW_OP_plus_uconst from an expression.3629 SmallVector<uint64_t, 8> Ops = {dwarf::DW_OP_plus_uconst, 0};3630 auto *Expr = DIExpression::get(Context, Ops);3631 auto *E = Expr->foldConstantMath();3632 SmallVector<uint64_t, 8> ResOps;3633 auto *EmptyExpr = DIExpression::get(Context, ResOps);3634 EXPECT_EQ(E, EmptyExpr);3635 3636 // Remove a No-op add from an expression.3637 Ops.clear();3638 Ops.push_back(dwarf::DW_OP_constu);3639 Ops.push_back(0);3640 Ops.push_back(dwarf::DW_OP_plus);3641 Expr = DIExpression::get(Context, Ops);3642 E = Expr->foldConstantMath();3643 EXPECT_EQ(E, EmptyExpr);3644 3645 // Remove a No-op subtract from an expression.3646 Ops.clear();3647 Ops.push_back(dwarf::DW_OP_constu);3648 Ops.push_back(0);3649 Ops.push_back(dwarf::DW_OP_minus);3650 Expr = DIExpression::get(Context, Ops);3651 E = Expr->foldConstantMath();3652 EXPECT_EQ(E, EmptyExpr);3653 3654 // Remove a No-op shift left from an expression.3655 Ops.clear();3656 Ops.push_back(dwarf::DW_OP_constu);3657 Ops.push_back(0);3658 Ops.push_back(dwarf::DW_OP_shl);3659 Expr = DIExpression::get(Context, Ops);3660 E = Expr->foldConstantMath();3661 EXPECT_EQ(E, EmptyExpr);3662 3663 // Remove a No-op shift right from an expression.3664 Ops.clear();3665 Ops.push_back(dwarf::DW_OP_constu);3666 Ops.push_back(0);3667 Ops.push_back(dwarf::DW_OP_shr);3668 Expr = DIExpression::get(Context, Ops);3669 E = Expr->foldConstantMath();3670 EXPECT_EQ(E, EmptyExpr);3671 3672 // Remove a No-op multiply from an expression.3673 Ops.clear();3674 Ops.push_back(dwarf::DW_OP_constu);3675 Ops.push_back(1);3676 Ops.push_back(dwarf::DW_OP_mul);3677 Expr = DIExpression::get(Context, Ops);3678 E = Expr->foldConstantMath();3679 EXPECT_EQ(E, EmptyExpr);3680 3681 // Remove a No-op divide from an expression.3682 Ops.clear();3683 Ops.push_back(dwarf::DW_OP_constu);3684 Ops.push_back(1);3685 Ops.push_back(dwarf::DW_OP_div);3686 Expr = DIExpression::get(Context, Ops);3687 E = Expr->foldConstantMath();3688 EXPECT_EQ(E, EmptyExpr);3689 3690 // Test fold {DW_OP_plus_uconst, Const1, DW_OP_plus_uconst, Const2} ->3691 // {DW_OP_plus_uconst, Const1 + Const2}3692 Ops.clear();3693 Ops.push_back(dwarf::DW_OP_plus_uconst);3694 Ops.push_back(2);3695 Ops.push_back(dwarf::DW_OP_plus_uconst);3696 Ops.push_back(3);3697 Expr = DIExpression::get(Context, Ops);3698 E = Expr->foldConstantMath();3699 ResOps.push_back(dwarf::DW_OP_plus_uconst);3700 ResOps.push_back(5);3701 auto *ResExpr = DIExpression::get(Context, ResOps);3702 EXPECT_EQ(E, ResExpr);3703 3704 // Test {DW_OP_constu, Const1, DW_OP_plus_uconst, Const2} -> {DW_OP_constu,3705 // Const1 + Const2}3706 Ops.clear();3707 Ops.push_back(dwarf::DW_OP_constu);3708 Ops.push_back(2);3709 Ops.push_back(dwarf::DW_OP_plus_uconst);3710 Ops.push_back(3);3711 Expr = DIExpression::get(Context, Ops);3712 E = Expr->foldConstantMath();3713 ResOps.clear();3714 ResOps.push_back(dwarf::DW_OP_constu);3715 ResOps.push_back(5);3716 ResExpr = DIExpression::get(Context, ResOps);3717 EXPECT_EQ(E, ResExpr);3718 3719 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_plus} ->3720 // {DW_OP_constu, Const1 + Const2}3721 Ops.clear();3722 Ops.push_back(dwarf::DW_OP_constu);3723 Ops.push_back(8);3724 Ops.push_back(dwarf::DW_OP_constu);3725 Ops.push_back(2);3726 Ops.push_back(dwarf::DW_OP_plus);3727 Expr = DIExpression::get(Context, Ops);3728 E = Expr->foldConstantMath();3729 ResOps.clear();3730 ResOps.push_back(dwarf::DW_OP_constu);3731 ResOps.push_back(10);3732 ResExpr = DIExpression::get(Context, ResOps);3733 EXPECT_EQ(E, ResExpr);3734 3735 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_minus} ->3736 // {DW_OP_constu, Const1 - Const2}3737 Ops.clear();3738 Ops.push_back(dwarf::DW_OP_constu);3739 Ops.push_back(8);3740 Ops.push_back(dwarf::DW_OP_constu);3741 Ops.push_back(2);3742 Ops.push_back(dwarf::DW_OP_minus);3743 Expr = DIExpression::get(Context, Ops);3744 E = Expr->foldConstantMath();3745 ResOps.clear();3746 ResOps.push_back(dwarf::DW_OP_constu);3747 ResOps.push_back(6);3748 ResExpr = DIExpression::get(Context, ResOps);3749 EXPECT_EQ(E, ResExpr);3750 3751 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_mul} ->3752 // {DW_OP_constu, Const1 * Const2}3753 Ops.clear();3754 Ops.push_back(dwarf::DW_OP_constu);3755 Ops.push_back(8);3756 Ops.push_back(dwarf::DW_OP_constu);3757 Ops.push_back(2);3758 Ops.push_back(dwarf::DW_OP_mul);3759 Expr = DIExpression::get(Context, Ops);3760 E = Expr->foldConstantMath();3761 ResOps.clear();3762 ResOps.push_back(dwarf::DW_OP_constu);3763 ResOps.push_back(16);3764 ResExpr = DIExpression::get(Context, ResOps);3765 EXPECT_EQ(E, ResExpr);3766 3767 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_div} ->3768 // {DW_OP_constu, Const1 / Const2}3769 Ops.clear();3770 Ops.push_back(dwarf::DW_OP_constu);3771 Ops.push_back(8);3772 Ops.push_back(dwarf::DW_OP_constu);3773 Ops.push_back(2);3774 Ops.push_back(dwarf::DW_OP_div);3775 Expr = DIExpression::get(Context, Ops);3776 E = Expr->foldConstantMath();3777 ResOps.clear();3778 ResOps.push_back(dwarf::DW_OP_constu);3779 ResOps.push_back(4);3780 ResExpr = DIExpression::get(Context, ResOps);3781 EXPECT_EQ(E, ResExpr);3782 3783 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_shl} ->3784 // {DW_OP_constu, Const1 << Const2}3785 Ops.clear();3786 Ops.push_back(dwarf::DW_OP_constu);3787 Ops.push_back(8);3788 Ops.push_back(dwarf::DW_OP_constu);3789 Ops.push_back(2);3790 Ops.push_back(dwarf::DW_OP_shl);3791 Expr = DIExpression::get(Context, Ops);3792 E = Expr->foldConstantMath();3793 ResOps.clear();3794 ResOps.push_back(dwarf::DW_OP_constu);3795 ResOps.push_back(32);3796 ResExpr = DIExpression::get(Context, ResOps);3797 EXPECT_EQ(E, ResExpr);3798 3799 // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_shr} ->3800 // {DW_OP_constu, Const1 >> Const2}3801 Ops.clear();3802 Ops.push_back(dwarf::DW_OP_constu);3803 Ops.push_back(8);3804 Ops.push_back(dwarf::DW_OP_constu);3805 Ops.push_back(2);3806 Ops.push_back(dwarf::DW_OP_shr);3807 Expr = DIExpression::get(Context, Ops);3808 E = Expr->foldConstantMath();3809 ResOps.clear();3810 ResOps.push_back(dwarf::DW_OP_constu);3811 ResOps.push_back(2);3812 ResExpr = DIExpression::get(Context, ResOps);3813 EXPECT_EQ(E, ResExpr);3814 3815 // Test {DW_OP_plus_uconst, Const1, DW_OP_constu, Const2, DW_OP_plus} ->3816 // {DW_OP_plus_uconst, Const1 + Const2}3817 Ops.clear();3818 Ops.push_back(dwarf::DW_OP_plus_uconst);3819 Ops.push_back(8);3820 Ops.push_back(dwarf::DW_OP_constu);3821 Ops.push_back(2);3822 Ops.push_back(dwarf::DW_OP_plus);3823 Expr = DIExpression::get(Context, Ops);3824 E = Expr->foldConstantMath();3825 ResOps.clear();3826 ResOps.push_back(dwarf::DW_OP_plus_uconst);3827 ResOps.push_back(10);3828 ResExpr = DIExpression::get(Context, ResOps);3829 EXPECT_EQ(E, ResExpr);3830 3831 // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_plus_uconst, Const2} ->3832 // {DW_OP_plus_uconst, Const1 + Const2}3833 Ops.clear();3834 Ops.push_back(dwarf::DW_OP_constu);3835 Ops.push_back(8);3836 Ops.push_back(dwarf::DW_OP_plus);3837 Ops.push_back(dwarf::DW_OP_plus_uconst);3838 Ops.push_back(2);3839 Expr = DIExpression::get(Context, Ops);3840 E = Expr->foldConstantMath();3841 ResOps.clear();3842 ResOps.push_back(dwarf::DW_OP_plus_uconst);3843 ResOps.push_back(10);3844 ResExpr = DIExpression::get(Context, ResOps);3845 EXPECT_EQ(E, ResExpr);3846 3847 // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_constu, Const2, DW_OP_plus}3848 // -> {DW_OP_plus_uconst, Const1 + Const2}3849 Ops.clear();3850 Ops.push_back(dwarf::DW_OP_constu);3851 Ops.push_back(8);3852 Ops.push_back(dwarf::DW_OP_plus);3853 Ops.push_back(dwarf::DW_OP_constu);3854 Ops.push_back(2);3855 Ops.push_back(dwarf::DW_OP_plus);3856 Expr = DIExpression::get(Context, Ops);3857 E = Expr->foldConstantMath();3858 ResOps.clear();3859 ResOps.push_back(dwarf::DW_OP_plus_uconst);3860 ResOps.push_back(10);3861 ResExpr = DIExpression::get(Context, ResOps);3862 EXPECT_EQ(E, ResExpr);3863 3864 // Test {DW_OP_constu, Const1, DW_OP_mul, DW_OP_constu, Const2, DW_OP_mul} ->3865 // {DW_OP_constu, Const1 * Const2, DW_OP_mul}3866 Ops.clear();3867 Ops.push_back(dwarf::DW_OP_constu);3868 Ops.push_back(8);3869 Ops.push_back(dwarf::DW_OP_mul);3870 Ops.push_back(dwarf::DW_OP_constu);3871 Ops.push_back(2);3872 Ops.push_back(dwarf::DW_OP_mul);3873 Expr = DIExpression::get(Context, Ops);3874 E = Expr->foldConstantMath();3875 ResOps.clear();3876 ResOps.push_back(dwarf::DW_OP_constu);3877 ResOps.push_back(16);3878 ResOps.push_back(dwarf::DW_OP_mul);3879 ResExpr = DIExpression::get(Context, ResOps);3880 EXPECT_EQ(E, ResExpr);3881 3882 // Test {DW_OP_plus_uconst, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg,3883 // DW_OP_plus, DW_OP_constu, Const2, DW_OP_plus} -> {DW_OP_plus_uconst, Const13884 // + Const2, DW_OP_LLVM_arg, Arg, DW_OP_plus}3885 Ops.clear();3886 Ops.push_back(dwarf::DW_OP_plus_uconst);3887 Ops.push_back(8);3888 Ops.push_back(dwarf::DW_OP_LLVM_arg);3889 Ops.push_back(0);3890 Ops.push_back(dwarf::DW_OP_plus);3891 Ops.push_back(dwarf::DW_OP_constu);3892 Ops.push_back(2);3893 Ops.push_back(dwarf::DW_OP_plus);3894 Expr = DIExpression::get(Context, Ops);3895 E = Expr->foldConstantMath();3896 ResOps.clear();3897 ResOps.push_back(dwarf::DW_OP_plus_uconst);3898 ResOps.push_back(10);3899 ResOps.push_back(dwarf::DW_OP_LLVM_arg);3900 ResOps.push_back(0);3901 ResOps.push_back(dwarf::DW_OP_plus);3902 ResExpr = DIExpression::get(Context, ResOps);3903 EXPECT_EQ(E, ResExpr);3904 3905 // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus,3906 // DW_OP_plus_uconst, Const2} -> {DW_OP_constu, Const1 + Const2, DW_OP_plus,3907 // DW_OP_LLVM_arg, Arg, DW_OP_plus}3908 Ops.clear();3909 Ops.push_back(dwarf::DW_OP_constu);3910 Ops.push_back(8);3911 Ops.push_back(dwarf::DW_OP_plus);3912 Ops.push_back(dwarf::DW_OP_LLVM_arg);3913 Ops.push_back(0);3914 Ops.push_back(dwarf::DW_OP_plus);3915 Ops.push_back(dwarf::DW_OP_plus_uconst);3916 Ops.push_back(2);3917 Expr = DIExpression::get(Context, Ops);3918 E = Expr->foldConstantMath();3919 ResOps.clear();3920 ResOps.push_back(dwarf::DW_OP_plus_uconst);3921 ResOps.push_back(10);3922 ResOps.push_back(dwarf::DW_OP_LLVM_arg);3923 ResOps.push_back(0);3924 ResOps.push_back(dwarf::DW_OP_plus);3925 ResExpr = DIExpression::get(Context, ResOps);3926 EXPECT_EQ(E, ResExpr);3927 3928 // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus,3929 // DW_OP_constu, Const2, DW_OP_plus} -> {DW_OP_constu, Const1 + Const2,3930 // DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus}3931 Ops.clear();3932 Ops.push_back(dwarf::DW_OP_constu);3933 Ops.push_back(8);3934 Ops.push_back(dwarf::DW_OP_plus);3935 Ops.push_back(dwarf::DW_OP_LLVM_arg);3936 Ops.push_back(0);3937 Ops.push_back(dwarf::DW_OP_plus);3938 Ops.push_back(dwarf::DW_OP_constu);3939 Ops.push_back(2);3940 Ops.push_back(dwarf::DW_OP_plus);3941 Expr = DIExpression::get(Context, Ops);3942 E = Expr->foldConstantMath();3943 ResOps.clear();3944 ResOps.push_back(dwarf::DW_OP_plus_uconst);3945 ResOps.push_back(10);3946 ResOps.push_back(dwarf::DW_OP_LLVM_arg);3947 ResOps.push_back(0);3948 ResOps.push_back(dwarf::DW_OP_plus);3949 ResExpr = DIExpression::get(Context, ResOps);3950 EXPECT_EQ(E, ResExpr);3951 3952 // Test {DW_OP_constu, Const1, DW_OP_mul, DW_OP_LLVM_arg, Arg, DW_OP_mul,3953 // DW_OP_constu, Const2, DW_OP_mul} -> {DW_OP_constu, Const1 * Const2,3954 // DW_OP_mul, DW_OP_LLVM_arg, Arg, DW_OP_mul}3955 Ops.clear();3956 Ops.push_back(dwarf::DW_OP_constu);3957 Ops.push_back(8);3958 Ops.push_back(dwarf::DW_OP_mul);3959 Ops.push_back(dwarf::DW_OP_LLVM_arg);3960 Ops.push_back(0);3961 Ops.push_back(dwarf::DW_OP_mul);3962 Ops.push_back(dwarf::DW_OP_constu);3963 Ops.push_back(2);3964 Ops.push_back(dwarf::DW_OP_mul);3965 Expr = DIExpression::get(Context, Ops);3966 E = Expr->foldConstantMath();3967 ResOps.clear();3968 ResOps.push_back(dwarf::DW_OP_constu);3969 ResOps.push_back(16);3970 ResOps.push_back(dwarf::DW_OP_mul);3971 ResOps.push_back(dwarf::DW_OP_LLVM_arg);3972 ResOps.push_back(0);3973 ResOps.push_back(dwarf::DW_OP_mul);3974 ResExpr = DIExpression::get(Context, ResOps);3975 EXPECT_EQ(E, ResExpr);3976 3977 // Test an overflow addition.3978 Ops.clear();3979 Ops.push_back(dwarf::DW_OP_plus_uconst);3980 Ops.push_back(UINT64_MAX);3981 Ops.push_back(dwarf::DW_OP_plus_uconst);3982 Ops.push_back(2);3983 Expr = DIExpression::get(Context, Ops);3984 E = Expr->foldConstantMath();3985 ResOps.clear();3986 ResOps.push_back(dwarf::DW_OP_plus_uconst);3987 ResOps.push_back(UINT64_MAX);3988 ResOps.push_back(dwarf::DW_OP_plus_uconst);3989 ResOps.push_back(2);3990 ResExpr = DIExpression::get(Context, ResOps);3991 EXPECT_EQ(E, ResExpr);3992 3993 // Test an underflow subtraction.3994 Ops.clear();3995 Ops.push_back(dwarf::DW_OP_constu);3996 Ops.push_back(1);3997 Ops.push_back(dwarf::DW_OP_constu);3998 Ops.push_back(2);3999 Ops.push_back(dwarf::DW_OP_minus);4000 Expr = DIExpression::get(Context, Ops);4001 E = Expr->foldConstantMath();4002 ResOps.clear();4003 ResOps.push_back(dwarf::DW_OP_constu);4004 ResOps.push_back(1);4005 ResOps.push_back(dwarf::DW_OP_constu);4006 ResOps.push_back(2);4007 ResOps.push_back(dwarf::DW_OP_minus);4008 ResExpr = DIExpression::get(Context, ResOps);4009 EXPECT_EQ(E, ResExpr);4010 4011 // Test a left shift greater than 63.4012 Ops.clear();4013 Ops.push_back(dwarf::DW_OP_constu);4014 Ops.push_back(1);4015 Ops.push_back(dwarf::DW_OP_constu);4016 Ops.push_back(64);4017 Ops.push_back(dwarf::DW_OP_shl);4018 Expr = DIExpression::get(Context, Ops);4019 E = Expr->foldConstantMath();4020 ResOps.clear();4021 ResOps.push_back(dwarf::DW_OP_constu);4022 ResOps.push_back(1);4023 ResOps.push_back(dwarf::DW_OP_constu);4024 ResOps.push_back(64);4025 ResOps.push_back(dwarf::DW_OP_shl);4026 ResExpr = DIExpression::get(Context, ResOps);4027 EXPECT_EQ(E, ResExpr);4028 4029 // Test a right shift greater than 63.4030 Ops.clear();4031 Ops.push_back(dwarf::DW_OP_constu);4032 Ops.push_back(1);4033 Ops.push_back(dwarf::DW_OP_constu);4034 Ops.push_back(64);4035 Ops.push_back(dwarf::DW_OP_shr);4036 Expr = DIExpression::get(Context, Ops);4037 E = Expr->foldConstantMath();4038 ResOps.clear();4039 ResOps.push_back(dwarf::DW_OP_constu);4040 ResOps.push_back(1);4041 ResOps.push_back(dwarf::DW_OP_constu);4042 ResOps.push_back(64);4043 ResOps.push_back(dwarf::DW_OP_shr);4044 ResExpr = DIExpression::get(Context, ResOps);4045 EXPECT_EQ(E, ResExpr);4046 4047 // Test an overflow multiplication.4048 Ops.clear();4049 Ops.push_back(dwarf::DW_OP_constu);4050 Ops.push_back(UINT64_MAX);4051 Ops.push_back(dwarf::DW_OP_constu);4052 Ops.push_back(2);4053 Ops.push_back(dwarf::DW_OP_mul);4054 Expr = DIExpression::get(Context, Ops);4055 E = Expr->foldConstantMath();4056 ResOps.clear();4057 ResOps.push_back(dwarf::DW_OP_constu);4058 ResOps.push_back(UINT64_MAX);4059 ResOps.push_back(dwarf::DW_OP_constu);4060 ResOps.push_back(2);4061 ResOps.push_back(dwarf::DW_OP_mul);4062 ResExpr = DIExpression::get(Context, ResOps);4063 EXPECT_EQ(E, ResExpr);4064 4065 // Test a divide by 0.4066 Ops.clear();4067 Ops.push_back(dwarf::DW_OP_constu);4068 Ops.push_back(2);4069 Ops.push_back(dwarf::DW_OP_constu);4070 Ops.push_back(0);4071 Ops.push_back(dwarf::DW_OP_div);4072 Expr = DIExpression::get(Context, Ops);4073 E = Expr->foldConstantMath();4074 ResOps.clear();4075 ResOps.push_back(dwarf::DW_OP_constu);4076 ResOps.push_back(2);4077 ResOps.push_back(dwarf::DW_OP_lit0);4078 ResOps.push_back(dwarf::DW_OP_div);4079 ResExpr = DIExpression::get(Context, ResOps);4080 EXPECT_EQ(E, ResExpr);4081}4082 4083TEST_F(DIExpressionTest, Append) {4084 // Test appending a {dwarf::DW_OP_constu, <const>, DW_OP_plus} to a DW_OP_plus4085 // expression4086 SmallVector<uint64_t, 8> Ops = {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,4087 2, dwarf::DW_OP_plus};4088 auto *Expr = DIExpression::get(Context, Ops);4089 SmallVector<uint64_t, 8> AppendOps = {dwarf::DW_OP_constu, 3,4090 dwarf::DW_OP_plus};4091 auto *AppendExpr = DIExpression::append(Expr, AppendOps);4092 SmallVector<uint64_t, 8> OpsRes = {dwarf::DW_OP_LLVM_arg, 0,4093 dwarf::DW_OP_plus_uconst, 5};4094 auto *ResExpr = DIExpression::get(Context, OpsRes);4095 EXPECT_EQ(ResExpr, AppendExpr);4096 4097 // Test appending a {dwarf::DW_OP_plus_uconst, <const>} to a DW_OP_plus4098 // expression uint64_t PlusUConstOps[] = {dwarf::DW_OP_plus_uconst, 3};4099 AppendOps.clear();4100 AppendOps.push_back(dwarf::DW_OP_plus_uconst);4101 AppendOps.push_back(3);4102 AppendExpr = DIExpression::append(Expr, AppendOps);4103 OpsRes.clear();4104 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4105 OpsRes.push_back(0);4106 OpsRes.push_back(dwarf::DW_OP_plus_uconst);4107 OpsRes.push_back(5);4108 ResExpr = DIExpression::get(Context, OpsRes);4109 EXPECT_EQ(ResExpr, AppendExpr);4110 4111 // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_plus} to an expression4112 AppendOps.clear();4113 AppendOps.push_back(dwarf::DW_OP_constu);4114 AppendOps.push_back(0);4115 AppendOps.push_back(dwarf::DW_OP_plus);4116 AppendExpr = DIExpression::append(Expr, AppendOps);4117 OpsRes.clear();4118 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4119 OpsRes.push_back(0);4120 OpsRes.push_back(dwarf::DW_OP_plus_uconst);4121 OpsRes.push_back(2);4122 ResExpr = DIExpression::get(Context, OpsRes);4123 EXPECT_EQ(ResExpr, AppendExpr);4124 4125 // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_minus} to an expression4126 AppendOps.clear();4127 AppendOps.push_back(dwarf::DW_OP_constu);4128 AppendOps.push_back(0);4129 AppendOps.push_back(dwarf::DW_OP_minus);4130 AppendExpr = DIExpression::append(Expr, AppendOps);4131 OpsRes.clear();4132 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4133 OpsRes.push_back(0);4134 OpsRes.push_back(dwarf::DW_OP_plus_uconst);4135 OpsRes.push_back(2);4136 ResExpr = DIExpression::get(Context, OpsRes);4137 EXPECT_EQ(ResExpr, AppendExpr);4138 4139 // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shl} to an expression4140 AppendOps.clear();4141 AppendOps.push_back(dwarf::DW_OP_constu);4142 AppendOps.push_back(0);4143 AppendOps.push_back(dwarf::DW_OP_shl);4144 AppendExpr = DIExpression::append(Expr, AppendOps);4145 OpsRes.clear();4146 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4147 OpsRes.push_back(0);4148 OpsRes.push_back(dwarf::DW_OP_plus_uconst);4149 OpsRes.push_back(2);4150 ResExpr = DIExpression::get(Context, OpsRes);4151 EXPECT_EQ(ResExpr, AppendExpr);4152 4153 // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shr} to an expression4154 AppendOps.clear();4155 AppendOps.push_back(dwarf::DW_OP_constu);4156 AppendOps.push_back(0);4157 AppendOps.push_back(dwarf::DW_OP_shr);4158 AppendExpr = DIExpression::append(Expr, AppendOps);4159 OpsRes.clear();4160 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4161 OpsRes.push_back(0);4162 OpsRes.push_back(dwarf::DW_OP_plus_uconst);4163 OpsRes.push_back(2);4164 ResExpr = DIExpression::get(Context, OpsRes);4165 EXPECT_EQ(ResExpr, AppendExpr);4166 4167 // Test appending a {dwarf::DW_OP_constu, <const>, DW_OP_mul} to a DW_OP_mul4168 // expression4169 Ops.clear();4170 Ops.push_back(dwarf::DW_OP_LLVM_arg);4171 Ops.push_back(0);4172 Ops.push_back(dwarf::DW_OP_constu);4173 Ops.push_back(2);4174 Ops.push_back(dwarf::DW_OP_mul);4175 Expr = DIExpression::get(Context, Ops);4176 AppendOps.clear();4177 AppendOps.push_back(dwarf::DW_OP_constu);4178 AppendOps.push_back(3);4179 AppendOps.push_back(dwarf::DW_OP_mul);4180 AppendExpr = DIExpression::append(Expr, AppendOps);4181 OpsRes.clear();4182 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4183 OpsRes.push_back(0);4184 OpsRes.push_back(dwarf::DW_OP_constu);4185 OpsRes.push_back(6);4186 OpsRes.push_back(dwarf::DW_OP_mul);4187 ResExpr = DIExpression::get(Context, OpsRes);4188 EXPECT_EQ(ResExpr, AppendExpr);4189 4190 // Test appending a {dwarf::DW_OP_constu, 1, DW_OP_mul} to an expression4191 AppendOps.clear();4192 AppendOps.push_back(dwarf::DW_OP_constu);4193 AppendOps.push_back(1);4194 AppendOps.push_back(dwarf::DW_OP_mul);4195 AppendExpr = DIExpression::append(Expr, AppendOps);4196 OpsRes.clear();4197 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4198 OpsRes.push_back(0);4199 OpsRes.push_back(dwarf::DW_OP_constu);4200 OpsRes.push_back(2);4201 OpsRes.push_back(dwarf::DW_OP_mul);4202 ResExpr = DIExpression::get(Context, OpsRes);4203 EXPECT_EQ(ResExpr, AppendExpr);4204 4205 // Test appending a {dwarf::DW_OP_constu, 1, DW_OP_div} to an expression4206 AppendOps.clear();4207 AppendOps.push_back(dwarf::DW_OP_constu);4208 AppendOps.push_back(1);4209 AppendOps.push_back(dwarf::DW_OP_div);4210 AppendExpr = DIExpression::append(Expr, AppendOps);4211 OpsRes.clear();4212 OpsRes.push_back(dwarf::DW_OP_LLVM_arg);4213 OpsRes.push_back(0);4214 OpsRes.push_back(dwarf::DW_OP_constu);4215 OpsRes.push_back(2);4216 OpsRes.push_back(dwarf::DW_OP_mul);4217 ResExpr = DIExpression::get(Context, OpsRes);4218 EXPECT_EQ(ResExpr, AppendExpr);4219}4220 4221TEST_F(DIExpressionTest, isValid) {4222#define EXPECT_VALID(...) \4223 do { \4224 uint64_t Elements[] = {__VA_ARGS__}; \4225 EXPECT_TRUE(DIExpression::get(Context, Elements)->isValid()); \4226 } while (false)4227#define EXPECT_INVALID(...) \4228 do { \4229 uint64_t Elements[] = {__VA_ARGS__}; \4230 EXPECT_FALSE(DIExpression::get(Context, Elements)->isValid()); \4231 } while (false)4232 4233 // Empty expression should be valid.4234 EXPECT_TRUE(DIExpression::get(Context, {})->isValid());4235 4236 // Valid constructions.4237 EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6);4238 EXPECT_VALID(dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);4239 EXPECT_VALID(dwarf::DW_OP_deref);4240 EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);4241 EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);4242 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6);4243 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 3, 7);4244 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6,4245 dwarf::DW_OP_LLVM_fragment, 3, 7);4246 EXPECT_VALID(dwarf::DW_OP_LLVM_entry_value, 1);4247 EXPECT_VALID(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_entry_value, 1);4248 4249 // Invalid constructions.4250 EXPECT_INVALID(~0u);4251 EXPECT_INVALID(dwarf::DW_OP_plus, 0);4252 EXPECT_INVALID(dwarf::DW_OP_plus_uconst);4253 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);4254 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);4255 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus_uconst, 3);4256 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_deref);4257 EXPECT_INVALID(dwarf::DW_OP_LLVM_entry_value, 2);4258 EXPECT_INVALID(dwarf::DW_OP_plus_uconst, 5, dwarf::DW_OP_LLVM_entry_value, 1);4259 EXPECT_INVALID(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 5,4260 dwarf::DW_OP_LLVM_entry_value, 1);4261 EXPECT_INVALID(dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_LLVM_entry_value, 1);4262 4263#undef EXPECT_VALID4264#undef EXPECT_INVALID4265}4266 4267TEST_F(DIExpressionTest, createFragmentExpression) {4268#define EXPECT_VALID_FRAGMENT(Offset, Size, ...) \4269 do { \4270 uint64_t Elements[] = {__VA_ARGS__}; \4271 DIExpression *Expression = DIExpression::get(Context, Elements); \4272 EXPECT_TRUE( \4273 DIExpression::createFragmentExpression(Expression, Offset, Size) \4274 .has_value()); \4275 } while (false)4276#define EXPECT_INVALID_FRAGMENT(Offset, Size, ...) \4277 do { \4278 uint64_t Elements[] = {__VA_ARGS__}; \4279 DIExpression *Expression = DIExpression::get(Context, Elements); \4280 EXPECT_FALSE( \4281 DIExpression::createFragmentExpression(Expression, Offset, Size) \4282 .has_value()); \4283 } while (false)4284 4285 // createFragmentExpression adds correct ops.4286 std::optional<DIExpression*> R = DIExpression::createFragmentExpression(4287 DIExpression::get(Context, {}), 0, 32);4288 EXPECT_EQ(R.has_value(), true);4289 EXPECT_EQ(3u, (*R)->getNumElements());4290 EXPECT_EQ(dwarf::DW_OP_LLVM_fragment, (*R)->getElement(0));4291 EXPECT_EQ(0u, (*R)->getElement(1));4292 EXPECT_EQ(32u, (*R)->getElement(2));4293 4294 // Valid fragment expressions.4295 EXPECT_VALID_FRAGMENT(0, 32, {});4296 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_deref);4297 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_LLVM_fragment, 0, 32);4298 EXPECT_VALID_FRAGMENT(16, 16, dwarf::DW_OP_LLVM_fragment, 0, 32);4299 4300 // Invalid fragment expressions (incompatible ops).4301 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus,4302 dwarf::DW_OP_stack_value);4303 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 14, dwarf::DW_OP_minus,4304 dwarf::DW_OP_stack_value);4305 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shr,4306 dwarf::DW_OP_stack_value);4307 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shl,4308 dwarf::DW_OP_stack_value);4309 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shra,4310 dwarf::DW_OP_stack_value);4311 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4312 dwarf::DW_OP_stack_value);4313 4314 // Fragments can be created for expressions using DW_OP_plus to compute an4315 // address.4316 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);4317 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);4318 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref,4319 dwarf::DW_OP_stack_value);4320 4321 // Check the other deref operations work in the same way.4322 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4323 dwarf::DW_OP_deref_size, 1);4324 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4325 dwarf::DW_OP_deref_type, 1, 1);4326 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4327 dwarf::DW_OP_xderef);4328 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4329 dwarf::DW_OP_xderef_size, 1);4330 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,4331 dwarf::DW_OP_xderef_type, 1, 1);4332 4333 // Fragments cannot be created for expressions using DW_OP_plus to compute an4334 // implicit value (check that this correctly fails even though there is a4335 // deref in the expression).4336 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst,4337 2, dwarf::DW_OP_stack_value);4338 4339#undef EXPECT_VALID_FRAGMENT4340#undef EXPECT_INVALID_FRAGMENT4341}4342 4343TEST_F(DIExpressionTest, extractLeadingOffset) {4344 int64_t Offset;4345 SmallVector<uint64_t> Remaining;4346 using namespace dwarf;4347#define OPS(...) SmallVector<uint64_t>(ArrayRef<uint64_t>{__VA_ARGS__})4348#define EXTRACT_FROM(...) \4349 DIExpression::get(Context, {__VA_ARGS__}) \4350 ->extractLeadingOffset(Offset, Remaining)4351 // Test the number of expression inputs4352 // ------------------------------------4353 //4354 // Single location expressions are permitted.4355 EXPECT_TRUE(EXTRACT_FROM(DW_OP_plus_uconst, 2));4356 EXPECT_EQ(Offset, 2);4357 EXPECT_EQ(Remaining.size(), 0u);4358 // This is also a single-location.4359 EXPECT_TRUE(EXTRACT_FROM(DW_OP_LLVM_arg, 0, DW_OP_plus_uconst, 2));4360 EXPECT_EQ(Offset, 2);4361 EXPECT_EQ(Remaining.size(), 0u);4362 // Variadic locations are not permitted. A non-zero arg is assumed to4363 // indicate multiple inputs.4364 EXPECT_FALSE(EXTRACT_FROM(DW_OP_LLVM_arg, 1));4365 EXPECT_FALSE(EXTRACT_FROM(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus));4366 4367 // Test offsets expressions4368 // ------------------------4369 EXPECT_TRUE(EXTRACT_FROM());4370 EXPECT_EQ(Offset, 0);4371 EXPECT_EQ(Remaining.size(), 0u);4372 4373 EXPECT_TRUE(EXTRACT_FROM(DW_OP_constu, 4, DW_OP_plus));4374 EXPECT_EQ(Offset, 4);4375 EXPECT_EQ(Remaining.size(), 0u);4376 4377 EXPECT_TRUE(EXTRACT_FROM(DW_OP_constu, 2, DW_OP_minus));4378 EXPECT_EQ(Offset, -2);4379 EXPECT_EQ(Remaining.size(), 0u);4380 4381 EXPECT_TRUE(EXTRACT_FROM(DW_OP_plus_uconst, 8));4382 EXPECT_EQ(Offset, 8);4383 EXPECT_EQ(Remaining.size(), 0u);4384 4385 EXPECT_TRUE(EXTRACT_FROM(DW_OP_plus_uconst, 4, DW_OP_constu, 2, DW_OP_minus));4386 EXPECT_EQ(Offset, 2);4387 EXPECT_EQ(Remaining.size(), 0u);4388 4389 // Not all operations are permitted for simplicity. Can be added4390 // if needed in future.4391 EXPECT_FALSE(EXTRACT_FROM(DW_OP_constu, 2, DW_OP_mul));4392 4393 // Test "remaining ops"4394 // --------------------4395 EXPECT_TRUE(EXTRACT_FROM(DW_OP_plus_uconst, 4, DW_OP_constu, 8, DW_OP_minus,4396 DW_OP_LLVM_fragment, 0, 32));4397 EXPECT_EQ(Remaining, OPS(DW_OP_LLVM_fragment, 0, 32));4398 EXPECT_EQ(Offset, -4);4399 4400 EXPECT_TRUE(EXTRACT_FROM(DW_OP_deref));4401 EXPECT_EQ(Remaining, OPS(DW_OP_deref));4402 EXPECT_EQ(Offset, 0);4403 4404 // Check things after the non-offset ops are added too.4405 EXPECT_TRUE(EXTRACT_FROM(DW_OP_plus_uconst, 2, DW_OP_deref_size, 4,4406 DW_OP_stack_value));4407 EXPECT_EQ(Remaining, OPS(DW_OP_deref_size, 4, DW_OP_stack_value));4408 EXPECT_EQ(Offset, 2);4409 4410 // DW_OP_deref_type isn't supported in LLVM so this currently fails.4411 EXPECT_FALSE(EXTRACT_FROM(DW_OP_deref_type, 0));4412 4413 EXPECT_TRUE(EXTRACT_FROM(DW_OP_LLVM_extract_bits_zext, 0, 8));4414 EXPECT_EQ(Remaining, OPS(DW_OP_LLVM_extract_bits_zext, 0, 8));4415 4416 EXPECT_TRUE(EXTRACT_FROM(DW_OP_LLVM_extract_bits_sext, 4, 4));4417 EXPECT_EQ(Remaining, OPS(DW_OP_LLVM_extract_bits_sext, 4, 4));4418#undef EXTRACT_FROM4419#undef OPS4420}4421 4422TEST_F(DIExpressionTest, convertToUndefExpression) {4423#define EXPECT_UNDEF_OPS_EQUAL(TestExpr, Expected) \4424 do { \4425 const DIExpression *Undef = \4426 DIExpression::convertToUndefExpression(TestExpr); \4427 EXPECT_EQ(Undef, Expected); \4428 } while (false)4429#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})4430 4431 // Expressions which are single-location and non-complex should be unchanged.4432 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(), GET_EXPR());4433 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 32),4434 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 32));4435 4436 // Variadic expressions should become single-location.4437 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0), GET_EXPR());4438 EXPECT_UNDEF_OPS_EQUAL(4439 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_fragment, 32, 32),4440 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 32, 32));4441 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4442 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul),4443 GET_EXPR());4444 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4445 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul,4446 dwarf::DW_OP_LLVM_fragment, 64, 32),4447 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 64, 32));4448 4449 // Any stack-computing ops should be removed.4450 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 8), GET_EXPR());4451 EXPECT_UNDEF_OPS_EQUAL(4452 GET_EXPR(dwarf::DW_OP_plus_uconst, 8, dwarf::DW_OP_LLVM_fragment, 0, 16),4453 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 16));4454 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 24, dwarf::DW_OP_shra),4455 GET_EXPR());4456 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 24, dwarf::DW_OP_shra,4457 dwarf::DW_OP_LLVM_fragment, 8, 16),4458 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 8, 16));4459 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_deref), GET_EXPR());4460 EXPECT_UNDEF_OPS_EQUAL(4461 GET_EXPR(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 16, 16),4462 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 16, 16));4463 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 4, dwarf::DW_OP_minus),4464 GET_EXPR());4465 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 4, dwarf::DW_OP_minus,4466 dwarf::DW_OP_LLVM_fragment, 24, 16),4467 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 24, 16));4468 4469 // Stack-value operators are also not preserved.4470 EXPECT_UNDEF_OPS_EQUAL(4471 GET_EXPR(dwarf::DW_OP_plus_uconst, 8, dwarf::DW_OP_stack_value),4472 GET_EXPR());4473 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 8,4474 dwarf::DW_OP_stack_value,4475 dwarf::DW_OP_LLVM_fragment, 32, 16),4476 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 32, 16));4477 4478#undef EXPECT_UNDEF_OPS_EQUAL4479#undef GET_EXPR4480}4481 4482TEST_F(DIExpressionTest, convertToVariadicExpression) {4483#define EXPECT_CONVERT_IS_NOOP(TestExpr) \4484 do { \4485 const DIExpression *Variadic = \4486 DIExpression::convertToVariadicExpression(TestExpr); \4487 EXPECT_EQ(Variadic, TestExpr); \4488 } while (false)4489#define EXPECT_VARIADIC_OPS_EQUAL(TestExpr, Expected) \4490 do { \4491 const DIExpression *Variadic = \4492 DIExpression::convertToVariadicExpression(TestExpr); \4493 EXPECT_EQ(Variadic, Expected); \4494 } while (false)4495#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})4496 4497 // Expressions which are already variadic should be unaffected.4498 EXPECT_CONVERT_IS_NOOP(4499 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value));4500 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4501 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,4502 dwarf::DW_OP_stack_value));4503 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_constu, 5, dwarf::DW_OP_LLVM_arg,4504 0, dwarf::DW_OP_plus,4505 dwarf::DW_OP_stack_value));4506 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4507 dwarf::DW_OP_stack_value,4508 dwarf::DW_OP_LLVM_fragment, 0, 32));4509 4510 // Other expressions should receive a leading `LLVM_arg 0`.4511 EXPECT_VARIADIC_OPS_EQUAL(GET_EXPR(), GET_EXPR(dwarf::DW_OP_LLVM_arg, 0));4512 EXPECT_VARIADIC_OPS_EQUAL(4513 GET_EXPR(dwarf::DW_OP_plus_uconst, 4),4514 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4));4515 EXPECT_VARIADIC_OPS_EQUAL(4516 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value),4517 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4,4518 dwarf::DW_OP_stack_value));4519 EXPECT_VARIADIC_OPS_EQUAL(4520 GET_EXPR(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_stack_value,4521 dwarf::DW_OP_LLVM_fragment, 32, 32),4522 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 6,4523 dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 32, 32));4524 EXPECT_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 14,4525 dwarf::DW_OP_LLVM_fragment, 32, 32),4526 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4527 dwarf::DW_OP_plus_uconst, 14,4528 dwarf::DW_OP_LLVM_fragment, 32, 32));4529 4530#undef EXPECT_CONVERT_IS_NOOP4531#undef EXPECT_VARIADIC_OPS_EQUAL4532#undef GET_EXPR4533}4534 4535TEST_F(DIExpressionTest, convertToNonVariadicExpression) {4536#define EXPECT_CONVERT_IS_NOOP(TestExpr) \4537 do { \4538 std::optional<const DIExpression *> NonVariadic = \4539 DIExpression::convertToNonVariadicExpression(TestExpr); \4540 EXPECT_TRUE(NonVariadic.has_value()); \4541 EXPECT_EQ(*NonVariadic, TestExpr); \4542 } while (false)4543#define EXPECT_NON_VARIADIC_OPS_EQUAL(TestExpr, Expected) \4544 do { \4545 std::optional<const DIExpression *> NonVariadic = \4546 DIExpression::convertToNonVariadicExpression(TestExpr); \4547 EXPECT_TRUE(NonVariadic.has_value()); \4548 EXPECT_EQ(*NonVariadic, Expected); \4549 } while (false)4550#define EXPECT_INVALID_CONVERSION(TestExpr) \4551 do { \4552 std::optional<const DIExpression *> NonVariadic = \4553 DIExpression::convertToNonVariadicExpression(TestExpr); \4554 EXPECT_FALSE(NonVariadic.has_value()); \4555 } while (false)4556#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})4557 4558 // Expressions which are already non-variadic should be unaffected.4559 EXPECT_CONVERT_IS_NOOP(GET_EXPR());4560 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 4));4561 EXPECT_CONVERT_IS_NOOP(4562 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value));4563 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 6,4564 dwarf::DW_OP_stack_value,4565 dwarf::DW_OP_LLVM_fragment, 32, 32));4566 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 14,4567 dwarf::DW_OP_LLVM_fragment, 32, 32));4568 4569 // Variadic expressions with a single leading `LLVM_arg 0` and no other4570 // LLVM_args should have the leading arg removed.4571 EXPECT_NON_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0), GET_EXPR());4572 EXPECT_NON_VARIADIC_OPS_EQUAL(4573 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value),4574 GET_EXPR(dwarf::DW_OP_stack_value));4575 EXPECT_NON_VARIADIC_OPS_EQUAL(4576 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_fragment, 16, 32),4577 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 16, 32));4578 EXPECT_NON_VARIADIC_OPS_EQUAL(4579 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value,4580 dwarf::DW_OP_LLVM_fragment, 24, 32),4581 GET_EXPR(dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 24, 32));4582 EXPECT_NON_VARIADIC_OPS_EQUAL(4583 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4),4584 GET_EXPR(dwarf::DW_OP_plus_uconst, 4));4585 EXPECT_NON_VARIADIC_OPS_EQUAL(4586 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4,4587 dwarf::DW_OP_stack_value),4588 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value));4589 EXPECT_NON_VARIADIC_OPS_EQUAL(4590 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 6,4591 dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 32, 32),4592 GET_EXPR(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_stack_value,4593 dwarf::DW_OP_LLVM_fragment, 32, 32));4594 EXPECT_NON_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4595 dwarf::DW_OP_plus_uconst, 14,4596 dwarf::DW_OP_LLVM_fragment, 32, 32),4597 GET_EXPR(dwarf::DW_OP_plus_uconst, 14,4598 dwarf::DW_OP_LLVM_fragment, 32, 32));4599 4600 // Variadic expressions that have any LLVM_args other than a leading4601 // `LLVM_arg 0` cannot be converted and so should return std::nullopt.4602 EXPECT_INVALID_CONVERSION(GET_EXPR(4603 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul));4604 EXPECT_INVALID_CONVERSION(4605 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1,4606 dwarf::DW_OP_plus, dwarf::DW_OP_stack_value));4607 EXPECT_INVALID_CONVERSION(4608 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 0,4609 dwarf::DW_OP_minus, dwarf::DW_OP_stack_value));4610 EXPECT_INVALID_CONVERSION(GET_EXPR(dwarf::DW_OP_constu, 5,4611 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_div,4612 dwarf::DW_OP_stack_value));4613 4614#undef EXPECT_CONVERT_IS_NOOP4615#undef EXPECT_NON_VARIADIC_OPS_EQUAL4616#undef EXPECT_INVALID_CONVERSION4617#undef GET_EXPR4618}4619 4620TEST_F(DIExpressionTest, replaceArg) {4621#define EXPECT_REPLACE_ARG_EQ(Expr, OldArg, NewArg, ...) \4622 do { \4623 uint64_t Elements[] = {__VA_ARGS__}; \4624 ArrayRef<uint64_t> Expected = Elements; \4625 DIExpression *Expression = DIExpression::replaceArg(Expr, OldArg, NewArg); \4626 EXPECT_EQ(Expression->getElements(), Expected); \4627 } while (false)4628 4629 auto N = DIExpression::get(4630 Context, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1,4631 dwarf::DW_OP_plus, dwarf::DW_OP_LLVM_arg, 2, dwarf::DW_OP_mul});4632 EXPECT_REPLACE_ARG_EQ(N, 0, 1, dwarf::DW_OP_LLVM_arg, 0,4633 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus,4634 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);4635 EXPECT_REPLACE_ARG_EQ(N, 0, 2, dwarf::DW_OP_LLVM_arg, 1,4636 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus,4637 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);4638 EXPECT_REPLACE_ARG_EQ(N, 2, 0, dwarf::DW_OP_LLVM_arg, 0,4639 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,4640 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_mul);4641 EXPECT_REPLACE_ARG_EQ(N, 2, 1, dwarf::DW_OP_LLVM_arg, 0,4642 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,4643 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);4644 4645#undef EXPECT_REPLACE_ARG_EQ4646}4647 4648TEST_F(DIExpressionTest, isEqualExpression) {4649#define EXPECT_EQ_DEBUG_VALUE(ExprA, DirectA, ExprB, DirectB) \4650 EXPECT_TRUE(DIExpression::isEqualExpression(ExprA, DirectA, ExprB, DirectB))4651#define EXPECT_NE_DEBUG_VALUE(ExprA, DirectA, ExprB, DirectB) \4652 EXPECT_FALSE(DIExpression::isEqualExpression(ExprA, DirectA, ExprB, DirectB))4653#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})4654 4655 EXPECT_EQ_DEBUG_VALUE(GET_EXPR(), false, GET_EXPR(), false);4656 EXPECT_NE_DEBUG_VALUE(GET_EXPR(), false, GET_EXPR(), true);4657 EXPECT_EQ_DEBUG_VALUE(4658 GET_EXPR(dwarf::DW_OP_plus_uconst, 32), true,4659 GET_EXPR(dwarf::DW_OP_plus_uconst, 32, dwarf::DW_OP_deref), false);4660 EXPECT_NE_DEBUG_VALUE(4661 GET_EXPR(dwarf::DW_OP_plus_uconst, 16, dwarf::DW_OP_deref), true,4662 GET_EXPR(dwarf::DW_OP_plus_uconst, 16, dwarf::DW_OP_deref), false);4663 EXPECT_EQ_DEBUG_VALUE(4664 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 5), false,4665 GET_EXPR(dwarf::DW_OP_plus_uconst, 5), false);4666 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus),4667 false,4668 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,4669 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus),4670 false);4671 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,4672 8, dwarf::DW_OP_minus),4673 false,4674 GET_EXPR(dwarf::DW_OP_constu, 8, dwarf::DW_OP_LLVM_arg,4675 0, dwarf::DW_OP_minus),4676 false);4677 // These expressions are actually equivalent, but we do not currently identify4678 // commutative operations with different operand orders as being equivalent.4679 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,4680 8, dwarf::DW_OP_plus),4681 false,4682 GET_EXPR(dwarf::DW_OP_constu, 8, dwarf::DW_OP_LLVM_arg,4683 0, dwarf::DW_OP_plus),4684 false);4685 4686#undef EXPECT_EQ_DEBUG_VALUE4687#undef EXPECT_NE_DEBUG_VALUE4688#undef GET_EXPR4689}4690 4691TEST_F(DIExpressionTest, foldConstant) {4692 const ConstantInt *Int;4693 const ConstantInt *NewInt;4694 DIExpression *Expr;4695 DIExpression *NewExpr;4696 4697#define EXPECT_FOLD_CONST(StartWidth, StartValue, StartIsSigned, EndWidth, \4698 EndValue, EndIsSigned, NumElts) \4699 Int = \4700 ConstantInt::get(Context, APInt(StartWidth, StartValue, StartIsSigned)); \4701 std::tie(NewExpr, NewInt) = Expr->constantFold(Int); \4702 ASSERT_EQ(NewInt->getBitWidth(), EndWidth##u); \4703 EXPECT_EQ(NewInt->getValue(), APInt(EndWidth, EndValue, EndIsSigned)); \4704 EXPECT_EQ(NewExpr->getNumElements(), NumElts##u)4705 4706 // Unfoldable expression should return the original unmodified Int/Expr.4707 Expr = DIExpression::get(Context, {dwarf::DW_OP_deref});4708 EXPECT_FOLD_CONST(32, 117, false, 32, 117, false, 1);4709 EXPECT_EQ(NewExpr, Expr);4710 EXPECT_EQ(NewInt, Int);4711 EXPECT_TRUE(NewExpr->startsWithDeref());4712 4713 // One unsigned bit-width conversion.4714 Expr = DIExpression::get(4715 Context, {dwarf::DW_OP_LLVM_convert, 72, dwarf::DW_ATE_unsigned});4716 EXPECT_FOLD_CONST(8, 12, false, 72, 12, false, 0);4717 4718 // Two unsigned bit-width conversions (mask truncation).4719 Expr = DIExpression::get(4720 Context, {dwarf::DW_OP_LLVM_convert, 8, dwarf::DW_ATE_unsigned,4721 dwarf::DW_OP_LLVM_convert, 16, dwarf::DW_ATE_unsigned});4722 EXPECT_FOLD_CONST(32, -1, true, 16, 0xff, false, 0);4723 4724 // Sign extension.4725 Expr = DIExpression::get(4726 Context, {dwarf::DW_OP_LLVM_convert, 32, dwarf::DW_ATE_signed});4727 EXPECT_FOLD_CONST(16, -1, true, 32, -1, true, 0);4728 4729 // Get non-foldable operations back in the new Expr.4730 uint64_t Elements[] = {dwarf::DW_OP_deref, dwarf::DW_OP_stack_value};4731 ArrayRef<uint64_t> Expected = Elements;4732 Expr = DIExpression::get(4733 Context, {dwarf::DW_OP_LLVM_convert, 32, dwarf::DW_ATE_signed});4734 Expr = DIExpression::append(Expr, Expected);4735 ASSERT_EQ(Expr->getNumElements(), 5u);4736 EXPECT_FOLD_CONST(16, -1, true, 32, -1, true, 2);4737 EXPECT_EQ(NewExpr->getElements(), Expected);4738 4739#undef EXPECT_FOLD_CONST4740}4741 4742TEST_F(DIExpressionTest, appendToStackAssert) {4743 DIExpression *Expr = DIExpression::get(Context, {});4744 4745 // Verify that the DW_OP_LLVM_convert operands, which have the same values as4746 // DW_OP_stack_value and DW_OP_LLVM_fragment, do not get interpreted as such4747 // operations. This previously triggered an assert.4748 uint64_t FromSize = dwarf::DW_OP_stack_value;4749 uint64_t ToSize = dwarf::DW_OP_LLVM_fragment;4750 uint64_t Ops[] = {4751 dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed,4752 dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed,4753 };4754 Expr = DIExpression::appendToStack(Expr, Ops);4755 4756 uint64_t Expected[] = {4757 dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed,4758 dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed,4759 dwarf::DW_OP_stack_value};4760 EXPECT_EQ(Expr->getElements(), ArrayRef<uint64_t>(Expected));4761}4762 4763typedef MetadataTest DIObjCPropertyTest;4764 4765TEST_F(DIObjCPropertyTest, get) {4766 StringRef Name = "name";4767 DIFile *File = getFile();4768 unsigned Line = 5;4769 StringRef GetterName = "getter";4770 StringRef SetterName = "setter";4771 unsigned Attributes = 7;4772 DIType *Type = getBasicType("basic");4773 4774 auto *N = DIObjCProperty::get(Context, Name, File, Line, GetterName,4775 SetterName, Attributes, Type);4776 4777 EXPECT_EQ(dwarf::DW_TAG_APPLE_property, N->getTag());4778 EXPECT_EQ(Name, N->getName());4779 EXPECT_EQ(File, N->getFile());4780 EXPECT_EQ(Line, N->getLine());4781 EXPECT_EQ(GetterName, N->getGetterName());4782 EXPECT_EQ(SetterName, N->getSetterName());4783 EXPECT_EQ(Attributes, N->getAttributes());4784 EXPECT_EQ(Type, N->getType());4785 EXPECT_EQ(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,4786 SetterName, Attributes, Type));4787 4788 EXPECT_NE(N, DIObjCProperty::get(Context, "other", File, Line, GetterName,4789 SetterName, Attributes, Type));4790 EXPECT_NE(N, DIObjCProperty::get(Context, Name, getFile(), Line, GetterName,4791 SetterName, Attributes, Type));4792 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line + 1, GetterName,4793 SetterName, Attributes, Type));4794 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, "other",4795 SetterName, Attributes, Type));4796 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,4797 "other", Attributes, Type));4798 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,4799 SetterName, Attributes + 1, Type));4800 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,4801 SetterName, Attributes,4802 getBasicType("other")));4803 4804 TempDIObjCProperty Temp = N->clone();4805 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));4806}4807 4808typedef MetadataTest DIImportedEntityTest;4809 4810TEST_F(DIImportedEntityTest, get) {4811 unsigned Tag = dwarf::DW_TAG_imported_module;4812 DIScope *Scope = getSubprogram();4813 DINode *Entity = getCompositeType();4814 DIFile *File = getFile();4815 unsigned Line = 5;4816 StringRef Name = "name";4817 4818 auto *N =4819 DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name);4820 4821 EXPECT_EQ(Tag, N->getTag());4822 EXPECT_EQ(Scope, N->getScope());4823 EXPECT_EQ(Entity, N->getEntity());4824 EXPECT_EQ(File, N->getFile());4825 EXPECT_EQ(Line, N->getLine());4826 EXPECT_EQ(Name, N->getName());4827 EXPECT_EQ(4828 N, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name));4829 4830 EXPECT_NE(N,4831 DIImportedEntity::get(Context, dwarf::DW_TAG_imported_declaration,4832 Scope, Entity, File, Line, Name));4833 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, getSubprogram(), Entity,4834 File, Line, Name));4835 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, getCompositeType(),4836 File, Line, Name));4837 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, nullptr, Line,4838 Name));4839 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, File,4840 Line + 1, Name));4841 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,4842 "other"));4843 4844 TempDIImportedEntity Temp = N->clone();4845 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));4846 4847 MDTuple *Elements1 = getTuple();4848 MDTuple *Elements2 = getTuple();4849 auto *Ne = DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,4850 Name, Elements1);4851 4852 EXPECT_EQ(Elements1, Ne->getElements().get());4853 4854 EXPECT_EQ(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,4855 Name, Elements1));4856 EXPECT_NE(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,4857 "ModOther", Elements1));4858 EXPECT_NE(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,4859 Name, Elements2));4860 EXPECT_NE(4861 Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name));4862 4863 TempDIImportedEntity Tempe = Ne->clone();4864 EXPECT_EQ(Ne, MDNode::replaceWithUniqued(std::move(Tempe)));4865}4866 4867typedef MetadataTest MetadataAsValueTest;4868 4869TEST_F(MetadataAsValueTest, MDNode) {4870 MDNode *N = MDNode::get(Context, {});4871 auto *V = MetadataAsValue::get(Context, N);4872 EXPECT_TRUE(V->getType()->isMetadataTy());4873 EXPECT_EQ(N, V->getMetadata());4874 4875 auto *V2 = MetadataAsValue::get(Context, N);4876 EXPECT_EQ(V, V2);4877}4878 4879TEST_F(MetadataAsValueTest, MDNodeMDNode) {4880 MDNode *N = MDNode::get(Context, {});4881 Metadata *Ops[] = {N};4882 MDNode *N2 = MDNode::get(Context, Ops);4883 auto *V = MetadataAsValue::get(Context, N2);4884 EXPECT_TRUE(V->getType()->isMetadataTy());4885 EXPECT_EQ(N2, V->getMetadata());4886 4887 auto *V2 = MetadataAsValue::get(Context, N2);4888 EXPECT_EQ(V, V2);4889 4890 auto *V3 = MetadataAsValue::get(Context, N);4891 EXPECT_TRUE(V3->getType()->isMetadataTy());4892 EXPECT_NE(V, V3);4893 EXPECT_EQ(N, V3->getMetadata());4894}4895 4896TEST_F(MetadataAsValueTest, MDNodeConstant) {4897 auto *C = ConstantInt::getTrue(Context);4898 auto *MD = ConstantAsMetadata::get(C);4899 Metadata *Ops[] = {MD};4900 auto *N = MDNode::get(Context, Ops);4901 4902 auto *V = MetadataAsValue::get(Context, MD);4903 EXPECT_TRUE(V->getType()->isMetadataTy());4904 EXPECT_EQ(MD, V->getMetadata());4905 4906 auto *V2 = MetadataAsValue::get(Context, N);4907 EXPECT_EQ(MD, V2->getMetadata());4908 EXPECT_EQ(V, V2);4909}4910 4911typedef MetadataTest ValueAsMetadataTest;4912 4913TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {4914 Type *Ty = PointerType::getUnqual(Context);4915 std::unique_ptr<GlobalVariable> GV0(4916 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));4917 auto *MD = ValueAsMetadata::get(GV0.get());4918 EXPECT_TRUE(MD->getValue() == GV0.get());4919 ASSERT_TRUE(GV0->use_empty());4920 4921 std::unique_ptr<GlobalVariable> GV1(4922 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));4923 GV0->replaceAllUsesWith(GV1.get());4924 EXPECT_TRUE(MD->getValue() == GV1.get());4925}4926 4927TEST_F(ValueAsMetadataTest, handleRAUWWithTypeChange) {4928 // Test that handleRAUW supports type changes.4929 // This is helpful in cases where poison values are used to encode4930 // types in metadata, e.g. in type annotations.4931 // Changing the type stored in metadata requires to change the type of4932 // the stored poison value.4933 auto *I32Poison = PoisonValue::get(Type::getInt32Ty(Context));4934 auto *I64Poison = PoisonValue::get(Type::getInt64Ty(Context));4935 auto *MD = ConstantAsMetadata::get(I32Poison);4936 4937 EXPECT_EQ(MD->getValue(), I32Poison);4938 EXPECT_NE(MD->getValue(), I64Poison);4939 4940 ValueAsMetadata::handleRAUW(I32Poison, I64Poison);4941 4942 EXPECT_NE(MD->getValue(), I32Poison);4943 EXPECT_EQ(MD->getValue(), I64Poison);4944}4945 4946TEST_F(ValueAsMetadataTest, TempTempReplacement) {4947 // Create a constant.4948 ConstantAsMetadata *CI =4949 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(8, 0)));4950 4951 auto Temp1 = MDTuple::getTemporary(Context, {});4952 auto Temp2 = MDTuple::getTemporary(Context, {CI});4953 auto *N = MDTuple::get(Context, {Temp1.get()});4954 4955 // Test replacing a temporary node with another temporary node.4956 Temp1->replaceAllUsesWith(Temp2.get());4957 EXPECT_EQ(N->getOperand(0), Temp2.get());4958 4959 // Clean up Temp2 for teardown.4960 Temp2->replaceAllUsesWith(nullptr);4961}4962 4963TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) {4964 // Create a constant.4965 ConstantAsMetadata *CI =4966 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(8, 0)));4967 4968 // Create a temporary to prevent nodes from resolving.4969 auto Temp = MDTuple::getTemporary(Context, {});4970 4971 // When the first operand of N1 gets reset to nullptr, it'll collide with N2.4972 Metadata *Ops1[] = {CI, CI, Temp.get()};4973 Metadata *Ops2[] = {nullptr, CI, Temp.get()};4974 4975 auto *N1 = MDTuple::get(Context, Ops1);4976 auto *N2 = MDTuple::get(Context, Ops2);4977 ASSERT_NE(N1, N2);4978 4979 // Tell metadata that the constant is getting deleted.4980 //4981 // After this, N1 will be invalid, so don't touch it.4982 ValueAsMetadata::handleDeletion(CI->getValue());4983 EXPECT_EQ(nullptr, N2->getOperand(0));4984 EXPECT_EQ(nullptr, N2->getOperand(1));4985 EXPECT_EQ(Temp.get(), N2->getOperand(2));4986 4987 // Clean up Temp for teardown.4988 Temp->replaceAllUsesWith(nullptr);4989}4990 4991typedef MetadataTest DIArgListTest;4992 4993TEST_F(DIArgListTest, get) {4994 SmallVector<ValueAsMetadata *, 2> VMs;4995 VMs.push_back(4996 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(8, 0))));4997 VMs.push_back(4998 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(2, 0))));4999 DIArgList *DV0 = DIArgList::get(Context, VMs);5000 DIArgList *DV1 = DIArgList::get(Context, VMs);5001 EXPECT_EQ(DV0, DV1);5002}5003 5004TEST_F(DIArgListTest, UpdatesOnRAUW) {5005 Type *Ty = PointerType::getUnqual(Context);5006 ConstantAsMetadata *CI =5007 ConstantAsMetadata::get(ConstantInt::get(Context, APInt(8, 0)));5008 std::unique_ptr<GlobalVariable> GV0(5009 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));5010 auto *MD0 = ValueAsMetadata::get(GV0.get());5011 5012 SmallVector<ValueAsMetadata *, 2> VMs;5013 VMs.push_back(CI);5014 VMs.push_back(MD0);5015 auto *AL = DIArgList::get(Context, VMs);5016 EXPECT_EQ(AL->getArgs()[0], CI);5017 EXPECT_EQ(AL->getArgs()[1], MD0);5018 5019 std::unique_ptr<GlobalVariable> GV1(5020 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));5021 auto *MD1 = ValueAsMetadata::get(GV1.get());5022 GV0->replaceAllUsesWith(GV1.get());5023 EXPECT_EQ(AL->getArgs()[0], CI);5024 EXPECT_EQ(AL->getArgs()[1], MD1);5025}5026 5027typedef MetadataTest TrackingMDRefTest;5028 5029TEST_F(TrackingMDRefTest, UpdatesOnRAUW) {5030 Type *Ty = PointerType::getUnqual(Context);5031 std::unique_ptr<GlobalVariable> GV0(5032 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));5033 TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV0.get()));5034 EXPECT_TRUE(MD->getValue() == GV0.get());5035 ASSERT_TRUE(GV0->use_empty());5036 5037 std::unique_ptr<GlobalVariable> GV1(5038 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));5039 GV0->replaceAllUsesWith(GV1.get());5040 EXPECT_TRUE(MD->getValue() == GV1.get());5041 5042 // Reset it, so we don't inadvertently test deletion.5043 MD.reset();5044}5045 5046TEST_F(TrackingMDRefTest, UpdatesOnDeletion) {5047 Type *Ty = PointerType::getUnqual(Context);5048 std::unique_ptr<GlobalVariable> GV(5049 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));5050 TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV.get()));5051 EXPECT_TRUE(MD->getValue() == GV.get());5052 ASSERT_TRUE(GV->use_empty());5053 5054 GV.reset();5055 EXPECT_TRUE(!MD);5056}5057 5058TEST(NamedMDNodeTest, Search) {5059 LLVMContext Context;5060 ConstantAsMetadata *C =5061 ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1));5062 ConstantAsMetadata *C2 =5063 ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2));5064 5065 Metadata *const V = C;5066 Metadata *const V2 = C2;5067 MDNode *n = MDNode::get(Context, V);5068 MDNode *n2 = MDNode::get(Context, V2);5069 5070 Module M("MyModule", Context);5071 const char *Name = "llvm.NMD1";5072 NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name);5073 NMD->addOperand(n);5074 NMD->addOperand(n2);5075 5076 std::string Str;5077 raw_string_ostream oss(Str);5078 NMD->print(oss);5079 EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n", Str.c_str());5080}5081 5082typedef MetadataTest FunctionAttachmentTest;5083TEST_F(FunctionAttachmentTest, setMetadata) {5084 Function *F = getFunction("foo");5085 ASSERT_FALSE(F->hasMetadata());5086 EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));5087 EXPECT_EQ(nullptr, F->getMetadata("dbg"));5088 EXPECT_EQ(nullptr, F->getMetadata("other"));5089 5090 DISubprogram *SP1 = getSubprogram();5091 DISubprogram *SP2 = getSubprogram();5092 ASSERT_NE(SP1, SP2);5093 5094 F->setMetadata("dbg", SP1);5095 EXPECT_TRUE(F->hasMetadata());5096 EXPECT_EQ(SP1, F->getMetadata(LLVMContext::MD_dbg));5097 EXPECT_EQ(SP1, F->getMetadata("dbg"));5098 EXPECT_EQ(nullptr, F->getMetadata("other"));5099 5100 F->setMetadata(LLVMContext::MD_dbg, SP2);5101 EXPECT_TRUE(F->hasMetadata());5102 EXPECT_EQ(SP2, F->getMetadata(LLVMContext::MD_dbg));5103 EXPECT_EQ(SP2, F->getMetadata("dbg"));5104 EXPECT_EQ(nullptr, F->getMetadata("other"));5105 5106 F->setMetadata("dbg", nullptr);5107 EXPECT_FALSE(F->hasMetadata());5108 EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));5109 EXPECT_EQ(nullptr, F->getMetadata("dbg"));5110 EXPECT_EQ(nullptr, F->getMetadata("other"));5111 5112 MDTuple *T1 = getTuple();5113 MDTuple *T2 = getTuple();5114 ASSERT_NE(T1, T2);5115 5116 F->setMetadata("other1", T1);5117 F->setMetadata("other2", T2);5118 EXPECT_TRUE(F->hasMetadata());5119 EXPECT_EQ(T1, F->getMetadata("other1"));5120 EXPECT_EQ(T2, F->getMetadata("other2"));5121 EXPECT_EQ(nullptr, F->getMetadata("dbg"));5122 5123 F->setMetadata("other1", T2);5124 F->setMetadata("other2", T1);5125 EXPECT_EQ(T2, F->getMetadata("other1"));5126 EXPECT_EQ(T1, F->getMetadata("other2"));5127 5128 F->setMetadata("other1", nullptr);5129 F->setMetadata("other2", nullptr);5130 EXPECT_FALSE(F->hasMetadata());5131 EXPECT_EQ(nullptr, F->getMetadata("other1"));5132 EXPECT_EQ(nullptr, F->getMetadata("other2"));5133}5134 5135TEST_F(FunctionAttachmentTest, getAll) {5136 Function *F = getFunction("foo");5137 5138 MDTuple *T1 = getTuple();5139 MDTuple *T2 = getTuple();5140 MDTuple *P = getTuple();5141 DISubprogram *SP = getSubprogram();5142 5143 F->setMetadata("other1", T2);5144 F->setMetadata(LLVMContext::MD_dbg, SP);5145 F->setMetadata("other2", T1);5146 F->setMetadata(LLVMContext::MD_prof, P);5147 F->setMetadata("other2", T2);5148 F->setMetadata("other1", T1);5149 5150 SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;5151 F->getAllMetadata(MDs);5152 ASSERT_EQ(4u, MDs.size());5153 EXPECT_EQ(LLVMContext::MD_dbg, MDs[0].first);5154 EXPECT_EQ(LLVMContext::MD_prof, MDs[1].first);5155 EXPECT_EQ(Context.getMDKindID("other1"), MDs[2].first);5156 EXPECT_EQ(Context.getMDKindID("other2"), MDs[3].first);5157 EXPECT_EQ(SP, MDs[0].second);5158 EXPECT_EQ(P, MDs[1].second);5159 EXPECT_EQ(T1, MDs[2].second);5160 EXPECT_EQ(T2, MDs[3].second);5161}5162 5163TEST_F(FunctionAttachmentTest, Verifier) {5164 Function *F = getFunction("foo");5165 F->setMetadata("attach", getTuple());5166 F->setIsMaterializable(true);5167 5168 // Confirm this is materializable.5169 ASSERT_TRUE(F->isMaterializable());5170 5171 // Materializable functions cannot have metadata attachments.5172 EXPECT_TRUE(verifyFunction(*F));5173 5174 // Function declarations can.5175 F->setIsMaterializable(false);5176 EXPECT_FALSE(verifyModule(*F->getParent()));5177 EXPECT_FALSE(verifyFunction(*F));5178 5179 // So can definitions.5180 (void)new UnreachableInst(Context, BasicBlock::Create(Context, "bb", F));5181 EXPECT_FALSE(verifyModule(*F->getParent()));5182 EXPECT_FALSE(verifyFunction(*F));5183}5184 5185TEST_F(FunctionAttachmentTest, RealEntryCount) {5186 Function *F = getFunction("foo");5187 EXPECT_FALSE(F->getEntryCount().has_value());5188 F->setEntryCount(12304, Function::PCT_Real);5189 auto Count = F->getEntryCount();5190 EXPECT_TRUE(Count.has_value());5191 EXPECT_EQ(12304u, Count->getCount());5192 EXPECT_EQ(Function::PCT_Real, Count->getType());5193}5194 5195TEST_F(FunctionAttachmentTest, SyntheticEntryCount) {5196 Function *F = getFunction("bar");5197 EXPECT_FALSE(F->getEntryCount().has_value());5198 F->setEntryCount(123, Function::PCT_Synthetic);5199 auto Count = F->getEntryCount(true /*allow synthetic*/);5200 EXPECT_TRUE(Count.has_value());5201 EXPECT_EQ(123u, Count->getCount());5202 EXPECT_EQ(Function::PCT_Synthetic, Count->getType());5203}5204 5205TEST_F(FunctionAttachmentTest, SubprogramAttachment) {5206 Function *F = getFunction("foo");5207 DISubprogram *SP = getSubprogram();5208 F->setSubprogram(SP);5209 5210 // Note that the static_cast confirms that F->getSubprogram() actually5211 // returns an DISubprogram.5212 EXPECT_EQ(SP, static_cast<DISubprogram *>(F->getSubprogram()));5213 EXPECT_EQ(SP, F->getMetadata("dbg"));5214 EXPECT_EQ(SP, F->getMetadata(LLVMContext::MD_dbg));5215}5216 5217typedef MetadataTest DistinctMDOperandPlaceholderTest;5218TEST_F(DistinctMDOperandPlaceholderTest, getID) {5219 EXPECT_EQ(7u, DistinctMDOperandPlaceholder(7).getID());5220}5221 5222TEST_F(DistinctMDOperandPlaceholderTest, replaceUseWith) {5223 // Set up some placeholders.5224 DistinctMDOperandPlaceholder PH0(7);5225 DistinctMDOperandPlaceholder PH1(3);5226 DistinctMDOperandPlaceholder PH2(0);5227 Metadata *Ops[] = {&PH0, &PH1, &PH2};5228 auto *D = MDTuple::getDistinct(Context, Ops);5229 ASSERT_EQ(&PH0, D->getOperand(0));5230 ASSERT_EQ(&PH1, D->getOperand(1));5231 ASSERT_EQ(&PH2, D->getOperand(2));5232 5233 // Replace them.5234 auto *N0 = MDTuple::get(Context, {});5235 auto *N1 = MDTuple::get(Context, N0);5236 PH0.replaceUseWith(N0);5237 PH1.replaceUseWith(N1);5238 PH2.replaceUseWith(nullptr);5239 EXPECT_EQ(N0, D->getOperand(0));5240 EXPECT_EQ(N1, D->getOperand(1));5241 EXPECT_EQ(nullptr, D->getOperand(2));5242}5243 5244TEST_F(DistinctMDOperandPlaceholderTest, replaceUseWithNoUser) {5245 // There is no user, but we can still call replace.5246 DistinctMDOperandPlaceholder(7).replaceUseWith(MDTuple::get(Context, {}));5247}5248 5249// Test various assertions in metadata tracking. Don't run these tests if gtest5250// will use SEH to recover from them. Two of these tests get halfway through5251// inserting metadata into DenseMaps for tracking purposes, and then they5252// assert, and we attempt to destroy an LLVMContext with broken invariants,5253// leading to infinite loops.5254#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)5255TEST_F(DistinctMDOperandPlaceholderTest, MetadataAsValue) {5256 // This shouldn't crash.5257 DistinctMDOperandPlaceholder PH(7);5258 EXPECT_DEATH(MetadataAsValue::get(Context, &PH),5259 "Unexpected callback to owner");5260}5261 5262TEST_F(DistinctMDOperandPlaceholderTest, UniquedMDNode) {5263 // This shouldn't crash.5264 DistinctMDOperandPlaceholder PH(7);5265 EXPECT_DEATH(MDTuple::get(Context, &PH), "Unexpected callback to owner");5266}5267 5268TEST_F(DistinctMDOperandPlaceholderTest, SecondDistinctMDNode) {5269 // This shouldn't crash.5270 DistinctMDOperandPlaceholder PH(7);5271 MDTuple::getDistinct(Context, &PH);5272 EXPECT_DEATH(MDTuple::getDistinct(Context, &PH),5273 "Placeholders can only be used once");5274}5275 5276TEST_F(DistinctMDOperandPlaceholderTest, TrackingMDRefAndDistinctMDNode) {5277 // TrackingMDRef doesn't install an owner callback, so it can't be detected5278 // as an invalid use. However, using a placeholder in a TrackingMDRef *and*5279 // a distinct node isn't possible and we should assert.5280 //5281 // (There's no positive test for using TrackingMDRef because it's not a5282 // useful thing to do.)5283 {5284 DistinctMDOperandPlaceholder PH(7);5285 MDTuple::getDistinct(Context, &PH);5286 EXPECT_DEATH(TrackingMDRef Ref(&PH), "Placeholders can only be used once");5287 }5288 {5289 DistinctMDOperandPlaceholder PH(7);5290 TrackingMDRef Ref(&PH);5291 EXPECT_DEATH(MDTuple::getDistinct(Context, &PH),5292 "Placeholders can only be used once");5293 }5294}5295#endif5296 5297typedef MetadataTest DebugVariableTest;5298TEST_F(DebugVariableTest, DenseMap) {5299 DenseMap<DebugVariable, uint64_t> DebugVariableMap;5300 5301 DILocalScope *Scope = getSubprogram();5302 DIFile *File = getFile();5303 DIType *Type = getDerivedType();5304 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);5305 5306 DILocation *InlinedLoc = DILocation::get(Context, 2, 7, Scope);5307 5308 DILocalVariable *VarA =5309 DILocalVariable::get(Context, Scope, "A", File, 5, Type, 2, Flags, 8, nullptr);5310 DILocalVariable *VarB =5311 DILocalVariable::get(Context, Scope, "B", File, 7, Type, 3, Flags, 8, nullptr);5312 5313 DebugVariable DebugVariableA(VarA, std::nullopt, nullptr);5314 DebugVariable DebugVariableInlineA(VarA, std::nullopt, InlinedLoc);5315 DebugVariable DebugVariableB(VarB, std::nullopt, nullptr);5316 DebugVariable DebugVariableFragB(VarB, {{16, 16}}, nullptr);5317 5318 DebugVariableMap.insert({DebugVariableA, 2});5319 DebugVariableMap.insert({DebugVariableInlineA, 3});5320 DebugVariableMap.insert({DebugVariableB, 6});5321 DebugVariableMap.insert({DebugVariableFragB, 12});5322 5323 EXPECT_EQ(DebugVariableMap.count(DebugVariableA), 1u);5324 EXPECT_EQ(DebugVariableMap.count(DebugVariableInlineA), 1u);5325 EXPECT_EQ(DebugVariableMap.count(DebugVariableB), 1u);5326 EXPECT_EQ(DebugVariableMap.count(DebugVariableFragB), 1u);5327 5328 EXPECT_EQ(DebugVariableMap.find(DebugVariableA)->second, 2u);5329 EXPECT_EQ(DebugVariableMap.find(DebugVariableInlineA)->second, 3u);5330 EXPECT_EQ(DebugVariableMap.find(DebugVariableB)->second, 6u);5331 EXPECT_EQ(DebugVariableMap.find(DebugVariableFragB)->second, 12u);5332}5333 5334typedef MetadataTest MDTupleAllocationTest;5335TEST_F(MDTupleAllocationTest, Tracking) {5336 // Make sure that the move constructor and move assignment op5337 // for MDOperand correctly adjust tracking information.5338 auto *Value1 = getConstantAsMetadata();5339 MDTuple *A = MDTuple::getDistinct(Context, {Value1, Value1});5340 EXPECT_EQ(A->getOperand(0), Value1);5341 EXPECT_EQ(A->getOperand(1), Value1);5342 5343 MDNode::op_range Ops = A->operands();5344 5345 MDOperand NewOps1;5346 // Move assignment operator.5347 NewOps1 = std::move(*const_cast<MDOperand *>(Ops.begin()));5348 // Move constructor.5349 MDOperand NewOps2(std::move(*const_cast<MDOperand *>(Ops.begin() + 1)));5350 5351 EXPECT_EQ(NewOps1.get(), static_cast<Metadata *>(Value1));5352 EXPECT_EQ(NewOps2.get(), static_cast<Metadata *>(Value1));5353 5354 auto *Value2 = getConstantAsMetadata();5355 Value *V1 = Value1->getValue();5356 Value *V2 = Value2->getValue();5357 ValueAsMetadata::handleRAUW(V1, V2);5358 5359 EXPECT_EQ(NewOps1.get(), static_cast<Metadata *>(Value2));5360 EXPECT_EQ(NewOps2.get(), static_cast<Metadata *>(Value2));5361}5362 5363TEST_F(MDTupleAllocationTest, Resize) {5364 MDTuple *A = getTuple();5365 Metadata *Value1 = getConstantAsMetadata();5366 Metadata *Value2 = getConstantAsMetadata();5367 Metadata *Value3 = getConstantAsMetadata();5368 5369 EXPECT_EQ(A->getNumOperands(), 0u);5370 5371 // Add a couple of elements to it, which resizes the node.5372 A->push_back(Value1);5373 EXPECT_EQ(A->getNumOperands(), 1u);5374 EXPECT_EQ(A->getOperand(0), Value1);5375 5376 A->push_back(Value2);5377 EXPECT_EQ(A->getNumOperands(), 2u);5378 EXPECT_EQ(A->getOperand(0), Value1);5379 EXPECT_EQ(A->getOperand(1), Value2);5380 5381 // Append another element, which should resize the node5382 // to a "large" node, though not detectable by the user.5383 A->push_back(Value3);5384 EXPECT_EQ(A->getNumOperands(), 3u);5385 EXPECT_EQ(A->getOperand(0), Value1);5386 EXPECT_EQ(A->getOperand(1), Value2);5387 EXPECT_EQ(A->getOperand(2), Value3);5388 5389 // Remove the last element5390 A->pop_back();5391 EXPECT_EQ(A->getNumOperands(), 2u);5392 EXPECT_EQ(A->getOperand(1), Value2);5393 5394 // Allocate a node with 4 operands.5395 Metadata *Value4 = getConstantAsMetadata();5396 Metadata *Value5 = getConstantAsMetadata();5397 5398 Metadata *Ops[] = {Value1, Value2, Value3, Value4};5399 MDTuple *B = MDTuple::getDistinct(Context, Ops);5400 5401 EXPECT_EQ(B->getNumOperands(), 4u);5402 B->pop_back();5403 EXPECT_EQ(B->getNumOperands(), 3u);5404 B->push_back(Value5);5405 EXPECT_EQ(B->getNumOperands(), 4u);5406 EXPECT_EQ(B->getOperand(0), Value1);5407 EXPECT_EQ(B->getOperand(1), Value2);5408 EXPECT_EQ(B->getOperand(2), Value3);5409 EXPECT_EQ(B->getOperand(3), Value5);5410 5411 // Check that we can resize temporary nodes as well.5412 auto Temp1 = MDTuple::getTemporary(Context, {});5413 EXPECT_EQ(Temp1->getNumOperands(), 0u);5414 5415 Temp1->push_back(Value1);5416 EXPECT_EQ(Temp1->getNumOperands(), 1u);5417 EXPECT_EQ(Temp1->getOperand(0), Value1);5418 5419 for (int i = 0; i < 11; i++)5420 Temp1->push_back(Value2);5421 EXPECT_EQ(Temp1->getNumOperands(), 12u);5422 EXPECT_EQ(Temp1->getOperand(2), Value2);5423 EXPECT_EQ(Temp1->getOperand(11), Value2);5424 5425 // Allocate a node that starts off as a large one.5426 Metadata *OpsLarge[] = {Value1, Value2, Value3, Value4,5427 Value1, Value2, Value3, Value4,5428 Value1, Value2, Value3, Value4,5429 Value1, Value2, Value3, Value4,5430 Value1, Value2, Value3, Value4};5431 MDTuple *C = MDTuple::getDistinct(Context, OpsLarge);5432 EXPECT_EQ(C->getNumOperands(), 20u);5433 EXPECT_EQ(C->getOperand(7), Value4);5434 EXPECT_EQ(C->getOperand(13), Value2);5435 5436 C->push_back(Value1);5437 C->push_back(Value2);5438 EXPECT_EQ(C->getNumOperands(), 22u);5439 EXPECT_EQ(C->getOperand(21), Value2);5440 C->pop_back();5441 EXPECT_EQ(C->getNumOperands(), 21u);5442 EXPECT_EQ(C->getOperand(20), Value1);5443}5444 5445TEST_F(MDTupleAllocationTest, Tracking2) {5446 // Resize a tuple and check that we can still RAUW one of its operands.5447 auto *Value1 = getConstantAsMetadata();5448 MDTuple *A = getTuple();5449 A->push_back(Value1);5450 A->push_back(Value1);5451 A->push_back(Value1); // Causes a resize to large.5452 EXPECT_EQ(A->getOperand(0), Value1);5453 EXPECT_EQ(A->getOperand(1), Value1);5454 EXPECT_EQ(A->getOperand(2), Value1);5455 5456 auto *Value2 = getConstantAsMetadata();5457 Value *V1 = Value1->getValue();5458 Value *V2 = Value2->getValue();5459 ValueAsMetadata::handleRAUW(V1, V2);5460 5461 EXPECT_EQ(A->getOperand(0), Value2);5462 EXPECT_EQ(A->getOperand(1), Value2);5463 EXPECT_EQ(A->getOperand(2), Value2);5464}5465 5466#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)5467typedef MetadataTest MDTupleAllocationDeathTest;5468TEST_F(MDTupleAllocationDeathTest, ResizeRejected) {5469 MDTuple *A = MDTuple::get(Context, std::nullopt);5470 auto *Value1 = getConstantAsMetadata();5471 EXPECT_DEATH(A->push_back(Value1),5472 "Resizing is not supported for uniqued nodes");5473 5474 // Check that a node, which has been allocated as a temporary,5475 // cannot be resized after it has been uniqued.5476 auto *Value2 = getConstantAsMetadata();5477 auto B = MDTuple::getTemporary(Context, {Value2});5478 B->push_back(Value2);5479 MDTuple *BUniqued = MDNode::replaceWithUniqued(std::move(B));5480 EXPECT_EQ(BUniqued->getNumOperands(), 2u);5481 EXPECT_EQ(BUniqued->getOperand(1), Value2);5482 EXPECT_DEATH(BUniqued->push_back(Value2),5483 "Resizing is not supported for uniqued nodes");5484}5485#endif5486 5487} // end namespace5488