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