[MemProf] Templatize CallStackRadixTreeBuilder (NFC) (#117014)
[llvm-project.git] / llvm / unittests / CodeGen / AsmPrinterDwarfTest.cpp
blobdc738d85547bbc6991de441131c5b4a322431880
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-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm;
24 using testing::_;
25 using testing::DoAll;
26 using testing::InSequence;
27 using testing::SaveArg;
29 namespace {
31 class 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());
40 protected:
41 bool init(const std::string &TripleStr, unsigned DwarfVersion,
42 dwarf::DwarfFormat DwarfFormat) {
43 setupTestPrinter(TripleStr, DwarfVersion, DwarfFormat);
44 return TestPrinter != nullptr;
47 std::unique_ptr<TestAsmPrinter> TestPrinter;
50 class AsmPrinterEmitDwarfSymbolReferenceTest : public AsmPrinterFixtureBase {
51 protected:
52 bool init(const std::string &TripleStr, unsigned DwarfVersion,
53 dwarf::DwarfFormat DwarfFormat) {
54 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
55 return false;
57 // AsmPrinter::emitDwarfSymbolReference(Label, true) gets the associated
58 // section from `Label` to find its BeginSymbol.
59 // Prepare the test symbol `Val` accordingly.
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());
68 return true;
71 MCSymbol *Val = nullptr;
72 MCSymbol *SecBeginSymbol = nullptr;
75 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFF) {
76 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
77 GTEST_SKIP();
79 EXPECT_CALL(TestPrinter->getMS(), emitCOFFSecRel32(Val, 0));
80 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
83 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFFForceOffset) {
84 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
85 GTEST_SKIP();
87 EXPECT_CALL(TestPrinter->getMS(),
88 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
89 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
92 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32) {
93 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
94 GTEST_SKIP();
96 const MCExpr *Arg0 = nullptr;
97 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
98 .WillOnce(SaveArg<0>(&Arg0));
99 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
101 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
102 ASSERT_NE(ActualArg0, nullptr);
103 EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
106 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32ForceOffset) {
107 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
108 GTEST_SKIP();
110 EXPECT_CALL(TestPrinter->getMS(),
111 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
112 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
115 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64) {
116 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
117 GTEST_SKIP();
119 const MCExpr *Arg0 = nullptr;
120 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
121 .WillOnce(SaveArg<0>(&Arg0));
122 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
124 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
125 ASSERT_NE(ActualArg0, nullptr);
126 EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
129 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64ForceOffset) {
130 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
131 GTEST_SKIP();
133 EXPECT_CALL(TestPrinter->getMS(),
134 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 8));
135 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
138 class AsmPrinterEmitDwarfStringOffsetTest : public AsmPrinterFixtureBase {
139 protected:
140 bool init(const std::string &TripleStr, unsigned DwarfVersion,
141 dwarf::DwarfFormat DwarfFormat) {
142 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
143 return false;
145 Val.Index = DwarfStringPoolEntry::NotIndexed;
146 Val.Symbol = TestPrinter->getCtx().createTempSymbol();
147 Val.Offset = 42;
148 return true;
151 DwarfStringPoolEntry Val;
154 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF32) {
155 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
156 GTEST_SKIP();
158 const MCExpr *Arg0 = nullptr;
159 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
160 .WillOnce(SaveArg<0>(&Arg0));
161 TestPrinter->getAP()->emitDwarfStringOffset(Val);
163 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
164 ASSERT_NE(ActualArg0, nullptr);
165 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
168 TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
169 DWARF32NoRelocationsAcrossSections) {
170 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
171 GTEST_SKIP();
173 TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
174 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 4));
175 TestPrinter->getAP()->emitDwarfStringOffset(Val);
178 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF64) {
179 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
180 GTEST_SKIP();
182 const MCExpr *Arg0 = nullptr;
183 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
184 .WillOnce(SaveArg<0>(&Arg0));
185 TestPrinter->getAP()->emitDwarfStringOffset(Val);
187 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
188 ASSERT_NE(ActualArg0, nullptr);
189 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
192 TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
193 DWARF64NoRelocationsAcrossSections) {
194 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
195 GTEST_SKIP();
197 TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
198 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 8));
199 TestPrinter->getAP()->emitDwarfStringOffset(Val);
202 class AsmPrinterEmitDwarfOffsetTest : public AsmPrinterFixtureBase {
203 protected:
204 bool init(const std::string &TripleStr, unsigned DwarfVersion,
205 dwarf::DwarfFormat DwarfFormat) {
206 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
207 return false;
209 Label = TestPrinter->getCtx().createTempSymbol();
210 return true;
213 MCSymbol *Label = nullptr;
214 uint64_t Offset = 42;
217 TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF32) {
218 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
219 GTEST_SKIP();
221 const MCExpr *Arg0 = nullptr;
222 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
223 .WillOnce(SaveArg<0>(&Arg0));
224 TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
226 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
227 ASSERT_NE(ActualArg0, nullptr);
228 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
230 const MCSymbolRefExpr *ActualLHS =
231 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
232 ASSERT_NE(ActualLHS, nullptr);
233 EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
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);
241 TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF64) {
242 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
243 GTEST_SKIP();
245 const MCExpr *Arg0 = nullptr;
246 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
247 .WillOnce(SaveArg<0>(&Arg0));
248 TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
250 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
251 ASSERT_NE(ActualArg0, nullptr);
252 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
254 const MCSymbolRefExpr *ActualLHS =
255 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
256 ASSERT_NE(ActualLHS, nullptr);
257 EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
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);
265 class AsmPrinterEmitDwarfLengthOrOffsetTest : public AsmPrinterFixtureBase {
266 protected:
267 uint64_t Val = 42;
270 TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF32) {
271 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
272 GTEST_SKIP();
274 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));
275 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);
278 TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF64) {
279 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
280 GTEST_SKIP();
282 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));
283 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val);
286 class AsmPrinterGetUnitLengthFieldByteSizeTest : public AsmPrinterFixtureBase {
289 TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF32) {
290 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
291 GTEST_SKIP();
293 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 4u);
296 TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF64) {
297 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
298 GTEST_SKIP();
300 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 12u);
303 class AsmPrinterEmitDwarfUnitLengthAsIntTest : public AsmPrinterFixtureBase {
304 protected:
305 uint64_t Val = 42;
308 TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF32) {
309 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
310 GTEST_SKIP();
312 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4));
313 TestPrinter->getAP()->emitDwarfUnitLength(Val, "");
316 TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF64) {
317 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
318 GTEST_SKIP();
320 InSequence S;
321 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4));
322 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8));
324 TestPrinter->getAP()->emitDwarfUnitLength(Val, "");
327 class AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest
328 : public AsmPrinterFixtureBase {
329 protected:
330 bool init(const std::string &TripleStr, unsigned DwarfVersion,
331 dwarf::DwarfFormat DwarfFormat) {
332 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
333 return false;
335 return true;
339 TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF32) {
340 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
341 GTEST_SKIP();
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>(&LTmp));
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);
359 TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF64) {
360 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
361 GTEST_SKIP();
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>(&LTmp));
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);
380 class AsmPrinterHandlerTest : public AsmPrinterFixtureBase {
381 class TestHandler : public AsmPrinterHandler {
382 AsmPrinterHandlerTest &Test;
384 public:
385 TestHandler(AsmPrinterHandlerTest &Test) : Test(Test) {}
386 virtual ~TestHandler() {}
387 virtual void beginModule(Module *M) override { Test.BeginCount++; }
388 virtual void endModule() override { Test.EndCount++; }
389 virtual void beginFunction(const MachineFunction *MF) override {}
390 virtual void endFunction(const MachineFunction *MF) override {}
393 protected:
394 bool init(const std::string &TripleStr, unsigned DwarfVersion,
395 dwarf::DwarfFormat DwarfFormat) {
396 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
397 return false;
399 auto *AP = TestPrinter->getAP();
400 AP->addAsmPrinterHandler(std::make_unique<TestHandler>(*this));
401 TargetMachine *TM = &AP->TM;
402 legacy::PassManager PM;
403 PM.add(new MachineModuleInfoWrapperPass(TM));
404 PM.add(TestPrinter->releaseAP()); // Takes ownership of destroying AP
405 LLVMContext Context;
406 std::unique_ptr<Module> M(new Module("TestModule", Context));
407 M->setDataLayout(TM->createDataLayout());
408 PM.run(*M);
409 // Now check that we can run it twice.
410 AP->addAsmPrinterHandler(std::make_unique<TestHandler>(*this));
411 PM.run(*M);
412 return true;
415 int BeginCount = 0;
416 int EndCount = 0;
419 TEST_F(AsmPrinterHandlerTest, Basic) {
420 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
421 GTEST_SKIP();
423 ASSERT_EQ(BeginCount, 3);
424 ASSERT_EQ(EndCount, 3);
427 class AsmPrinterDebugHandlerTest : public AsmPrinterFixtureBase {
428 class TestDebugHandler : public DebugHandlerBase {
429 AsmPrinterDebugHandlerTest &Test;
431 public:
432 TestDebugHandler(AsmPrinterDebugHandlerTest &Test, AsmPrinter *AP)
433 : DebugHandlerBase(AP), Test(Test) {}
434 virtual ~TestDebugHandler() {}
435 virtual void beginModule(Module *M) override { Test.BeginCount++; }
436 virtual void endModule() override { Test.EndCount++; }
437 virtual void beginFunctionImpl(const MachineFunction *MF) override {}
438 virtual void endFunctionImpl(const MachineFunction *MF) override {}
439 virtual void beginInstruction(const MachineInstr *MI) override {}
440 virtual void endInstruction() override {}
443 protected:
444 bool init(const std::string &TripleStr, unsigned DwarfVersion,
445 dwarf::DwarfFormat DwarfFormat) {
446 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
447 return false;
449 auto *AP = TestPrinter->getAP();
450 AP->addDebugHandler(std::make_unique<TestDebugHandler>(*this, AP));
451 TargetMachine *TM = &AP->TM;
452 legacy::PassManager PM;
453 PM.add(new MachineModuleInfoWrapperPass(TM));
454 PM.add(TestPrinter->releaseAP()); // Takes ownership of destroying AP
455 LLVMContext Context;
456 std::unique_ptr<Module> M(new Module("TestModule", Context));
457 M->setDataLayout(TM->createDataLayout());
458 PM.run(*M);
459 // Now check that we can run it twice.
460 AP->addDebugHandler(std::make_unique<TestDebugHandler>(*this, AP));
461 PM.run(*M);
462 return true;
465 int BeginCount = 0;
466 int EndCount = 0;
469 TEST_F(AsmPrinterDebugHandlerTest, Basic) {
470 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
471 GTEST_SKIP();
473 ASSERT_EQ(BeginCount, 3);
474 ASSERT_EQ(EndCount, 3);
477 } // end namespace