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