MCAssembler.h revision 1f3e445184e5ca2aa4295c2a77f2a4e0b957fea1
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 /// @} 511 /// @name Symbol Attributes 512 /// @{ 513 514 bool isExternal() const { return IsExternal; } 515 void setExternal(bool Value) { IsExternal = Value; } 516 517 bool isPrivateExtern() const { return IsPrivateExtern; } 518 void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } 519 520 /// isCommon - Is this a 'common' symbol. 521 bool isCommon() const { return CommonSize != 0; } 522 523 /// setCommon - Mark this symbol as being 'common'. 524 /// 525 /// \param Size - The size of the symbol. 526 /// \param Align - The alignment of the symbol. 527 void setCommon(uint64_t Size, unsigned Align) { 528 CommonSize = Size; 529 CommonAlign = Align; 530 } 531 532 /// getCommonSize - Return the size of a 'common' symbol. 533 uint64_t getCommonSize() const { 534 assert(isCommon() && "Not a 'common' symbol!"); 535 return CommonSize; 536 } 537 538 /// getCommonAlignment - Return the alignment of a 'common' symbol. 539 unsigned getCommonAlignment() const { 540 assert(isCommon() && "Not a 'common' symbol!"); 541 return CommonAlign; 542 } 543 544 /// getFlags - Get the (implementation defined) symbol flags. 545 uint32_t getFlags() const { return Flags; } 546 547 /// setFlags - Set the (implementation defined) symbol flags. 548 void setFlags(uint32_t Value) { Flags = Value; } 549 550 /// getIndex - Get the (implementation defined) index. 551 uint64_t getIndex() const { return Index; } 552 553 /// setIndex - Set the (implementation defined) index. 554 void setIndex(uint64_t Value) { Index = Value; } 555 556 /// @} 557 558 void dump(); 559}; 560 561// FIXME: This really doesn't belong here. See comments below. 562struct IndirectSymbolData { 563 MCSymbol *Symbol; 564 MCSectionData *SectionData; 565}; 566 567class MCAssembler { 568public: 569 typedef iplist<MCSectionData> SectionDataListType; 570 typedef iplist<MCSymbolData> SymbolDataListType; 571 572 typedef SectionDataListType::const_iterator const_iterator; 573 typedef SectionDataListType::iterator iterator; 574 575 typedef SymbolDataListType::const_iterator const_symbol_iterator; 576 typedef SymbolDataListType::iterator symbol_iterator; 577 578 typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; 579 580private: 581 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT 582 void operator=(const MCAssembler&); // DO NOT IMPLEMENT 583 584 MCContext &Context; 585 586 TargetAsmBackend &Backend; 587 588 raw_ostream &OS; 589 590 iplist<MCSectionData> Sections; 591 592 iplist<MCSymbolData> Symbols; 593 594 /// The map of sections to their associated assembler backend data. 595 // 596 // FIXME: Avoid this indirection? 597 DenseMap<const MCSection*, MCSectionData*> SectionMap; 598 599 /// The map of symbols to their associated assembler backend data. 600 // 601 // FIXME: Avoid this indirection? 602 DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap; 603 604 std::vector<IndirectSymbolData> IndirectSymbols; 605 606 unsigned SubsectionsViaSymbols : 1; 607 608private: 609 /// LayoutSection - Assign offsets and sizes to the fragments in the section 610 /// \arg SD, and update the section size. The section file offset should 611 /// already have been computed. 612 void LayoutSection(MCSectionData &SD); 613 614public: 615 /// Construct a new assembler instance. 616 /// 617 /// \arg OS - The stream to output to. 618 // 619 // FIXME: How are we going to parameterize this? Two obvious options are stay 620 // concrete and require clients to pass in a target like object. The other 621 // option is to make this abstract, and have targets provide concrete 622 // implementations as we do with AsmParser. 623 MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS); 624 ~MCAssembler(); 625 626 MCContext &getContext() const { return Context; } 627 628 /// Finish - Do final processing and write the object to the output stream. 629 void Finish(); 630 631 // FIXME: This does not belong here. 632 bool getSubsectionsViaSymbols() const { 633 return SubsectionsViaSymbols; 634 } 635 void setSubsectionsViaSymbols(bool Value) { 636 SubsectionsViaSymbols = Value; 637 } 638 639 /// @name Section List Access 640 /// @{ 641 642 const SectionDataListType &getSectionList() const { return Sections; } 643 SectionDataListType &getSectionList() { return Sections; } 644 645 iterator begin() { return Sections.begin(); } 646 const_iterator begin() const { return Sections.begin(); } 647 648 iterator end() { return Sections.end(); } 649 const_iterator end() const { return Sections.end(); } 650 651 size_t size() const { return Sections.size(); } 652 653 /// @} 654 /// @name Symbol List Access 655 /// @{ 656 657 const SymbolDataListType &getSymbolList() const { return Symbols; } 658 SymbolDataListType &getSymbolList() { return Symbols; } 659 660 symbol_iterator symbol_begin() { return Symbols.begin(); } 661 const_symbol_iterator symbol_begin() const { return Symbols.begin(); } 662 663 symbol_iterator symbol_end() { return Symbols.end(); } 664 const_symbol_iterator symbol_end() const { return Symbols.end(); } 665 666 size_t symbol_size() const { return Symbols.size(); } 667 668 /// @} 669 /// @name Indirect Symbol List Access 670 /// @{ 671 672 // FIXME: This is a total hack, this should not be here. Once things are 673 // factored so that the streamer has direct access to the .o writer, it can 674 // disappear. 675 std::vector<IndirectSymbolData> &getIndirectSymbols() { 676 return IndirectSymbols; 677 } 678 679 indirect_symbol_iterator indirect_symbol_begin() { 680 return IndirectSymbols.begin(); 681 } 682 683 indirect_symbol_iterator indirect_symbol_end() { 684 return IndirectSymbols.end(); 685 } 686 687 size_t indirect_symbol_size() const { return IndirectSymbols.size(); } 688 689 /// @} 690 /// @name Backend Data Access 691 /// @{ 692 693 MCSectionData &getSectionData(const MCSection &Section) { 694 MCSectionData *&Entry = SectionMap[&Section]; 695 assert(Entry && "Missing section data!"); 696 return *Entry; 697 } 698 699 MCSectionData &getOrCreateSectionData(const MCSection &Section, 700 bool *Created = 0) { 701 MCSectionData *&Entry = SectionMap[&Section]; 702 703 if (Created) *Created = !Entry; 704 if (!Entry) 705 Entry = new MCSectionData(Section, this); 706 707 return *Entry; 708 } 709 710 MCSymbolData &getSymbolData(const MCSymbol &Symbol) { 711 MCSymbolData *&Entry = SymbolMap[&Symbol]; 712 assert(Entry && "Missing symbol data!"); 713 return *Entry; 714 } 715 716 MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, 717 bool *Created = 0) { 718 MCSymbolData *&Entry = SymbolMap[&Symbol]; 719 720 if (Created) *Created = !Entry; 721 if (!Entry) 722 Entry = new MCSymbolData(Symbol, 0, 0, this); 723 724 return *Entry; 725 } 726 727 /// @} 728 729 void dump(); 730}; 731 732} // end namespace llvm 733 734#endif 735