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