MCAssembler.h revision be9635569401b9a40984c02c6e171aa9da9ad0a2
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  typedef iplist<MCFragment> FragmentListType;
250
251  typedef FragmentListType::const_iterator const_iterator;
252  typedef FragmentListType::iterator iterator;
253
254private:
255  iplist<MCFragment> Fragments;
256  const MCSection &Section;
257
258  /// Alignment - The maximum alignment seen in this section.
259  unsigned Alignment;
260
261  /// @name Assembler Backend Data
262  /// @{
263  //
264  // FIXME: This could all be kept private to the assembler implementation.
265
266  /// Address - The computed address of this section. This is ~0 until
267  /// initialized.
268  uint64_t Address;
269
270  /// Size - The content size of this section. This is ~0 until initialized.
271  uint64_t Size;
272
273  /// FileSize - The size of this section in the object file. This is ~0 until
274  /// initialized.
275  uint64_t FileSize;
276
277  /// @}
278
279public:
280  // Only for use as sentinel.
281  MCSectionData();
282  MCSectionData(const MCSection &Section, MCAssembler *A = 0);
283
284  const MCSection &getSection() const { return Section; }
285
286  unsigned getAlignment() const { return Alignment; }
287  void setAlignment(unsigned Value) { Alignment = Value; }
288
289  /// @name Fragment Access
290  /// @{
291
292  const FragmentListType &getFragmentList() const { return Fragments; }
293  FragmentListType &getFragmentList() { return Fragments; }
294
295  iterator begin() { return Fragments.begin(); }
296  const_iterator begin() const { return Fragments.begin(); }
297
298  iterator end() { return Fragments.end(); }
299  const_iterator end() const { return Fragments.end(); }
300
301  size_t size() const { return Fragments.size(); }
302
303  bool empty() const { return Fragments.empty(); }
304
305  /// @}
306  /// @name Assembler Backend Support
307  /// @{
308  //
309  // FIXME: This could all be kept private to the assembler implementation.
310
311  uint64_t getAddress() const {
312    assert(Address != ~UINT64_C(0) && "Address not set!");
313    return Address;
314  }
315  void setAddress(uint64_t Value) { Address = Value; }
316
317  uint64_t getSize() const {
318    assert(Size != ~UINT64_C(0) && "File size not set!");
319    return Size;
320  }
321  void setSize(uint64_t Value) { Size = Value; }
322
323  uint64_t getFileSize() const {
324    assert(FileSize != ~UINT64_C(0) && "File size not set!");
325    return FileSize;
326  }
327  void setFileSize(uint64_t Value) { FileSize = Value; }
328
329  /// @}
330};
331
332// FIXME: Same concerns as with SectionData.
333class MCSymbolData : public ilist_node<MCSymbolData> {
334public:
335  MCSymbol &Symbol;
336
337  /// Fragment - The fragment this symbol's value is relative to, if any.
338  MCFragment *Fragment;
339
340  /// Offset - The offset to apply to the fragment address to form this symbol's
341  /// value.
342  uint64_t Offset;
343
344  /// IsExternal - True if this symbol is visible outside this translation
345  /// unit.
346  unsigned IsExternal : 1;
347
348  /// IsPrivateExtern - True if this symbol is private extern.
349  unsigned IsPrivateExtern : 1;
350
351  /// Flags - The Flags field is used by object file implementations to store
352  /// additional per symbol information which is not easily classified.
353  uint32_t Flags;
354
355  /// Index - Index field, for use by the object file implementation.
356  uint64_t Index;
357
358public:
359  // Only for use as sentinel.
360  MCSymbolData();
361  MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
362               MCAssembler *A = 0);
363
364  /// @name Accessors
365  /// @{
366
367  MCSymbol &getSymbol() const { return Symbol; }
368
369  MCFragment *getFragment() const { return Fragment; }
370  void setFragment(MCFragment *Value) { Fragment = Value; }
371
372  uint64_t getOffset() const { return Offset; }
373  void setOffset(uint64_t Value) { Offset = Value; }
374
375  /// @}
376  /// @name Symbol Attributes
377  /// @{
378
379  bool isExternal() const { return IsExternal; }
380  void setExternal(bool Value) { IsExternal = Value; }
381
382  bool isPrivateExtern() const { return IsPrivateExtern; }
383  void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
384
385  /// getFlags - Get the (implementation defined) symbol flags.
386  uint32_t getFlags() const { return Flags; }
387
388  /// setFlags - Set the (implementation defined) symbol flags.
389  void setFlags(uint32_t Value) { Flags = Value; }
390
391  /// getIndex - Get the (implementation defined) index.
392  uint64_t getIndex() const { return Index; }
393
394  /// setIndex - Set the (implementation defined) index.
395  void setIndex(uint64_t Value) { Index = Value; }
396
397  /// @}
398};
399
400// FIXME: This really doesn't belong here. See comments below.
401struct IndirectSymbolData {
402  MCSymbol *Symbol;
403  MCSectionData *SectionData;
404};
405
406class MCAssembler {
407public:
408  typedef iplist<MCSectionData> SectionDataListType;
409  typedef iplist<MCSymbolData> SymbolDataListType;
410
411  typedef SectionDataListType::const_iterator const_iterator;
412  typedef SectionDataListType::iterator iterator;
413
414  typedef SymbolDataListType::const_iterator const_symbol_iterator;
415  typedef SymbolDataListType::iterator symbol_iterator;
416
417  typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
418
419private:
420  MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
421  void operator=(const MCAssembler&); // DO NOT IMPLEMENT
422
423  raw_ostream &OS;
424
425  iplist<MCSectionData> Sections;
426
427  iplist<MCSymbolData> Symbols;
428
429  std::vector<IndirectSymbolData> IndirectSymbols;
430
431private:
432  /// LayoutSection - Assign offsets and sizes to the fragments in the section
433  /// \arg SD, and update the section size. The section file offset should
434  /// already have been computed.
435  ///
436  /// \param NextAlign - The alignment for the section end address, which may
437  /// add padding bytes to the section (these are included in the section "file"
438  /// size, but not its regular size).
439  void LayoutSection(MCSectionData &SD, unsigned NextAlign);
440
441public:
442  /// Construct a new assembler instance.
443  ///
444  /// \arg OS - The stream to output to.
445  //
446  // FIXME: How are we going to parameterize this? Two obvious options are stay
447  // concrete and require clients to pass in a target like object. The other
448  // option is to make this abstract, and have targets provide concrete
449  // implementations as we do with AsmParser.
450  MCAssembler(raw_ostream &OS);
451  ~MCAssembler();
452
453  /// Finish - Do final processing and write the object to the output stream.
454  void Finish();
455
456  /// @name Section List Access
457  /// @{
458
459  const SectionDataListType &getSectionList() const { return Sections; }
460  SectionDataListType &getSectionList() { return Sections; }
461
462  iterator begin() { return Sections.begin(); }
463  const_iterator begin() const { return Sections.begin(); }
464
465  iterator end() { return Sections.end(); }
466  const_iterator end() const { return Sections.end(); }
467
468  size_t size() const { return Sections.size(); }
469
470  /// @}
471  /// @name Symbol List Access
472  /// @{
473
474  const SymbolDataListType &getSymbolList() const { return Symbols; }
475  SymbolDataListType &getSymbolList() { return Symbols; }
476
477  symbol_iterator symbol_begin() { return Symbols.begin(); }
478  const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
479
480  symbol_iterator symbol_end() { return Symbols.end(); }
481  const_symbol_iterator symbol_end() const { return Symbols.end(); }
482
483  size_t symbol_size() const { return Symbols.size(); }
484
485  /// @}
486  /// @name Indirect Symbol List Access
487  /// @{
488
489  // FIXME: This is a total hack, this should not be here. Once things are
490  // factored so that the streamer has direct access to the .o writer, it can
491  // disappear.
492  std::vector<IndirectSymbolData> &getIndirectSymbols() {
493    return IndirectSymbols;
494  }
495
496  indirect_symbol_iterator indirect_symbol_begin() {
497    return IndirectSymbols.begin();
498  }
499
500  indirect_symbol_iterator indirect_symbol_end() {
501    return IndirectSymbols.end();
502  }
503
504  size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
505
506  /// @}
507};
508
509} // end namespace llvm
510
511#endif
512