diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -476,8 +476,7 @@ case dwarf::DW_FORM_data8: return 8; case dwarf::DW_FORM_sec_offset: - // FIXME: add support for DWARF64 - return 4; + return AP->getDwarfOffsetByteSize(); default: llvm_unreachable("DIE Value form not supported yet"); } @@ -505,8 +504,7 @@ return 4; case dwarf::DW_FORM_sec_offset: case dwarf::DW_FORM_strp: - // FIXME: add support for DWARF64 - return 4; + return AP->getDwarfOffsetByteSize(); case dwarf::DW_FORM_addr: return AP->MAI->getCodePointerSize(); default: @@ -551,8 +549,7 @@ case dwarf::DW_FORM_data4: return 4; case dwarf::DW_FORM_sec_offset: - // FIXME: add support for DWARF64 - return 4; + return AP->getDwarfOffsetByteSize(); default: llvm_unreachable("DIE Value form not supported yet"); } @@ -822,10 +819,17 @@ case dwarf::DW_FORM_loclistx: return getULEB128Size(Index); case dwarf::DW_FORM_data4: + assert(!AP->isDwarf64() && + "DW_FORM_data4 is not suitable to emit a pointer to a location list " + "in the 64-bit DWARF format"); return 4; + case dwarf::DW_FORM_data8: + assert(AP->isDwarf64() && + "DW_FORM_data8 is not suitable to emit a pointer to a location list " + "in the 32-bit DWARF format"); + return 8; case dwarf::DW_FORM_sec_offset: - // FIXME: add support for DWARF64 - return 4; + return AP->getDwarfOffsetByteSize(); default: llvm_unreachable("DIE Value form not supported yet"); } diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt --- a/llvm/unittests/CodeGen/CMakeLists.txt +++ b/llvm/unittests/CodeGen/CMakeLists.txt @@ -17,6 +17,7 @@ AArch64SelectionDAGTest.cpp AsmPrinterDwarfTest.cpp DIEHashTest.cpp + DIETest.cpp LowLevelTypeTest.cpp LexicalScopesTest.cpp MachineInstrBundleIteratorTest.cpp diff --git a/llvm/unittests/CodeGen/DIETest.cpp b/llvm/unittests/CodeGen/DIETest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/CodeGen/DIETest.cpp @@ -0,0 +1,189 @@ +//===- llvm/unittest/CodeGen/DIETest.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 "llvm/CodeGen/DIE.h" +#include "TestAsmPrinter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Testing/Support/Error.h" + +using namespace llvm; +using testing::_; +using testing::SaveArg; + +namespace { + +using DIETestParams = + std::tuple; + +class DIEFixtureBase : public testing::TestWithParam { +protected: + void SetUp() override { + unsigned Version; + dwarf::DwarfFormat Format; + std::tie(Version, Format, Form, Size) = GetParam(); + auto ExpectedTestPrinter = + TestAsmPrinter::create("x86_64-pc-linux", Version, Format); + ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded()); + TestPrinter = std::move(ExpectedTestPrinter.get()); + } + + dwarf::Form Form; + unsigned Size; + std::unique_ptr TestPrinter; +}; + +struct DIEExprFixture : public DIEFixtureBase { + void SetUp() override { + DIEFixtureBase::SetUp(); + if (!TestPrinter) + return; + + Val = MCConstantExpr::create(42, TestPrinter->getCtx()); + } + + const MCExpr *Val = nullptr; +}; + +TEST_P(DIEExprFixture, SizeOf) { + if (!TestPrinter) + return; + + DIEExpr Tst(Val); + EXPECT_EQ(Size, Tst.SizeOf(TestPrinter->getAP(), Form)); +} + +TEST_P(DIEExprFixture, EmitValue) { + if (!TestPrinter) + return; + + DIEExpr Tst(Val); + EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(Val, Size, _)); + Tst.emitValue(TestPrinter->getAP(), Form); +} + +INSTANTIATE_TEST_CASE_P( + DIETestParams, DIEExprFixture, + testing::Values( + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_data8, 8u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_sec_offset, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_data8, 8u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_sec_offset, 8u}), ); + +struct DIELabelFixture : public DIEFixtureBase { + void SetUp() override { + DIEFixtureBase::SetUp(); + if (!TestPrinter) + return; + + Val = TestPrinter->getCtx().createTempSymbol(); + } + + const MCSymbol *Val = nullptr; +}; + +TEST_P(DIELabelFixture, SizeOf) { + if (!TestPrinter) + return; + + DIELabel Tst(Val); + EXPECT_EQ(Size, Tst.SizeOf(TestPrinter->getAP(), Form)); +} + +TEST_P(DIELabelFixture, EmitValue) { + if (!TestPrinter) + return; + + DIELabel Tst(Val); + + const MCExpr *Arg0 = nullptr; + EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, Size, _)) + .WillOnce(SaveArg<0>(&Arg0)); + Tst.emitValue(TestPrinter->getAP(), Form); + + const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null(Arg0); + ASSERT_NE(ActualArg0, nullptr); + EXPECT_EQ(&(ActualArg0->getSymbol()), Val); +} + +INSTANTIATE_TEST_CASE_P( + DIETestParams, DIELabelFixture, + testing::Values( + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_sec_offset, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_strp, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_addr, 8u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_sec_offset, 8u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_strp, 8u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_addr, 8u}), ); + +struct DIEDeltaFixture : public DIEFixtureBase { + void SetUp() override { + DIEFixtureBase::SetUp(); + if (!TestPrinter) + return; + + Hi = TestPrinter->getCtx().createTempSymbol(); + Lo = TestPrinter->getCtx().createTempSymbol(); + } + + const MCSymbol *Hi = nullptr; + const MCSymbol *Lo = nullptr; +}; + +TEST_P(DIEDeltaFixture, SizeOf) { + if (!TestPrinter) + return; + + DIEDelta Tst(Hi, Lo); + EXPECT_EQ(Size, Tst.SizeOf(TestPrinter->getAP(), Form)); +} + +TEST_P(DIEDeltaFixture, EmitValue) { + if (!TestPrinter) + return; + + DIEDelta Tst(Hi, Lo); + EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(Hi, Lo, Size)); + Tst.emitValue(TestPrinter->getAP(), Form); +} + +INSTANTIATE_TEST_CASE_P( + DIETestParams, DIEDeltaFixture, + testing::Values( + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_sec_offset, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_sec_offset, 8u}), ); + +struct DIELocListFixture : public DIEFixtureBase { + void SetUp() override { DIEFixtureBase::SetUp(); } +}; + +TEST_P(DIELocListFixture, SizeOf) { + if (!TestPrinter) + return; + + DIELocList Tst(999); + EXPECT_EQ(Size, Tst.SizeOf(TestPrinter->getAP(), Form)); +} + +INSTANTIATE_TEST_CASE_P( + DIETestParams, DIELocListFixture, + testing::Values( + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_loclistx, 2u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_data4, 4u}, + DIETestParams{4, dwarf::DWARF32, dwarf::DW_FORM_sec_offset, 4u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_loclistx, 2u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_data8, 8u}, + DIETestParams{4, dwarf::DWARF64, dwarf::DW_FORM_sec_offset, 8u}), ); + +} // end namespace