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