[AMDGPU] Test codegen'ing True16 additions.
[llvm-project.git] / llvm / unittests / DebugInfo / LogicalView / CodeViewReaderTest.cpp
blobeb9477e40ed90b7ab0ac599b851ec33229d67ed3
1 //===- llvm/unittest/DebugInfo/LogicalView/CodeViewReaderTest.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/LVCompare.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVLine.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/DebugInfo/LogicalView/LVReaderHandler.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/COM.h"
17 #include "llvm/Support/InitLLVM.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Support/ToolOutputFile.h"
21 #include "llvm/Testing/Support/Error.h"
23 #include "gtest/gtest.h"
25 using namespace llvm;
26 using namespace llvm::logicalview;
28 extern const char *TestMainArgv0;
30 namespace {
32 const char *CodeViewClang = "test-codeview-clang.o";
33 const char *CodeViewMsvc = "test-codeview-msvc.o";
34 const char *CodeViewPdbMsvc = "test-codeview-pdb-msvc.o";
36 // Helper function to get the first scope child from the given parent.
37 LVScope *getFirstScopeChild(LVScope *Parent) {
38 EXPECT_NE(Parent, nullptr);
39 const LVScopes *Scopes = Parent->getScopes();
40 EXPECT_NE(Scopes, nullptr);
41 EXPECT_EQ(Scopes->size(), 1u);
43 LVScopes::const_iterator Iter = Scopes->begin();
44 LVScope *Child = *Iter;
45 EXPECT_NE(Child, nullptr);
46 return Child;
49 // Helper function to create a reader.
50 std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
51 SmallString<128> &InputsDir,
52 StringRef Filename) {
53 SmallString<128> ObjectName(InputsDir);
54 llvm::sys::path::append(ObjectName, Filename);
56 Expected<std::unique_ptr<LVReader>> ReaderOrErr =
57 ReaderHandler.createReader(std::string(ObjectName));
58 EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
59 std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
60 EXPECT_NE(Reader, nullptr);
61 return Reader;
64 // Check the logical elements basic properties (Clang - Codeview).
65 void checkElementPropertiesClangCodeview(LVReader *Reader) {
66 LVScopeRoot *Root = Reader->getScopesRoot();
67 LVScopeCompileUnit *CompileUnit =
68 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
69 LVScopeFunction *Function =
70 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
72 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
73 EXPECT_EQ(Root->getName(), CodeViewClang);
75 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
76 EXPECT_TRUE(CompileUnit->getProducer().startswith("clang"));
77 EXPECT_EQ(CompileUnit->getName(), "test.cpp");
79 EXPECT_EQ(Function->lineCount(), 16u);
80 EXPECT_EQ(Function->scopeCount(), 1u);
81 EXPECT_EQ(Function->symbolCount(), 3u);
82 EXPECT_EQ(Function->typeCount(), 1u);
83 EXPECT_EQ(Function->rangeCount(), 1u);
85 const LVLocations *Ranges = Function->getRanges();
86 ASSERT_NE(Ranges, nullptr);
87 ASSERT_EQ(Ranges->size(), 1u);
88 LVLocations::const_iterator IterLocation = Ranges->begin();
89 LVLocation *Location = (*IterLocation);
90 EXPECT_STREQ(Location->getIntervalInfo().c_str(),
91 "{Range} Lines 2:9 [0x0000000000:0x0000000046]");
93 LVRange RangeList;
94 Function->getRanges(RangeList);
96 const LVRangeEntries &RangeEntries = RangeList.getEntries();
97 ASSERT_EQ(RangeEntries.size(), 2u);
98 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
99 LVRangeEntry RangeEntry = *IterRanges;
100 EXPECT_EQ(RangeEntry.lower(), 0u);
101 EXPECT_EQ(RangeEntry.upper(), 0x46u);
102 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
103 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
104 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
106 ++IterRanges;
107 RangeEntry = *IterRanges;
108 EXPECT_EQ(RangeEntry.lower(), 0x21u);
109 EXPECT_EQ(RangeEntry.upper(), 0x35u);
110 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
111 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
112 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
114 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
115 ASSERT_EQ(PublicNames.size(), 1u);
116 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
117 LVScope *Foo = (*IterNames).first;
118 EXPECT_EQ(Foo->getName(), "foo");
119 EXPECT_EQ(Foo->getLineNumber(), 0u);
120 LVNameInfo NameInfo = (*IterNames).second;
121 EXPECT_EQ(NameInfo.first, 0u);
122 EXPECT_EQ(NameInfo.second, 0x46u);
124 // Lines (debug and assembler) for 'foo'.
125 const LVLines *Lines = Foo->getLines();
126 ASSERT_NE(Lines, nullptr);
127 EXPECT_EQ(Lines->size(), 0x10u);
130 // Check the logical elements basic properties (MSVC - Codeview).
131 void checkElementPropertiesMsvcCodeview(LVReader *Reader) {
132 LVScopeRoot *Root = Reader->getScopesRoot();
133 LVScopeCompileUnit *CompileUnit =
134 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
135 LVScopeFunction *Function =
136 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
138 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
139 EXPECT_EQ(Root->getName(), CodeViewMsvc);
141 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
142 EXPECT_TRUE(CompileUnit->getProducer().startswith("Microsoft"));
143 EXPECT_EQ(CompileUnit->getName(), "test.cpp");
145 EXPECT_EQ(Function->lineCount(), 14u);
146 EXPECT_EQ(Function->scopeCount(), 1u);
147 EXPECT_EQ(Function->symbolCount(), 3u);
148 EXPECT_EQ(Function->typeCount(), 0u);
149 EXPECT_EQ(Function->rangeCount(), 1u);
151 const LVLocations *Ranges = Function->getRanges();
152 ASSERT_NE(Ranges, nullptr);
153 ASSERT_EQ(Ranges->size(), 1u);
154 LVLocations::const_iterator IterLocation = Ranges->begin();
155 LVLocation *Location = (*IterLocation);
156 EXPECT_STREQ(Location->getIntervalInfo().c_str(),
157 "{Range} Lines 2:9 [0x0000000000:0x0000000031]");
159 LVRange RangeList;
160 Function->getRanges(RangeList);
162 const LVRangeEntries &RangeEntries = RangeList.getEntries();
163 ASSERT_EQ(RangeEntries.size(), 2u);
164 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
165 LVRangeEntry RangeEntry = *IterRanges;
166 EXPECT_EQ(RangeEntry.lower(), 0u);
167 EXPECT_EQ(RangeEntry.upper(), 0x31u);
168 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
169 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
170 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
172 ++IterRanges;
173 RangeEntry = *IterRanges;
174 EXPECT_EQ(RangeEntry.lower(), 0x1bu);
175 EXPECT_EQ(RangeEntry.upper(), 0x28u);
176 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
177 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
178 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
180 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
181 ASSERT_EQ(PublicNames.size(), 1u);
182 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
183 LVScope *Foo = (*IterNames).first;
184 EXPECT_EQ(Foo->getName(), "foo");
185 EXPECT_EQ(Foo->getLineNumber(), 0u);
186 LVNameInfo NameInfo = (*IterNames).second;
187 EXPECT_EQ(NameInfo.first, 0u);
188 EXPECT_EQ(NameInfo.second, 0x31u);
190 // Lines (debug and assembler) for 'foo'.
191 const LVLines *Lines = Foo->getLines();
192 ASSERT_NE(Lines, nullptr);
193 EXPECT_EQ(Lines->size(), 0x0eu);
196 // Check the logical elements basic properties (MSVC - PDB).
197 void checkElementPropertiesMsvcCodeviewPdb(LVReader *Reader) {
198 LVScopeRoot *Root = Reader->getScopesRoot();
199 LVScopeCompileUnit *CompileUnit =
200 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
201 LVScopeFunction *Function =
202 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
204 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
205 EXPECT_EQ(Root->getName(), CodeViewPdbMsvc);
207 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
208 EXPECT_TRUE(CompileUnit->getProducer().startswith("Microsoft"));
209 EXPECT_EQ(CompileUnit->getName(), "test.cpp");
211 EXPECT_EQ(Function->lineCount(), 14u);
212 EXPECT_EQ(Function->scopeCount(), 1u);
213 EXPECT_EQ(Function->symbolCount(), 3u);
214 EXPECT_EQ(Function->typeCount(), 0u);
215 EXPECT_EQ(Function->rangeCount(), 1u);
217 const LVLocations *Ranges = Function->getRanges();
218 ASSERT_NE(Ranges, nullptr);
219 ASSERT_EQ(Ranges->size(), 1u);
220 LVLocations::const_iterator IterLocation = Ranges->begin();
221 LVLocation *Location = (*IterLocation);
222 EXPECT_STREQ(Location->getIntervalInfo().c_str(),
223 "{Range} Lines 2:9 [0x0000000000:0x0000000031]");
225 LVRange RangeList;
226 Function->getRanges(RangeList);
228 const LVRangeEntries &RangeEntries = RangeList.getEntries();
229 ASSERT_EQ(RangeEntries.size(), 2u);
230 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
231 LVRangeEntry RangeEntry = *IterRanges;
232 EXPECT_EQ(RangeEntry.lower(), 0u);
233 EXPECT_EQ(RangeEntry.upper(), 0x31u);
234 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
235 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
236 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
238 ++IterRanges;
239 RangeEntry = *IterRanges;
240 EXPECT_EQ(RangeEntry.lower(), 0x1bu);
241 EXPECT_EQ(RangeEntry.upper(), 0x28u);
242 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
243 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
244 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
246 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
247 ASSERT_EQ(PublicNames.size(), 1u);
248 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
249 LVScope *Foo = (*IterNames).first;
250 EXPECT_EQ(Foo->getName(), "foo");
251 EXPECT_EQ(Foo->getLineNumber(), 0u);
252 LVNameInfo NameInfo = (*IterNames).second;
253 EXPECT_EQ(NameInfo.first, 0u);
254 EXPECT_EQ(NameInfo.second, 0x31u);
256 // Lines (debug and assembler) for 'foo'.
257 const LVLines *Lines = Foo->getLines();
258 ASSERT_NE(Lines, nullptr);
259 EXPECT_EQ(Lines->size(), 0x0eu);
262 struct SelectionInfo {
263 const char *Name;
264 LVElementGetFunction Function;
267 // Check the logical elements selection.
268 void checkElementSelection(LVReader *Reader, std::vector<SelectionInfo> &Data,
269 size_t Size) {
270 LVScopeRoot *Root = Reader->getScopesRoot();
271 LVScopeCompileUnit *CompileUnit =
272 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
274 // Get the matched elements.
275 LVElements MatchedElements = CompileUnit->getMatchedElements();
276 std::map<StringRef, LVElement *> MapElements;
277 for (LVElement *Element : MatchedElements)
278 MapElements[Element->getName()] = Element;
279 ASSERT_EQ(MapElements.size(), Size);
281 std::map<StringRef, LVElement *>::iterator Iter = MapElements.begin();
282 for (const SelectionInfo &Entry : Data) {
283 // Get matched element.
284 EXPECT_NE(Iter, MapElements.end());
285 LVElement *Element = Iter->second;
286 ASSERT_NE(Element, nullptr);
287 EXPECT_NE(Element->getName().find(Entry.Name), StringRef::npos);
288 EXPECT_EQ((Element->*Entry.Function)(), 1u);
289 ++Iter;
292 // Get the parents for the matched elements.
293 LVScopes MatchedScopes = CompileUnit->getMatchedScopes();
294 std::set<StringRef> SetScopes;
295 for (LVScope *Scope : MatchedScopes)
296 SetScopes.insert(Scope->getName());
297 ASSERT_EQ(SetScopes.size(), 3u);
299 // Parents of selected elements.
300 std::set<StringRef>::iterator IterScope;
301 IterScope = SetScopes.find("foo");
302 EXPECT_NE(IterScope, SetScopes.end());
303 IterScope = SetScopes.find("foo::?");
304 EXPECT_NE(IterScope, SetScopes.end());
305 IterScope = SetScopes.find("test.cpp");
306 EXPECT_NE(IterScope, SetScopes.end());
309 // Check the logical elements comparison.
310 void checkElementComparison(LVReader *Reference, LVReader *Target) {
311 LVCompare Compare(nulls());
312 Error Err = Compare.execute(Reference, Target);
313 ASSERT_THAT_ERROR(std::move(Err), Succeeded());
315 // Get comparison table.
316 LVPassTable PassTable = Compare.getPassTable();
317 ASSERT_EQ(PassTable.size(), 2u);
319 LVReader *Reader;
320 LVElement *Element;
321 LVComparePass Pass;
323 // Reference: Missing TypeDefinition 'INTEGER'
324 std::tie(Reader, Element, Pass) = PassTable[0];
325 ASSERT_NE(Reader, nullptr);
326 ASSERT_NE(Element, nullptr);
327 EXPECT_EQ(Reader, Reference);
328 EXPECT_EQ(Element->getLevel(), 3u);
329 EXPECT_EQ(Element->getLineNumber(), 0u);
330 EXPECT_EQ(Element->getName(), "INTEGER");
331 EXPECT_EQ(Pass, LVComparePass::Missing);
333 // Target: Added TypeDefinition 'INTEGER'
334 std::tie(Reader, Element, Pass) = PassTable[1];
335 ASSERT_NE(Reader, nullptr);
336 ASSERT_NE(Element, nullptr);
337 EXPECT_EQ(Reader, Target);
338 EXPECT_EQ(Element->getLevel(), 4u);
339 EXPECT_EQ(Element->getLineNumber(), 0u);
340 EXPECT_EQ(Element->getName(), "INTEGER");
341 EXPECT_EQ(Pass, LVComparePass::Added);
344 // Logical elements properties.
345 void elementProperties(SmallString<128> &InputsDir) {
346 // Reader options.
347 LVOptions ReaderOptions;
348 ReaderOptions.setAttributeOffset();
349 ReaderOptions.setAttributeFormat();
350 ReaderOptions.setAttributeFilename();
351 ReaderOptions.setAttributeProducer();
352 ReaderOptions.setAttributePublics();
353 ReaderOptions.setAttributeRange();
354 ReaderOptions.setAttributeLocation();
355 ReaderOptions.setPrintAll();
356 ReaderOptions.resolveDependencies();
358 std::vector<std::string> Objects;
359 ScopedPrinter W(outs());
360 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
362 // Check logical elements properties.
364 std::unique_ptr<LVReader> Reader =
365 createReader(ReaderHandler, InputsDir, CodeViewClang);
366 checkElementPropertiesClangCodeview(Reader.get());
369 std::unique_ptr<LVReader> Reader =
370 createReader(ReaderHandler, InputsDir, CodeViewMsvc);
371 checkElementPropertiesMsvcCodeview(Reader.get());
374 std::unique_ptr<LVReader> Reader =
375 createReader(ReaderHandler, InputsDir, CodeViewPdbMsvc);
376 checkElementPropertiesMsvcCodeviewPdb(Reader.get());
380 // Logical elements selection.
381 void elementSelection(SmallString<128> &InputsDir) {
382 // Reader options.
383 LVOptions ReaderOptions;
384 ReaderOptions.setAttributeOffset();
385 ReaderOptions.setPrintAll();
387 ReaderOptions.setSelectIgnoreCase();
388 ReaderOptions.setSelectUseRegex();
390 ReaderOptions.setReportList(); // Matched elements.
391 ReaderOptions.setReportView(); // Parents for matched elements.
393 // Add patterns.
394 ReaderOptions.Select.Generic.insert("foo");
395 ReaderOptions.Select.Generic.insert("movl[ \t]?%");
396 ReaderOptions.Select.Generic.insert("INT[a-z]*");
397 ReaderOptions.Select.Generic.insert("CONSTANT");
399 ReaderOptions.resolveDependencies();
401 std::vector<std::string> Objects;
402 ScopedPrinter W(outs());
403 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
405 // Check logical elements selection.
407 std::vector<SelectionInfo> DataClang = {
408 {"* const int", &LVElement::getIsType},
409 {"CONSTANT", &LVElement::getIsSymbol},
410 {"INTEGER", &LVElement::getIsType},
411 {"INTPTR", &LVElement::getIsType},
412 {"ParamPtr", &LVElement::getIsSymbol},
413 {"const int", &LVElement::getIsType},
414 {"foo", &LVElement::getIsScope},
415 {"foo::?", &LVElement::getIsScope},
416 {"int", &LVElement::getIsType},
417 {"movl", &LVElement::getIsLine},
418 {"movl", &LVElement::getIsLine}};
419 std::unique_ptr<LVReader> Reader =
420 createReader(ReaderHandler, InputsDir, CodeViewClang);
421 checkElementSelection(Reader.get(), DataClang, DataClang.size());
424 std::vector<SelectionInfo> DataMsvc = {
425 {"* const int", &LVElement::getIsType},
426 {"CONSTANT", &LVElement::getIsSymbol},
427 {"INTEGER", &LVElement::getIsType},
428 {"INTPTR", &LVElement::getIsType},
429 {"ParamPtr", &LVElement::getIsSymbol},
430 {"const int", &LVElement::getIsType},
431 {"foo", &LVElement::getIsScope},
432 {"foo::?", &LVElement::getIsScope},
433 {"int", &LVElement::getIsType},
434 {"movl", &LVElement::getIsLine}};
435 std::unique_ptr<LVReader> Reader =
436 createReader(ReaderHandler, InputsDir, CodeViewMsvc);
437 checkElementSelection(Reader.get(), DataMsvc, DataMsvc.size());
441 // Compare logical elements.
442 void compareElements(SmallString<128> &InputsDir) {
443 // Reader options.
444 LVOptions ReaderOptions;
445 ReaderOptions.setAttributeOffset();
446 ReaderOptions.setPrintLines();
447 ReaderOptions.setPrintSymbols();
448 ReaderOptions.setPrintTypes();
449 ReaderOptions.setCompareLines();
450 ReaderOptions.setCompareSymbols();
451 ReaderOptions.setCompareTypes();
453 ReaderOptions.resolveDependencies();
455 std::vector<std::string> Objects;
456 ScopedPrinter W(outs());
457 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
459 // Check logical comparison.
460 std::unique_ptr<LVReader> Reference =
461 createReader(ReaderHandler, InputsDir, CodeViewClang);
462 std::unique_ptr<LVReader> Target =
463 createReader(ReaderHandler, InputsDir, CodeViewMsvc);
464 checkElementComparison(Reference.get(), Target.get());
467 TEST(LogicalViewTest, CodeViewReader) {
468 // Initialize targets and assembly printers/parsers.
469 llvm::InitializeAllTargetInfos();
470 llvm::InitializeAllTargetMCs();
471 InitializeAllDisassemblers();
473 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
475 // This test requires a x86-registered-target.
476 Triple TT;
477 TT.setArch(Triple::x86_64);
478 TT.setVendor(Triple::UnknownVendor);
479 TT.setOS(Triple::UnknownOS);
481 std::string TargetLookupError;
482 if (!TargetRegistry::lookupTarget(std::string(TT.str()), TargetLookupError))
483 return;
485 SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);
487 // Logical elements general properties and selection.
488 elementProperties(InputsDir);
489 elementSelection(InputsDir);
491 // Compare logical elements.
492 compareElements(InputsDir);
495 } // namespace