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::InSequence; 18 using testing::SaveArg; 19 20 namespace { 21 22 class AsmPrinterFixtureBase : public testing::Test { 23 void setupTestPrinter(const std::string &TripleStr, unsigned DwarfVersion, 24 dwarf::DwarfFormat DwarfFormat) { 25 auto ExpectedTestPrinter = 26 TestAsmPrinter::create(TripleStr, DwarfVersion, DwarfFormat); 27 ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded()); 28 TestPrinter = std::move(ExpectedTestPrinter.get()); 29 } 30 31 protected: 32 bool init(const std::string &TripleStr, unsigned DwarfVersion, 33 dwarf::DwarfFormat DwarfFormat) { 34 setupTestPrinter(TripleStr, DwarfVersion, DwarfFormat); 35 return TestPrinter != nullptr; 36 } 37 38 std::unique_ptr<TestAsmPrinter> TestPrinter; 39 }; 40 41 class AsmPrinterEmitDwarfSymbolReferenceTest : public AsmPrinterFixtureBase { 42 protected: 43 bool init(const std::string &TripleStr, unsigned DwarfVersion, 44 dwarf::DwarfFormat DwarfFormat) { 45 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat)) 46 return false; 47 48 // Create a symbol which will be emitted in the tests and associate it 49 // with a section because that is required in some code paths. 50 51 Val = TestPrinter->getCtx().createTempSymbol(); 52 Sec = TestPrinter->getCtx().getELFSection(".tst", ELF::SHT_PROGBITS, 0); 53 SecBeginSymbol = Sec->getBeginSymbol(); 54 TestPrinter->getMS().SwitchSection(Sec); 55 TestPrinter->getMS().emitLabel(Val); 56 return true; 57 } 58 59 MCSymbol *Val = nullptr; 60 MCSection *Sec = nullptr; 61 MCSymbol *SecBeginSymbol = nullptr; 62 }; 63 64 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFF) { 65 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32)) 66 return; 67 68 EXPECT_CALL(TestPrinter->getMS(), EmitCOFFSecRel32(Val, 0)); 69 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false); 70 } 71 72 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, COFFForceOffset) { 73 if (!init("x86_64-pc-windows", /*DwarfVersion=*/4, dwarf::DWARF32)) 74 return; 75 76 EXPECT_CALL(TestPrinter->getMS(), 77 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4)); 78 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true); 79 } 80 81 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32) { 82 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 83 return; 84 85 const MCExpr *Arg0 = nullptr; 86 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _)) 87 .WillOnce(SaveArg<0>(&Arg0)); 88 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false); 89 90 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0); 91 ASSERT_NE(ActualArg0, nullptr); 92 EXPECT_EQ(&(ActualArg0->getSymbol()), Val); 93 } 94 95 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF32ForceOffset) { 96 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 97 return; 98 99 EXPECT_CALL(TestPrinter->getMS(), 100 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 4)); 101 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true); 102 } 103 104 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64) { 105 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 106 return; 107 108 const MCExpr *Arg0 = nullptr; 109 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _)) 110 .WillOnce(SaveArg<0>(&Arg0)); 111 TestPrinter->getAP()->emitDwarfSymbolReference(Val, false); 112 113 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0); 114 ASSERT_NE(ActualArg0, nullptr); 115 EXPECT_EQ(&(ActualArg0->getSymbol()), Val); 116 } 117 118 TEST_F(AsmPrinterEmitDwarfSymbolReferenceTest, ELFDWARF64ForceOffset) { 119 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 120 return; 121 122 EXPECT_CALL(TestPrinter->getMS(), 123 emitAbsoluteSymbolDiff(Val, SecBeginSymbol, 8)); 124 TestPrinter->getAP()->emitDwarfSymbolReference(Val, true); 125 } 126 127 class AsmPrinterEmitDwarfStringOffsetTest : public AsmPrinterFixtureBase { 128 protected: 129 bool init(const std::string &TripleStr, unsigned DwarfVersion, 130 dwarf::DwarfFormat DwarfFormat) { 131 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat)) 132 return false; 133 134 Val.Index = DwarfStringPoolEntry::NotIndexed; 135 Val.Symbol = TestPrinter->getCtx().createTempSymbol(); 136 Val.Offset = 42; 137 return true; 138 } 139 140 DwarfStringPoolEntry Val; 141 }; 142 143 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF32) { 144 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 145 return; 146 147 const MCExpr *Arg0 = nullptr; 148 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _)) 149 .WillOnce(SaveArg<0>(&Arg0)); 150 TestPrinter->getAP()->emitDwarfStringOffset(Val); 151 152 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0); 153 ASSERT_NE(ActualArg0, nullptr); 154 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol); 155 } 156 157 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, 158 DWARF32NoRelocationsAcrossSections) { 159 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 160 return; 161 162 TestPrinter->setDwarfUsesRelocationsAcrossSections(false); 163 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 4)); 164 TestPrinter->getAP()->emitDwarfStringOffset(Val); 165 } 166 167 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, DWARF64) { 168 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 169 return; 170 171 const MCExpr *Arg0 = nullptr; 172 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _)) 173 .WillOnce(SaveArg<0>(&Arg0)); 174 TestPrinter->getAP()->emitDwarfStringOffset(Val); 175 176 const MCSymbolRefExpr *ActualArg0 = dyn_cast_or_null<MCSymbolRefExpr>(Arg0); 177 ASSERT_NE(ActualArg0, nullptr); 178 EXPECT_EQ(&(ActualArg0->getSymbol()), Val.Symbol); 179 } 180 181 TEST_F(AsmPrinterEmitDwarfStringOffsetTest, 182 DWARF64NoRelocationsAcrossSections) { 183 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 184 return; 185 186 TestPrinter->setDwarfUsesRelocationsAcrossSections(false); 187 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val.Offset, 8)); 188 TestPrinter->getAP()->emitDwarfStringOffset(Val); 189 } 190 191 class AsmPrinterEmitDwarfOffsetTest : public AsmPrinterFixtureBase { 192 protected: 193 bool init(const std::string &TripleStr, unsigned DwarfVersion, 194 dwarf::DwarfFormat DwarfFormat) { 195 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat)) 196 return false; 197 198 Label = TestPrinter->getCtx().createTempSymbol(); 199 return true; 200 } 201 202 MCSymbol *Label = nullptr; 203 uint64_t Offset = 42; 204 }; 205 206 TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF32) { 207 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 208 return; 209 210 const MCExpr *Arg0 = nullptr; 211 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 4, _)) 212 .WillOnce(SaveArg<0>(&Arg0)); 213 TestPrinter->getAP()->emitDwarfOffset(Label, Offset); 214 215 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0); 216 ASSERT_NE(ActualArg0, nullptr); 217 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add); 218 219 const MCSymbolRefExpr *ActualLHS = 220 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS()); 221 ASSERT_NE(ActualLHS, nullptr); 222 EXPECT_EQ(&(ActualLHS->getSymbol()), Label); 223 224 const MCConstantExpr *ActualRHS = 225 dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS()); 226 ASSERT_NE(ActualRHS, nullptr); 227 EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset); 228 } 229 230 TEST_F(AsmPrinterEmitDwarfOffsetTest, DWARF64) { 231 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 232 return; 233 234 const MCExpr *Arg0 = nullptr; 235 EXPECT_CALL(TestPrinter->getMS(), emitValueImpl(_, 8, _)) 236 .WillOnce(SaveArg<0>(&Arg0)); 237 TestPrinter->getAP()->emitDwarfOffset(Label, Offset); 238 239 const MCBinaryExpr *ActualArg0 = dyn_cast_or_null<MCBinaryExpr>(Arg0); 240 ASSERT_NE(ActualArg0, nullptr); 241 EXPECT_EQ(ActualArg0->getOpcode(), MCBinaryExpr::Add); 242 243 const MCSymbolRefExpr *ActualLHS = 244 dyn_cast_or_null<MCSymbolRefExpr>(ActualArg0->getLHS()); 245 ASSERT_NE(ActualLHS, nullptr); 246 EXPECT_EQ(&(ActualLHS->getSymbol()), Label); 247 248 const MCConstantExpr *ActualRHS = 249 dyn_cast_or_null<MCConstantExpr>(ActualArg0->getRHS()); 250 ASSERT_NE(ActualRHS, nullptr); 251 EXPECT_EQ(static_cast<uint64_t>(ActualRHS->getValue()), Offset); 252 } 253 254 class AsmPrinterEmitDwarfLengthOrOffsetTest : public AsmPrinterFixtureBase { 255 protected: 256 uint64_t Val = 42; 257 }; 258 259 TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF32) { 260 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 261 return; 262 263 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4)); 264 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val); 265 } 266 267 TEST_F(AsmPrinterEmitDwarfLengthOrOffsetTest, DWARF64) { 268 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 269 return; 270 271 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8)); 272 TestPrinter->getAP()->emitDwarfLengthOrOffset(Val); 273 } 274 275 class AsmPrinterGetUnitLengthFieldByteSizeTest : public AsmPrinterFixtureBase { 276 }; 277 278 TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF32) { 279 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 280 return; 281 282 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 4u); 283 } 284 285 TEST_F(AsmPrinterGetUnitLengthFieldByteSizeTest, DWARF64) { 286 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 287 return; 288 289 EXPECT_EQ(TestPrinter->getAP()->getUnitLengthFieldByteSize(), 12u); 290 } 291 292 class AsmPrinterMaybeEmitDwarf64MarkTest : public AsmPrinterFixtureBase {}; 293 294 TEST_F(AsmPrinterMaybeEmitDwarf64MarkTest, DWARF32) { 295 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 296 return; 297 298 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(_, _)).Times(0); 299 TestPrinter->getAP()->maybeEmitDwarf64Mark(); 300 } 301 302 TEST_F(AsmPrinterMaybeEmitDwarf64MarkTest, DWARF64) { 303 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 304 return; 305 306 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4)); 307 TestPrinter->getAP()->maybeEmitDwarf64Mark(); 308 } 309 310 class AsmPrinterEmitDwarfUnitLengthAsIntTest : public AsmPrinterFixtureBase { 311 protected: 312 uint64_t Val = 42; 313 }; 314 315 TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF32) { 316 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 317 return; 318 319 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 4)); 320 TestPrinter->getAP()->emitDwarfUnitLength(Val, ""); 321 } 322 323 TEST_F(AsmPrinterEmitDwarfUnitLengthAsIntTest, DWARF64) { 324 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 325 return; 326 327 InSequence S; 328 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4)); 329 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(Val, 8)); 330 331 TestPrinter->getAP()->emitDwarfUnitLength(Val, ""); 332 } 333 334 class AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest 335 : public AsmPrinterFixtureBase { 336 protected: 337 bool init(const std::string &TripleStr, unsigned DwarfVersion, 338 dwarf::DwarfFormat DwarfFormat) { 339 if (!AsmPrinterFixtureBase::init(TripleStr, DwarfVersion, DwarfFormat)) 340 return false; 341 342 Hi = TestPrinter->getCtx().createTempSymbol(); 343 Lo = TestPrinter->getCtx().createTempSymbol(); 344 return true; 345 } 346 347 MCSymbol *Hi = nullptr; 348 MCSymbol *Lo = nullptr; 349 }; 350 351 TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF32) { 352 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF32)) 353 return; 354 355 EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(Hi, Lo, 4)); 356 TestPrinter->getAP()->emitDwarfUnitLength(Hi, Lo, ""); 357 } 358 359 TEST_F(AsmPrinterEmitDwarfUnitLengthAsHiLoDiffTest, DWARF64) { 360 if (!init("x86_64-pc-linux", /*DwarfVersion=*/4, dwarf::DWARF64)) 361 return; 362 363 InSequence S; 364 EXPECT_CALL(TestPrinter->getMS(), emitIntValue(dwarf::DW_LENGTH_DWARF64, 4)); 365 EXPECT_CALL(TestPrinter->getMS(), emitAbsoluteSymbolDiff(Hi, Lo, 8)); 366 367 TestPrinter->getAP()->emitDwarfUnitLength(Hi, Lo, ""); 368 } 369 370 } // end namespace 371