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