609 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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"22 23#include "gtest/gtest.h"24#include <algorithm>25 26using namespace llvm;27using namespace llvm::logicalview;28 29extern const char *TestMainArgv0;30 31namespace {32 33const char *CodeViewClang = "test-codeview-clang.o";34const char *CodeViewMsvc = "test-codeview-msvc.o";35const char *CodeViewMsvcLib = "test-codeview-msvc.lib";36const char *CodeViewMsvcLibContentName =37 "test-codeview-msvc.lib(test-codeview-msvc.o)";38const char *CodeViewPdbMsvc = "test-codeview-pdb-msvc.o";39 40// Helper function to get the first scope child from the given parent.41LVScope *getFirstScopeChild(LVScope *Parent) {42 EXPECT_NE(Parent, nullptr);43 const LVScopes *Scopes = Parent->getScopes();44 EXPECT_NE(Scopes, nullptr);45 EXPECT_EQ(Scopes->size(), 1u);46 47 LVScopes::const_iterator Iter = Scopes->begin();48 LVScope *Child = *Iter;49 EXPECT_NE(Child, nullptr);50 return Child;51}52 53// Helper function to create a reader.54std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,55 SmallString<128> &InputsDir,56 StringRef Filename) {57 SmallString<128> ObjectName(InputsDir);58 llvm::sys::path::append(ObjectName, Filename);59 60 Expected<std::unique_ptr<LVReader>> ReaderOrErr =61 ReaderHandler.createReader(std::string(ObjectName));62 EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());63 std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);64 EXPECT_NE(Reader, nullptr);65 return Reader;66}67 68// Check the logical elements basic properties (Clang - Codeview).69void checkElementPropertiesClangCodeview(LVReader *Reader) {70 LVScopeRoot *Root = Reader->getScopesRoot();71 LVScopeCompileUnit *CompileUnit =72 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));73 LVScopeFunction *Function =74 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));75 76 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");77 EXPECT_EQ(Root->getName(), CodeViewClang);78 79 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);80 EXPECT_TRUE(CompileUnit->getProducer().starts_with("clang"));81 EXPECT_EQ(CompileUnit->getName(), "test.cpp");82 LVSourceLanguage Language = CompileUnit->getSourceLanguage();83 EXPECT_TRUE(Language.isValid());84 ASSERT_EQ(Language, LVSourceLanguage::CV_LANG_Cpp);85 ASSERT_EQ(Language.getName(), "Cpp");86 87 EXPECT_EQ(Function->lineCount(), 16u);88 EXPECT_EQ(Function->scopeCount(), 1u);89 EXPECT_EQ(Function->symbolCount(), 3u);90 EXPECT_EQ(Function->typeCount(), 1u);91 EXPECT_EQ(Function->rangeCount(), 1u);92 93 const LVLocations *Ranges = Function->getRanges();94 ASSERT_NE(Ranges, nullptr);95 ASSERT_EQ(Ranges->size(), 1u);96 LVLocations::const_iterator IterLocation = Ranges->begin();97 LVLocation *Location = (*IterLocation);98 EXPECT_STREQ(Location->getIntervalInfo().c_str(),99 "{Range} Lines 2:9 [0x0000000000:0x0000000046]");100 101 LVRange RangeList;102 Function->getRanges(RangeList);103 104 const LVRangeEntries &RangeEntries = RangeList.getEntries();105 ASSERT_EQ(RangeEntries.size(), 2u);106 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();107 LVRangeEntry RangeEntry = *IterRanges;108 EXPECT_EQ(RangeEntry.lower(), 0u);109 EXPECT_EQ(RangeEntry.upper(), 0x46u);110 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);111 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");112 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);113 114 ++IterRanges;115 RangeEntry = *IterRanges;116 EXPECT_EQ(RangeEntry.lower(), 0x21u);117 EXPECT_EQ(RangeEntry.upper(), 0x35u);118 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);119 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");120 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);121 122 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();123 ASSERT_EQ(PublicNames.size(), 1u);124 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();125 LVScope *Foo = (*IterNames).first;126 EXPECT_EQ(Foo->getName(), "foo");127 EXPECT_EQ(Foo->getLineNumber(), 0u);128 LVNameInfo NameInfo = (*IterNames).second;129 EXPECT_EQ(NameInfo.first, 0u);130 EXPECT_EQ(NameInfo.second, 0x46u);131 132 // Lines (debug and assembler) for 'foo'.133 const LVLines *Lines = Foo->getLines();134 ASSERT_NE(Lines, nullptr);135 EXPECT_EQ(Lines->size(), 0x10u);136 137 // Check size of types in CompileUnit.138 const LVTypes *Types = CompileUnit->getTypes();139 ASSERT_NE(Types, nullptr);140 EXPECT_EQ(Types->size(), 6u);141 142 const auto BoolType = llvm::find_if(143 *Types, [](const LVElement *elt) { return elt->getName() == "bool"; });144 ASSERT_NE(BoolType, Types->end());145 const auto IntType = llvm::find_if(146 *Types, [](const LVElement *elt) { return elt->getName() == "int"; });147 ASSERT_NE(IntType, Types->end());148 EXPECT_EQ(static_cast<LVType *>(*BoolType)->getBitSize(), 8u);149 EXPECT_EQ(static_cast<LVType *>(*BoolType)->getStorageSizeInBytes(), 1u);150 EXPECT_EQ(static_cast<LVType *>(*IntType)->getBitSize(), 32u);151 EXPECT_EQ(static_cast<LVType *>(*IntType)->getStorageSizeInBytes(), 4u);152}153 154// Check the logical elements basic properties (MSVC - Codeview).155void checkElementPropertiesMsvcCodeview(LVReader *Reader) {156 LVScopeRoot *Root = Reader->getScopesRoot();157 LVScopeCompileUnit *CompileUnit =158 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));159 LVScopeFunction *Function =160 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));161 162 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");163 EXPECT_EQ(Root->getName(), CodeViewMsvc);164 165 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);166 EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));167 EXPECT_EQ(CompileUnit->getName(), "test.cpp");168 169 EXPECT_EQ(Function->lineCount(), 14u);170 EXPECT_EQ(Function->scopeCount(), 1u);171 EXPECT_EQ(Function->symbolCount(), 3u);172 EXPECT_EQ(Function->typeCount(), 0u);173 EXPECT_EQ(Function->rangeCount(), 1u);174 175 const LVLocations *Ranges = Function->getRanges();176 ASSERT_NE(Ranges, nullptr);177 ASSERT_EQ(Ranges->size(), 1u);178 LVLocations::const_iterator IterLocation = Ranges->begin();179 LVLocation *Location = (*IterLocation);180 EXPECT_STREQ(Location->getIntervalInfo().c_str(),181 "{Range} Lines 2:9 [0x0000000000:0x0000000031]");182 183 LVRange RangeList;184 Function->getRanges(RangeList);185 186 const LVRangeEntries &RangeEntries = RangeList.getEntries();187 ASSERT_EQ(RangeEntries.size(), 2u);188 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();189 LVRangeEntry RangeEntry = *IterRanges;190 EXPECT_EQ(RangeEntry.lower(), 0u);191 EXPECT_EQ(RangeEntry.upper(), 0x31u);192 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);193 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");194 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);195 196 ++IterRanges;197 RangeEntry = *IterRanges;198 EXPECT_EQ(RangeEntry.lower(), 0x1bu);199 EXPECT_EQ(RangeEntry.upper(), 0x28u);200 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);201 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");202 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);203 204 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();205 ASSERT_EQ(PublicNames.size(), 1u);206 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();207 LVScope *Foo = (*IterNames).first;208 EXPECT_EQ(Foo->getName(), "foo");209 EXPECT_EQ(Foo->getLineNumber(), 0u);210 LVNameInfo NameInfo = (*IterNames).second;211 EXPECT_EQ(NameInfo.first, 0u);212 EXPECT_EQ(NameInfo.second, 0x31u);213 214 // Lines (debug and assembler) for 'foo'.215 const LVLines *Lines = Foo->getLines();216 ASSERT_NE(Lines, nullptr);217 EXPECT_EQ(Lines->size(), 0x0eu);218 219 // Check size of types in CompileUnit.220 const LVTypes *Types = CompileUnit->getTypes();221 ASSERT_NE(Types, nullptr);222 EXPECT_EQ(Types->size(), 8u);223 224 const auto BoolType = llvm::find_if(225 *Types, [](const LVElement *elt) { return elt->getName() == "bool"; });226 ASSERT_NE(BoolType, Types->end());227 const auto IntType = llvm::find_if(228 *Types, [](const LVElement *elt) { return elt->getName() == "int"; });229 ASSERT_NE(IntType, Types->end());230 EXPECT_EQ(static_cast<LVType *>(*BoolType)->getBitSize(), 8u);231 EXPECT_EQ(static_cast<LVType *>(*BoolType)->getStorageSizeInBytes(), 1u);232 EXPECT_EQ(static_cast<LVType *>(*IntType)->getBitSize(), 32u);233 EXPECT_EQ(static_cast<LVType *>(*IntType)->getStorageSizeInBytes(), 4u);234}235 236// Check the logical elements basic properties (MSVC library - Codeview).237void checkElementPropertiesMsvcLibraryCodeview(LVReader *Reader) {238 LVScopeRoot *Root = Reader->getScopesRoot();239 LVScopeCompileUnit *CompileUnit =240 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));241 LVScopeFunction *Function =242 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));243 244 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");245 EXPECT_EQ(Root->getName(), CodeViewMsvcLibContentName);246 247 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);248 EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));249 EXPECT_EQ(CompileUnit->getName(), "test.cpp");250 251 EXPECT_EQ(Function->lineCount(), 14u);252 EXPECT_EQ(Function->scopeCount(), 1u);253 EXPECT_EQ(Function->symbolCount(), 3u);254 EXPECT_EQ(Function->typeCount(), 0u);255 EXPECT_EQ(Function->rangeCount(), 1u);256 257 const LVLocations *Ranges = Function->getRanges();258 ASSERT_NE(Ranges, nullptr);259 ASSERT_EQ(Ranges->size(), 1u);260 LVLocations::const_iterator IterLocation = Ranges->begin();261 LVLocation *Location = (*IterLocation);262 EXPECT_STREQ(Location->getIntervalInfo().c_str(),263 "{Range} Lines 2:9 [0x0000000000:0x0000000031]");264 265 LVRange RangeList;266 Function->getRanges(RangeList);267 268 const LVRangeEntries &RangeEntries = RangeList.getEntries();269 ASSERT_EQ(RangeEntries.size(), 2u);270 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();271 LVRangeEntry RangeEntry = *IterRanges;272 EXPECT_EQ(RangeEntry.lower(), 0u);273 EXPECT_EQ(RangeEntry.upper(), 0x31u);274 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);275 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");276 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);277 278 ++IterRanges;279 RangeEntry = *IterRanges;280 EXPECT_EQ(RangeEntry.lower(), 0x1bu);281 EXPECT_EQ(RangeEntry.upper(), 0x28u);282 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);283 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");284 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);285 286 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();287 ASSERT_EQ(PublicNames.size(), 1u);288 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();289 LVScope *Foo = (*IterNames).first;290 EXPECT_EQ(Foo->getName(), "foo");291 EXPECT_EQ(Foo->getLineNumber(), 0u);292 LVNameInfo NameInfo = (*IterNames).second;293 EXPECT_EQ(NameInfo.first, 0u);294 EXPECT_EQ(NameInfo.second, 0x31u);295 296 // Lines (debug and assembler) for 'foo'.297 const LVLines *Lines = Foo->getLines();298 ASSERT_NE(Lines, nullptr);299 EXPECT_EQ(Lines->size(), 0x0eu);300}301 302// Check the logical elements basic properties (MSVC - PDB).303void checkElementPropertiesMsvcCodeviewPdb(LVReader *Reader) {304 LVScopeRoot *Root = Reader->getScopesRoot();305 LVScopeCompileUnit *CompileUnit =306 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));307 LVScopeFunction *Function =308 static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));309 310 EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");311 EXPECT_EQ(Root->getName(), CodeViewPdbMsvc);312 313 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);314 EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));315 EXPECT_EQ(CompileUnit->getName(), "test.cpp");316 317 EXPECT_EQ(Function->lineCount(), 14u);318 EXPECT_EQ(Function->scopeCount(), 1u);319 EXPECT_EQ(Function->symbolCount(), 3u);320 EXPECT_EQ(Function->typeCount(), 0u);321 EXPECT_EQ(Function->rangeCount(), 1u);322 323 const LVLocations *Ranges = Function->getRanges();324 ASSERT_NE(Ranges, nullptr);325 ASSERT_EQ(Ranges->size(), 1u);326 LVLocations::const_iterator IterLocation = Ranges->begin();327 LVLocation *Location = (*IterLocation);328 EXPECT_STREQ(Location->getIntervalInfo().c_str(),329 "{Range} Lines 2:9 [0x0000000000:0x0000000031]");330 331 LVRange RangeList;332 Function->getRanges(RangeList);333 334 const LVRangeEntries &RangeEntries = RangeList.getEntries();335 ASSERT_EQ(RangeEntries.size(), 2u);336 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();337 LVRangeEntry RangeEntry = *IterRanges;338 EXPECT_EQ(RangeEntry.lower(), 0u);339 EXPECT_EQ(RangeEntry.upper(), 0x31u);340 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);341 EXPECT_EQ(RangeEntry.scope()->getName(), "foo");342 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);343 344 ++IterRanges;345 RangeEntry = *IterRanges;346 EXPECT_EQ(RangeEntry.lower(), 0x1bu);347 EXPECT_EQ(RangeEntry.upper(), 0x28u);348 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);349 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");350 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);351 352 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();353 ASSERT_EQ(PublicNames.size(), 1u);354 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();355 LVScope *Foo = (*IterNames).first;356 EXPECT_EQ(Foo->getName(), "foo");357 EXPECT_EQ(Foo->getLineNumber(), 0u);358 LVNameInfo NameInfo = (*IterNames).second;359 EXPECT_EQ(NameInfo.first, 0u);360 EXPECT_EQ(NameInfo.second, 0x31u);361 362 // Lines (debug and assembler) for 'foo'.363 const LVLines *Lines = Foo->getLines();364 ASSERT_NE(Lines, nullptr);365 EXPECT_EQ(Lines->size(), 0x0eu);366}367 368struct SelectionInfo {369 const char *Name;370 LVElementGetFunction Function;371};372 373// Check the logical elements selection.374void checkElementSelection(LVReader *Reader, std::vector<SelectionInfo> &Data,375 size_t Size) {376 LVScopeRoot *Root = Reader->getScopesRoot();377 LVScopeCompileUnit *CompileUnit =378 static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));379 380 // Get the matched elements.381 LVElements MatchedElements = CompileUnit->getMatchedElements();382 std::map<StringRef, LVElement *> MapElements;383 for (LVElement *Element : MatchedElements)384 MapElements[Element->getName()] = Element;385 ASSERT_EQ(MapElements.size(), Size);386 387 std::map<StringRef, LVElement *>::iterator Iter = MapElements.begin();388 for (const SelectionInfo &Entry : Data) {389 // Get matched element.390 EXPECT_NE(Iter, MapElements.end());391 LVElement *Element = Iter->second;392 ASSERT_NE(Element, nullptr);393 EXPECT_NE(Element->getName().find(Entry.Name), StringRef::npos);394 EXPECT_EQ((Element->*Entry.Function)(), 1u);395 ++Iter;396 }397 398 // Get the parents for the matched elements.399 LVScopes MatchedScopes = CompileUnit->getMatchedScopes();400 std::set<StringRef> SetScopes;401 for (LVScope *Scope : MatchedScopes)402 SetScopes.insert(Scope->getName());403 ASSERT_EQ(SetScopes.size(), 3u);404 405 // Parents of selected elements.406 std::set<StringRef>::iterator IterScope;407 IterScope = SetScopes.find("foo");408 EXPECT_NE(IterScope, SetScopes.end());409 IterScope = SetScopes.find("foo::?");410 EXPECT_NE(IterScope, SetScopes.end());411 IterScope = SetScopes.find("test.cpp");412 EXPECT_NE(IterScope, SetScopes.end());413}414 415// Check the logical elements comparison.416void checkElementComparison(LVReader *Reference, LVReader *Target) {417 LVCompare Compare(nulls());418 Error Err = Compare.execute(Reference, Target);419 ASSERT_THAT_ERROR(std::move(Err), Succeeded());420 421 // Get comparison table.422 LVPassTable PassTable = Compare.getPassTable();423 ASSERT_EQ(PassTable.size(), 2u);424 425 LVReader *Reader;426 LVElement *Element;427 LVComparePass Pass;428 429 // Reference: Missing TypeDefinition 'INTEGER'430 std::tie(Reader, Element, Pass) = PassTable[0];431 ASSERT_NE(Reader, nullptr);432 ASSERT_NE(Element, nullptr);433 EXPECT_EQ(Reader, Reference);434 EXPECT_EQ(Element->getLevel(), 3u);435 EXPECT_EQ(Element->getLineNumber(), 0u);436 EXPECT_EQ(Element->getName(), "INTEGER");437 EXPECT_EQ(Pass, LVComparePass::Missing);438 439 // Target: Added TypeDefinition 'INTEGER'440 std::tie(Reader, Element, Pass) = PassTable[1];441 ASSERT_NE(Reader, nullptr);442 ASSERT_NE(Element, nullptr);443 EXPECT_EQ(Reader, Target);444 EXPECT_EQ(Element->getLevel(), 4u);445 EXPECT_EQ(Element->getLineNumber(), 0u);446 EXPECT_EQ(Element->getName(), "INTEGER");447 EXPECT_EQ(Pass, LVComparePass::Added);448}449 450// Logical elements properties.451void elementProperties(SmallString<128> &InputsDir) {452 // Reader options.453 LVOptions ReaderOptions;454 ReaderOptions.setAttributeOffset();455 ReaderOptions.setAttributeFormat();456 ReaderOptions.setAttributeFilename();457 ReaderOptions.setAttributeProducer();458 ReaderOptions.setAttributePublics();459 ReaderOptions.setAttributeRange();460 ReaderOptions.setAttributeLanguage();461 ReaderOptions.setAttributeLocation();462 ReaderOptions.setAttributeSize();463 ReaderOptions.setPrintAll();464 ReaderOptions.resolveDependencies();465 466 std::vector<std::string> Objects;467 ScopedPrinter W(outs());468 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);469 470 // Check logical elements properties.471 {472 std::unique_ptr<LVReader> Reader =473 createReader(ReaderHandler, InputsDir, CodeViewClang);474 checkElementPropertiesClangCodeview(Reader.get());475 }476 {477 std::unique_ptr<LVReader> Reader =478 createReader(ReaderHandler, InputsDir, CodeViewMsvc);479 checkElementPropertiesMsvcCodeview(Reader.get());480 }481 {482 std::unique_ptr<LVReader> Reader =483 createReader(ReaderHandler, InputsDir, CodeViewMsvcLib);484 checkElementPropertiesMsvcLibraryCodeview(Reader.get());485 }486 {487 std::unique_ptr<LVReader> Reader =488 createReader(ReaderHandler, InputsDir, CodeViewPdbMsvc);489 checkElementPropertiesMsvcCodeviewPdb(Reader.get());490 }491}492 493// Logical elements selection.494void elementSelection(SmallString<128> &InputsDir) {495 // Reader options.496 LVOptions ReaderOptions;497 ReaderOptions.setAttributeOffset();498 ReaderOptions.setPrintAll();499 500 ReaderOptions.setSelectIgnoreCase();501 ReaderOptions.setSelectUseRegex();502 503 ReaderOptions.setReportList(); // Matched elements.504 ReaderOptions.setReportView(); // Parents for matched elements.505 506 // Add patterns.507 ReaderOptions.Select.Generic.insert("foo");508 ReaderOptions.Select.Generic.insert("movl[ \t]?%");509 ReaderOptions.Select.Generic.insert("INT[a-z]*");510 ReaderOptions.Select.Generic.insert("CONSTANT");511 512 ReaderOptions.resolveDependencies();513 514 std::vector<std::string> Objects;515 ScopedPrinter W(outs());516 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);517 518 // Check logical elements selection.519 {520 std::vector<SelectionInfo> DataClang = {521 {"* const int", &LVElement::getIsType},522 {"CONSTANT", &LVElement::getIsSymbol},523 {"INTEGER", &LVElement::getIsType},524 {"INTPTR", &LVElement::getIsType},525 {"ParamPtr", &LVElement::getIsSymbol},526 {"const int", &LVElement::getIsType},527 {"foo", &LVElement::getIsScope},528 {"foo::?", &LVElement::getIsScope},529 {"int", &LVElement::getIsType},530 {"movl", &LVElement::getIsLine},531 {"movl", &LVElement::getIsLine}};532 std::unique_ptr<LVReader> Reader =533 createReader(ReaderHandler, InputsDir, CodeViewClang);534 checkElementSelection(Reader.get(), DataClang, DataClang.size());535 }536 {537 std::vector<SelectionInfo> DataMsvc = {538 {"* const int", &LVElement::getIsType},539 {"CONSTANT", &LVElement::getIsSymbol},540 {"INTEGER", &LVElement::getIsType},541 {"INTPTR", &LVElement::getIsType},542 {"ParamPtr", &LVElement::getIsSymbol},543 {"const int", &LVElement::getIsType},544 {"foo", &LVElement::getIsScope},545 {"foo::?", &LVElement::getIsScope},546 {"int", &LVElement::getIsType},547 {"movl", &LVElement::getIsLine}};548 std::unique_ptr<LVReader> Reader =549 createReader(ReaderHandler, InputsDir, CodeViewMsvc);550 checkElementSelection(Reader.get(), DataMsvc, DataMsvc.size());551 }552}553 554// Compare logical elements.555void compareElements(SmallString<128> &InputsDir) {556 // Reader options.557 LVOptions ReaderOptions;558 ReaderOptions.setAttributeOffset();559 ReaderOptions.setPrintLines();560 ReaderOptions.setPrintSymbols();561 ReaderOptions.setPrintTypes();562 ReaderOptions.setCompareLines();563 ReaderOptions.setCompareSymbols();564 ReaderOptions.setCompareTypes();565 566 ReaderOptions.resolveDependencies();567 568 std::vector<std::string> Objects;569 ScopedPrinter W(outs());570 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);571 572 // Check logical comparison.573 std::unique_ptr<LVReader> Reference =574 createReader(ReaderHandler, InputsDir, CodeViewClang);575 std::unique_ptr<LVReader> Target =576 createReader(ReaderHandler, InputsDir, CodeViewMsvc);577 checkElementComparison(Reference.get(), Target.get());578}579 580TEST(LogicalViewTest, CodeViewReader) {581 // Initialize targets and assembly printers/parsers.582 llvm::InitializeAllTargetInfos();583 llvm::InitializeAllTargetMCs();584 InitializeAllDisassemblers();585 586 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);587 588 // This test requires a x86-registered-target.589 Triple TT;590 TT.setArch(Triple::x86_64);591 TT.setVendor(Triple::UnknownVendor);592 TT.setOS(Triple::UnknownOS);593 594 std::string TargetLookupError;595 if (!TargetRegistry::lookupTarget(TT, TargetLookupError))596 return;597 598 SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);599 600 // Logical elements general properties and selection.601 elementProperties(InputsDir);602 elementSelection(InputsDir);603 604 // Compare logical elements.605 compareElements(InputsDir);606}607 608} // namespace609