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