Rename TargetAsmInfo (and its subclasses) to MCAsmInfo.
[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   /// @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.
305 class MCSymbolData : public ilist_node<MCSymbolData> {
306 public:
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 public:
321   // Only for use as sentinel.
322   MCSymbolData();
323   MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
324                MCAssembler *A = 0);
325
326   /// @name Accessors
327   /// @{
328
329   MCSymbol &getSymbol() const { return Symbol; }
330
331   MCFragment *getFragment() const { return Fragment; }
332   void setFragment(MCFragment *Value) { Fragment = Value; }
333
334   uint64_t getOffset() const { return Offset; }
335   void setOffset(uint64_t Value) { Offset = Value; }
336
337     /// @}
338     /// @name Symbol Attributes
339     /// @{
340
341     bool isExternal() const { return IsExternal; }
342     void setExternal(bool Value) { IsExternal = Value; }
343
344   /// @}  
345 };
346
347 class MCAssembler {
348 public:
349   typedef iplist<MCSectionData> SectionDataListType;
350   typedef iplist<MCSymbolData> SymbolDataListType;
351
352   typedef SectionDataListType::const_iterator const_iterator;
353   typedef SectionDataListType::iterator iterator;
354
355   typedef SymbolDataListType::const_iterator const_symbol_iterator;
356   typedef SymbolDataListType::iterator symbol_iterator;
357
358 private:
359   MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
360   void operator=(const MCAssembler&); // DO NOT IMPLEMENT
361
362   raw_ostream &OS;
363   
364   iplist<MCSectionData> Sections;
365
366   iplist<MCSymbolData> Symbols;
367
368 private:
369   /// LayoutSection - Assign offsets and sizes to the fragments in the section
370   /// \arg SD, and update the section size. The section file offset should
371   /// already have been computed.
372   void LayoutSection(MCSectionData &SD);
373
374 public:
375   /// Construct a new assembler instance.
376   ///
377   /// \arg OS - The stream to output to.
378   //
379   // FIXME: How are we going to parameterize this? Two obvious options are stay
380   // concrete and require clients to pass in a target like object. The other
381   // option is to make this abstract, and have targets provide concrete
382   // implementations as we do with AsmParser.
383   MCAssembler(raw_ostream &OS);
384   ~MCAssembler();
385
386   /// Finish - Do final processing and write the object to the output stream.
387   void Finish();
388
389   /// @name Section List Access
390   /// @{
391
392   const SectionDataListType &getSectionList() const { return Sections; }
393   SectionDataListType &getSectionList() { return Sections; }  
394
395   iterator begin() { return Sections.begin(); }
396   const_iterator begin() const { return Sections.begin(); }
397
398   iterator end() { return Sections.end(); }
399   const_iterator end() const { return Sections.end(); }
400
401   size_t size() const { return Sections.size(); }
402
403   /// @}
404   /// @name Symbol List Access
405   /// @{
406
407   const SymbolDataListType &getSymbolList() const { return Symbols; }
408   SymbolDataListType &getSymbolList() { return Symbols; }
409
410   symbol_iterator symbol_begin() { return Symbols.begin(); }
411   const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
412
413   symbol_iterator symbol_end() { return Symbols.end(); }
414   const_symbol_iterator symbol_end() const { return Symbols.end(); }
415
416   size_t symbol_size() const { return Symbols.size(); }
417
418   /// @}
419 };
420
421 } // end namespace llvm
422
423 #endif