1*380e746bSIgor Kudrin //===- llvm/unittest/CodeGen/AsmPrinterDwarfTest.cpp ----------------------===//
2*380e746bSIgor Kudrin //
3*380e746bSIgor Kudrin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*380e746bSIgor Kudrin // See https://llvm.org/LICENSE.txt for license information.
5*380e746bSIgor Kudrin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*380e746bSIgor Kudrin //
7*380e746bSIgor Kudrin //===----------------------------------------------------------------------===//
8*380e746bSIgor Kudrin 
9*380e746bSIgor Kudrin #include "TestAsmPrinter.h"
10*380e746bSIgor Kudrin #include "llvm/CodeGen/AsmPrinter.h"
11*380e746bSIgor Kudrin #include "llvm/MC/MCContext.h"
12*380e746bSIgor Kudrin #include "llvm/MC/MCSectionELF.h"
13*380e746bSIgor Kudrin #include "llvm/Testing/Support/Error.h"
14*380e746bSIgor Kudrin 
15*380e746bSIgor Kudrin using namespace llvm;
16*380e746bSIgor Kudrin using testing::_;
17*380e746bSIgor Kudrin using testing::SaveArg;
18*380e746bSIgor Kudrin 
19*380e746bSIgor Kudrin namespace {
20*380e746bSIgor Kudrin 
21*380e746bSIgor Kudrin class AsmPrinterFixtureBase : public testing::Test {
22*380e746bSIgor Kudrin   void setupTestPrinter(const std::string &TripleStr, unsigned DwarfVersion,
23*380e746bSIgor Kudrin                         dwarf::DwarfFormat DwarfFormat) {
24*380e746bSIgor Kudrin     auto ExpectedTestPrinter =
25*380e746bSIgor Kudrin         TestAsmPrinter::create(TripleStr, DwarfVersion, DwarfFormat);
26*380e746bSIgor Kudrin     ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded());
27*380e746bSIgor Kudrin     TestPrinter = std::move(ExpectedTestPrinter.get());
28*380e746bSIgor Kudrin   }
29*380e746bSIgor Kudrin 
30*380e746bSIgor Kudrin protected:
31*380e746bSIgor Kudrin   bool init(const std::string &TripleStr, unsigned DwarfVersion,
32*380e746bSIgor Kudrin             dwarf::DwarfFormat DwarfFormat) {
33*380e746bSIgor Kudrin     setupTestPrinter(TripleStr, DwarfVersion, DwarfFormat);
34*380e746bSIgor Kudrin     return TestPrinter != nullptr;
35*380e746bSIgor Kudrin   }
36*380e746bSIgor Kudrin 
37*380e746bSIgor Kudrin   std::unique_ptr<TestAsmPrinter> TestPrinter;
38*380e746bSIgor Kudrin };
39*380e746bSIgor Kudrin 
40*380e746bSIgor Kudrin class AsmPrinterEmitDwarfSymbolReferenceTest : public AsmPrinterFixtureBase {
41*380e746bSIgor Kudrin protected:
42*380e746bSIgor Kudrin   bool init(const std::string &TripleStr, unsigned DwarfVersion,
43*380e746bSIgor Kudrin             dwarf::DwarfFormat DwarfFormat) {
44*380e746bSIgor Kudrin     if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
45*380e746bSIgor Kudrin       return false;
46*380e746bSIgor Kudrin 
47*380e746bSIgor Kudrin     // Create a symbol which will be emitted in the tests and associate it
48*380e746bSIgor Kudrin     // with a section because that is required in some code paths.
49*380e746bSIgor Kudrin 
50*380e746bSIgor Kudrin     Val = TestPrinter->getCtx().createTempSymbol();
51*380e746bSIgor Kudrin     Sec = TestPrinter->getCtx().getELFSection(".tst", ELF::SHT_PROGBITS, 0);
52*380e746bSIgor Kudrin     SecBeginSymbol = Sec->getBeginSymbol();
53*380e746bSIgor Kudrin     TestPrinter->getMS().SwitchSection(Sec);
54*380e746bSIgor Kudrin     TestPrinter->getMS().emitLabel(Val);
55*380e746bSIgor Kudrin     return true;
56*380e746bSIgor Kudrin   }
57*380e746bSIgor Kudrin 
58*380e746bSIgor Kudrin   MCSymbol *Val = nullptr;
59*380e746bSIgor Kudrin   MCSection *Sec = nullptr;
60*380e746bSIgor Kudrin   MCSymbol *SecBeginSymbol = nullptr;
61*380e746bSIgor Kudrin };
62*380e746bSIgor Kudrin 
63*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFF) {
64*380e746bSIgor Kudrin   if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
65*380e746bSIgor Kudrin     return;
66*380e746bSIgor Kudrin 
67*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), EmitCOFFSecRel32(Val, 0));
68*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
69*380e746bSIgor Kudrin }
70*380e746bSIgor Kudrin 
71*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFFForceOffset) {
72*380e746bSIgor Kudrin   if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32))
73*380e746bSIgor Kudrin     return;
74*380e746bSIgor Kudrin 
75*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(),
76*380e746bSIgor Kudrin               emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
77*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
78*380e746bSIgor Kudrin }
79*380e746bSIgor Kudrin 
80*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32) {
81*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
82*380e746bSIgor Kudrin     return;
83*380e746bSIgor Kudrin 
84*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
85*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
86*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
87*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
88*380e746bSIgor Kudrin 
89*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
90*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
91*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
92*380e746bSIgor Kudrin }
93*380e746bSIgor Kudrin 
94*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32ForceOffset) {
95*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
96*380e746bSIgor Kudrin     return;
97*380e746bSIgor Kudrin 
98*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(),
99*380e746bSIgor Kudrin               emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4));
100*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
101*380e746bSIgor Kudrin }
102*380e746bSIgor Kudrin 
103*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64) {
104*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
105*380e746bSIgor Kudrin     return;
106*380e746bSIgor Kudrin 
107*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
108*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
109*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
110*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, false);
111*380e746bSIgor Kudrin 
112*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
113*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
114*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualArg0->getSymbol()), Val);
115*380e746bSIgor Kudrin }
116*380e746bSIgor Kudrin 
117*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64ForceOffset) {
118*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
119*380e746bSIgor Kudrin     return;
120*380e746bSIgor Kudrin 
121*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(),
122*380e746bSIgor Kudrin               emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 8));
123*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfSymbolReference(Val, true);
124*380e746bSIgor Kudrin }
125*380e746bSIgor Kudrin 
126*380e746bSIgor Kudrin class AsmPrinterEmitDwarfStringOffsetTest : public AsmPrinterFixtureBase {
127*380e746bSIgor Kudrin protected:
128*380e746bSIgor Kudrin   bool init(const std::string &TripleStr, unsigned DwarfVersion,
129*380e746bSIgor Kudrin             dwarf::DwarfFormat DwarfFormat) {
130*380e746bSIgor Kudrin     if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
131*380e746bSIgor Kudrin       return false;
132*380e746bSIgor Kudrin 
133*380e746bSIgor Kudrin     Val.Index = DwarfStringPoolEntry::NotIndexed;
134*380e746bSIgor Kudrin     Val.Symbol = TestPrinter->getCtx().createTempSymbol();
135*380e746bSIgor Kudrin     Val.Offset = 42;
136*380e746bSIgor Kudrin     return true;
137*380e746bSIgor Kudrin   }
138*380e746bSIgor Kudrin 
139*380e746bSIgor Kudrin   DwarfStringPoolEntry Val;
140*380e746bSIgor Kudrin };
141*380e746bSIgor Kudrin 
142*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF32) {
143*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
144*380e746bSIgor Kudrin     return;
145*380e746bSIgor Kudrin 
146*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
147*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
148*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
149*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfStringOffset(Val);
150*380e746bSIgor Kudrin 
151*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
152*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
153*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
154*380e746bSIgor Kudrin }
155*380e746bSIgor Kudrin 
156*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
157*380e746bSIgor Kudrin        DWARF32NoRelocationsAcrossSections) {
158*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
159*380e746bSIgor Kudrin     return;
160*380e746bSIgor Kudrin 
161*380e746bSIgor Kudrin   TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
162*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 4));
163*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfStringOffset(Val);
164*380e746bSIgor Kudrin }
165*380e746bSIgor Kudrin 
166*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF64) {
167*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
168*380e746bSIgor Kudrin     return;
169*380e746bSIgor Kudrin 
170*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
171*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
172*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
173*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfStringOffset(Val);
174*380e746bSIgor Kudrin 
175*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0);
176*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
177*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol);
178*380e746bSIgor Kudrin }
179*380e746bSIgor Kudrin 
180*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfStringOffsetTest,
181*380e746bSIgor Kudrin        DWARF64NoRelocationsAcrossSections) {
182*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
183*380e746bSIgor Kudrin     return;
184*380e746bSIgor Kudrin 
185*380e746bSIgor Kudrin   TestPrinter->setDwarfUsesRelocationsAcrossSections(false);
186*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 8));
187*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfStringOffset(Val);
188*380e746bSIgor Kudrin }
189*380e746bSIgor Kudrin 
190*380e746bSIgor Kudrin class AsmPrinterEmitDwarfOffsetTest : public AsmPrinterFixtureBase {
191*380e746bSIgor Kudrin protected:
192*380e746bSIgor Kudrin   bool init(const std::string &TripleStr, unsigned DwarfVersion,
193*380e746bSIgor Kudrin             dwarf::DwarfFormat DwarfFormat) {
194*380e746bSIgor Kudrin     if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat))
195*380e746bSIgor Kudrin       return false;
196*380e746bSIgor Kudrin 
197*380e746bSIgor Kudrin     Label = TestPrinter->getCtx().createTempSymbol();
198*380e746bSIgor Kudrin     return true;
199*380e746bSIgor Kudrin   }
200*380e746bSIgor Kudrin 
201*380e746bSIgor Kudrin   MCSymbol *Label = nullptr;
202*380e746bSIgor Kudrin   uint64_t Offset = 42;
203*380e746bSIgor Kudrin };
204*380e746bSIgor Kudrin 
205*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF32) {
206*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32))
207*380e746bSIgor Kudrin     return;
208*380e746bSIgor Kudrin 
209*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
210*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _))
211*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
212*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
213*380e746bSIgor Kudrin 
214*380e746bSIgor Kudrin   const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
215*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
216*380e746bSIgor Kudrin   EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
217*380e746bSIgor Kudrin 
218*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualLHS =
219*380e746bSIgor Kudrin       dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
220*380e746bSIgor Kudrin   ASSERT_NE(ActualLHS, nullptr);
221*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
222*380e746bSIgor Kudrin 
223*380e746bSIgor Kudrin   const MCConstantExpr *ActualRHS =
224*380e746bSIgor Kudrin       dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());
225*380e746bSIgor Kudrin   ASSERT_NE(ActualRHS, nullptr);
226*380e746bSIgor Kudrin   EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);
227*380e746bSIgor Kudrin }
228*380e746bSIgor Kudrin 
229*380e746bSIgor Kudrin TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF64) {
230*380e746bSIgor Kudrin   if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64))
231*380e746bSIgor Kudrin     return;
232*380e746bSIgor Kudrin 
233*380e746bSIgor Kudrin   const MCExpr *Arg0 = nullptr;
234*380e746bSIgor Kudrin   EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _))
235*380e746bSIgor Kudrin       .WillOnce(SaveArg<0>(&Arg0));
236*380e746bSIgor Kudrin   TestPrinter->getAP()->emitDwarfOffset(Label, Offset);
237*380e746bSIgor Kudrin 
238*380e746bSIgor Kudrin   const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0);
239*380e746bSIgor Kudrin   ASSERT_NE(ActualArg0, nullptr);
240*380e746bSIgor Kudrin   EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add);
241*380e746bSIgor Kudrin 
242*380e746bSIgor Kudrin   const MCSymbolRefExpr *ActualLHS =
243*380e746bSIgor Kudrin       dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS());
244*380e746bSIgor Kudrin   ASSERT_NE(ActualLHS, nullptr);
245*380e746bSIgor Kudrin   EXPECT_EQ(&(ActualLHS->getSymbol()), Label);
246*380e746bSIgor Kudrin 
247*380e746bSIgor Kudrin   const MCConstantExpr *ActualRHS =
248*380e746bSIgor Kudrin       dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS());
249*380e746bSIgor Kudrin   ASSERT_NE(ActualRHS, nullptr);
250*380e746bSIgor Kudrin   EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset);
251*380e746bSIgor Kudrin }
252*380e746bSIgor Kudrin 
253*380e746bSIgor Kudrin } // end namespace
254