MCAssembler.h revision e1ec617c6abf0b9dc1eecbbfe483bda3bb2b7795
1//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLVM_MC_MCASSEMBLER_H 11#define LLVM_MC_MCASSEMBLER_H 12 13#include "llvm/ADT/SmallString.h" 14#include "llvm/ADT/ilist.h" 15#include "llvm/ADT/ilist_node.h" 16#include "llvm/Support/Casting.h" 17#include "llvm/System/DataTypes.h" 18#include <vector> // FIXME: Shouldn't be needed. 19 20namespace llvm { 21class raw_ostream; 22class MCAssembler; 23class MCContext; 24class MCExpr; 25class MCSection; 26class MCSectionData; 27class MCSymbol; 28 29class MCFragment : public ilist_node<MCFragment> { 30 MCFragment(const MCFragment&); // DO NOT IMPLEMENT 31 void operator=(const MCFragment&); // DO NOT IMPLEMENT 32 33public: 34 enum FragmentType { 35 FT_Data, 36 FT_Align, 37 FT_Fill, 38 FT_Org, 39 FT_ZeroFill 40 }; 41 42private: 43 FragmentType Kind; 44 45 /// Parent - The data for the section this fragment is in. 46 MCSectionData *Parent; 47 48 /// @name Assembler Backend Data 49 /// @{ 50 // 51 // FIXME: This could all be kept private to the assembler implementation. 52 53 /// Offset - The offset of this fragment in its section. This is ~0 until 54 /// initialized. 55 uint64_t Offset; 56 57 /// FileSize - The file size of this section. This is ~0 until initialized. 58 uint64_t FileSize; 59 60 /// @} 61 62protected: 63 MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0); 64 65public: 66 // Only for sentinel. 67 MCFragment(); 68 virtual ~MCFragment(); 69 70 FragmentType getKind() const { return Kind; } 71 72 MCSectionData *getParent() const { return Parent; } 73 void setParent(MCSectionData *Value) { Parent = Value; } 74 75 // FIXME: This should be abstract, fix sentinel. 76 virtual uint64_t getMaxFileSize() const { 77 assert(0 && "Invalid getMaxFileSize call!"); 78 return 0; 79 } 80 81 /// @name Assembler Backend Support 82 /// @{ 83 // 84 // FIXME: This could all be kept private to the assembler implementation. 85 86 uint64_t getAddress() const; 87 88 uint64_t getFileSize() const { 89 assert(FileSize != ~UINT64_C(0) && "File size not set!"); 90 return FileSize; 91 } 92 void setFileSize(uint64_t Value) { 93 assert(Value <= getMaxFileSize() && "Invalid file size!"); 94 FileSize = Value; 95 } 96 97 uint64_t getOffset() const { 98 assert(Offset != ~UINT64_C(0) && "File offset not set!"); 99 return Offset; 100 } 101 void setOffset(uint64_t Value) { Offset = Value; } 102 103 /// @} 104 105 static bool classof(const MCFragment *O) { return true; } 106}; 107 108class MCDataFragment : public MCFragment { 109 SmallString<32> Contents; 110 111public: 112 MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} 113 114 /// @name Accessors 115 /// @{ 116 117 uint64_t getMaxFileSize() const { 118 return Contents.size(); 119 } 120 121 SmallString<32> &getContents() { return Contents; } 122 const SmallString<32> &getContents() const { return Contents; } 123 124 /// @} 125 126 static bool classof(const MCFragment *F) { 127 return F->getKind() == MCFragment::FT_Data; 128 } 129 static bool classof(const MCDataFragment *) { return true; } 130}; 131 132class MCAlignFragment : public MCFragment { 133 /// Alignment - The alignment to ensure, in bytes. 134 unsigned Alignment; 135 136 /// Value - Value to use for filling padding bytes. 137 int64_t Value; 138 139 /// ValueSize - The size of the integer (in bytes) of \arg Value. 140 unsigned ValueSize; 141 142 /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment 143 /// cannot be satisfied in this width then this fragment is ignored. 144 unsigned MaxBytesToEmit; 145 146public: 147 MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, 148 unsigned _MaxBytesToEmit, MCSectionData *SD = 0) 149 : MCFragment(FT_Align, SD), Alignment(_Alignment), 150 Value(_Value),ValueSize(_ValueSize), 151 MaxBytesToEmit(_MaxBytesToEmit) {} 152 153 /// @name Accessors 154 /// @{ 155 156 uint64_t getMaxFileSize() const { 157 return std::max(Alignment - 1, MaxBytesToEmit); 158 } 159 160 unsigned getAlignment() const { return Alignment; } 161 162 int64_t getValue() const { return Value; } 163 164 unsigned getValueSize() const { return ValueSize; } 165 166 unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } 167 168 /// @} 169 170 static bool classof(const MCFragment *F) { 171 return F->getKind() == MCFragment::FT_Align; 172 } 173 static bool classof(const MCAlignFragment *) { return true; } 174}; 175 176class MCFillFragment : public MCFragment { 177 /// Value - Value to use for filling bytes. 178 const MCExpr *Value; 179 180 /// ValueSize - The size (in bytes) of \arg Value to use when filling. 181 unsigned ValueSize; 182 183 /// Count - The number of copies of \arg Value to insert. 184 uint64_t Count; 185 186public: 187 MCFillFragment(const MCExpr &_Value, unsigned _ValueSize, uint64_t _Count, 188 MCSectionData *SD = 0) 189 : MCFragment(FT_Fill, SD), 190 Value(&_Value), ValueSize(_ValueSize), Count(_Count) {} 191 192 /// @name Accessors 193 /// @{ 194 195 uint64_t getMaxFileSize() const { 196 return ValueSize * Count; 197 } 198 199 const MCExpr &getValue() const { return *Value; } 200 201 unsigned getValueSize() const { return ValueSize; } 202 203 uint64_t getCount() const { return Count; } 204 205 /// @} 206 207 static bool classof(const MCFragment *F) { 208 return F->getKind() == MCFragment::FT_Fill; 209 } 210 static bool classof(const MCFillFragment *) { return true; } 211}; 212 213class MCOrgFragment : public MCFragment { 214 /// Offset - The offset this fragment should start at. 215 const MCExpr *Offset; 216 217 /// Value - Value to use for filling bytes. 218 int8_t Value; 219 220public: 221 MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) 222 : MCFragment(FT_Org, SD), 223 Offset(&_Offset), Value(_Value) {} 224 225 /// @name Accessors 226 /// @{ 227 228 uint64_t getMaxFileSize() const { 229 // FIXME: This doesn't make much sense. 230 return ~UINT64_C(0); 231 } 232 233 const MCExpr &getOffset() const { return *Offset; } 234 235 uint8_t getValue() const { return Value; } 236 237 /// @} 238 239 static bool classof(const MCFragment *F) { 240 return F->getKind() == MCFragment::FT_Org; 241 } 242 static bool classof(const MCOrgFragment *) { return true; } 243}; 244 245/// MCZeroFillFragment - Represent data which has a fixed size and alignment, 246/// but requires no physical space in the object file. 247class MCZeroFillFragment : public MCFragment { 248 /// Size - The size of this fragment. 249 uint64_t Size; 250 251 /// Alignment - The alignment for this fragment. 252 unsigned Alignment; 253 254public: 255 MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0) 256 : MCFragment(FT_ZeroFill, SD), 257 Size(_Size), Alignment(_Alignment) {} 258 259 /// @name Accessors 260 /// @{ 261 262 uint64_t getMaxFileSize() const { 263 // FIXME: This also doesn't make much sense, this method is misnamed. 264 return ~UINT64_C(0); 265 } 266 267 uint64_t getSize() const { return Size; } 268 269 unsigned getAlignment() const { return Alignment; } 270 271 /// @} 272 273 static bool classof(const MCFragment *F) { 274 return F->getKind() == MCFragment::FT_ZeroFill; 275 } 276 static bool classof(const MCZeroFillFragment *) { return true; } 277}; 278 279// FIXME: Should this be a separate class, or just merged into MCSection? Since 280// we anticipate the fast path being through an MCAssembler, the only reason to 281// keep it out is for API abstraction. 282class MCSectionData : public ilist_node<MCSectionData> { 283 MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT 284 void operator=(const MCSectionData&); // DO NOT IMPLEMENT 285 286public: 287 /// Fixup - Represent a fixed size region of bytes inside some fragment which 288 /// needs to be rewritten. This region will either be rewritten by the 289 /// assembler or cause a relocation entry to be generated. 290 struct Fixup { 291 /// Fragment - The fragment containing the fixup. 292 MCFragment *Fragment; 293 294 /// Offset - The offset inside the fragment which needs to be rewritten. 295 uint64_t Offset; 296 297 /// Value - The expression to eventually write into the fragment. 298 const MCExpr *Value; 299 300 /// Size - The fixup size. 301 unsigned Size; 302 303 /// FixedValue - The value to replace the fix up by. 304 // 305 // FIXME: This should not be here. 306 uint64_t FixedValue; 307 308 public: 309 Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCExpr &_Value, 310 unsigned _Size) 311 : Fragment(&_Fragment), Offset(_Offset), Value(&_Value), Size(_Size), 312 FixedValue(0) {} 313 }; 314 315 typedef iplist<MCFragment> FragmentListType; 316 317 typedef FragmentListType::const_iterator const_iterator; 318 typedef FragmentListType::iterator iterator; 319 320 typedef std::vector<Fixup>::const_iterator const_fixup_iterator; 321 typedef std::vector<Fixup>::iterator fixup_iterator; 322 323private: 324 iplist<MCFragment> Fragments; 325 const MCSection *Section; 326 327 /// Alignment - The maximum alignment seen in this section. 328 unsigned Alignment; 329 330 /// @name Assembler Backend Data 331 /// @{ 332 // 333 // FIXME: This could all be kept private to the assembler implementation. 334 335 /// Address - The computed address of this section. This is ~0 until 336 /// initialized. 337 uint64_t Address; 338 339 /// Size - The content size of this section. This is ~0 until initialized. 340 uint64_t Size; 341 342 /// FileSize - The size of this section in the object file. This is ~0 until 343 /// initialized. 344 uint64_t FileSize; 345 346 /// LastFixupLookup - Cache for the last looked up fixup. 347 mutable unsigned LastFixupLookup; 348 349 /// Fixups - The list of fixups in this section. 350 std::vector<Fixup> Fixups; 351 352 /// HasInstructions - Whether this section has had instructions emitted into 353 /// it. 354 unsigned HasInstructions : 1; 355 356 /// @} 357 358public: 359 // Only for use as sentinel. 360 MCSectionData(); 361 MCSectionData(const MCSection &Section, MCAssembler *A = 0); 362 363 const MCSection &getSection() const { return *Section; } 364 365 unsigned getAlignment() const { return Alignment; } 366 void setAlignment(unsigned Value) { Alignment = Value; } 367 368 /// @name Fragment Access 369 /// @{ 370 371 const FragmentListType &getFragmentList() const { return Fragments; } 372 FragmentListType &getFragmentList() { return Fragments; } 373 374 iterator begin() { return Fragments.begin(); } 375 const_iterator begin() const { return Fragments.begin(); } 376 377 iterator end() { return Fragments.end(); } 378 const_iterator end() const { return Fragments.end(); } 379 380 size_t size() const { return Fragments.size(); } 381 382 bool empty() const { return Fragments.empty(); } 383 384 /// @} 385 /// @name Fixup Access 386 /// @{ 387 388 std::vector<Fixup> &getFixups() { 389 return Fixups; 390 } 391 392 fixup_iterator fixup_begin() { 393 return Fixups.begin(); 394 } 395 396 fixup_iterator fixup_end() { 397 return Fixups.end(); 398 } 399 400 size_t fixup_size() const { return Fixups.size(); } 401 402 /// @} 403 /// @name Assembler Backend Support 404 /// @{ 405 // 406 // FIXME: This could all be kept private to the assembler implementation. 407 408 /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg 409 /// Offset. 410 /// 411 /// If multiple fixups exist for the same fragment and offset it is undefined 412 /// which one is returned. 413 // 414 // FIXME: This isn't horribly slow in practice, but there are much nicer 415 // solutions to applying the fixups. 416 const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const; 417 418 uint64_t getAddress() const { 419 assert(Address != ~UINT64_C(0) && "Address not set!"); 420 return Address; 421 } 422 void setAddress(uint64_t Value) { Address = Value; } 423 424 uint64_t getSize() const { 425 assert(Size != ~UINT64_C(0) && "File size not set!"); 426 return Size; 427 } 428 void setSize(uint64_t Value) { Size = Value; } 429 430 uint64_t getFileSize() const { 431 assert(FileSize != ~UINT64_C(0) && "File size not set!"); 432 return FileSize; 433 } 434 void setFileSize(uint64_t Value) { FileSize = Value; } 435 436 bool hasInstructions() const { return HasInstructions; } 437 void setHasInstructions(bool Value) { HasInstructions = Value; } 438 439 /// @} 440}; 441 442// FIXME: Same concerns as with SectionData. 443class MCSymbolData : public ilist_node<MCSymbolData> { 444public: 445 const MCSymbol *Symbol; 446 447 /// Fragment - The fragment this symbol's value is relative to, if any. 448 MCFragment *Fragment; 449 450 /// Offset - The offset to apply to the fragment address to form this symbol's 451 /// value. 452 uint64_t Offset; 453 454 /// IsExternal - True if this symbol is visible outside this translation 455 /// unit. 456 unsigned IsExternal : 1; 457 458 /// IsPrivateExtern - True if this symbol is private extern. 459 unsigned IsPrivateExtern : 1; 460 461 /// CommonSize - The size of the symbol, if it is 'common', or 0. 462 // 463 // FIXME: Pack this in with other fields? We could put it in offset, since a 464 // common symbol can never get a definition. 465 uint64_t CommonSize; 466 467 /// CommonAlign - The alignment of the symbol, if it is 'common'. 468 // 469 // FIXME: Pack this in with other fields? 470 unsigned CommonAlign; 471 472 /// Flags - The Flags field is used by object file implementations to store 473 /// additional per symbol information which is not easily classified. 474 uint32_t Flags; 475 476 /// Index - Index field, for use by the object file implementation. 477 uint64_t Index; 478 479public: 480 // Only for use as sentinel. 481 MCSymbolData(); 482 MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, 483 MCAssembler *A = 0); 484 485 /// @name Accessors 486 /// @{ 487 488 const MCSymbol &getSymbol() const { return *Symbol; } 489 490 MCFragment *getFragment() const { return Fragment; } 491 void setFragment(MCFragment *Value) { Fragment = Value; } 492 493 uint64_t getOffset() const { return Offset; } 494 void setOffset(uint64_t Value) { Offset = Value; } 495 496 /// @} 497 /// @name Symbol Attributes 498 /// @{ 499 500 bool isExternal() const { return IsExternal; } 501 void setExternal(bool Value) { IsExternal = Value; } 502 503 bool isPrivateExtern() const { return IsPrivateExtern; } 504 void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } 505 506 /// isCommon - Is this a 'common' symbol. 507 bool isCommon() const { return CommonSize != 0; } 508 509 /// setCommon - Mark this symbol as being 'common'. 510 /// 511 /// \param Size - The size of the symbol. 512 /// \param Align - The alignment of the symbol. 513 void setCommon(uint64_t Size, unsigned Align) { 514 CommonSize = Size; 515 CommonAlign = Align; 516 } 517 518 /// getCommonSize - Return the size of a 'common' symbol. 519 uint64_t getCommonSize() const { 520 assert(isCommon() && "Not a 'common' symbol!"); 521 return CommonSize; 522 } 523 524 /// getCommonAlignment - Return the alignment of a 'common' symbol. 525 unsigned getCommonAlignment() const { 526 assert(isCommon() && "Not a 'common' symbol!"); 527 return CommonAlign; 528 } 529 530 /// getFlags - Get the (implementation defined) symbol flags. 531 uint32_t getFlags() const { return Flags; } 532 533 /// setFlags - Set the (implementation defined) symbol flags. 534 void setFlags(uint32_t Value) { Flags = Value; } 535 536 /// getIndex - Get the (implementation defined) index. 537 uint64_t getIndex() const { return Index; } 538 539 /// setIndex - Set the (implementation defined) index. 540 void setIndex(uint64_t Value) { Index = Value; } 541 542 /// @} 543}; 544 545// FIXME: This really doesn't belong here. See comments below. 546struct IndirectSymbolData { 547 MCSymbol *Symbol; 548 MCSectionData *SectionData; 549}; 550 551class MCAssembler { 552public: 553 typedef iplist<MCSectionData> SectionDataListType; 554 typedef iplist<MCSymbolData> SymbolDataListType; 555 556 typedef SectionDataListType::const_iterator const_iterator; 557 typedef SectionDataListType::iterator iterator; 558 559 typedef SymbolDataListType::const_iterator const_symbol_iterator; 560 typedef SymbolDataListType::iterator symbol_iterator; 561 562 typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; 563 564private: 565 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT 566 void operator=(const MCAssembler&); // DO NOT IMPLEMENT 567 568 MCContext &Context; 569 570 raw_ostream &OS; 571 572 iplist<MCSectionData> Sections; 573 574 iplist<MCSymbolData> Symbols; 575 576 std::vector<IndirectSymbolData> IndirectSymbols; 577 578 unsigned SubsectionsViaSymbols : 1; 579 580private: 581 /// LayoutSection - Assign offsets and sizes to the fragments in the section 582 /// \arg SD, and update the section size. The section file offset should 583 /// already have been computed. 584 void LayoutSection(MCSectionData &SD); 585 586public: 587 /// Construct a new assembler instance. 588 /// 589 /// \arg OS - The stream to output to. 590 // 591 // FIXME: How are we going to parameterize this? Two obvious options are stay 592 // concrete and require clients to pass in a target like object. The other 593 // option is to make this abstract, and have targets provide concrete 594 // implementations as we do with AsmParser. 595 MCAssembler(MCContext &_Context, raw_ostream &OS); 596 ~MCAssembler(); 597 598 MCContext &getContext() const { return Context; } 599 600 /// Finish - Do final processing and write the object to the output stream. 601 void Finish(); 602 603 // FIXME: This does not belong here. 604 bool getSubsectionsViaSymbols() const { 605 return SubsectionsViaSymbols; 606 } 607 void setSubsectionsViaSymbols(bool Value) { 608 SubsectionsViaSymbols = Value; 609 } 610 611 /// @name Section List Access 612 /// @{ 613 614 const SectionDataListType &getSectionList() const { return Sections; } 615 SectionDataListType &getSectionList() { return Sections; } 616 617 iterator begin() { return Sections.begin(); } 618 const_iterator begin() const { return Sections.begin(); } 619 620 iterator end() { return Sections.end(); } 621 const_iterator end() const { return Sections.end(); } 622 623 size_t size() const { return Sections.size(); } 624 625 /// @} 626 /// @name Symbol List Access 627 /// @{ 628 629 const SymbolDataListType &getSymbolList() const { return Symbols; } 630 SymbolDataListType &getSymbolList() { return Symbols; } 631 632 symbol_iterator symbol_begin() { return Symbols.begin(); } 633 const_symbol_iterator symbol_begin() const { return Symbols.begin(); } 634 635 symbol_iterator symbol_end() { return Symbols.end(); } 636 const_symbol_iterator symbol_end() const { return Symbols.end(); } 637 638 size_t symbol_size() const { return Symbols.size(); } 639 640 /// @} 641 /// @name Indirect Symbol List Access 642 /// @{ 643 644 // FIXME: This is a total hack, this should not be here. Once things are 645 // factored so that the streamer has direct access to the .o writer, it can 646 // disappear. 647 std::vector<IndirectSymbolData> &getIndirectSymbols() { 648 return IndirectSymbols; 649 } 650 651 indirect_symbol_iterator indirect_symbol_begin() { 652 return IndirectSymbols.begin(); 653 } 654 655 indirect_symbol_iterator indirect_symbol_end() { 656 return IndirectSymbols.end(); 657 } 658 659 size_t indirect_symbol_size() const { return IndirectSymbols.size(); } 660 661 /// @} 662}; 663 664} // end namespace llvm 665 666#endif 667