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