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