[llvm-debuginfo-analyzer] Common handling of unsigned attribute values. (#116027)
- In the DWARF reader, for those attributes that can have an unsigned value, allow for the following cases: * Is an implicit constant * Is an optional value - The testing is done by creating a file with generated DWARF, using `DwarfGenerator` (generate DWARF debug info for unit tests).
This commit is contained in:
committed by
GitHub
parent
f710b04233
commit
fb3765959f
@@ -253,15 +253,18 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
// We are processing .debug_info section, implicit_const attribute
|
||||
// values are not really stored here, but in .debug_abbrev section.
|
||||
auto GetAsUnsignedConstant = [&]() -> int64_t {
|
||||
return AttrSpec.isImplicitConst() ? AttrSpec.getImplicitConstValue()
|
||||
: *FormValue.getAsUnsignedConstant();
|
||||
if (AttrSpec.isImplicitConst())
|
||||
return AttrSpec.getImplicitConstValue();
|
||||
if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
|
||||
return *Val;
|
||||
return 0;
|
||||
};
|
||||
|
||||
auto GetFlag = [](const DWARFFormValue &FormValue) -> bool {
|
||||
return FormValue.isFormClass(DWARFFormValue::FC_Flag);
|
||||
};
|
||||
|
||||
auto GetBoundValue = [](const DWARFFormValue &FormValue) -> int64_t {
|
||||
auto GetBoundValue = [&AttrSpec](const DWARFFormValue &FormValue) -> int64_t {
|
||||
switch (FormValue.getForm()) {
|
||||
case dwarf::DW_FORM_ref_addr:
|
||||
case dwarf::DW_FORM_ref1:
|
||||
@@ -282,6 +285,8 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
return *FormValue.getAsUnsignedConstant();
|
||||
case dwarf::DW_FORM_sdata:
|
||||
return *FormValue.getAsSignedConstant();
|
||||
case dwarf::DW_FORM_implicit_const:
|
||||
return AttrSpec.getImplicitConstValue();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -294,13 +299,13 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
|
||||
switch (AttrSpec.Attr) {
|
||||
case dwarf::DW_AT_accessibility:
|
||||
CurrentElement->setAccessibilityCode(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setAccessibilityCode(GetAsUnsignedConstant());
|
||||
break;
|
||||
case dwarf::DW_AT_artificial:
|
||||
CurrentElement->setIsArtificial();
|
||||
break;
|
||||
case dwarf::DW_AT_bit_size:
|
||||
CurrentElement->setBitSize(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setBitSize(GetAsUnsignedConstant());
|
||||
break;
|
||||
case dwarf::DW_AT_call_file:
|
||||
CurrentElement->setCallFilenameIndex(IncrementFileIndex
|
||||
@@ -332,13 +337,12 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
Stream << hexString(Value, 2);
|
||||
CurrentElement->setValue(Stream.str());
|
||||
} else
|
||||
CurrentElement->setValue(
|
||||
hexString(*FormValue.getAsUnsignedConstant(), 2));
|
||||
CurrentElement->setValue(hexString(GetAsUnsignedConstant(), 2));
|
||||
} else
|
||||
CurrentElement->setValue(dwarf::toStringRef(FormValue));
|
||||
break;
|
||||
case dwarf::DW_AT_count:
|
||||
CurrentElement->setCount(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setCount(GetAsUnsignedConstant());
|
||||
break;
|
||||
case dwarf::DW_AT_decl_line:
|
||||
CurrentElement->setLineNumber(GetAsUnsignedConstant());
|
||||
@@ -357,10 +361,10 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
CurrentElement->setIsExternal();
|
||||
break;
|
||||
case dwarf::DW_AT_GNU_discriminator:
|
||||
CurrentElement->setDiscriminator(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setDiscriminator(GetAsUnsignedConstant());
|
||||
break;
|
||||
case dwarf::DW_AT_inline:
|
||||
CurrentElement->setInlineCode(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setInlineCode(GetAsUnsignedConstant());
|
||||
break;
|
||||
case dwarf::DW_AT_lower_bound:
|
||||
CurrentElement->setLowerBound(GetBoundValue(FormValue));
|
||||
@@ -380,7 +384,7 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
|
||||
CurrentElement->setUpperBound(GetBoundValue(FormValue));
|
||||
break;
|
||||
case dwarf::DW_AT_virtuality:
|
||||
CurrentElement->setVirtualityCode(*FormValue.getAsUnsignedConstant());
|
||||
CurrentElement->setVirtualityCode(GetAsUnsignedConstant());
|
||||
break;
|
||||
|
||||
case dwarf::DW_AT_abstract_origin:
|
||||
|
||||
@@ -43,14 +43,14 @@
|
||||
; ONE-EMPTY:
|
||||
; ONE-NEXT: [001] {CompileUnit} 'pr-43860.cpp'
|
||||
; ONE-NEXT: [002] {Producer} 'clang version 15.0.0 {{.*}}'
|
||||
; ONE-NEXT: [002] 2 {Function} extern not_inlined 'InlineFunction' -> 'int'
|
||||
; ONE-NEXT: [002] 2 {Function} extern inlined 'InlineFunction' -> 'int'
|
||||
; ONE-NEXT: [003] {Block}
|
||||
; ONE-NEXT: [004] 5 {Variable} 'Var_2' -> 'int'
|
||||
; ONE-NEXT: [003] 2 {Parameter} 'Param' -> 'int'
|
||||
; ONE-NEXT: [003] 3 {Variable} 'Var_1' -> 'int'
|
||||
; ONE-NEXT: [002] 11 {Function} extern not_inlined 'test' -> 'int'
|
||||
; ONE-NEXT: [003] 12 {Variable} 'A' -> 'int'
|
||||
; ONE-NEXT: [003] 13 {InlinedFunction} not_inlined 'InlineFunction' -> 'int'
|
||||
; ONE-NEXT: [003] 13 {InlinedFunction} inlined 'InlineFunction' -> 'int'
|
||||
; ONE-NEXT: [004] {Block}
|
||||
; ONE-NEXT: [005] {Variable} 'Var_2' -> 'int'
|
||||
; ONE-NEXT: [004] {Parameter} 'Param' -> 'int'
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
${LLVM_TARGETS_TO_BUILD}
|
||||
AllTargetsDescs
|
||||
AllTargetsDisassemblers
|
||||
AllTargetsInfos
|
||||
AsmPrinter
|
||||
DebugInfoLogicalView
|
||||
MC
|
||||
MCDisassembler
|
||||
@@ -9,9 +11,12 @@ set(LLVM_LINK_COMPONENTS
|
||||
)
|
||||
|
||||
add_llvm_unittest_with_input_files(DebugInfoLogicalViewTests
|
||||
../DWARF/DwarfGenerator.cpp
|
||||
../DWARF/DwarfUtils.cpp
|
||||
CodeViewReaderTest.cpp
|
||||
CommandLineOptionsTest.cpp
|
||||
CompareElementsTest.cpp
|
||||
DWARFGeneratedTest.cpp
|
||||
DWARFReaderTest.cpp
|
||||
SelectElementsTest.cpp
|
||||
LocationRangesTest.cpp
|
||||
|
||||
362
llvm/unittests/DebugInfo/LogicalView/DWARFGeneratedTest.cpp
Normal file
362
llvm/unittests/DebugInfo/LogicalView/DWARFGeneratedTest.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
//===- llvm/unittest/DebugInfo/LogicalView/DWARFGeneratedTest.cpp ---------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../DWARF/DwarfGenerator.h"
|
||||
#include "../DWARF/DwarfUtils.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
|
||||
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
|
||||
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
|
||||
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
|
||||
#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Support/COM.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
#include "llvm/Testing/Support/Error.h"
|
||||
#include "llvm/Testing/Support/SupportHelpers.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::logicalview;
|
||||
using namespace llvm::dwarf;
|
||||
using namespace llvm::dwarf::utils;
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper function to get the first compile unit.
|
||||
LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) {
|
||||
if (!Root)
|
||||
return nullptr;
|
||||
|
||||
const LVScopes *CompileUnits = Root->getScopes();
|
||||
if (!CompileUnits)
|
||||
return nullptr;
|
||||
|
||||
LVScopes::const_iterator Iter = CompileUnits->begin();
|
||||
return (Iter != CompileUnits->end())
|
||||
? static_cast<LVScopeCompileUnit *>(*Iter)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
// Helper function to create a reader.
|
||||
std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
|
||||
SmallString<128> &InputsDir,
|
||||
StringRef Filename) {
|
||||
SmallString<128> ObjectName(InputsDir);
|
||||
llvm::sys::path::append(ObjectName, Filename);
|
||||
|
||||
Expected<std::unique_ptr<LVReader>> ReaderOrErr =
|
||||
ReaderHandler.createReader(std::string(ObjectName));
|
||||
EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
|
||||
std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
|
||||
return Reader;
|
||||
}
|
||||
|
||||
// Create a file with generated DWARF.
|
||||
void generateDebugInfo(StringRef Path, Triple &Triple) {
|
||||
uint16_t Version = 5;
|
||||
auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
|
||||
ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
|
||||
dwarfgen::Generator *DG = ExpectedDG.get().get();
|
||||
dwarfgen::CompileUnit &CU = DG->addCompileUnit();
|
||||
|
||||
dwarfgen::DIE CUDie = CU.getUnitDIE();
|
||||
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "test.cpp");
|
||||
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C_plus_plus);
|
||||
CUDie.addAttribute(DW_AT_producer, DW_FORM_strp, "dwarfgen::Generator");
|
||||
|
||||
dwarfgen::DIE ScopeValueDie = CUDie.addChild(DW_TAG_inlined_subroutine);
|
||||
ScopeValueDie.addAttribute(DW_AT_accessibility, DW_FORM_data1, 1);
|
||||
ScopeValueDie.addAttribute(DW_AT_inline, DW_FORM_data4, 2);
|
||||
ScopeValueDie.addAttribute(DW_AT_virtuality, DW_FORM_data4, 3);
|
||||
ScopeValueDie.addAttribute(DW_AT_call_file, DW_FORM_data4, 4);
|
||||
ScopeValueDie.addAttribute(DW_AT_call_line, DW_FORM_data4, 5);
|
||||
ScopeValueDie.addAttribute(DW_AT_decl_file, DW_FORM_data4, 6);
|
||||
ScopeValueDie.addAttribute(DW_AT_decl_line, DW_FORM_data4, 7);
|
||||
ScopeValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_data4, 8);
|
||||
|
||||
dwarfgen::DIE ScopeNoValueDie = CUDie.addChild(DW_TAG_inlined_subroutine);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_accessibility, DW_FORM_sdata, 1);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_inline, DW_FORM_sdata, 2);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_virtuality, DW_FORM_sdata, 3);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_call_file, DW_FORM_sdata, 4);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_call_line, DW_FORM_sdata, 5);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_decl_file, DW_FORM_sdata, 6);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_decl_line, DW_FORM_sdata, 7);
|
||||
ScopeNoValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_sdata, 8);
|
||||
|
||||
dwarfgen::DIE ScopeImplicitDie = CUDie.addChild(DW_TAG_inlined_subroutine);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_accessibility, DW_FORM_implicit_const, 1);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_inline, DW_FORM_implicit_const, 2);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_virtuality, DW_FORM_implicit_const, 3);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_call_file, DW_FORM_implicit_const, 4);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_call_line, DW_FORM_implicit_const, 5);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_decl_file, DW_FORM_implicit_const, 6);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_decl_line, DW_FORM_implicit_const, 7);
|
||||
ScopeImplicitDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_implicit_const,
|
||||
8);
|
||||
|
||||
dwarfgen::DIE SymbolValueDie = CUDie.addChild(DW_TAG_variable);
|
||||
SymbolValueDie.addAttribute(DW_AT_bit_size, DW_FORM_data1, 1);
|
||||
|
||||
dwarfgen::DIE SymbolNoValueDie = CUDie.addChild(DW_TAG_variable);
|
||||
SymbolNoValueDie.addAttribute(DW_AT_bit_size, DW_FORM_sdata, 1);
|
||||
|
||||
dwarfgen::DIE SymbolImplicitDie = CUDie.addChild(DW_TAG_variable);
|
||||
SymbolImplicitDie.addAttribute(DW_AT_bit_size, DW_FORM_implicit_const, 1);
|
||||
|
||||
dwarfgen::DIE TypeValueCountDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeValueCountDie.addAttribute(DW_AT_count, DW_FORM_data4, 1);
|
||||
|
||||
dwarfgen::DIE TypeNoValueCountDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeNoValueCountDie.addAttribute(DW_AT_count, DW_FORM_sdata, 1);
|
||||
|
||||
dwarfgen::DIE TypeImplicitCountDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeImplicitCountDie.addAttribute(DW_AT_count, DW_FORM_implicit_const, 1);
|
||||
|
||||
dwarfgen::DIE TypeValueRangeDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_data4, 1);
|
||||
TypeValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_data4, 2);
|
||||
|
||||
dwarfgen::DIE TypeNoValueRangeDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeNoValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_addr, 3);
|
||||
TypeNoValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_addr, 4);
|
||||
|
||||
dwarfgen::DIE TypeImplicitRangeDie = CUDie.addChild(DW_TAG_subrange_type);
|
||||
TypeImplicitRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_implicit_const,
|
||||
5);
|
||||
TypeImplicitRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_implicit_const,
|
||||
6);
|
||||
|
||||
// Generate the DWARF.
|
||||
StringRef FileBytes = DG->generate();
|
||||
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
|
||||
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
|
||||
EXPECT_TRUE((bool)Obj);
|
||||
std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
|
||||
|
||||
// Verify the number of compile units is correct.
|
||||
uint32_t NumCUs = DwarfContext->getNumCompileUnits();
|
||||
EXPECT_EQ(NumCUs, 1u);
|
||||
DWARFCompileUnit *U = cast<DWARFCompileUnit>(DwarfContext->getUnitAtIndex(0));
|
||||
auto DieDG = U->getUnitDIE(false);
|
||||
EXPECT_TRUE(DieDG.isValid());
|
||||
|
||||
// Verify the siblings correct order.
|
||||
// ScopeValue
|
||||
// ScopeNoValue
|
||||
// ScopeImplicit
|
||||
auto ScopeValueDieDG = DieDG.getFirstChild();
|
||||
EXPECT_TRUE(ScopeValueDieDG.isValid());
|
||||
EXPECT_EQ(ScopeValueDieDG.getTag(), DW_TAG_inlined_subroutine);
|
||||
auto ScopeNoValueDieDG = ScopeValueDieDG.getSibling();
|
||||
EXPECT_TRUE(ScopeNoValueDieDG.isValid());
|
||||
EXPECT_EQ(ScopeNoValueDieDG.getTag(), DW_TAG_inlined_subroutine);
|
||||
auto ScopeImplicitDieDG = ScopeNoValueDieDG.getSibling();
|
||||
EXPECT_TRUE(ScopeImplicitDieDG.isValid());
|
||||
EXPECT_EQ(ScopeImplicitDieDG.getTag(), DW_TAG_inlined_subroutine);
|
||||
|
||||
// Verify the siblings correct order.
|
||||
// SymbolValue
|
||||
// SymbolNoValue
|
||||
// SymbolImplicitValue
|
||||
auto SymbolValueDieDG = ScopeImplicitDieDG.getSibling();
|
||||
EXPECT_TRUE(SymbolValueDieDG.isValid());
|
||||
EXPECT_EQ(SymbolValueDieDG.getTag(), DW_TAG_variable);
|
||||
auto SymbolNoValueDieDG = SymbolValueDieDG.getSibling();
|
||||
EXPECT_TRUE(SymbolNoValueDieDG.isValid());
|
||||
EXPECT_EQ(SymbolNoValueDieDG.getTag(), DW_TAG_variable);
|
||||
auto SymbolImplicitDieDG = SymbolNoValueDieDG.getSibling();
|
||||
EXPECT_TRUE(SymbolImplicitDieDG.isValid());
|
||||
EXPECT_EQ(SymbolImplicitDieDG.getTag(), DW_TAG_variable);
|
||||
|
||||
// Verify the siblings correct order.
|
||||
// TypeValueCount
|
||||
// TypeNoValueCount
|
||||
// TypeImplicitValueCount
|
||||
auto TypeValueCountDieDG = SymbolImplicitDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeValueCountDieDG.isValid());
|
||||
EXPECT_EQ(TypeValueCountDieDG.getTag(), DW_TAG_subrange_type);
|
||||
auto TypeNoValueCountDieDG = TypeValueCountDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeNoValueCountDieDG.isValid());
|
||||
EXPECT_EQ(TypeNoValueCountDieDG.getTag(), DW_TAG_subrange_type);
|
||||
auto TypeImplicitCountDieDG = TypeNoValueCountDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeImplicitCountDieDG.isValid());
|
||||
EXPECT_EQ(TypeImplicitCountDieDG.getTag(), DW_TAG_subrange_type);
|
||||
|
||||
// Verify the siblings correct order.
|
||||
// TypeValueRange
|
||||
// TypeNoValueRange
|
||||
// TypeImplicitValueRange
|
||||
auto TypeValueRangeDieDG = TypeImplicitCountDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeValueRangeDieDG.isValid());
|
||||
EXPECT_EQ(TypeValueRangeDieDG.getTag(), DW_TAG_subrange_type);
|
||||
auto TypeNoValueRangeDieDG = TypeValueRangeDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeNoValueRangeDieDG.isValid());
|
||||
EXPECT_EQ(TypeNoValueRangeDieDG.getTag(), DW_TAG_subrange_type);
|
||||
auto TypeImplicitRangeDieDG = TypeNoValueRangeDieDG.getSibling();
|
||||
EXPECT_TRUE(TypeImplicitRangeDieDG.isValid());
|
||||
EXPECT_EQ(TypeImplicitRangeDieDG.getTag(), DW_TAG_subrange_type);
|
||||
|
||||
// Save the generated DWARF file to disk.
|
||||
EXPECT_TRUE(DG->saveFile(Path));
|
||||
}
|
||||
|
||||
// Check the logical elements basic properties.
|
||||
void checkElementAttributes(LVReader *Reader) {
|
||||
LVScopeRoot *Root = Reader->getScopesRoot();
|
||||
ASSERT_NE(Root, nullptr);
|
||||
LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
|
||||
ASSERT_NE(CompileUnit, nullptr);
|
||||
|
||||
const LVScopes *Scopes = CompileUnit->getScopes();
|
||||
ASSERT_NE(Scopes, nullptr);
|
||||
ASSERT_EQ(Scopes->size(), 3u);
|
||||
|
||||
// Check values.
|
||||
LVScopes::const_iterator ScopeIter = Scopes->begin();
|
||||
ASSERT_NE(ScopeIter, Scopes->end());
|
||||
LVScope *Scope = static_cast<LVScope *>(*ScopeIter);
|
||||
ASSERT_NE(Scope, nullptr);
|
||||
EXPECT_EQ(Scope->getAccessibilityCode(), 1); // Element
|
||||
EXPECT_EQ(Scope->getInlineCode(), 2); // Element
|
||||
EXPECT_EQ(Scope->getVirtualityCode(), 3); // Element
|
||||
EXPECT_EQ(Scope->getCallFilenameIndex(), 5); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getCallLineNumber(), 5); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getFilenameIndex(), 7); // Element
|
||||
EXPECT_EQ(Scope->getLineNumber(), 7); // Element
|
||||
EXPECT_EQ(Scope->getDiscriminator(), 8); // ScopeFunctionInlined
|
||||
|
||||
// Check no-values.
|
||||
ASSERT_NE(++ScopeIter, Scopes->end());
|
||||
Scope = static_cast<LVScope *>(*ScopeIter);
|
||||
ASSERT_NE(Scope, nullptr);
|
||||
EXPECT_EQ(Scope->getAccessibilityCode(), 0); // Element
|
||||
EXPECT_EQ(Scope->getInlineCode(), 0); // Element
|
||||
EXPECT_EQ(Scope->getVirtualityCode(), 0); // Element
|
||||
EXPECT_EQ(Scope->getCallFilenameIndex(), 1); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getCallLineNumber(), 0); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getFilenameIndex(), 1); // Element
|
||||
EXPECT_EQ(Scope->getLineNumber(), 0); // Element
|
||||
EXPECT_EQ(Scope->getDiscriminator(), 0); // ScopeFunctionInlined
|
||||
|
||||
// Check implicit values.
|
||||
ASSERT_NE(++ScopeIter, Scopes->end());
|
||||
Scope = static_cast<LVScope *>(*ScopeIter);
|
||||
ASSERT_NE(Scope, nullptr);
|
||||
EXPECT_EQ(Scope->getAccessibilityCode(), 1); // Element
|
||||
EXPECT_EQ(Scope->getInlineCode(), 2); // Element
|
||||
EXPECT_EQ(Scope->getVirtualityCode(), 3); // Element
|
||||
EXPECT_EQ(Scope->getCallFilenameIndex(), 5); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getCallLineNumber(), 5); // ScopeFunctionInlined
|
||||
EXPECT_EQ(Scope->getFilenameIndex(), 7); // Element
|
||||
EXPECT_EQ(Scope->getLineNumber(), 7); // Element
|
||||
EXPECT_EQ(Scope->getDiscriminator(), 8); // ScopeFunctionInlined
|
||||
|
||||
const LVSymbols *Symbols = CompileUnit->getSymbols();
|
||||
ASSERT_NE(Symbols, nullptr);
|
||||
ASSERT_EQ(Symbols->size(), 3u);
|
||||
|
||||
LVSymbols::const_iterator SymbolIter = Symbols->begin();
|
||||
ASSERT_NE(SymbolIter, Symbols->end());
|
||||
LVSymbol *Symbol = static_cast<LVSymbol *>(*SymbolIter);
|
||||
ASSERT_NE(Symbol, nullptr);
|
||||
EXPECT_EQ(Symbol->getBitSize(), 1); // Symbol
|
||||
|
||||
ASSERT_NE(++SymbolIter, Symbols->end());
|
||||
Symbol = static_cast<LVSymbol *>(*SymbolIter);
|
||||
ASSERT_NE(Symbol, nullptr);
|
||||
EXPECT_EQ(Symbol->getBitSize(), 0); // Symbol
|
||||
|
||||
ASSERT_NE(++SymbolIter, Symbols->end());
|
||||
Symbol = static_cast<LVSymbol *>(*SymbolIter);
|
||||
ASSERT_NE(Symbol, nullptr);
|
||||
EXPECT_EQ(Symbol->getBitSize(), 1); // Symbol
|
||||
|
||||
const LVTypes *Types = CompileUnit->getTypes();
|
||||
ASSERT_NE(Types, nullptr);
|
||||
ASSERT_EQ(Types->size(), 6u);
|
||||
|
||||
LVTypes::const_iterator TypeIter = Types->begin();
|
||||
ASSERT_NE(TypeIter, Types->end());
|
||||
LVType *Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getCount(), 1); // Type
|
||||
|
||||
ASSERT_NE(++TypeIter, Types->end());
|
||||
Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getCount(), 0); // Type
|
||||
|
||||
ASSERT_NE(++TypeIter, Types->end());
|
||||
Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getCount(), 1); // Type
|
||||
|
||||
ASSERT_NE(++TypeIter, Types->end());
|
||||
Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getLowerBound(), 1); // Type
|
||||
EXPECT_EQ(Type->getUpperBound(), 2); // Type
|
||||
|
||||
ASSERT_NE(++TypeIter, Types->end());
|
||||
Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getLowerBound(), 0); // Type
|
||||
EXPECT_EQ(Type->getUpperBound(), 0); // Type
|
||||
|
||||
ASSERT_NE(++TypeIter, Types->end());
|
||||
Type = static_cast<LVType *>(*TypeIter);
|
||||
ASSERT_NE(Type, nullptr);
|
||||
EXPECT_EQ(Type->getLowerBound(), 5); // Type
|
||||
EXPECT_EQ(Type->getUpperBound(), 6); // Type
|
||||
}
|
||||
|
||||
TEST(LogicalViewTest, ElementAttributes) {
|
||||
// Initialize targets and assembly printers/parsers.
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
InitializeAllDisassemblers();
|
||||
|
||||
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
|
||||
|
||||
Triple Triple(Triple::normalize("x86_64-pc-linux-gnu"));
|
||||
if (!isConfigurationSupported(Triple))
|
||||
GTEST_SKIP();
|
||||
|
||||
unittest::TempDir TestDirectory("dwarf-test", /*Unique=*/true);
|
||||
llvm::SmallString<128> DirName(TestDirectory.path());
|
||||
StringRef Filename("test.o");
|
||||
llvm::SmallString<128> Path(TestDirectory.path(Filename));
|
||||
generateDebugInfo(Path, Triple);
|
||||
|
||||
// Reader options.
|
||||
LVOptions ReaderOptions;
|
||||
ReaderOptions.setPrintScopes();
|
||||
ReaderOptions.setPrintSymbols();
|
||||
ReaderOptions.setPrintTypes();
|
||||
ReaderOptions.resolveDependencies();
|
||||
|
||||
std::vector<std::string> Objects;
|
||||
ScopedPrinter W(outs());
|
||||
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
|
||||
|
||||
// Check logical elements properties.
|
||||
std::unique_ptr<LVReader> Reader =
|
||||
createReader(ReaderHandler, DirName, Filename);
|
||||
ASSERT_NE(Reader, nullptr);
|
||||
|
||||
checkElementAttributes(Reader.get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user