llvm-mc/Mach-O: Support byte and fill value emission.
[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   /// 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
56 protected:
57   MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
58
59 public:
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 unsigned 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
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   unsigned 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   unsigned 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   unsigned 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   int64_t Value;
207
208   /// ValueSize - The size (in bytes) of \arg Value to use when filling.
209   unsigned ValueSize;
210
211 public:
212   MCOrgFragment(MCValue _Offset, int64_t _Value, unsigned _ValueSize,
213                 MCSectionData *SD = 0)
214     : MCFragment(FT_Org, SD),
215       Offset(_Offset), Value(_Value), ValueSize(_ValueSize) {}
216   /// @name Accessors
217   /// @{
218
219   unsigned getMaxFileSize() const {
220     // FIXME
221     return 0;
222   }
223
224   MCValue getOffset() const { return Offset; }
225   
226   int64_t getValue() const { return Value; }
227   
228   unsigned getValueSize() const { return ValueSize; }
229
230   /// @}
231
232   static bool classof(const MCFragment *F) { 
233     return F->getKind() == MCFragment::FT_Org; 
234   }
235   static bool classof(const MCOrgFragment *) { return true; }
236 };
237
238 // FIXME: Should this be a separate class, or just merged into MCSection? Since
239 // we anticipate the fast path being through an MCAssembler, the only reason to
240 // keep it out is for API abstraction.
241 class MCSectionData : public ilist_node<MCSectionData> {
242   MCSectionData(const MCSectionData&);  // DO NOT IMPLEMENT
243   void operator=(const MCSectionData&); // DO NOT IMPLEMENT
244
245 public:
246   typedef iplist<MCFragment> FragmentListType;
247
248   typedef FragmentListType::const_iterator const_iterator;
249   typedef FragmentListType::iterator iterator;
250
251 private:
252   iplist<MCFragment> Fragments;
253   const MCSection &Section;
254
255   /// Alignment - The maximum alignment seen in this section.
256   unsigned Alignment;
257
258   /// @name Assembler Backend Data
259   /// @{
260   //
261   // FIXME: This could all be kept private to the assembler implementation.
262
263   /// FileOffset - The offset of this section in the object file. This is ~0
264   /// until initialized.
265   uint64_t FileOffset;
266
267   /// FileSize - The size of this section in the object file. This is ~0 until
268   /// initialized.
269   uint64_t FileSize;
270
271   /// @}
272
273 public:    
274   // Only for use as sentinel.
275   MCSectionData();
276   MCSectionData(const MCSection &Section, MCAssembler *A = 0);
277
278   const MCSection &getSection() const { return Section; }
279
280   unsigned getAlignment() const { return Alignment; }
281   void setAlignment(unsigned Value) { Alignment = Value; }
282
283
284   /// @name Section List Access
285   /// @{
286
287   const FragmentListType &getFragmentList() const { return Fragments; }
288   FragmentListType &getFragmentList() { return Fragments; }
289
290   iterator begin() { return Fragments.begin(); }
291   const_iterator begin() const { return Fragments.begin(); }
292
293   iterator end() { return Fragments.end(); }
294   const_iterator end() const { return Fragments.end(); }
295
296   size_t size() const { return Fragments.size(); }
297
298   /// @}
299   /// @name Assembler Backend Support
300   /// @{
301   //
302   // FIXME: This could all be kept private to the assembler implementation.
303
304   unsigned getFileSize() const { 
305     assert(FileSize != ~UINT64_C(0) && "File size not set!");
306     return FileSize;
307   }
308   void setFileSize(uint64_t Value) { FileSize = Value; }
309
310   uint64_t getFileOffset() const {
311     assert(FileOffset != ~UINT64_C(0) && "File offset not set!");
312     return FileOffset;
313   }
314   void setFileOffset(uint64_t Value) { FileOffset = Value; }
315
316   /// @}
317 };
318
319 class MCAssembler {
320 public:
321   typedef iplist<MCSectionData> SectionDataListType;
322
323   typedef SectionDataListType::const_iterator const_iterator;
324   typedef SectionDataListType::iterator iterator;
325
326 private:
327   MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
328   void operator=(const MCAssembler&); // DO NOT IMPLEMENT
329
330   raw_ostream &OS;
331   
332   iplist<MCSectionData> Sections;
333
334 private:
335   /// LayoutSection - Assign offsets and sizes to the fragments in the section
336   /// \arg SD, and update the section size. The section file offset should
337   /// already have been computed.
338   void LayoutSection(MCSectionData &SD);
339
340 public:
341   /// Construct a new assembler instance.
342   ///
343   /// \arg OS - The stream to output to.
344   //
345   // FIXME: How are we going to parameterize this? Two obvious options are stay
346   // concrete and require clients to pass in a target like object. The other
347   // option is to make this abstract, and have targets provide concrete
348   // implementations as we do with AsmParser.
349   MCAssembler(raw_ostream &OS);
350   ~MCAssembler();
351
352   /// Finish - Do final processing and write the object to the output stream.
353   void Finish();
354
355   /// @name Section List Access
356   /// @{
357
358   const SectionDataListType &getSectionList() const { return Sections; }
359   SectionDataListType &getSectionList() { return Sections; }  
360
361   iterator begin() { return Sections.begin(); }
362   const_iterator begin() const { return Sections.begin(); }
363
364   iterator end() { return Sections.end(); }
365   const_iterator end() const { return Sections.end(); }
366
367   size_t size() const { return Sections.size(); }
368
369   /// @}
370 };
371
372 } // end namespace llvm
373
374 #endif