591 lines · cpp
1//===- llvm/unittest/DebugInfo/LogicalView/LocationRangesTest.cpp ---------===//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/DebugInfo/LogicalView/Core/LVLine.h"10#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"11#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"12#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"13#include "llvm/DebugInfo/LogicalView/Core/LVType.h"14#include "llvm/Support/ScopedPrinter.h"15#include "llvm/Support/ToolOutputFile.h"16#include "llvm/Testing/Support/Error.h"17 18#include "gtest/gtest.h"19 20using namespace llvm;21using namespace llvm::logicalview;22 23namespace {24 25class ReaderTest : public LVReader {26protected:27 void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);28 void add(LVScope *Parent, LVElement *Element);29 void set(LVElement *Element, StringRef Name, LVOffset Offset,30 uint32_t LineNumber = 0, LVElement *Type = nullptr);31 void set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,32 LVAddress LowerAddress, LVAddress UpperAddress);33 34public:35 ReaderTest(ScopedPrinter &W) : LVReader("", "", W) { setInstance(this); }36 37 Error createScopes() override { return LVReader::createScopes(); }38};39 40// Helper function to add a logical element to a given scope.41void ReaderTest::add(LVScope *Parent, LVElement *Child) {42 Parent->addElement(Child);43 EXPECT_EQ(Child->getParent(), Parent);44 EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);45}46 47// Helper function to set the initial values for a given logical element.48void ReaderTest::set(LVElement *Element, StringRef Name, LVOffset Offset,49 uint32_t LineNumber, LVElement *Type) {50 Element->setName(Name);51 Element->setOffset(Offset);52 Element->setLineNumber(LineNumber);53 Element->setType(Type);54 EXPECT_EQ(Element->getName(), Name);55 EXPECT_EQ(Element->getOffset(), Offset);56 EXPECT_EQ(Element->getLineNumber(), LineNumber);57 EXPECT_EQ(Element->getType(), Type);58}59 60// Helper function to set the initial values for a given logical location.61void ReaderTest::set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,62 LVAddress LowerAddress, LVAddress UpperAddress) {63 Location->setLowerLine(LowerLine);64 Location->setUpperLine(UpperLine);65 Location->setLowerAddress(LowerAddress);66 Location->setUpperAddress(UpperAddress);67 EXPECT_EQ(Location->getLowerLine(), LowerLine);68 EXPECT_EQ(Location->getUpperLine(), UpperLine);69 EXPECT_EQ(Location->getLowerAddress(), LowerAddress);70 EXPECT_EQ(Location->getUpperAddress(), UpperAddress);71}72 73// Helper function to add a logical location to a logical symbol.74void ReaderTest::add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine) {75 dwarf::Attribute Attr = dwarf::DW_AT_location;76 77 Symbol->addLocation(Attr, LowerLine->getAddress(), UpperLine->getAddress(),78 /*SectionOffset=*/0, /*LocDesOffset=*/0);79}80 81class ReaderTestLocations : public ReaderTest {82#define CREATE(VARIABLE, CREATE_FUNCTION) \83 VARIABLE = CREATE_FUNCTION(); \84 EXPECT_NE(VARIABLE, nullptr);85 86 // Types.87 LVType *IntegerType = nullptr;88 89 // Scopes.90 LVScope *NestedScope = nullptr;91 LVScopeFunction *Function = nullptr;92 93 // Symbols.94 LVSymbol *LocalVariable = nullptr;95 LVSymbol *NestedVariable = nullptr;96 LVSymbol *Parameter = nullptr;97 98 // Lines.99 LVLine *LineOne = nullptr;100 LVLine *LineTwo = nullptr;101 LVLine *LineThree = nullptr;102 LVLine *LineFour = nullptr;103 LVLine *LineFive = nullptr;104 LVLine *LineSix = nullptr;105 106 // Locations.107 LVLocation *LocationOne = nullptr;108 LVLocation *LocationTwo = nullptr;109 LVLocation *LocationThree = nullptr;110 LVLocation *LocationFour = nullptr;111 LVLocation *LocationFive = nullptr;112 LVLocation *LocationSix = nullptr;113 114public:115 ReaderTestLocations(ScopedPrinter &W) : ReaderTest(W) {}116 117 void createElements();118 void addElements();119 void initElements();120};121 122// Create the logical elements.123void ReaderTestLocations::createElements() {124 // Create scope root.125 Error Err = createScopes();126 ASSERT_THAT_ERROR(std::move(Err), Succeeded());127 Root = getScopesRoot();128 EXPECT_NE(Root, nullptr);129 130 // Create the logical types.131 CREATE(IntegerType, createType);132 133 // Create the logical scopes.134 CREATE(NestedScope, createScope);135 CREATE(CompileUnit, createScopeCompileUnit);136 CREATE(Function, createScopeFunction);137 138 // Create the logical symbols.139 CREATE(LocalVariable, createSymbol);140 CREATE(NestedVariable, createSymbol);141 CREATE(Parameter, createSymbol);142 143 // Create the logical lines.144 CREATE(LineOne, createLine);145 CREATE(LineTwo, createLine);146 CREATE(LineThree, createLine);147 CREATE(LineFour, createLine);148 CREATE(LineFive, createLine);149 CREATE(LineSix, createLine);150 151 // Create the logical locations.152 CREATE(LocationOne, createLocation);153 CREATE(LocationTwo, createLocation);154 CREATE(LocationThree, createLocation);155 CREATE(LocationFour, createLocation);156 CREATE(LocationFive, createLocation);157 CREATE(LocationSix, createLocation);158}159 160// Create the logical view adding the created logical elements.161void ReaderTestLocations::addElements() {162 setCompileUnit(CompileUnit);163 164 // Root165 // CompileUnit166 // IntegerType167 // Function168 // LocationOne169 // LocationTwo170 // LocationFive171 // LocationSix172 // Parameter173 // LocalVariable174 // LineOne175 // LineTwo176 // NestedScope177 // LocationThree178 // LocationFour179 // NestedVariable180 // LineThree181 // LineFour182 // LineFive183 // LineSix184 185 // Add elements to Root.186 add(Root, CompileUnit);187 188 // Add elements to CompileUnit.189 add(CompileUnit, IntegerType);190 add(CompileUnit, Function);191 192 // Add elements to Function.193 add(Function, Parameter);194 add(Function, LocalVariable);195 add(Function, LineOne);196 add(Function, LineTwo);197 add(Function, LineFive);198 add(Function, LineSix);199 add(Function, NestedScope);200 201 // Add elements to NestedScope.202 add(NestedScope, NestedVariable);203 add(NestedScope, LineThree);204 add(NestedScope, LineFour);205}206 207// Set initial values to logical elements.208void ReaderTestLocations::initElements() {209 // Types.210 set(IntegerType, "int", 0x1000);211 212 // Scopes.213 set(CompileUnit, "foo.cpp", 0x2000);214 set(Function, "foo", 0x2010, 100, IntegerType);215 set(NestedScope, "", 0x2020, 300);216 217 // Symbols.218 set(Parameter, "Param", 0x3000, 110, IntegerType);219 set(LocalVariable, "LocalVariable", 0x3000, 120, IntegerType);220 set(NestedVariable, "NestedVariable", 0x3010, 310, IntegerType);221 222 // Lines.223 set(LineOne, "", 0x5000, 100);224 set(LineTwo, "", 0x5200, 200);225 set(LineThree, "", 0x5400, 300);226 set(LineFour, "", 0x5600, 400);227 set(LineFive, "", 0x5800, 500);228 set(LineSix, "", 0x6000, 600);229 230 // Locations.231 set(LocationOne, LineOne, LineOne, 0x5000, 0x5100);232 EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),233 " Lines 100:100 [0x0000005000:0x0000005100]");234 235 set(LocationTwo, LineTwo, LineTwo, 0x5200, 0x5300);236 EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),237 " Lines 200:200 [0x0000005200:0x0000005300]");238 239 set(LocationThree, LineThree, LineThree, 0x5400, 0x5500);240 EXPECT_STREQ(LocationThree->getIntervalInfo().c_str(),241 " Lines 300:300 [0x0000005400:0x0000005500]");242 243 set(LocationFour, LineFour, LineFour, 0x5600, 0x5700);244 LocationFour->setIsAddressRange();245 EXPECT_STREQ(LocationFour->getIntervalInfo().c_str(),246 "{Range} Lines 400:400 [0x0000005600:0x0000005700]");247 248 set(LocationFive, LineFive, LineFive, 0x5800, 0x5900);249 LocationFive->setIsAddressRange();250 EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),251 "{Range} Lines 500:500 [0x0000005800:0x0000005900]");252 253 set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);254 LocationSix->setIsAddressRange();255 EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),256 "{Range} Lines 600:600 [0x0000006000:0x0000006100]");257 258 // Add ranges to Function.259 // Function: LocationOne, LocationTwo, LocationFive, LocationSix260 Function->addObject(LocationOne);261 Function->addObject(LocationTwo);262 Function->addObject(LocationFive);263 Function->addObject(LocationSix);264 EXPECT_EQ(Function->rangeCount(), 4u);265 266 // Add ranges to NestedScope.267 // NestedScope: LocationThree, LocationFour268 NestedScope->addObject(LocationThree);269 NestedScope->addObject(LocationFour);270 EXPECT_EQ(NestedScope->rangeCount(), 2u);271 272 // Get all ranges.273 LVRange Ranges;274 CompileUnit->getRanges(Ranges);275 Ranges.startSearch();276 EXPECT_EQ(Ranges.getEntry(0x4000), nullptr);277 278 EXPECT_EQ(Ranges.getEntry(0x5060), Function);279 EXPECT_EQ(Ranges.getEntry(0x5850), Function);280 EXPECT_EQ(Ranges.getEntry(0x5010, 0x5090), Function);281 EXPECT_EQ(Ranges.getEntry(0x5210, 0x5290), Function);282 EXPECT_EQ(Ranges.getEntry(0x5810, 0x5890), Function);283 EXPECT_EQ(Ranges.getEntry(0x6010, 0x6090), Function);284 285 EXPECT_EQ(Ranges.getEntry(0x5400), NestedScope);286 EXPECT_EQ(Ranges.getEntry(0x5650), NestedScope);287 EXPECT_EQ(Ranges.getEntry(0x5410, 0x5490), NestedScope);288 EXPECT_EQ(Ranges.getEntry(0x5610, 0x5690), NestedScope);289 290 EXPECT_EQ(Ranges.getEntry(0x8000), nullptr);291 Ranges.endSearch();292 293 // Add locations to symbols.294 // Parameter: [LineOne, LineSix]295 // LocalVariable: [LineTwo, LineSix], [LineFour, LineFive]296 // NestedVariable: [LineThree, LineFour]297 add(Parameter, LineOne, LineSix);298 add(LocalVariable, LineTwo, LineSix);299 add(LocalVariable, LineFour, LineFive);300 add(NestedVariable, LineThree, LineFour);301 302 LVLocation *Location;303 LVLocations Locations;304 Parameter->getLocations(Locations);305 ASSERT_EQ(Locations.size(), 1u);306 Location = Locations[0];307 EXPECT_EQ(Location->getLowerAddress(), LineOne->getAddress());308 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());309 310 Locations.clear();311 LocalVariable->getLocations(Locations);312 ASSERT_EQ(Locations.size(), 2u);313 Location = Locations[0];314 EXPECT_EQ(Location->getLowerAddress(), LineTwo->getAddress());315 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());316 Location = Locations[1];317 EXPECT_EQ(Location->getLowerAddress(), LineFour->getAddress());318 EXPECT_EQ(Location->getUpperAddress(), LineFive->getAddress());319 320 Locations.clear();321 NestedVariable->getLocations(Locations);322 ASSERT_EQ(Locations.size(), 1u);323 Location = Locations[0];324 EXPECT_EQ(Location->getLowerAddress(), LineThree->getAddress());325 EXPECT_EQ(Location->getUpperAddress(), LineFour->getAddress());326}327 328class ReaderTestCoverage : public ReaderTest {329 // Types.330 LVType *IntegerType = nullptr;331 332 // Scopes.333 LVScopeFunction *Function = nullptr;334 LVScopeFunctionInlined *InlinedFunction = nullptr;335 336 // Symbols.337 LVSymbol *Variable = nullptr;338 LVSymbol *Parameter = nullptr;339 340 // Lines.341 LVLine *LineOne = nullptr;342 LVLine *LineTwo = nullptr;343 LVLine *LineThree = nullptr;344 LVLine *LineFour = nullptr;345 LVLine *LineFive = nullptr;346 LVLine *LineSix = nullptr;347 348 // Locations.349 LVLocation *LocationOne = nullptr;350 LVLocation *LocationTwo = nullptr;351 LVLocation *LocationFive = nullptr;352 LVLocation *LocationSix = nullptr;353 354public:355 ReaderTestCoverage(ScopedPrinter &W) : ReaderTest(W) {}356 357 void createElements();358 void addElements();359 void initElements();360};361 362// Create the logical elements.363void ReaderTestCoverage::createElements() {364 // Create scope root.365 Error Err = createScopes();366 ASSERT_THAT_ERROR(std::move(Err), Succeeded());367 Root = getScopesRoot();368 EXPECT_NE(Root, nullptr);369 370 // Create the logical types.371 IntegerType = createType();372 EXPECT_NE(IntegerType, nullptr);373 374 // Create the logical scopes.375 CompileUnit = createScopeCompileUnit();376 EXPECT_NE(CompileUnit, nullptr);377 Function = createScopeFunction();378 EXPECT_NE(Function, nullptr);379 InlinedFunction = createScopeFunctionInlined();380 EXPECT_NE(InlinedFunction, nullptr);381 382 // Create the logical symbols.383 Variable = createSymbol();384 EXPECT_NE(Variable, nullptr);385 Parameter = createSymbol();386 EXPECT_NE(Parameter, nullptr);387 388 // Create the logical lines.389 LineOne = createLine();390 EXPECT_NE(LineOne, nullptr);391 LineTwo = createLine();392 EXPECT_NE(LineTwo, nullptr);393 LineThree = createLine();394 EXPECT_NE(LineThree, nullptr);395 LineFour = createLine();396 EXPECT_NE(LineFour, nullptr);397 LineFive = createLine();398 EXPECT_NE(LineFive, nullptr);399 LineSix = createLine();400 EXPECT_NE(LineSix, nullptr);401 402 // Create the logical locations.403 LocationOne = createLocation();404 EXPECT_NE(LocationOne, nullptr);405 LocationTwo = createLocation();406 EXPECT_NE(LocationTwo, nullptr);407 LocationFive = createLocation();408 EXPECT_NE(LocationFive, nullptr);409 LocationSix = createLocation();410 EXPECT_NE(LocationSix, nullptr);411}412 413// Create the logical view adding the created logical elements.414void ReaderTestCoverage::addElements() {415 setCompileUnit(CompileUnit);416 417 // Root418 // CompileUnit419 // IntegerType420 // Function421 // Ranges422 // [LineOne, LineOne]423 // [LineTwo, LineSix]424 // [LineSix, LineSix]425 // LineOne426 // LineTwo427 // InlinedFunction428 // Ranges429 // [LineFive, LineFive]430 // Parameter431 // Location432 // [LineThree, LineThree]433 // Variable434 // Location435 // [LineFour, LineFive]436 // [LineFive, LineSix]437 // LineThree438 // LineFour439 // LineFive440 // LineSix441 442 // Add elements to Root.443 add(Root, CompileUnit);444 445 // Add elements to CompileUnit.446 add(CompileUnit, IntegerType);447 add(CompileUnit, Function);448 449 // Add elements to Function.450 add(Function, InlinedFunction);451 add(Function, LineOne);452 add(Function, LineTwo);453 add(Function, LineSix);454 455 // Add elements to function InlinedFunction.456 add(InlinedFunction, Parameter);457 add(InlinedFunction, Variable);458 add(InlinedFunction, LineThree);459 add(InlinedFunction, LineFour);460 add(InlinedFunction, LineFive);461}462 463// Set initial values to logical elements.464void ReaderTestCoverage::initElements() {465 // Types.466 set(IntegerType, "int", 0x1000);467 468 // Scopes.469 set(CompileUnit, "foo.cpp", 0x2000);470 set(Function, "foo", 0x2500, 100, IntegerType);471 set(InlinedFunction, "InlinedFunction", 0x3000, 300);472 473 // Symbols.474 set(Parameter, "Parameter", 0x3100, 310, IntegerType);475 set(Variable, "Variable", 0x3200, 320, IntegerType);476 477 // Lines.478 set(LineOne, "", 0x5000, 100);479 set(LineTwo, "", 0x5200, 200);480 set(LineThree, "", 0x5400, 300);481 set(LineFour, "", 0x5600, 400);482 set(LineFive, "", 0x5800, 500);483 set(LineSix, "", 0x6000, 600);484 485 // Locations.486 set(LocationOne, LineOne, LineOne, 0x5000, 0x5199);487 EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),488 " Lines 100:100 [0x0000005000:0x0000005199]");489 490 set(LocationTwo, LineTwo, LineSix, 0x5200, 0x6100);491 EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),492 " Lines 200:600 [0x0000005200:0x0000006100]");493 494 set(LocationFive, LineFive, LineFive, 0x5800, 0x5900);495 EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),496 " Lines 500:500 [0x0000005800:0x0000005900]");497 498 set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);499 EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),500 " Lines 600:600 [0x0000006000:0x0000006100]");501 502 // Add ranges to Function.503 // Function: LocationOne, LocationTwo, LocationSix504 Function->addObject(LocationOne);505 Function->addObject(LocationTwo);506 Function->addObject(LocationSix);507 EXPECT_EQ(Function->rangeCount(), 3u);508 509 // Add ranges to Inlined.510 // Inlined: LocationFive511 InlinedFunction->addObject(LocationFive);512 EXPECT_EQ(InlinedFunction->rangeCount(), 1u);513 514 // Add locations to symbols.515 // Parameter: [LineThree, LineThree]516 // Variable: [LineFour, LineFive], [LineFive, LineSix]517 add(Parameter, LineThree, LineThree);518 add(Variable, LineFour, LineFive);519 add(Variable, LineFive, LineSix);520 521 CompileUnit->processRangeLocationCoverage();522 523 LVLocation *Location;524 LVLocations Locations;525 Parameter->getLocations(Locations);526 ASSERT_EQ(Locations.size(), 1u);527 Location = Locations[0];528 EXPECT_EQ(Location->getLowerAddress(), LineThree->getAddress());529 EXPECT_EQ(Location->getUpperAddress(), LineThree->getAddress());530 531 Locations.clear();532 Variable->getLocations(Locations);533 ASSERT_EQ(Locations.size(), 2u);534 Location = Locations[0];535 EXPECT_EQ(Location->getLowerAddress(), LineFour->getAddress());536 EXPECT_EQ(Location->getUpperAddress(), LineFive->getAddress());537 Location = Locations[1];538 EXPECT_EQ(Location->getLowerAddress(), LineFive->getAddress());539 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());540 541 // Test the changes done to 'LVScope::outermostParent' to use the542 // ranges allocated int the current scope during the scopes traversal.543 // These are the pre-conditions for the symbol:544 // - Its parent must be an inlined function.545 // - Have more than one location description.546 547 // Before the changes: Parameter: CoveragePercentage = 100.00548 // After the changes: Parameter: CoveragePercentage = 100.00549 EXPECT_FLOAT_EQ(Parameter->getCoveragePercentage(), 100.00f);550 551 // Before the changes: Variable: CoveragePercentage = 1000.00552 // After the changes: Variable: CoveragePercentage = 56.83553 EXPECT_FLOAT_EQ(Variable->getCoveragePercentage(), 56.83f);554}555 556TEST(LogicalViewTest, LocationRanges) {557 ScopedPrinter W(outs());558 ReaderTestLocations Reader(W);559 560 // Reader options.561 LVOptions ReaderOptions;562 ReaderOptions.setAttributeOffset();563 ReaderOptions.setPrintAll();564 ReaderOptions.resolveDependencies();565 options().setOptions(&ReaderOptions);566 567 Reader.createElements();568 Reader.addElements();569 Reader.initElements();570}571 572TEST(LogicalViewTest, LocationCoverage) {573 ScopedPrinter W(outs());574 ReaderTestCoverage Reader(W);575 576 // Reader options.577 LVOptions ReaderOptions;578 ReaderOptions.setAttributeOffset();579 ReaderOptions.setAttributeRange();580 ReaderOptions.setAttributeLocation();581 ReaderOptions.setPrintAll();582 ReaderOptions.resolveDependencies();583 options().setOptions(&ReaderOptions);584 585 Reader.createElements();586 Reader.addElements();587 Reader.initElements();588}589 590} // namespace591