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