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