1 //===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===// 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 "llvm/MC/MCFragment.h" 10 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/ADT/StringExtras.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/Config/llvm-config.h" 14 #include "llvm/MC/MCAsmLayout.h" 15 #include "llvm/MC/MCAssembler.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCFixup.h" 19 #include "llvm/MC/MCSection.h" 20 #include "llvm/MC/MCSymbol.h" 21 #include "llvm/MC/MCValue.h" 22 #include "llvm/Support/Casting.h" 23 #include "llvm/Support/Compiler.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include <cassert> 27 #include <cstdint> 28 #include <utility> 29 30 using namespace llvm; 31 32 MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) { 33 // Compute the section layout order. Virtual sections must go last. 34 for (MCSection &Sec : Asm) 35 if (!Sec.isVirtualSection()) 36 SectionOrder.push_back(&Sec); 37 for (MCSection &Sec : Asm) 38 if (Sec.isVirtualSection()) 39 SectionOrder.push_back(&Sec); 40 } 41 42 bool MCAsmLayout::isFragmentValid(const MCFragment *F) const { 43 const MCSection *Sec = F->getParent(); 44 const MCFragment *LastValid = LastValidFragment.lookup(Sec); 45 if (!LastValid) 46 return false; 47 assert(LastValid->getParent() == Sec); 48 return F->getLayoutOrder() <= LastValid->getLayoutOrder(); 49 } 50 51 bool MCAsmLayout::canGetFragmentOffset(const MCFragment *F) const { 52 MCSection *Sec = F->getParent(); 53 MCSection::iterator I; 54 if (MCFragment *LastValid = LastValidFragment[Sec]) { 55 // Fragment already valid, offset is available. 56 if (F->getLayoutOrder() <= LastValid->getLayoutOrder()) 57 return true; 58 I = ++MCSection::iterator(LastValid); 59 } else 60 I = Sec->begin(); 61 62 // A fragment ordered before F is currently being laid out. 63 const MCFragment *FirstInvalidFragment = &*I; 64 if (FirstInvalidFragment->IsBeingLaidOut) 65 return false; 66 67 return true; 68 } 69 70 void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { 71 // If this fragment wasn't already valid, we don't need to do anything. 72 if (!isFragmentValid(F)) 73 return; 74 75 // Otherwise, reset the last valid fragment to the previous fragment 76 // (if this is the first fragment, it will be NULL). 77 LastValidFragment[F->getParent()] = F->getPrevNode(); 78 } 79 80 void MCAsmLayout::ensureValid(const MCFragment *F) const { 81 MCSection *Sec = F->getParent(); 82 MCSection::iterator I; 83 if (MCFragment *Cur = LastValidFragment[Sec]) 84 I = ++MCSection::iterator(Cur); 85 else 86 I = Sec->begin(); 87 88 // Advance the layout position until the fragment is valid. 89 while (!isFragmentValid(F)) { 90 assert(I != Sec->end() && "Layout bookkeeping error"); 91 const_cast<MCAsmLayout *>(this)->layoutFragment(&*I); 92 ++I; 93 } 94 } 95 96 uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { 97 ensureValid(F); 98 assert(F->Offset != ~UINT64_C(0) && "Address not set!"); 99 return F->Offset; 100 } 101 102 // Simple getSymbolOffset helper for the non-variable case. 103 static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, 104 bool ReportError, uint64_t &Val) { 105 if (!S.getFragment()) { 106 if (ReportError) 107 report_fatal_error("unable to evaluate offset to undefined symbol '" + 108 S.getName() + "'"); 109 return false; 110 } 111 Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset(); 112 return true; 113 } 114 115 static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, 116 bool ReportError, uint64_t &Val) { 117 if (!S.isVariable()) 118 return getLabelOffset(Layout, S, ReportError, Val); 119 120 // If SD is a variable, evaluate it. 121 MCValue Target; 122 if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) 123 report_fatal_error("unable to evaluate offset for variable '" + 124 S.getName() + "'"); 125 126 uint64_t Offset = Target.getConstant(); 127 128 const MCSymbolRefExpr *A = Target.getSymA(); 129 if (A) { 130 uint64_t ValA; 131 if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA)) 132 return false; 133 Offset += ValA; 134 } 135 136 const MCSymbolRefExpr *B = Target.getSymB(); 137 if (B) { 138 uint64_t ValB; 139 if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB)) 140 return false; 141 Offset -= ValB; 142 } 143 144 Val = Offset; 145 return true; 146 } 147 148 bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val) const { 149 return getSymbolOffsetImpl(*this, S, false, Val); 150 } 151 152 uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S) const { 153 uint64_t Val; 154 getSymbolOffsetImpl(*this, S, true, Val); 155 return Val; 156 } 157 158 const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { 159 if (!Symbol.isVariable()) 160 return &Symbol; 161 162 const MCExpr *Expr = Symbol.getVariableValue(); 163 MCValue Value; 164 if (!Expr->evaluateAsValue(Value, *this)) { 165 Assembler.getContext().reportError( 166 Expr->getLoc(), "expression could not be evaluated"); 167 return nullptr; 168 } 169 170 const MCSymbolRefExpr *RefB = Value.getSymB(); 171 if (RefB) { 172 Assembler.getContext().reportError( 173 Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() + 174 "' could not be evaluated in a subtraction expression"); 175 return nullptr; 176 } 177 178 const MCSymbolRefExpr *A = Value.getSymA(); 179 if (!A) 180 return nullptr; 181 182 const MCSymbol &ASym = A->getSymbol(); 183 const MCAssembler &Asm = getAssembler(); 184 if (ASym.isCommon()) { 185 Asm.getContext().reportError(Expr->getLoc(), 186 "Common symbol '" + ASym.getName() + 187 "' cannot be used in assignment expr"); 188 return nullptr; 189 } 190 191 return &ASym; 192 } 193 194 uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const { 195 // The size is the last fragment's end offset. 196 const MCFragment &F = Sec->getFragmentList().back(); 197 return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F); 198 } 199 200 uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const { 201 // Virtual sections have no file size. 202 if (Sec->isVirtualSection()) 203 return 0; 204 205 // Otherwise, the file size is the same as the address space size. 206 return getSectionAddressSize(Sec); 207 } 208 209 uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, 210 const MCEncodedFragment *F, 211 uint64_t FOffset, uint64_t FSize) { 212 uint64_t BundleSize = Assembler.getBundleAlignSize(); 213 assert(BundleSize > 0 && 214 "computeBundlePadding should only be called if bundling is enabled"); 215 uint64_t BundleMask = BundleSize - 1; 216 uint64_t OffsetInBundle = FOffset & BundleMask; 217 uint64_t EndOfFragment = OffsetInBundle + FSize; 218 219 // There are two kinds of bundling restrictions: 220 // 221 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will 222 // *end* on a bundle boundary. 223 // 2) Otherwise, check if the fragment would cross a bundle boundary. If it 224 // would, add padding until the end of the bundle so that the fragment 225 // will start in a new one. 226 if (F->alignToBundleEnd()) { 227 // Three possibilities here: 228 // 229 // A) The fragment just happens to end at a bundle boundary, so we're good. 230 // B) The fragment ends before the current bundle boundary: pad it just 231 // enough to reach the boundary. 232 // C) The fragment ends after the current bundle boundary: pad it until it 233 // reaches the end of the next bundle boundary. 234 // 235 // Note: this code could be made shorter with some modulo trickery, but it's 236 // intentionally kept in its more explicit form for simplicity. 237 if (EndOfFragment == BundleSize) 238 return 0; 239 else if (EndOfFragment < BundleSize) 240 return BundleSize - EndOfFragment; 241 else { // EndOfFragment > BundleSize 242 return 2 * BundleSize - EndOfFragment; 243 } 244 } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize) 245 return BundleSize - OffsetInBundle; 246 else 247 return 0; 248 } 249 250 /* *** */ 251 252 void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); } 253 254 MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, 255 MCSection *Parent) 256 : Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0), 257 Kind(Kind), IsBeingLaidOut(false), HasInstructions(HasInstructions) { 258 if (Parent && !isa<MCDummyFragment>(*this)) 259 Parent->getFragmentList().push_back(this); 260 } 261 262 void MCFragment::destroy() { 263 // First check if we are the sentinal. 264 if (Kind == FragmentType(~0)) { 265 delete this; 266 return; 267 } 268 269 switch (Kind) { 270 case FT_Align: 271 delete cast<MCAlignFragment>(this); 272 return; 273 case FT_Data: 274 delete cast<MCDataFragment>(this); 275 return; 276 case FT_CompactEncodedInst: 277 delete cast<MCCompactEncodedInstFragment>(this); 278 return; 279 case FT_Fill: 280 delete cast<MCFillFragment>(this); 281 return; 282 case FT_Relaxable: 283 delete cast<MCRelaxableFragment>(this); 284 return; 285 case FT_Org: 286 delete cast<MCOrgFragment>(this); 287 return; 288 case FT_Dwarf: 289 delete cast<MCDwarfLineAddrFragment>(this); 290 return; 291 case FT_DwarfFrame: 292 delete cast<MCDwarfCallFrameFragment>(this); 293 return; 294 case FT_LEB: 295 delete cast<MCLEBFragment>(this); 296 return; 297 case FT_BoundaryAlign: 298 delete cast<MCBoundaryAlignFragment>(this); 299 return; 300 case FT_SymbolId: 301 delete cast<MCSymbolIdFragment>(this); 302 return; 303 case FT_CVInlineLines: 304 delete cast<MCCVInlineLineTableFragment>(this); 305 return; 306 case FT_CVDefRange: 307 delete cast<MCCVDefRangeFragment>(this); 308 return; 309 case FT_Dummy: 310 delete cast<MCDummyFragment>(this); 311 return; 312 } 313 } 314 315 // Debugging methods 316 317 namespace llvm { 318 319 raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { 320 OS << "<MCFixup" << " Offset:" << AF.getOffset() 321 << " Value:" << *AF.getValue() 322 << " Kind:" << AF.getKind() << ">"; 323 return OS; 324 } 325 326 } // end namespace llvm 327 328 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329 LLVM_DUMP_METHOD void MCFragment::dump() const { 330 raw_ostream &OS = errs(); 331 332 OS << "<"; 333 switch (getKind()) { 334 case MCFragment::FT_Align: OS << "MCAlignFragment"; break; 335 case MCFragment::FT_Data: OS << "MCDataFragment"; break; 336 case MCFragment::FT_CompactEncodedInst: 337 OS << "MCCompactEncodedInstFragment"; break; 338 case MCFragment::FT_Fill: OS << "MCFillFragment"; break; 339 case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break; 340 case MCFragment::FT_Org: OS << "MCOrgFragment"; break; 341 case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break; 342 case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; 343 case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; 344 case MCFragment::FT_BoundaryAlign: OS<<"MCBoundaryAlignFragment"; break; 345 case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break; 346 case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break; 347 case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break; 348 case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; 349 } 350 351 OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder 352 << " Offset:" << Offset << " HasInstructions:" << hasInstructions(); 353 if (const auto *EF = dyn_cast<MCEncodedFragment>(this)) 354 OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding()); 355 OS << ">"; 356 357 switch (getKind()) { 358 case MCFragment::FT_Align: { 359 const auto *AF = cast<MCAlignFragment>(this); 360 if (AF->hasEmitNops()) 361 OS << " (emit nops)"; 362 OS << "\n "; 363 OS << " Alignment:" << AF->getAlignment() 364 << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize() 365 << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">"; 366 break; 367 } 368 case MCFragment::FT_Data: { 369 const auto *DF = cast<MCDataFragment>(this); 370 OS << "\n "; 371 OS << " Contents:["; 372 const SmallVectorImpl<char> &Contents = DF->getContents(); 373 for (unsigned i = 0, e = Contents.size(); i != e; ++i) { 374 if (i) OS << ","; 375 OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); 376 } 377 OS << "] (" << Contents.size() << " bytes)"; 378 379 if (DF->fixup_begin() != DF->fixup_end()) { 380 OS << ",\n "; 381 OS << " Fixups:["; 382 for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(), 383 ie = DF->fixup_end(); it != ie; ++it) { 384 if (it != DF->fixup_begin()) OS << ",\n "; 385 OS << *it; 386 } 387 OS << "]"; 388 } 389 break; 390 } 391 case MCFragment::FT_CompactEncodedInst: { 392 const auto *CEIF = 393 cast<MCCompactEncodedInstFragment>(this); 394 OS << "\n "; 395 OS << " Contents:["; 396 const SmallVectorImpl<char> &Contents = CEIF->getContents(); 397 for (unsigned i = 0, e = Contents.size(); i != e; ++i) { 398 if (i) OS << ","; 399 OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); 400 } 401 OS << "] (" << Contents.size() << " bytes)"; 402 break; 403 } 404 case MCFragment::FT_Fill: { 405 const auto *FF = cast<MCFillFragment>(this); 406 OS << " Value:" << static_cast<unsigned>(FF->getValue()) 407 << " ValueSize:" << static_cast<unsigned>(FF->getValueSize()) 408 << " NumValues:" << FF->getNumValues(); 409 break; 410 } 411 case MCFragment::FT_Relaxable: { 412 const auto *F = cast<MCRelaxableFragment>(this); 413 OS << "\n "; 414 OS << " Inst:"; 415 F->getInst().dump_pretty(OS); 416 OS << " (" << F->getContents().size() << " bytes)"; 417 break; 418 } 419 case MCFragment::FT_Org: { 420 const auto *OF = cast<MCOrgFragment>(this); 421 OS << "\n "; 422 OS << " Offset:" << OF->getOffset() 423 << " Value:" << static_cast<unsigned>(OF->getValue()); 424 break; 425 } 426 case MCFragment::FT_Dwarf: { 427 const auto *OF = cast<MCDwarfLineAddrFragment>(this); 428 OS << "\n "; 429 OS << " AddrDelta:" << OF->getAddrDelta() 430 << " LineDelta:" << OF->getLineDelta(); 431 break; 432 } 433 case MCFragment::FT_DwarfFrame: { 434 const auto *CF = cast<MCDwarfCallFrameFragment>(this); 435 OS << "\n "; 436 OS << " AddrDelta:" << CF->getAddrDelta(); 437 break; 438 } 439 case MCFragment::FT_LEB: { 440 const auto *LF = cast<MCLEBFragment>(this); 441 OS << "\n "; 442 OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned(); 443 break; 444 } 445 case MCFragment::FT_BoundaryAlign: { 446 const auto *BF = cast<MCBoundaryAlignFragment>(this); 447 OS << "\n "; 448 OS << " BoundarySize:" << BF->getAlignment().value() 449 << " LastFragment:" << BF->getLastFragment() 450 << " Size:" << BF->getSize(); 451 break; 452 } 453 case MCFragment::FT_SymbolId: { 454 const auto *F = cast<MCSymbolIdFragment>(this); 455 OS << "\n "; 456 OS << " Sym:" << F->getSymbol(); 457 break; 458 } 459 case MCFragment::FT_CVInlineLines: { 460 const auto *F = cast<MCCVInlineLineTableFragment>(this); 461 OS << "\n "; 462 OS << " Sym:" << *F->getFnStartSym(); 463 break; 464 } 465 case MCFragment::FT_CVDefRange: { 466 const auto *F = cast<MCCVDefRangeFragment>(this); 467 OS << "\n "; 468 for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd : 469 F->getRanges()) { 470 OS << " RangeStart:" << RangeStartEnd.first; 471 OS << " RangeEnd:" << RangeStartEnd.second; 472 } 473 break; 474 } 475 case MCFragment::FT_Dummy: 476 break; 477 } 478 OS << ">"; 479 } 480 #endif 481