[llvm] 380e746 - [DebugInfo] Fix methods of AsmPrinter to emit values corresponding to the DWARF format (1/19).
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 22:24:17 PDT 2020
Author: Igor Kudrin
Date: 2020-09-15T11:29:48+07:00
New Revision: 380e746bcca87baa5c746854b44d6a5cea6f7bde
URL: https://github.com/llvm/llvm-project/commit/380e746bcca87baa5c746854b44d6a5cea6f7bde
DIFF: https://github.com/llvm/llvm-project/commit/380e746bcca87baa5c746854b44d6a5cea6f7bde.diff
LOG: [DebugInfo] Fix methods of AsmPrinter to emit values corresponding to the DWARF format (1/19).
These methods are used to emit values which are 32-bit in DWARF32 and
64-bit in DWARF64. The patch fixes them so that they choose the length
automatically, depending on the DWARF format set in the Context.
Differential Revision: https://reviews.llvm.org/D87008
Added:
llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp
llvm/unittests/CodeGen/TestAsmPrinter.cpp
llvm/unittests/CodeGen/TestAsmPrinter.h
Modified:
llvm/include/llvm/CodeGen/AsmPrinter.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
llvm/unittests/CodeGen/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index c157bb0672ba..89d266b4286b 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -216,6 +216,11 @@ class AsmPrinter : public MachineFunctionPass {
uint16_t getDwarfVersion() const;
void setDwarfVersion(uint16_t Version);
+ bool isDwarf64() const;
+
+ /// Returns 4 for DWARF32 and 8 for DWARF64.
+ unsigned int getDwarfOffsetByteSize() const;
+
bool isPositionIndependent() const;
/// Return true if assembly output should contain comments.
@@ -562,9 +567,6 @@ class AsmPrinter : public MachineFunctionPass {
emitLabelPlusOffset(Label, 0, Size, IsSectionRelative);
}
- /// Emit something like ".long Label + Offset".
- void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const;
-
//===------------------------------------------------------------------===//
// Dwarf Emission Helper Routines
//===------------------------------------------------------------------===//
@@ -593,18 +595,24 @@ class AsmPrinter : public MachineFunctionPass {
void emitDwarfSymbolReference(const MCSymbol *Label,
bool ForceOffset = false) const;
- /// Emit the 4-byte offset of a string from the start of its section.
+ /// Emit the 4- or 8-byte offset of a string from the start of its section.
///
/// When possible, emit a DwarfStringPool section offset without any
/// relocations, and without using the symbol. Otherwise, defers to \a
/// emitDwarfSymbolReference().
+ ///
+ /// The length of the emitted value depends on the DWARF format.
void emitDwarfStringOffset(DwarfStringPoolEntry S) const;
- /// Emit the 4-byte offset of a string from the start of its section.
+ /// Emit the 4-or 8-byte offset of a string from the start of its section.
void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
emitDwarfStringOffset(S.getEntry());
}
+ /// Emit something like ".long Label + Offset" or ".quad Label + Offset"
+ /// depending on the DWARF format.
+ void emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const;
+
/// Emit reference to a call site with a specified encoding
void emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Encoding) const;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 01370baa4fd1..35a40bb277b9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -3432,3 +3432,12 @@ uint16_t AsmPrinter::getDwarfVersion() const {
void AsmPrinter::setDwarfVersion(uint16_t Version) {
OutStreamer->getContext().setDwarfVersion(Version);
}
+
+bool AsmPrinter::isDwarf64() const {
+ return OutStreamer->getContext().getDwarfFormat() == dwarf::DWARF64;
+}
+
+unsigned int AsmPrinter::getDwarfOffsetByteSize() const {
+ return dwarf::getDwarfOffsetByteSize(
+ OutStreamer->getContext().getDwarfFormat());
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index b6a9a9568360..7f8f6c646925 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -154,19 +154,22 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
if (!ForceOffset) {
// On COFF targets, we have to emit the special .secrel32 directive.
if (MAI->needsDwarfSectionOffsetDirective()) {
+ assert(!isDwarf64() &&
+ "emitting DWARF64 is not implemented for COFF targets");
OutStreamer->EmitCOFFSecRel32(Label, /*Offset=*/0);
return;
}
// If the format uses relocations with dwarf, refer to the symbol directly.
if (MAI->doesDwarfUseRelocationsAcrossSections()) {
- OutStreamer->emitSymbolValue(Label, 4);
+ OutStreamer->emitSymbolValue(Label, getDwarfOffsetByteSize());
return;
}
}
// Otherwise, emit it as a label
diff erence from the start of the section.
- emitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4);
+ emitLabelDifference(Label, Label->getSection().getBeginSymbol(),
+ getDwarfOffsetByteSize());
}
void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const {
@@ -177,12 +180,11 @@ void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const {
}
// Just emit the offset directly; no need for symbol math.
- emitInt32(S.Offset);
+ OutStreamer->emitIntValue(S.Offset, getDwarfOffsetByteSize());
}
void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const {
- // TODO: Support DWARF64
- emitLabelPlusOffset(Label, Offset, 4);
+ emitLabelPlusOffset(Label, Offset, getDwarfOffsetByteSize());
}
void AsmPrinter::emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo,
diff --git a/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp b/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp
new file mode 100644
index 000000000000..948b8851149d
--- /dev/null
+++ b/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp
@@ -0,0 +1,253 @@
+//===- llvm/unittest/CodeGen/AsmPrinterDwarfTest.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 "TestAsmPrinter.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/Testing/Support/Error.h"
+
+using namespace llvm;
+using testing::_;
+using testing::SaveArg;
+
+namespace {
+
+class AsmPrinterFixtureBase : public testing::Test {
+ void setupTestPrinter(const std::string &TripleStr, unsigned DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ auto ExpectedTestPrinter =
+ TestAsmPrinter::create(TripleStr, DwarfVersion, DwarfFormat);
+ ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded());
+ TestPrinter = std::move(ExpectedTestPrinter.get());
+ }
+
+protected:
+ bool init(const std::string &TripleStr, unsigned DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ setupTestPrinter(TripleStr, DwarfVersion, DwarfFormat);
+ return TestPrinter != nullptr;
+ }
+
+ std::unique_ptr<TestAsmPrinter> TestPrinter;
+};
+
+class AsmPrinterEmitDwarfSymbolReferenceTest : public AsmPrinterFixtureBase {
+protected:
+ bool init(const std::string &TripleStr, unsigned DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
+ return false;
+
+ // Create a symbol which will be emitted in the tests and associate it
+ // with a section because that is required in some code paths.
+
+ Val = TestPrinter->getCtx().createTempSymbol();
+ Sec = TestPrinter->getCtx().getELFSection(".tst", ELF::SHT_PROGBITS, 0);
+ SecBeginSymbol = Sec->getBeginSymbol();
+ TestPrinter->getMS().SwitchSection(Sec);
+ TestPrinter->getMS().emitLabel(Val);
+ return true;
+ }
+
+ MCSymbol *Val = nullptr;
+ MCSection *Sec = nullptr;
+ MCSymbol *SecBeginSymbol = nullptr;
+};
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFF) {
+ if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ EXPECT_CALL(TestPrinter->getMS(), EmitCOFFSecRel32(Val, 0));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
+}
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFFForceOffset) {
+ if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ EXPECT_CALL(TestPrinter->getMS(),
+ emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
+}
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
+
+ const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
+}
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32ForceOffset) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ EXPECT_CALL(TestPrinter->getMS(),
+ emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
+}
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
+
+ const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
+}
+
+TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64ForceOffset) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
+ return;
+
+ EXPECT_CALL(TestPrinter->getMS(),
+ emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 8));
+ TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
+}
+
+class AsmPrinterEmitDwarfStringOffsetTest : public AsmPrinterFixtureBase {
+protected:
+ bool init(const std::string &TripleStr, unsigned DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
+ return false;
+
+ Val.Index = DwarfStringPoolEntry::NotIndexed;
+ Val.Symbol = TestPrinter->getCtx().createTempSymbol();
+ Val.Offset = 42;
+ return true;
+ }
+
+ DwarfStringPoolEntry Val;
+};
+
+TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF32) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfStringOffset(Val);
+
+ const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
+}
+
+TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
+ DWARF32NoRelocationsAcrossSections) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
+ EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 4));
+ TestPrinter->getAP()->emitDwarfStringOffset(Val);
+}
+
+TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF64) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfStringOffset(Val);
+
+ const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
+}
+
+TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
+ DWARF64NoRelocationsAcrossSections) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
+ return;
+
+ TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
+ EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 8));
+ TestPrinter->getAP()->emitDwarfStringOffset(Val);
+}
+
+class AsmPrinterEmitDwarfOffsetTest : public AsmPrinterFixtureBase {
+protected:
+ bool init(const std::string &TripleStr, unsigned DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
+ return false;
+
+ Label = TestPrinter->getCtx().createTempSymbol();
+ return true;
+ }
+
+ MCSymbol *Label = nullptr;
+ uint64_t Offset = 42;
+};
+
+TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF32) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
+
+ const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
+
+ const MCSymbolRefExpr *ActualLHS =
+ dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
+ ASSERT_NE(ActualLHS, nullptr);
+ EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
+
+ const MCConstantExpr *ActualRHS =
+ dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());
+ ASSERT_NE(ActualRHS, nullptr);
+ EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);
+}
+
+TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF64) {
+ if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
+ return;
+
+ const MCExpr *Arg0 = nullptr;
+ EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
+ .WillOnce(SaveArg<0>(&Arg0));
+ TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
+
+ const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
+ ASSERT_NE(ActualArg0, nullptr);
+ EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
+
+ const MCSymbolRefExpr *ActualLHS =
+ dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
+ ASSERT_NE(ActualLHS, nullptr);
+ EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
+
+ const MCConstantExpr *ActualRHS =
+ dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());
+ ASSERT_NE(ActualRHS, nullptr);
+ EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);
+}
+
+} // end namespace
diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
index 831eb66e82cf..3af8b7f74297 100644
--- a/llvm/unittests/CodeGen/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/CMakeLists.txt
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(CodeGenTests
AArch64SelectionDAGTest.cpp
+ AsmPrinterDwarfTest.cpp
DIEHashTest.cpp
LowLevelTypeTest.cpp
LexicalScopesTest.cpp
@@ -25,6 +26,9 @@ add_llvm_unittest(CodeGenTests
ScalableVectorMVTsTest.cpp
TypeTraitsTest.cpp
TargetOptionsTest.cpp
+ TestAsmPrinter.cpp
)
add_subdirectory(GlobalISel)
+
+target_link_libraries(CodeGenTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/CodeGen/TestAsmPrinter.cpp b/llvm/unittests/CodeGen/TestAsmPrinter.cpp
new file mode 100644
index 000000000000..7d0420206768
--- /dev/null
+++ b/llvm/unittests/CodeGen/TestAsmPrinter.cpp
@@ -0,0 +1,88 @@
+//===--- unittests/CodeGen/TestAsmPrinter.cpp -------------------*- C++ -*-===//
+//
+// 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 "TestAsmPrinter.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+using ::testing::StrictMock;
+
+// Note: a non-const reference argument cannot be passed through
+// testing::StrictMock, thus, we pass a pointer and dereference it here.
+MockMCStreamer::MockMCStreamer(MCContext *Ctx) : MCStreamer(*Ctx) {}
+
+MockMCStreamer::~MockMCStreamer() = default;
+
+TestAsmPrinter::TestAsmPrinter() = default;
+
+TestAsmPrinter::~TestAsmPrinter() = default;
+
+llvm::Expected<std::unique_ptr<TestAsmPrinter>>
+TestAsmPrinter::create(const std::string &TripleStr, uint16_t DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ std::string ErrorStr;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrorStr);
+ if (!TheTarget)
+ return std::unique_ptr<TestAsmPrinter>();
+
+ std::unique_ptr<TestAsmPrinter> TestPrinter(new TestAsmPrinter);
+ if (llvm::Error E =
+ TestPrinter->init(TheTarget, TripleStr, DwarfVersion, DwarfFormat))
+ return std::move(E);
+
+ return std::move(TestPrinter);
+}
+
+// Note:: based on dwarfgen::Generator::init() from
+// llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
+llvm::Error TestAsmPrinter::init(const Target *TheTarget, StringRef TripleName,
+ uint16_t DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat) {
+ TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
+ None));
+ if (!TM)
+ return make_error<StringError>("no target machine for target " + TripleName,
+ inconvertibleErrorCode());
+
+ MC.reset(new MCContext(TM->getMCAsmInfo(), TM->getMCRegisterInfo(),
+ TM->getObjFileLowering()));
+ TM->getObjFileLowering()->Initialize(*MC, *TM);
+
+ MS = new StrictMock<MockMCStreamer>(MC.get());
+
+ Asm.reset(
+ TheTarget->createAsmPrinter(*TM, std::unique_ptr<MockMCStreamer>(MS)));
+ if (!Asm)
+ return make_error<StringError>("no asm printer for target " + TripleName,
+ inconvertibleErrorCode());
+
+ // Set the DWARF version correctly on all classes that we use.
+ MC->setDwarfVersion(DwarfVersion);
+ Asm->setDwarfVersion(DwarfVersion);
+
+ // Set the DWARF format.
+ MC->setDwarfFormat(DwarfFormat);
+
+ return Error::success();
+}
+
+void TestAsmPrinter::setDwarfUsesRelocationsAcrossSections(bool Enable) {
+ struct HackMCAsmInfo : MCAsmInfo {
+ void setDwarfUsesRelocationsAcrossSections(bool Enable) {
+ DwarfUsesRelocationsAcrossSections = Enable;
+ }
+ };
+ static_cast<HackMCAsmInfo *>(const_cast<MCAsmInfo *>(TM->getMCAsmInfo()))
+ ->setDwarfUsesRelocationsAcrossSections(Enable);
+}
diff --git a/llvm/unittests/CodeGen/TestAsmPrinter.h b/llvm/unittests/CodeGen/TestAsmPrinter.h
new file mode 100644
index 000000000000..65e557b9b4a6
--- /dev/null
+++ b/llvm/unittests/CodeGen/TestAsmPrinter.h
@@ -0,0 +1,82 @@
+//===--- unittests/CodeGen/TestAsmPrinter.h ---------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UNITTESTS_CODEGEN_TESTASMPRINTER_H
+#define LLVM_UNITTESTS_CODEGEN_TESTASMPRINTER_H
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/MC/MCStreamer.h"
+#include "gmock/gmock.h"
+
+#include <memory>
+
+namespace llvm {
+class AsmPrinter;
+class MCContext;
+class Target;
+class TargetMachine;
+
+class MockMCStreamer : public MCStreamer {
+public:
+ explicit MockMCStreamer(MCContext *Ctx);
+ ~MockMCStreamer();
+
+ // These methods are pure virtual in MCStreamer, thus, have to be overridden:
+
+ MOCK_METHOD2(emitSymbolAttribute,
+ bool(MCSymbol *Symbol, MCSymbolAttr Attribute));
+ MOCK_METHOD3(emitCommonSymbol,
+ void(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment));
+ MOCK_METHOD5(emitZerofill,
+ void(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment, SMLoc Loc));
+
+ // The following are mock methods to be used in tests.
+
+ MOCK_METHOD2(emitIntValue, void(uint64_t Value, unsigned Size));
+ MOCK_METHOD3(emitValueImpl,
+ void(const MCExpr *Value, unsigned Size, SMLoc Loc));
+ MOCK_METHOD3(emitAbsoluteSymbolDiff,
+ void(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size));
+ MOCK_METHOD2(EmitCOFFSecRel32, void(MCSymbol const *Symbol, uint64_t Offset));
+};
+
+class TestAsmPrinter {
+ std::unique_ptr<MCContext> MC;
+ MockMCStreamer *MS = nullptr; // Owned by AsmPrinter
+ std::unique_ptr<TargetMachine> TM;
+ std::unique_ptr<AsmPrinter> Asm;
+
+ /// Private constructor; call TestAsmPrinter::create(...)
+ /// to create an instance.
+ TestAsmPrinter();
+
+ /// Initialize an AsmPrinter instance with a mocked MCStreamer.
+ llvm::Error init(const Target *TheTarget, StringRef TripleStr,
+ uint16_t DwarfVersion, dwarf::DwarfFormat DwarfFormat);
+
+public:
+ /// Create an AsmPrinter and accompanied objects.
+ /// Returns ErrorSuccess() with an empty value if the requested target is not
+ /// supported so that the corresponding test can be gracefully skipped.
+ static llvm::Expected<std::unique_ptr<TestAsmPrinter>>
+ create(const std::string &TripleStr, uint16_t DwarfVersion,
+ dwarf::DwarfFormat DwarfFormat);
+
+ ~TestAsmPrinter();
+
+ void setDwarfUsesRelocationsAcrossSections(bool Enable);
+
+ AsmPrinter *getAP() const { return Asm.get(); }
+ MCContext &getCtx() const { return *MC; }
+ MockMCStreamer &getMS() const { return *MS; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_UNITTESTS_CODEGEN_TESTASMPRINTER_H
More information about the llvm-commits
mailing list