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