[NFC][MLIR][Linalg] Refactor linalg.matmul tablegen ODS and related C++ code. (#116377)
[llvm-project.git] / llvm / unittests / DebugInfo / LogicalView / WarningInternalTest.cpp
blob36c6e16a78dfad953e42815c4fdc8bfaa62eab49
1 //===- llvm/unittest/DebugInfo/LogicalView/WarningInternalTest.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-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
18 #include "gtest/gtest.h"
20 using namespace llvm;
21 using namespace llvm::logicalview;
23 namespace {
25 class MyLocation : public LVLocation {
26 public:
27 bool validateRanges();
30 // This code emulates the work done by the Readers when processing the
31 // binary files and the creation of the AddressToLine mapping is done
32 // automatically, using the text sections.
33 class MyAddressToLine {
34 using LVAddressToLine = std::map<LVAddress, LVLine *>;
35 LVAddressToLine AddressToLineData;
37 public:
38 MyAddressToLine() = default;
40 void insert(LVLine *Line) {
41 AddressToLineData.emplace(Line->getOffset(), Line);
44 LVLine *lineLowerBound(LVAddress Address);
45 LVLine *lineUpperBound(LVAddress Address);
48 LVLine *MyAddressToLine::lineLowerBound(LVAddress Address) {
49 LVAddressToLine::const_iterator Iter = AddressToLineData.lower_bound(Address);
50 return (Iter != AddressToLineData.end()) ? Iter->second : nullptr;
53 LVLine *MyAddressToLine::lineUpperBound(LVAddress Address) {
54 if (AddressToLineData.empty())
55 return nullptr;
56 LVAddressToLine::const_iterator Iter = AddressToLineData.upper_bound(Address);
57 if (Iter != AddressToLineData.begin())
58 Iter = std::prev(Iter);
59 return Iter->second;
62 MyAddressToLine AddressToLine;
64 class ReaderTestWarningInternal : public LVReader {
65 #define CREATE(VARIABLE, CREATE_FUNCTION) \
66 VARIABLE = CREATE_FUNCTION(); \
67 EXPECT_NE(VARIABLE, nullptr);
69 #define CREATE_CUSTOM(VARIABLE, CREATE_FUNCTION) \
70 VARIABLE = CREATE_FUNCTION(); \
71 EXPECT_NE(VARIABLE, nullptr);
73 // Types.
74 LVType *IntegerType = nullptr;
76 // Scopes.
77 LVScope *NestedScope = nullptr;
78 LVScopeFunction *Function = nullptr;
80 // Symbols.
81 LVSymbol *LocalVariable = nullptr;
82 LVSymbol *NestedVariable = nullptr;
83 LVSymbol *Parameter = nullptr;
85 // Lines.
86 LVLine *LineOne = nullptr;
87 LVLine *LineTwo = nullptr;
88 LVLine *LineThree = nullptr;
89 LVLine *LineFour = nullptr;
90 LVLine *LineFive = nullptr;
91 LVLine *LineSix = nullptr;
93 // Locations.
94 MyLocation *LocationOne = nullptr;
95 MyLocation *LocationTwo = nullptr;
96 MyLocation *LocationThree = nullptr;
97 MyLocation *LocationFour = nullptr;
98 MyLocation *LocationFive = nullptr;
99 MyLocation *LocationSix = nullptr;
101 llvm::SpecificBumpPtrAllocator<MyLocation> AllocatedLocations;
103 protected:
104 MyLocation *createCustomLocation() {
105 return new (AllocatedLocations.Allocate()) MyLocation();
108 void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
109 void add(LVScope *Parent, LVElement *Element);
110 void set(LVElement *Element, StringRef Name, LVOffset Offset,
111 uint32_t LineNumber = 0, LVElement *Type = nullptr);
112 void set(MyLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
113 LVAddress LowerAddress, LVAddress UpperAddress);
115 public:
116 ReaderTestWarningInternal(ScopedPrinter &W) : LVReader("", "", W) {
117 setInstance(this);
120 Error createScopes() { return LVReader::createScopes(); }
122 void setMapping();
123 void createElements();
124 void addElements();
125 void initElements();
126 void resolveElements();
127 void checkWarnings();
130 bool MyLocation::validateRanges() {
131 // Traverse the locations and validate them against the address to line
132 // mapping in the current compile unit. Record those invalid ranges.
133 // A valid range must meet the following conditions:
134 // a) line(lopc) <= line(hipc)
135 // b) line(lopc) and line(hipc) are valid.
137 LVLine *LowLine = AddressToLine.lineLowerBound(getLowerAddress());
138 LVLine *HighLine = AddressToLine.lineUpperBound(getUpperAddress());
139 if (LowLine)
140 setLowerLine(LowLine);
141 else {
142 setIsInvalidLower();
143 return false;
145 if (HighLine)
146 setUpperLine(HighLine);
147 else {
148 setIsInvalidUpper();
149 return false;
151 // Check for a valid interval.
152 if (LowLine->getLineNumber() > HighLine->getLineNumber()) {
153 setIsInvalidRange();
154 return false;
157 return true;
160 // Map all logical lines with their addresses.
161 void ReaderTestWarningInternal::setMapping() {
162 AddressToLine.insert(LineOne);
163 AddressToLine.insert(LineTwo);
164 AddressToLine.insert(LineThree);
165 AddressToLine.insert(LineFour);
166 AddressToLine.insert(LineFive);
167 AddressToLine.insert(LineSix);
170 // Helper function to add a logical element to a given scope.
171 void ReaderTestWarningInternal::add(LVScope *Parent, LVElement *Child) {
172 Parent->addElement(Child);
173 EXPECT_EQ(Child->getParent(), Parent);
174 EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);
177 // Helper function to set the initial values for a given logical element.
178 void ReaderTestWarningInternal::set(LVElement *Element, StringRef Name,
179 LVOffset Offset, uint32_t LineNumber,
180 LVElement *Type) {
181 Element->setName(Name);
182 Element->setOffset(Offset);
183 Element->setLineNumber(LineNumber);
184 Element->setType(Type);
185 EXPECT_EQ(Element->getName(), Name);
186 EXPECT_EQ(Element->getOffset(), Offset);
187 EXPECT_EQ(Element->getLineNumber(), LineNumber);
188 EXPECT_EQ(Element->getType(), Type);
191 // Helper function to set the initial values for a given logical location.
192 void ReaderTestWarningInternal::set(MyLocation *Location, LVLine *LowerLine,
193 LVLine *UpperLine, LVAddress LowerAddress,
194 LVAddress UpperAddress) {
195 Location->setLowerLine(LowerLine);
196 Location->setUpperLine(UpperLine);
197 Location->setLowerAddress(LowerAddress);
198 Location->setUpperAddress(UpperAddress);
199 EXPECT_EQ(Location->getLowerLine(), LowerLine);
200 EXPECT_EQ(Location->getUpperLine(), UpperLine);
201 EXPECT_EQ(Location->getLowerAddress(), LowerAddress);
202 EXPECT_EQ(Location->getUpperAddress(), UpperAddress);
205 // Helper function to add a logical location to a logical symbol.
206 void ReaderTestWarningInternal::add(LVSymbol *Symbol, LVLine *LowerLine,
207 LVLine *UpperLine) {
208 dwarf::Attribute Attr = dwarf::DW_AT_location;
210 Symbol->addLocation(Attr, LowerLine->getAddress(), UpperLine->getAddress(),
211 /*SectionOffset=*/0, /*LocDesOffset=*/0);
214 // Create the logical elements.
215 void ReaderTestWarningInternal::createElements() {
216 // Create scope root.
217 Error Err = createScopes();
218 ASSERT_THAT_ERROR(std::move(Err), Succeeded());
219 Root = getScopesRoot();
220 EXPECT_NE(Root, nullptr);
222 // Create the logical types.
223 CREATE(IntegerType, createType);
225 // Create the logical scopes.
226 CREATE(NestedScope, createScope);
227 CREATE(CompileUnit, createScopeCompileUnit);
228 CREATE(Function, createScopeFunction);
230 // Create the logical symbols.
231 CREATE(LocalVariable, createSymbol);
232 CREATE(NestedVariable, createSymbol);
233 CREATE(Parameter, createSymbol);
235 // Create the logical lines.
236 CREATE(LineOne, createLine);
237 CREATE(LineTwo, createLine);
238 CREATE(LineThree, createLine);
239 CREATE(LineFour, createLine);
240 CREATE(LineFive, createLine);
241 CREATE(LineSix, createLine);
243 // Create the logical locations.
244 CREATE_CUSTOM(LocationOne, createCustomLocation);
245 CREATE_CUSTOM(LocationTwo, createCustomLocation);
246 CREATE_CUSTOM(LocationThree, createCustomLocation);
247 CREATE_CUSTOM(LocationFour, createCustomLocation);
248 CREATE_CUSTOM(LocationFive, createCustomLocation);
249 CREATE_CUSTOM(LocationSix, createCustomLocation);
252 // Create the logical view adding the created logical elements.
253 void ReaderTestWarningInternal::addElements() {
254 setCompileUnit(CompileUnit);
256 // Root
257 // CompileUnit
258 // IntegerType
259 // Function
260 // LocationOne
261 // LocationTwo
262 // LocationFive
263 // LocationSix
264 // Parameter
265 // LocalVariable
266 // LineOne
267 // LineTwo
268 // NestedScope
269 // LocationThree
270 // LocationFour
271 // NestedVariable
272 // LineThree
273 // LineFour
274 // LineFive
275 // LineSix
277 // Add elements to Root.
278 add(Root, CompileUnit);
280 // Add elements to CompileUnit.
281 add(CompileUnit, IntegerType);
282 add(CompileUnit, Function);
284 // Add elements to Function.
285 add(Function, Parameter);
286 add(Function, LocalVariable);
287 add(Function, LineOne);
288 add(Function, LineTwo);
289 add(Function, LineFive);
290 add(Function, LineSix);
291 add(Function, NestedScope);
293 // Add elements to NestedScope.
294 add(NestedScope, NestedVariable);
295 add(NestedScope, LineThree);
296 add(NestedScope, LineFour);
299 void ReaderTestWarningInternal::resolveElements() {
300 // Traverse the given scope and its children checking for any warnings.
301 std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
302 auto Warnings = [&](auto *Entry) {
303 if (Entry->getIsLine()) {
304 LVLine *Line = (LVLine *)Entry;
305 if (options().getWarningLines() && Line->getIsLineDebug() &&
306 !Line->getLineNumber())
307 CompileUnit->addLineZero(Line);
310 auto Traverse = [&](const auto *Set) {
311 if (Set)
312 for (const auto &Entry : *Set) {
313 Warnings(Entry);
317 Warnings(Parent);
319 Traverse(Parent->getSymbols());
320 Traverse(Parent->getTypes());
321 Traverse(Parent->getLines());
323 if (const LVScopes *Scopes = Parent->getScopes())
324 for (LVScope *Scope : *Scopes) {
325 Warnings(Scope);
326 TraverseScope(Scope);
330 // Start traversing the scopes root and resolve the elements.
331 TraverseScope(Root);
334 // Set initial values to logical elements.
335 void ReaderTestWarningInternal::initElements() {
336 // Types.
337 set(IntegerType, "int", 0x1000);
339 // Scopes.
340 set(CompileUnit, "foo.cpp", 0x2000);
341 set(Function, "foo", 0x2010, 100, IntegerType);
342 set(NestedScope, "", 0x2020, 300);
344 // Symbols.
345 set(Parameter, "Param", 0x3000, 110, IntegerType);
346 set(LocalVariable, "LocalVariable", 0x3020, 120, IntegerType);
347 set(NestedVariable, "NestedVariable", 0x3010, 310, IntegerType);
349 // Lines.
350 set(LineOne, "", 0x5000, 100);
351 LineOne->setIsLineDebug();
352 set(LineTwo, "", 0x5200, 000);
353 LineTwo->setIsLineDebug();
354 set(LineThree, "", 0x5400, 300);
355 LineThree->setIsLineDebug();
356 set(LineFour, "", 0x5600, 000);
357 LineFour->setIsLineDebug();
358 set(LineFive, "", 0x5800, 500);
359 LineOne->setIsLineDebug();
360 set(LineSix, "", 0x6000, 600);
361 LineSix->setIsLineDebug();
363 // Locations.
364 set(LocationOne, LineOne, LineOne, 0x5000, 0x5100);
365 EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),
366 " Lines 100:100 [0x0000005000:0x0000005100]");
368 // Uses a Line zero.
369 set(LocationTwo, LineTwo, LineTwo, 0x5200, 0x5300);
370 EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),
371 " Lines -:- [0x0000005200:0x0000005300]");
373 set(LocationThree, LineThree, LineThree, 0x5400, 0x5500);
374 EXPECT_STREQ(LocationThree->getIntervalInfo().c_str(),
375 " Lines 300:300 [0x0000005400:0x0000005500]");
377 // Uses a Line zero.
378 set(LocationFour, LineFour, LineFour, 0x5600, 0x5700);
379 LocationFour->setIsAddressRange();
380 EXPECT_STREQ(LocationFour->getIntervalInfo().c_str(),
381 "{Range} Lines -:- [0x0000005600:0x0000005700]");
383 // Invalid range.
384 set(LocationFive, LineFive, LineFive, 0x7800, 0x5900);
385 LocationFive->setIsAddressRange();
386 EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),
387 "{Range} Lines 500:500 [0x0000007800:0x0000005900]");
389 set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);
390 LocationSix->setIsAddressRange();
391 EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),
392 "{Range} Lines 600:600 [0x0000006000:0x0000006100]");
394 // Add ranges to Function.
395 // Function: LocationOne, LocationTwo, LocationFive, LocationSix
396 Function->addObject(LocationOne);
397 Function->addObject(LocationTwo);
398 Function->addObject(LocationFive);
399 Function->addObject(LocationSix);
400 EXPECT_EQ(Function->rangeCount(), 4u);
402 // Add ranges to NestedScope.
403 // NestedScope: LocationThree, LocationFour
404 NestedScope->addObject(LocationThree);
405 NestedScope->addObject(LocationFour);
406 EXPECT_EQ(NestedScope->rangeCount(), 2u);
408 // Get all ranges.
409 LVRange Ranges;
410 CompileUnit->getRanges(Ranges);
411 Ranges.startSearch();
412 EXPECT_EQ(Ranges.getEntry(0x4000), nullptr);
414 EXPECT_EQ(Ranges.getEntry(0x5060), Function);
415 EXPECT_EQ(Ranges.getEntry(0x5850), nullptr);
416 EXPECT_EQ(Ranges.getEntry(0x5010, 0x5090), Function);
417 EXPECT_EQ(Ranges.getEntry(0x5210, 0x5290), Function);
418 EXPECT_EQ(Ranges.getEntry(0x5810, 0x5890), nullptr);
419 EXPECT_EQ(Ranges.getEntry(0x6010, 0x6090), Function);
421 EXPECT_EQ(Ranges.getEntry(0x5400), NestedScope);
422 EXPECT_EQ(Ranges.getEntry(0x5650), NestedScope);
423 EXPECT_EQ(Ranges.getEntry(0x5410, 0x5490), NestedScope);
424 EXPECT_EQ(Ranges.getEntry(0x5610, 0x5690), NestedScope);
426 EXPECT_EQ(Ranges.getEntry(0x8000), nullptr);
427 Ranges.endSearch();
429 // Add locations to symbols.
430 // Parameter: [LineOne, LineSix]
431 // LocalVariable: [LineTwo, LineSix], [LineFour, LineFive]
432 // NestedVariable: [LineThree, LineFour]
433 add(Parameter, LineOne, LineSix);
434 add(LocalVariable, LineTwo, LineSix);
435 add(LocalVariable, LineFour, LineFive);
436 add(NestedVariable, LineThree, LineFour);
437 add(NestedVariable, LineOne, LineSix);
440 // Check logical elements warnigs.
441 void ReaderTestWarningInternal::checkWarnings() {
442 // Map all lines with their addresses.
443 setMapping();
445 // Check for lines with line zero.
446 resolveElements();
448 // Check invalid locations and ranges using a customized validation.
449 CompileUnit->processRangeLocationCoverage(
450 (LVValidLocation)(&MyLocation::validateRanges));
452 // Get lines with line zero. [Parent, Line]
453 // Function, LineTwo
454 // NestedScope, LineFour
455 LVOffsetLinesMap LinesZero = CompileUnit->getLinesZero();
456 ASSERT_EQ(LinesZero.size(), 2u);
458 LVOffsetLinesMap::iterator IterZero = LinesZero.begin();
459 EXPECT_EQ(IterZero->first, Function->getOffset());
460 LVLines *Lines = &IterZero->second;
461 EXPECT_NE(Lines, nullptr);
462 ASSERT_EQ(Lines->size(), 1u);
463 LVLine *Line = *(Lines->begin());
464 EXPECT_NE(Line, nullptr);
465 EXPECT_EQ(Line, LineTwo);
467 ++IterZero;
468 EXPECT_EQ(IterZero->first, NestedScope->getOffset());
469 Lines = &IterZero->second;
470 EXPECT_NE(Lines, nullptr);
471 ASSERT_EQ(Lines->size(), 1u);
472 Line = *(Lines->begin());
473 EXPECT_NE(Line, nullptr);
474 EXPECT_EQ(Line, LineFour);
476 // Elements with invalid offsets.
477 // Function (line zero)
478 // NestedScope (line zero)
479 // NestedVariable (invalid location)
480 LVOffsetElementMap InvalidOffsets = CompileUnit->getWarningOffsets();
481 ASSERT_EQ(InvalidOffsets.size(), 3u);
483 LVOffsetElementMap::iterator IterOffset = InvalidOffsets.begin();
484 EXPECT_EQ(IterOffset->second, Function);
485 ++IterOffset;
486 EXPECT_EQ(IterOffset->second, NestedScope);
487 ++IterOffset;
488 EXPECT_EQ(IterOffset->second, NestedVariable);
490 // Invalid ranges.
491 // Function
492 LVOffsetLocationsMap InvalidRanges = CompileUnit->getInvalidRanges();
493 ASSERT_EQ(InvalidRanges.size(), 1u);
495 LVOffsetLocationsMap::iterator IterRange = InvalidRanges.begin();
496 EXPECT_EQ(IterRange->first, Function->getOffset());
497 LVLocations *Locations = &IterRange->second;
498 EXPECT_NE(Locations, nullptr);
499 ASSERT_EQ(Locations->size(), 1u);
500 LVLocation *Location = *(Locations->begin());
501 EXPECT_NE(Location, nullptr);
502 EXPECT_EQ(Location, LocationFive);
504 // Invalid location.
505 // NestedVariable
506 LVOffsetLocationsMap InvalidLocations = CompileUnit->getInvalidLocations();
507 ASSERT_EQ(InvalidLocations.size(), 1u);
509 LVOffsetLocationsMap::iterator IterLocations = InvalidLocations.begin();
510 EXPECT_EQ(IterLocations->first, NestedVariable->getOffset());
511 Locations = &IterLocations->second;
512 EXPECT_NE(Locations, nullptr);
513 ASSERT_EQ(Locations->size(), 1u);
514 Location = *(Locations->begin());
515 EXPECT_NE(Location, nullptr);
516 EXPECT_EQ(Location->getLowerAddress(), LocationThree->getLowerAddress());
517 EXPECT_EQ(Location->getUpperAddress(), LocationFour->getLowerAddress());
518 EXPECT_EQ(Location->getLowerLine()->getLineNumber(),
519 LineThree->getLineNumber());
520 EXPECT_EQ(Location->getUpperLine()->getLineNumber(), 0u);
522 // Invalid coverages.
523 // NestedVariable
524 LVOffsetSymbolMap InvalidCoverages = CompileUnit->getInvalidCoverages();
525 ASSERT_EQ(InvalidCoverages.size(), 1u);
527 LVOffsetSymbolMap::iterator IterCoverages = InvalidCoverages.begin();
528 EXPECT_EQ(IterCoverages->first, NestedVariable->getOffset());
529 EXPECT_EQ(IterCoverages->second, NestedVariable);
530 EXPECT_GE((int)NestedVariable->getCoveragePercentage(), 100);
531 EXPECT_EQ((int)NestedVariable->getCoveragePercentage(), 900);
532 EXPECT_EQ(NestedVariable->getCoverageFactor(), 0x1200u);
534 EXPECT_EQ((unsigned)Parameter->getCoveragePercentage(), 100u);
535 EXPECT_EQ(Parameter->getCoverageFactor(), 100u);
537 EXPECT_EQ((unsigned)LocalVariable->getCoveragePercentage(), 47u);
538 EXPECT_EQ(LocalVariable->getCoverageFactor(),
539 LineSix->getAddress() - LineOne->getAddress());
542 TEST(LogicalViewTest, WarningInternal) {
543 ScopedPrinter W(outs());
544 ReaderTestWarningInternal Reader(W);
546 // Reader options.
547 LVOptions ReaderOptions;
548 ReaderOptions.setAttributeOffset();
549 ReaderOptions.setAttributeRange();
550 ReaderOptions.setAttributeLocation();
551 ReaderOptions.setPrintAll();
552 ReaderOptions.setWarningCoverages();
553 ReaderOptions.setWarningLines();
554 ReaderOptions.setWarningLocations();
555 ReaderOptions.setWarningRanges();
556 ReaderOptions.resolveDependencies();
557 options().setOptions(&ReaderOptions);
559 Reader.createElements();
560 Reader.addElements();
561 Reader.initElements();
562 Reader.checkWarnings();
565 } // namespace