1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00
llvm-mirror/unittests/CodeGen/AsmPrinterDwarfTest.cpp
Jameson Nash 11a667f122 make the AsmPrinterHandler array public
This lets external consumers customize the output, similar to how
AssemblyAnnotationWriter lets the caller define callbacks when printing
IR. The array of handlers already existed, this just cleans up the code
so that it can be exposed publically.

Replaces https://reviews.llvm.org/D74158

Differential Revision: https://reviews.llvm.org/D89613
2020-11-03 10:02:09 -05:00

430 lines
14 KiB
C++

//===- 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/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Testing/Support/Error.h"
using namespace llvm;
using testing::_;
using testing::InSequence;
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);
}
class AsmPrinterEmitDwarfLengthOrOffsetTest : public AsmPrinterFixtureBase {
protected:
uint64_t Val = 42;
};
TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF32) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));
TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);
}
TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF64) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
return;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));
TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);
}
class AsmPrinterGetUnitLengthFieldByteSizeTest : public AsmPrinterFixtureBase {
};
TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF32) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 4u);
}
TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF64) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
return;
EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 12u);
}
class AsmPrinterMaybeEmitDwarf64MarkTest : public AsmPrinterFixtureBase {};
TEST_F(AsmPrinterMaybeEmitDwarf64MarkTest, DWARF32) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(_, _)).Times(0);
TestPrinter->getAP()->maybeEmitDwarf64Mark();
}
TEST_F(AsmPrinterMaybeEmitDwarf64MarkTest, DWARF64) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
return;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));
TestPrinter->getAP()->maybeEmitDwarf64Mark();
}
class AsmPrinterEmitDwarfUnitLengthAsIntTest : public AsmPrinterFixtureBase {
protected:
uint64_t Val = 42;
};
TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF32) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));
TestPrinter->getAP()->emitDwarfUnitLength(Val, "");
}
TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF64) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
return;
InSequence S;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));
TestPrinter->getAP()->emitDwarfUnitLength(Val, "");
}
class AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest
: public AsmPrinterFixtureBase {
protected:
bool init(const std::string &TripleStr, unsigned DwarfVersion,
dwarf::DwarfFormat DwarfFormat) {
if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
return false;
Hi = TestPrinter->getCtx().createTempSymbol();
Lo = TestPrinter->getCtx().createTempSymbol();
return true;
}
MCSymbol *Hi = nullptr;
MCSymbol *Lo = nullptr;
};
TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF32) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(Hi, Lo, 4));
TestPrinter->getAP()->emitDwarfUnitLength(Hi, Lo, "");
}
TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF64) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
return;
InSequence S;
EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));
EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(Hi, Lo, 8));
TestPrinter->getAP()->emitDwarfUnitLength(Hi, Lo, "");
}
class AsmPrinterHandlerTest : public AsmPrinterFixtureBase {
class TestHandler : public AsmPrinterHandler {
AsmPrinterHandlerTest &Test;
public:
TestHandler(AsmPrinterHandlerTest &Test) : Test(Test) {}
virtual ~TestHandler() {}
virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
virtual void beginModule(Module *M) override { Test.BeginCount++; }
virtual void endModule() override { Test.EndCount++; }
virtual void beginFunction(const MachineFunction *MF) override {}
virtual void endFunction(const MachineFunction *MF) override {}
virtual void beginInstruction(const MachineInstr *MI) override {}
virtual void endInstruction() override {}
};
protected:
bool init(const std::string &TripleStr, unsigned DwarfVersion,
dwarf::DwarfFormat DwarfFormat) {
if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
return false;
auto *AP = TestPrinter->getAP();
AP->addAsmPrinterHandler(AsmPrinter::HandlerInfo(
std::unique_ptr<AsmPrinterHandler>(new TestHandler(*this)),
"TestTimerName", "TestTimerDesc", "TestGroupName", "TestGroupDesc"));
LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(&AP->TM);
legacy::PassManager PM;
PM.add(new MachineModuleInfoWrapperPass(LLVMTM));
PM.add(TestPrinter->releaseAP()); // Takes ownership of destroying AP
LLVMContext Context;
std::unique_ptr<Module> M(new Module("TestModule", Context));
M->setDataLayout(LLVMTM->createDataLayout());
PM.run(*M);
// Now check that we can run it twice.
AP->addAsmPrinterHandler(AsmPrinter::HandlerInfo(
std::unique_ptr<AsmPrinterHandler>(new TestHandler(*this)),
"TestTimerName", "TestTimerDesc", "TestGroupName", "TestGroupDesc"));
PM.run(*M);
return true;
}
int BeginCount = 0;
int EndCount = 0;
};
TEST_F(AsmPrinterHandlerTest, Basic) {
if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
return;
ASSERT_EQ(BeginCount, 3);
ASSERT_EQ(EndCount, 3);
}
} // end namespace