MCAssembler.h revision d6f761e0eb610936a6b8495360b62696dcd85164
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  /// FileOffset - The offset of this section in the object file. This is ~0
47  /// until initialized.
48  uint64_t FileOffset;
49
50  /// FileSize - The size of this section in the object file. This is ~0 until
51  /// initialized.
52  uint64_t FileSize;
53
54  /// @}
55
56protected:
57  MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
58
59public:
60  // Only for sentinel.
61  MCFragment();
62  virtual ~MCFragment();
63
64  FragmentType getKind() const { return Kind; }
65
66  // FIXME: This should be abstract, fix sentinel.
67  virtual uint64_t getMaxFileSize() const {
68    assert(0 && "Invalid getMaxFileSize call !");
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 getFileOffset() const {
86    assert(FileOffset != ~UINT64_C(0) && "File offset not set!");
87    return FileOffset;
88  }
89  void setFileOffset(uint64_t Value) { FileOffset = 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  /// FileOffset - The offset of this section in the object file. This is ~0
258  /// until initialized.
259  uint64_t FileOffset;
260
261  /// FileSize - The size of this section in the object file. This is ~0 until
262  /// initialized.
263  uint64_t FileSize;
264
265  /// @}
266
267public:
268  // Only for use as sentinel.
269  MCSectionData();
270  MCSectionData(const MCSection &Section, MCAssembler *A = 0);
271
272  const MCSection &getSection() const { return Section; }
273
274  unsigned getAlignment() const { return Alignment; }
275  void setAlignment(unsigned Value) { Alignment = Value; }
276
277
278  /// @name Section List Access
279  /// @{
280
281  const FragmentListType &getFragmentList() const { return Fragments; }
282  FragmentListType &getFragmentList() { return Fragments; }
283
284  iterator begin() { return Fragments.begin(); }
285  const_iterator begin() const { return Fragments.begin(); }
286
287  iterator end() { return Fragments.end(); }
288  const_iterator end() const { return Fragments.end(); }
289
290  size_t size() const { return Fragments.size(); }
291
292  /// @}
293  /// @name Assembler Backend Support
294  /// @{
295  //
296  // FIXME: This could all be kept private to the assembler implementation.
297
298  unsigned getFileSize() const {
299    assert(FileSize != ~UINT64_C(0) && "File size not set!");
300    return FileSize;
301  }
302  void setFileSize(uint64_t Value) { FileSize = Value; }
303
304  uint64_t getFileOffset() const {
305    assert(FileOffset != ~UINT64_C(0) && "File offset not set!");
306    return FileOffset;
307  }
308  void setFileOffset(uint64_t Value) { FileOffset = Value; }
309
310  /// @}
311};
312
313class MCAssembler {
314public:
315  typedef iplist<MCSectionData> SectionDataListType;
316
317  typedef SectionDataListType::const_iterator const_iterator;
318  typedef SectionDataListType::iterator iterator;
319
320private:
321  MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
322  void operator=(const MCAssembler&); // DO NOT IMPLEMENT
323
324  raw_ostream &OS;
325
326  iplist<MCSectionData> Sections;
327
328private:
329  /// LayoutSection - Assign offsets and sizes to the fragments in the section
330  /// \arg SD, and update the section size. The section file offset should
331  /// already have been computed.
332  void LayoutSection(MCSectionData &SD);
333
334public:
335  /// Construct a new assembler instance.
336  ///
337  /// \arg OS - The stream to output to.
338  //
339  // FIXME: How are we going to parameterize this? Two obvious options are stay
340  // concrete and require clients to pass in a target like object. The other
341  // option is to make this abstract, and have targets provide concrete
342  // implementations as we do with AsmParser.
343  MCAssembler(raw_ostream &OS);
344  ~MCAssembler();
345
346  /// Finish - Do final processing and write the object to the output stream.
347  void Finish();
348
349  /// @name Section List Access
350  /// @{
351
352  const SectionDataListType &getSectionList() const { return Sections; }
353  SectionDataListType &getSectionList() { return Sections; }
354
355  iterator begin() { return Sections.begin(); }
356  const_iterator begin() const { return Sections.begin(); }
357
358  iterator end() { return Sections.end(); }
359  const_iterator end() const { return Sections.end(); }
360
361  size_t size() const { return Sections.size(); }
362
363  /// @}
364};
365
366} // end namespace llvm
367
368#endif
369