MCAssembler.h revision 6aff2fbd56d4bc2d6029f7c9bd49a97f6dc01213
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
20namespace llvm {
21class raw_ostream;
22class MCAssembler;
23class MCSection;
24class MCSectionData;
25
26class MCFragment : public ilist_node<MCFragment> {
27  MCFragment(const MCFragment&);     // DO NOT IMPLEMENT
28  void operator=(const MCFragment&); // DO NOT IMPLEMENT
29
30public:
31  enum FragmentType {
32    FT_Data,
33    FT_Align,
34    FT_Fill,
35    FT_Org
36  };
37
38private:
39  FragmentType Kind;
40
41  /// @name Assembler Backend Data
42  /// @{
43  //
44  // FIXME: This could all be kept private to the assembler implementation.
45
46  /// Offset - The offset of this fragment in its section. This is ~0 until
47  /// initialized.
48  uint64_t Offset;
49
50  /// FileSize - The file size of this section. This is ~0 until initialized.
51  uint64_t FileSize;
52
53  /// @}
54
55protected:
56  MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
57
58public:
59  // Only for sentinel.
60  MCFragment();
61  virtual ~MCFragment();
62
63  FragmentType getKind() const { return Kind; }
64
65  // FIXME: This should be abstract, fix sentinel.
66  virtual uint64_t getMaxFileSize() const {
67    assert(0 && "Invalid getMaxFileSize call!");
68    return 0;
69  };
70
71  /// @name Assembler Backend Support
72  /// @{
73  //
74  // FIXME: This could all be kept private to the assembler implementation.
75
76  unsigned getFileSize() const {
77    assert(FileSize != ~UINT64_C(0) && "File size not set!");
78    return FileSize;
79  }
80  void setFileSize(uint64_t Value) {
81    assert(Value <= getMaxFileSize() && "Invalid file size!");
82    FileSize = Value;
83  }
84
85  uint64_t getOffset() const {
86    assert(Offset != ~UINT64_C(0) && "File offset not set!");
87    return Offset;
88  }
89  void setOffset(uint64_t Value) { Offset = Value; }
90
91  /// @}
92
93  static bool classof(const MCFragment *O) { return true; }
94};
95
96class MCDataFragment : public MCFragment {
97  SmallString<32> Contents;
98
99public:
100  MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {}
101
102  /// @name Accessors
103  /// @{
104
105  uint64_t getMaxFileSize() const {
106    return Contents.size();
107  }
108
109  SmallString<32> &getContents() { return Contents; }
110  const SmallString<32> &getContents() const { return Contents; }
111
112  /// @}
113
114  static bool classof(const MCFragment *F) {
115    return F->getKind() == MCFragment::FT_Data;
116  }
117  static bool classof(const MCDataFragment *) { return true; }
118};
119
120class MCAlignFragment : public MCFragment {
121  /// Alignment - The alignment to ensure, in bytes.
122  unsigned Alignment;
123
124  /// Value - Value to use for filling padding bytes.
125  int64_t Value;
126
127  /// ValueSize - The size of the integer (in bytes) of \arg Value.
128  unsigned ValueSize;
129
130  /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
131  /// cannot be satisfied in this width then this fragment is ignored.
132  unsigned MaxBytesToEmit;
133
134public:
135  MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
136                  unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
137    : MCFragment(FT_Align, SD), Alignment(_Alignment),
138      Value(_Value),ValueSize(_ValueSize),
139      MaxBytesToEmit(_MaxBytesToEmit) {}
140
141  /// @name Accessors
142  /// @{
143
144  uint64_t getMaxFileSize() const {
145    return std::max(Alignment - 1, MaxBytesToEmit);
146  }
147
148  unsigned getAlignment() const { return Alignment; }
149
150  int64_t getValue() const { return Value; }
151
152  unsigned getValueSize() const { return ValueSize; }
153
154  unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
155
156  /// @}
157
158  static bool classof(const MCFragment *F) {
159    return F->getKind() == MCFragment::FT_Align;
160  }
161  static bool classof(const MCAlignFragment *) { return true; }
162};
163
164class MCFillFragment : public MCFragment {
165  /// Value - Value to use for filling bytes.
166  MCValue Value;
167
168  /// ValueSize - The size (in bytes) of \arg Value to use when filling.
169  unsigned ValueSize;
170
171  /// Count - The number of copies of \arg Value to insert.
172  uint64_t Count;
173
174public:
175  MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count,
176                 MCSectionData *SD = 0)
177    : MCFragment(FT_Fill, SD),
178      Value(_Value), ValueSize(_ValueSize), Count(_Count) {}
179
180  /// @name Accessors
181  /// @{
182
183  uint64_t getMaxFileSize() const {
184    return ValueSize * Count;
185  }
186
187  MCValue getValue() const { return Value; }
188
189  unsigned getValueSize() const { return ValueSize; }
190
191  uint64_t getCount() const { return Count; }
192
193  /// @}
194
195  static bool classof(const MCFragment *F) {
196    return F->getKind() == MCFragment::FT_Fill;
197  }
198  static bool classof(const MCFillFragment *) { return true; }
199};
200
201class MCOrgFragment : public MCFragment {
202  /// Offset - The offset this fragment should start at.
203  MCValue Offset;
204
205  /// Value - Value to use for filling bytes.
206  int8_t Value;
207
208public:
209  MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0)
210    : MCFragment(FT_Org, SD),
211      Offset(_Offset), Value(_Value) {}
212  /// @name Accessors
213  /// @{
214
215  uint64_t getMaxFileSize() const {
216    // FIXME: This doesn't make much sense.
217    return ~UINT64_C(0);
218  }
219
220  MCValue getOffset() const { return Offset; }
221
222  uint8_t getValue() const { return Value; }
223
224  /// @}
225
226  static bool classof(const MCFragment *F) {
227    return F->getKind() == MCFragment::FT_Org;
228  }
229  static bool classof(const MCOrgFragment *) { return true; }
230};
231
232// FIXME: Should this be a separate class, or just merged into MCSection? Since
233// we anticipate the fast path being through an MCAssembler, the only reason to
234// keep it out is for API abstraction.
235class MCSectionData : public ilist_node<MCSectionData> {
236  MCSectionData(const MCSectionData&);  // DO NOT IMPLEMENT
237  void operator=(const MCSectionData&); // DO NOT IMPLEMENT
238
239public:
240  typedef iplist<MCFragment> FragmentListType;
241
242  typedef FragmentListType::const_iterator const_iterator;
243  typedef FragmentListType::iterator iterator;
244
245private:
246  iplist<MCFragment> Fragments;
247  const MCSection &Section;
248
249  /// Alignment - The maximum alignment seen in this section.
250  unsigned Alignment;
251
252  /// @name Assembler Backend Data
253  /// @{
254  //
255  // FIXME: This could all be kept private to the assembler implementation.
256
257  /// FileSize - The size of this section in the object file. This is ~0 until
258  /// initialized.
259  uint64_t FileSize;
260
261  /// @}
262
263public:
264  // Only for use as sentinel.
265  MCSectionData();
266  MCSectionData(const MCSection &Section, MCAssembler *A = 0);
267
268  const MCSection &getSection() const { return Section; }
269
270  unsigned getAlignment() const { return Alignment; }
271  void setAlignment(unsigned Value) { Alignment = Value; }
272
273  /// @name Section List Access
274  /// @{
275
276  const FragmentListType &getFragmentList() const { return Fragments; }
277  FragmentListType &getFragmentList() { return Fragments; }
278
279  iterator begin() { return Fragments.begin(); }
280  const_iterator begin() const { return Fragments.begin(); }
281
282  iterator end() { return Fragments.end(); }
283  const_iterator end() const { return Fragments.end(); }
284
285  size_t size() const { return Fragments.size(); }
286
287  bool empty() const { return Fragments.empty(); }
288
289  /// @}
290  /// @name Assembler Backend Support
291  /// @{
292  //
293  // FIXME: This could all be kept private to the assembler implementation.
294
295  unsigned getFileSize() const {
296    assert(FileSize != ~UINT64_C(0) && "File size not set!");
297    return FileSize;
298  }
299  void setFileSize(uint64_t Value) { FileSize = Value; }
300
301  /// @}
302};
303
304// FIXME: Same concerns as with SectionData.
305class MCSymbolData : public ilist_node<MCSymbolData> {
306public:
307  MCSymbol &Symbol;
308
309  /// Fragment - The fragment this symbol's value is relative to, if any.
310  MCFragment *Fragment;
311
312  /// Offset - The offset to apply to the fragment address to form this symbol's
313  /// value.
314  uint64_t Offset;
315
316  /// IsExternal - True if this symbol is visible outside this translation
317  /// unit.
318  unsigned IsExternal : 1;
319
320  /// IsPrivateExtern - True if this symbol is private extern.
321  unsigned IsPrivateExtern : 1;
322
323  /// Flags - The Flags field is used by object file implementations to store
324  /// additional per symbol information which is not easily classified.
325  uint32_t Flags;
326
327public:
328  // Only for use as sentinel.
329  MCSymbolData();
330  MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
331               MCAssembler *A = 0);
332
333  /// @name Accessors
334  /// @{
335
336  MCSymbol &getSymbol() const { return Symbol; }
337
338  MCFragment *getFragment() const { return Fragment; }
339  void setFragment(MCFragment *Value) { Fragment = Value; }
340
341  uint64_t getOffset() const { return Offset; }
342  void setOffset(uint64_t Value) { Offset = Value; }
343
344  /// @}
345  /// @name Symbol Attributes
346  /// @{
347
348  bool isExternal() const { return IsExternal; }
349  void setExternal(bool Value) { IsExternal = Value; }
350
351  bool isPrivateExtern() const { return IsPrivateExtern; }
352  void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
353
354  /// getFlags - Get the (implementation defined) symbol flags.
355  uint32_t getFlags() const { return Flags; }
356
357  /// setFlags - Set the (implementation defined) symbol flags.
358  void setFlags(uint32_t Value) { Flags = Value; }
359
360  /// @}
361};
362
363class MCAssembler {
364public:
365  typedef iplist<MCSectionData> SectionDataListType;
366  typedef iplist<MCSymbolData> SymbolDataListType;
367
368  typedef SectionDataListType::const_iterator const_iterator;
369  typedef SectionDataListType::iterator iterator;
370
371  typedef SymbolDataListType::const_iterator const_symbol_iterator;
372  typedef SymbolDataListType::iterator symbol_iterator;
373
374private:
375  MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
376  void operator=(const MCAssembler&); // DO NOT IMPLEMENT
377
378  raw_ostream &OS;
379
380  iplist<MCSectionData> Sections;
381
382  iplist<MCSymbolData> Symbols;
383
384private:
385  /// LayoutSection - Assign offsets and sizes to the fragments in the section
386  /// \arg SD, and update the section size. The section file offset should
387  /// already have been computed.
388  void LayoutSection(MCSectionData &SD);
389
390public:
391  /// Construct a new assembler instance.
392  ///
393  /// \arg OS - The stream to output to.
394  //
395  // FIXME: How are we going to parameterize this? Two obvious options are stay
396  // concrete and require clients to pass in a target like object. The other
397  // option is to make this abstract, and have targets provide concrete
398  // implementations as we do with AsmParser.
399  MCAssembler(raw_ostream &OS);
400  ~MCAssembler();
401
402  /// Finish - Do final processing and write the object to the output stream.
403  void Finish();
404
405  /// @name Section List Access
406  /// @{
407
408  const SectionDataListType &getSectionList() const { return Sections; }
409  SectionDataListType &getSectionList() { return Sections; }
410
411  iterator begin() { return Sections.begin(); }
412  const_iterator begin() const { return Sections.begin(); }
413
414  iterator end() { return Sections.end(); }
415  const_iterator end() const { return Sections.end(); }
416
417  size_t size() const { return Sections.size(); }
418
419  /// @}
420  /// @name Symbol List Access
421  /// @{
422
423  const SymbolDataListType &getSymbolList() const { return Symbols; }
424  SymbolDataListType &getSymbolList() { return Symbols; }
425
426  symbol_iterator symbol_begin() { return Symbols.begin(); }
427  const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
428
429  symbol_iterator symbol_end() { return Symbols.end(); }
430  const_symbol_iterator symbol_end() const { return Symbols.end(); }
431
432  size_t symbol_size() const { return Symbols.size(); }
433
434  /// @}
435};
436
437} // end namespace llvm
438
439#endif
440