llvm-mc/Mach-O: Move more logic for writing the Mach-O file into the writer
[oota-llvm.git] / include / llvm / MC / MCAssembler.h
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
20 namespace llvm {
21 class raw_ostream;
22 class MCAssembler;
23 class MCSection;
24 class MCSectionData;
25
26 class MCFragment : public ilist_node<MCFragment> {
27   MCFragment(const MCFragment&);     // DO NOT IMPLEMENT
28   void operator=(const MCFragment&); // DO NOT IMPLEMENT
29
30 public:
31   enum FragmentType {
32     FT_Data,
33     FT_Align,
34     FT_Fill,
35     FT_Org
36   };
37
38 private:
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
55 protected:
56   MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
57
58 public:
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
96 class MCDataFragment : public MCFragment {
97   SmallString<32> Contents;
98
99 public:
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
120 class 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
134 public:
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
164 class 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
174 public:
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
201 class 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
208 public:
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.
235 class MCSectionData : public ilist_node<MCSectionData> {
236   MCSectionData(const MCSectionData&);  // DO NOT IMPLEMENT
237   void operator=(const MCSectionData&); // DO NOT IMPLEMENT
238
239 public:
240   typedef iplist<MCFragment> FragmentListType;
241
242   typedef FragmentListType::const_iterator const_iterator;
243   typedef FragmentListType::iterator iterator;
244
245 private:
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
263 public:    
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
274   /// @name Section List Access
275   /// @{
276
277   const FragmentListType &getFragmentList() const { return Fragments; }
278   FragmentListType &getFragmentList() { return Fragments; }
279
280   iterator begin() { return Fragments.begin(); }
281   const_iterator begin() const { return Fragments.begin(); }
282
283   iterator end() { return Fragments.end(); }
284   const_iterator end() const { return Fragments.end(); }
285
286   size_t size() const { return Fragments.size(); }
287
288   /// @}
289   /// @name Assembler Backend Support
290   /// @{
291   //
292   // FIXME: This could all be kept private to the assembler implementation.
293
294   unsigned getFileSize() const { 
295     assert(FileSize != ~UINT64_C(0) && "File size not set!");
296     return FileSize;
297   }
298   void setFileSize(uint64_t Value) { FileSize = Value; }
299
300   /// @}
301 };
302
303 class MCAssembler {
304 public:
305   typedef iplist<MCSectionData> SectionDataListType;
306
307   typedef SectionDataListType::const_iterator const_iterator;
308   typedef SectionDataListType::iterator iterator;
309
310 private:
311   MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
312   void operator=(const MCAssembler&); // DO NOT IMPLEMENT
313
314   raw_ostream &OS;
315   
316   iplist<MCSectionData> Sections;
317
318 private:
319   /// LayoutSection - Assign offsets and sizes to the fragments in the section
320   /// \arg SD, and update the section size. The section file offset should
321   /// already have been computed.
322   void LayoutSection(MCSectionData &SD);
323
324 public:
325   /// Construct a new assembler instance.
326   ///
327   /// \arg OS - The stream to output to.
328   //
329   // FIXME: How are we going to parameterize this? Two obvious options are stay
330   // concrete and require clients to pass in a target like object. The other
331   // option is to make this abstract, and have targets provide concrete
332   // implementations as we do with AsmParser.
333   MCAssembler(raw_ostream &OS);
334   ~MCAssembler();
335
336   /// Finish - Do final processing and write the object to the output stream.
337   void Finish();
338
339   /// @name Section List Access
340   /// @{
341
342   const SectionDataListType &getSectionList() const { return Sections; }
343   SectionDataListType &getSectionList() { return Sections; }  
344
345   iterator begin() { return Sections.begin(); }
346   const_iterator begin() const { return Sections.begin(); }
347
348   iterator end() { return Sections.end(); }
349   const_iterator end() const { return Sections.end(); }
350
351   size_t size() const { return Sections.size(); }
352
353   /// @}
354 };
355
356 } // end namespace llvm
357
358 #endif