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