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