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