431 lines · cpp
1//===- llvm/unittest/CodeGen/AsmPrinterDwarfTest.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 "TestAsmPrinter.h"10#include "llvm/BinaryFormat/ELF.h"11#include "llvm/CodeGen/AsmPrinter.h"12#include "llvm/CodeGen/AsmPrinterHandler.h"13#include "llvm/CodeGen/DebugHandlerBase.h"14#include "llvm/CodeGen/MachineModuleInfo.h"15#include "llvm/IR/LegacyPassManager.h"16#include "llvm/IR/Module.h"17#include "llvm/IR/PassManager.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCSectionELF.h"20#include "llvm/Target/TargetMachine.h"21#include "llvm/Testing/Support/Error.h"22 23using namespace llvm;24using testing::_;25using testing::DoAll;26using testing::InSequence;27using testing::SaveArg;28 29namespace {30 31class AsmPrinterFixtureBase : public testing::Test {32 void setupTestPrinter(const std::string &TripleStr, unsigned DwarfVersion,33 dwarf::DwarfFormat DwarfFormat) {34 auto ExpectedTestPrinter =35 TestAsmPrinter::create(TripleStr, DwarfVersion, DwarfFormat);36 ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded());37 TestPrinter = std::move(ExpectedTestPrinter.get());38 }39 40protected:41 bool init(const std::string &TripleStr, unsigned DwarfVersion,42 dwarf::DwarfFormat DwarfFormat) {43 setupTestPrinter(TripleStr, DwarfVersion, DwarfFormat);44 return TestPrinter != nullptr;45 }46 47 std::unique_ptr<TestAsmPrinter> TestPrinter;48};49 50class AsmPrinterEmitDwarfSymbolReferenceTest : public AsmPrinterFixtureBase {51protected:52 bool init(const std::string &TripleStr, unsigned DwarfVersion,53 dwarf::DwarfFormat DwarfFormat) {54 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))55 return false;56 57 // AsmPrinter::emitDwarfSymbolReference(Label, true) gets the associated58 // section from `Label` to find its BeginSymbol.59 // Prepare the test symbol `Val` accordingly.60 61 Val = TestPrinter->getCtx().createTempSymbol();62 MCSection *Sec =63 TestPrinter->getCtx().getELFSection(".tst", ELF::SHT_PROGBITS, 0);64 SecBeginSymbol = Sec->getBeginSymbol();65 TestPrinter->getMS().switchSection(Sec);66 Val->setFragment(&Sec->getDummyFragment());67 68 return true;69 }70 71 MCSymbol *Val = nullptr;72 MCSymbol *SecBeginSymbol = nullptr;73};74 75TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFF) {76 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))77 GTEST_SKIP();78 79 EXPECT_CALL(TestPrinter->getMS(), emitCOFFSecRel32(Val, 0));80 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);81}82 83TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFFForceOffset) {84 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))85 GTEST_SKIP();86 87 EXPECT_CALL(TestPrinter->getMS(),88 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));89 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);90}91 92TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32) {93 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))94 GTEST_SKIP();95 96 const MCExpr *Arg0 = nullptr;97 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))98 .WillOnce(SaveArg<0>(&Arg0));99 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);100 101 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);102 ASSERT_NE(ActualArg0, nullptr);103 EXPECT_EQ(&(ActualArg0->getSymbol()), Val);104}105 106TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32ForceOffset) {107 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))108 GTEST_SKIP();109 110 EXPECT_CALL(TestPrinter->getMS(),111 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));112 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);113}114 115TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64) {116 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))117 GTEST_SKIP();118 119 const MCExpr *Arg0 = nullptr;120 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))121 .WillOnce(SaveArg<0>(&Arg0));122 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);123 124 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);125 ASSERT_NE(ActualArg0, nullptr);126 EXPECT_EQ(&(ActualArg0->getSymbol()), Val);127}128 129TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64ForceOffset) {130 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))131 GTEST_SKIP();132 133 EXPECT_CALL(TestPrinter->getMS(),134 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 8));135 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);136}137 138class AsmPrinterEmitDwarfStringOffsetTest : public AsmPrinterFixtureBase {139protected:140 bool init(const std::string &TripleStr, unsigned DwarfVersion,141 dwarf::DwarfFormat DwarfFormat) {142 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))143 return false;144 145 Val.Index = DwarfStringPoolEntry::NotIndexed;146 Val.Symbol = TestPrinter->getCtx().createTempSymbol();147 Val.Offset = 42;148 return true;149 }150 151 DwarfStringPoolEntry Val;152};153 154TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF32) {155 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))156 GTEST_SKIP();157 158 const MCExpr *Arg0 = nullptr;159 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))160 .WillOnce(SaveArg<0>(&Arg0));161 TestPrinter->getAP()->emitDwarfStringOffset(Val);162 163 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);164 ASSERT_NE(ActualArg0, nullptr);165 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);166}167 168TEST_F(AsmPrinterEmitDwarfStringOffsetTest,169 DWARF32NoRelocationsAcrossSections) {170 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))171 GTEST_SKIP();172 173 TestPrinter->setDwarfUsesRelocationsAcrossSections(false);174 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 4));175 TestPrinter->getAP()->emitDwarfStringOffset(Val);176}177 178TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF64) {179 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))180 GTEST_SKIP();181 182 const MCExpr *Arg0 = nullptr;183 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))184 .WillOnce(SaveArg<0>(&Arg0));185 TestPrinter->getAP()->emitDwarfStringOffset(Val);186 187 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);188 ASSERT_NE(ActualArg0, nullptr);189 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);190}191 192TEST_F(AsmPrinterEmitDwarfStringOffsetTest,193 DWARF64NoRelocationsAcrossSections) {194 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))195 GTEST_SKIP();196 197 TestPrinter->setDwarfUsesRelocationsAcrossSections(false);198 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 8));199 TestPrinter->getAP()->emitDwarfStringOffset(Val);200}201 202class AsmPrinterEmitDwarfOffsetTest : public AsmPrinterFixtureBase {203protected:204 bool init(const std::string &TripleStr, unsigned DwarfVersion,205 dwarf::DwarfFormat DwarfFormat) {206 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))207 return false;208 209 Label = TestPrinter->getCtx().createTempSymbol();210 return true;211 }212 213 MCSymbol *Label = nullptr;214 uint64_t Offset = 42;215};216 217TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF32) {218 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))219 GTEST_SKIP();220 221 const MCExpr *Arg0 = nullptr;222 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))223 .WillOnce(SaveArg<0>(&Arg0));224 TestPrinter->getAP()->emitDwarfOffset(Label, Offset);225 226 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);227 ASSERT_NE(ActualArg0, nullptr);228 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);229 230 const MCSymbolRefExpr *ActualLHS =231 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());232 ASSERT_NE(ActualLHS, nullptr);233 EXPECT_EQ(&(ActualLHS->getSymbol()), Label);234 235 const MCConstantExpr *ActualRHS =236 dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());237 ASSERT_NE(ActualRHS, nullptr);238 EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);239}240 241TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF64) {242 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))243 GTEST_SKIP();244 245 const MCExpr *Arg0 = nullptr;246 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))247 .WillOnce(SaveArg<0>(&Arg0));248 TestPrinter->getAP()->emitDwarfOffset(Label, Offset);249 250 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);251 ASSERT_NE(ActualArg0, nullptr);252 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);253 254 const MCSymbolRefExpr *ActualLHS =255 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());256 ASSERT_NE(ActualLHS, nullptr);257 EXPECT_EQ(&(ActualLHS->getSymbol()), Label);258 259 const MCConstantExpr *ActualRHS =260 dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());261 ASSERT_NE(ActualRHS, nullptr);262 EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);263}264 265class AsmPrinterEmitDwarfLengthOrOffsetTest : public AsmPrinterFixtureBase {266protected:267 uint64_t Val = 42;268};269 270TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF32) {271 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))272 GTEST_SKIP();273 274 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));275 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);276}277 278TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF64) {279 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))280 GTEST_SKIP();281 282 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));283 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);284}285 286class AsmPrinterGetUnitLengthFieldByteSizeTest : public AsmPrinterFixtureBase {287};288 289TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF32) {290 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))291 GTEST_SKIP();292 293 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 4u);294}295 296TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF64) {297 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))298 GTEST_SKIP();299 300 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 12u);301}302 303class AsmPrinterEmitDwarfUnitLengthAsIntTest : public AsmPrinterFixtureBase {304protected:305 uint64_t Val = 42;306};307 308TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF32) {309 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))310 GTEST_SKIP();311 312 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));313 TestPrinter->getAP()->emitDwarfUnitLength(Val, "");314}315 316TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF64) {317 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))318 GTEST_SKIP();319 320 InSequence S;321 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));322 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));323 324 TestPrinter->getAP()->emitDwarfUnitLength(Val, "");325}326 327class AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest328 : public AsmPrinterFixtureBase {329protected:330 bool init(const std::string &TripleStr, unsigned DwarfVersion,331 dwarf::DwarfFormat DwarfFormat) {332 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))333 return false;334 335 return true;336 }337};338 339TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF32) {340 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))341 GTEST_SKIP();342 343 InSequence S;344 const MCSymbol *Hi = nullptr;345 const MCSymbol *Lo = nullptr;346 EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(_, _, 4))347 .WillOnce(DoAll(SaveArg<0>(&Hi), SaveArg<1>(&Lo)));348 MCSymbol *LTmp = nullptr;349 EXPECT_CALL(TestPrinter->getMS(), emitLabel(_, _))350 .WillOnce(SaveArg<0>(<mp));351 352 MCSymbol *HTmp = TestPrinter->getAP()->emitDwarfUnitLength("", "");353 EXPECT_NE(Lo, nullptr);354 EXPECT_EQ(Lo, LTmp);355 EXPECT_NE(Hi, nullptr);356 EXPECT_EQ(Hi, HTmp);357}358 359TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF64) {360 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))361 GTEST_SKIP();362 363 InSequence S;364 const MCSymbol *Hi = nullptr;365 const MCSymbol *Lo = nullptr;366 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));367 EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(_, _, 8))368 .WillOnce(DoAll(SaveArg<0>(&Hi), SaveArg<1>(&Lo)));369 MCSymbol *LTmp = nullptr;370 EXPECT_CALL(TestPrinter->getMS(), emitLabel(_, _))371 .WillOnce(SaveArg<0>(<mp));372 373 MCSymbol *HTmp = TestPrinter->getAP()->emitDwarfUnitLength("", "");374 EXPECT_NE(Lo, nullptr);375 EXPECT_EQ(Lo, LTmp);376 EXPECT_NE(Hi, nullptr);377 EXPECT_EQ(Hi, HTmp);378}379 380class AsmPrinterHandlerTest : public AsmPrinterFixtureBase {381 class TestHandler : public AsmPrinterHandler {382 AsmPrinterHandlerTest &Test;383 384 public:385 TestHandler(AsmPrinterHandlerTest &Test) : Test(Test) {}386 ~TestHandler() override = default;387 void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}388 void beginModule(Module *M) override { Test.BeginCount++; }389 void endModule() override { Test.EndCount++; }390 void beginFunction(const MachineFunction *MF) override {}391 void endFunction(const MachineFunction *MF) override {}392 void beginInstruction(const MachineInstr *MI) override {}393 void endInstruction() override {}394 };395 396protected:397 bool init(const std::string &TripleStr, unsigned DwarfVersion,398 dwarf::DwarfFormat DwarfFormat) {399 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))400 return false;401 402 auto *AP = TestPrinter->getAP();403 AP->addAsmPrinterHandler(std::make_unique<TestHandler>(*this));404 TargetMachine *TM = &AP->TM;405 legacy::PassManager PM;406 PM.add(new MachineModuleInfoWrapperPass(TM));407 PM.add(TestPrinter->releaseAP()); // Takes ownership of destroying AP408 LLVMContext Context;409 std::unique_ptr<Module> M(new Module("TestModule", Context));410 M->setDataLayout(TM->createDataLayout());411 PM.run(*M);412 // Now check that we can run it twice.413 AP->addAsmPrinterHandler(std::make_unique<TestHandler>(*this));414 PM.run(*M);415 return true;416 }417 418 int BeginCount = 0;419 int EndCount = 0;420};421 422TEST_F(AsmPrinterHandlerTest, Basic) {423 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))424 GTEST_SKIP();425 426 ASSERT_EQ(BeginCount, 3);427 ASSERT_EQ(EndCount, 3);428}429 430} // end namespace431