182d2fe4d0a88c88e5315e3e1cb359b21325f334
[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     FT_ZeroFill
38   };
39
40 private:
41   FragmentType Kind;
42
43   /// Parent - The data for the section this fragment is in.
44   MCSectionData *Parent;
45
46   /// @name Assembler Backend Data
47   /// @{
48   //
49   // FIXME: This could all be kept private to the assembler implementation.
50
51   /// Offset - The offset of this fragment in its section. This is ~0 until
52   /// initialized.
53   uint64_t Offset;
54
55   /// FileSize - The file size of this section. This is ~0 until initialized.
56   uint64_t FileSize;
57
58   /// @}
59
60 protected:
61   MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0);
62
63 public:
64   // Only for sentinel.
65   MCFragment();
66   virtual ~MCFragment();
67
68   FragmentType getKind() const { return Kind; }
69
70   MCSectionData *getParent() const { return Parent; }
71   void setParent(MCSectionData *Value) { Parent = Value; }
72
73   // FIXME: This should be abstract, fix sentinel.
74   virtual uint64_t getMaxFileSize() const {
75     assert(0 && "Invalid getMaxFileSize call!");
76     return 0;
77   };
78
79   /// @name Assembler Backend Support
80   /// @{
81   //
82   // FIXME: This could all be kept private to the assembler implementation.
83
84   uint64_t getAddress() const;
85
86   uint64_t getFileSize() const { 
87     assert(FileSize != ~UINT64_C(0) && "File size not set!");
88     return FileSize;
89   }
90   void setFileSize(uint64_t Value) {
91     assert(Value <= getMaxFileSize() && "Invalid file size!");
92     FileSize = Value;
93   }
94
95   uint64_t getOffset() const {
96     assert(Offset != ~UINT64_C(0) && "File offset not set!");
97     return Offset;
98   }
99   void setOffset(uint64_t Value) { Offset = Value; }
100
101   /// @}
102
103   static bool classof(const MCFragment *O) { return true; }
104 };
105
106 class MCDataFragment : public MCFragment {
107   SmallString<32> Contents;
108
109 public:
110   MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {}
111
112   /// @name Accessors
113   /// @{
114
115   uint64_t getMaxFileSize() const {
116     return Contents.size();
117   }
118
119   SmallString<32> &getContents() { return Contents; }
120   const SmallString<32> &getContents() const { return Contents; }
121
122   /// @}
123
124   static bool classof(const MCFragment *F) { 
125     return F->getKind() == MCFragment::FT_Data; 
126   }
127   static bool classof(const MCDataFragment *) { return true; }
128 };
129
130 class MCAlignFragment : public MCFragment {
131   /// Alignment - The alignment to ensure, in bytes.
132   unsigned Alignment;
133
134   /// Value - Value to use for filling padding bytes.
135   int64_t Value;
136
137   /// ValueSize - The size of the integer (in bytes) of \arg Value.
138   unsigned ValueSize;
139
140   /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
141   /// cannot be satisfied in this width then this fragment is ignored.
142   unsigned MaxBytesToEmit;
143
144 public:
145   MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
146                   unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
147     : MCFragment(FT_Align, SD), Alignment(_Alignment),
148       Value(_Value),ValueSize(_ValueSize),
149       MaxBytesToEmit(_MaxBytesToEmit) {}
150
151   /// @name Accessors
152   /// @{
153
154   uint64_t getMaxFileSize() const {
155     return std::max(Alignment - 1, MaxBytesToEmit);
156   }
157
158   unsigned getAlignment() const { return Alignment; }
159   
160   int64_t getValue() const { return Value; }
161
162   unsigned getValueSize() const { return ValueSize; }
163
164   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
165
166   /// @}
167
168   static bool classof(const MCFragment *F) { 
169     return F->getKind() == MCFragment::FT_Align; 
170   }
171   static bool classof(const MCAlignFragment *) { return true; }
172 };
173
174 class MCFillFragment : public MCFragment {
175   /// Value - Value to use for filling bytes.
176   MCValue Value;
177
178   /// ValueSize - The size (in bytes) of \arg Value to use when filling.
179   unsigned ValueSize;
180
181   /// Count - The number of copies of \arg Value to insert.
182   uint64_t Count;
183
184 public:
185   MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count,
186                  MCSectionData *SD = 0) 
187     : MCFragment(FT_Fill, SD),
188       Value(_Value), ValueSize(_ValueSize), Count(_Count) {}
189
190   /// @name Accessors
191   /// @{
192
193   uint64_t getMaxFileSize() const {
194     return ValueSize * Count;
195   }
196
197   MCValue getValue() const { return Value; }
198   
199   unsigned getValueSize() const { return ValueSize; }
200
201   uint64_t getCount() const { return Count; }
202
203   /// @}
204
205   static bool classof(const MCFragment *F) { 
206     return F->getKind() == MCFragment::FT_Fill; 
207   }
208   static bool classof(const MCFillFragment *) { return true; }
209 };
210
211 class MCOrgFragment : public MCFragment {
212   /// Offset - The offset this fragment should start at.
213   MCValue Offset;
214
215   /// Value - Value to use for filling bytes.  
216   int8_t Value;
217
218 public:
219   MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0)
220     : MCFragment(FT_Org, SD),
221       Offset(_Offset), Value(_Value) {}
222
223   /// @name Accessors
224   /// @{
225
226   uint64_t getMaxFileSize() const {
227     // FIXME: This doesn't make much sense.
228     return ~UINT64_C(0);
229   }
230
231   MCValue getOffset() const { return Offset; }
232   
233   uint8_t getValue() const { return Value; }
234
235   /// @}
236
237   static bool classof(const MCFragment *F) { 
238     return F->getKind() == MCFragment::FT_Org; 
239   }
240   static bool classof(const MCOrgFragment *) { return true; }
241 };
242
243 /// MCZeroFillFragment - Represent data which has a fixed size and alignment,
244 /// but requires no physical space in the object file.
245 class MCZeroFillFragment : public MCFragment {
246   /// Size - The size of this fragment.
247   uint64_t Size;
248
249   /// Alignment - The alignment for this fragment.
250   unsigned Alignment;
251
252 public:
253   MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0)
254     : MCFragment(FT_ZeroFill, SD),
255       Size(_Size), Alignment(_Alignment) {}
256
257   /// @name Accessors
258   /// @{
259
260   uint64_t getMaxFileSize() const {
261     // FIXME: This also doesn't make much sense, this method is misnamed.
262     return ~UINT64_C(0);
263   }
264
265   uint64_t getSize() const { return Size; }
266   
267   unsigned getAlignment() const { return Alignment; }
268
269   /// @}
270
271   static bool classof(const MCFragment *F) { 
272     return F->getKind() == MCFragment::FT_ZeroFill; 
273   }
274   static bool classof(const MCZeroFillFragment *) { return true; }
275 };
276
277 // FIXME: Should this be a separate class, or just merged into MCSection? Since
278 // we anticipate the fast path being through an MCAssembler, the only reason to
279 // keep it out is for API abstraction.
280 class MCSectionData : public ilist_node<MCSectionData> {
281   MCSectionData(const MCSectionData&);  // DO NOT IMPLEMENT
282   void operator=(const MCSectionData&); // DO NOT IMPLEMENT
283
284 public:
285   /// Fixup - Represent a fixed size region of bytes inside some fragment which
286   /// needs to be rewritten. This region will either be rewritten by the
287   /// assembler or cause a relocation entry to be generated.
288   struct Fixup {
289     /// Fragment - The fragment containing the fixup.
290     MCFragment *Fragment;
291     
292     /// Offset - The offset inside the fragment which needs to be rewritten.
293     uint64_t Offset;
294
295     /// Value - The expression to eventually write into the fragment.
296     //
297     // FIXME: We could probably get away with requiring the client to pass in an
298     // owned reference whose lifetime extends past that of the fixup.
299     MCValue Value;
300
301     /// Size - The fixup size.
302     unsigned Size;
303
304     /// FixedValue - The value to replace the fix up by.
305     //
306     // FIXME: This should not be here.
307     uint64_t FixedValue;
308
309   public:
310     Fixup(MCFragment &_Fragment, uint64_t _Offset, const MCValue &_Value, 
311           unsigned _Size) 
312       : Fragment(&_Fragment), Offset(_Offset), Value(_Value), Size(_Size),
313         FixedValue(0) {}
314   };
315
316   typedef iplist<MCFragment> FragmentListType;
317
318   typedef FragmentListType::const_iterator const_iterator;
319   typedef FragmentListType::iterator iterator;
320
321   typedef std::vector<Fixup>::const_iterator const_fixup_iterator;
322   typedef std::vector<Fixup>::iterator fixup_iterator;
323
324 private:
325   iplist<MCFragment> Fragments;
326   const MCSection *Section;
327
328   /// Alignment - The maximum alignment seen in this section.
329   unsigned Alignment;
330
331   /// @name Assembler Backend Data
332   /// @{
333   //
334   // FIXME: This could all be kept private to the assembler implementation.
335
336   /// Address - The computed address of this section. This is ~0 until
337   /// initialized.
338   uint64_t Address;
339
340   /// Size - The content size of this section. This is ~0 until initialized.
341   uint64_t Size;
342
343   /// FileSize - The size of this section in the object file. This is ~0 until
344   /// initialized.
345   uint64_t FileSize;
346
347   /// LastFixupLookup - Cache for the last looked up fixup.
348   mutable unsigned LastFixupLookup;
349
350   /// Fixups - The list of fixups in this section.
351   std::vector<Fixup> Fixups;
352   
353   /// @}
354
355 public:    
356   // Only for use as sentinel.
357   MCSectionData();
358   MCSectionData(const MCSection &Section, MCAssembler *A = 0);
359
360   const MCSection &getSection() const { return *Section; }
361
362   unsigned getAlignment() const { return Alignment; }
363   void setAlignment(unsigned Value) { Alignment = Value; }
364
365   /// @name Fragment Access
366   /// @{
367
368   const FragmentListType &getFragmentList() const { return Fragments; }
369   FragmentListType &getFragmentList() { return Fragments; }
370
371   iterator begin() { return Fragments.begin(); }
372   const_iterator begin() const { return Fragments.begin(); }
373
374   iterator end() { return Fragments.end(); }
375   const_iterator end() const { return Fragments.end(); }
376
377   size_t size() const { return Fragments.size(); }
378
379   bool empty() const { return Fragments.empty(); }
380
381   /// @}
382   /// @name Fixup Access
383   /// @{
384
385   std::vector<Fixup> &getFixups() {
386     return Fixups;
387   }
388
389   fixup_iterator fixup_begin() {
390     return Fixups.begin();
391   }
392
393   fixup_iterator fixup_end() {
394     return Fixups.end();
395   }
396
397   size_t fixup_size() const { return Fixups.size(); }
398
399   /// @}
400   /// @name Assembler Backend Support
401   /// @{
402   //
403   // FIXME: This could all be kept private to the assembler implementation.
404
405   /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
406   /// Offset.
407   ///
408   /// If multiple fixups exist for the same fragment and offset it is undefined
409   /// which one is returned.
410   //
411   // FIXME: This isn't horribly slow in practice, but there are much nicer
412   // solutions to applying the fixups.
413   const Fixup *LookupFixup(const MCFragment *Fragment, uint64_t Offset) const;
414
415   uint64_t getAddress() const { 
416     assert(Address != ~UINT64_C(0) && "Address not set!");
417     return Address;
418   }
419   void setAddress(uint64_t Value) { Address = Value; }
420
421   uint64_t getSize() const { 
422     assert(Size != ~UINT64_C(0) && "File size not set!");
423     return Size;
424   }
425   void setSize(uint64_t Value) { Size = Value; }
426
427   uint64_t getFileSize() const { 
428     assert(FileSize != ~UINT64_C(0) && "File size not set!");
429     return FileSize;
430   }
431   void setFileSize(uint64_t Value) { FileSize = Value; }  
432
433   /// @}
434 };
435
436 // FIXME: Same concerns as with SectionData.
437 class MCSymbolData : public ilist_node<MCSymbolData> {
438 public:
439   MCSymbol &Symbol;
440
441   /// Fragment - The fragment this symbol's value is relative to, if any.
442   MCFragment *Fragment;
443
444   /// Offset - The offset to apply to the fragment address to form this symbol's
445   /// value.
446   uint64_t Offset;
447     
448   /// IsExternal - True if this symbol is visible outside this translation
449   /// unit.
450   unsigned IsExternal : 1;
451
452   /// IsPrivateExtern - True if this symbol is private extern.
453   unsigned IsPrivateExtern : 1;
454
455   /// CommonSize - The size of the symbol, if it is 'common', or 0.
456   //
457   // FIXME: Pack this in with other fields? We could put it in offset, since a
458   // common symbol can never get a definition.
459   uint64_t CommonSize;
460
461   /// CommonAlign - The alignment of the symbol, if it is 'common'.
462   //
463   // FIXME: Pack this in with other fields?
464   unsigned CommonAlign;
465
466   /// Flags - The Flags field is used by object file implementations to store
467   /// additional per symbol information which is not easily classified.
468   uint32_t Flags;
469
470   /// Index - Index field, for use by the object file implementation.
471   uint64_t Index;
472
473 public:
474   // Only for use as sentinel.
475   MCSymbolData();
476   MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
477                MCAssembler *A = 0);
478
479   /// @name Accessors
480   /// @{
481
482   MCSymbol &getSymbol() const { return Symbol; }
483
484   MCFragment *getFragment() const { return Fragment; }
485   void setFragment(MCFragment *Value) { Fragment = Value; }
486
487   uint64_t getOffset() const { return Offset; }
488   void setOffset(uint64_t Value) { Offset = Value; }
489
490   /// @}
491   /// @name Symbol Attributes
492   /// @{
493   
494   bool isExternal() const { return IsExternal; }
495   void setExternal(bool Value) { IsExternal = Value; }
496   
497   bool isPrivateExtern() const { return IsPrivateExtern; }
498   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
499
500   /// isCommon - Is this a 'common' symbol.
501   bool isCommon() const { return CommonSize != 0; }
502
503   /// setCommon - Mark this symbol as being 'common'.
504   ///
505   /// \param Size - The size of the symbol.
506   /// \param Align - The alignment of the symbol.
507   void setCommon(uint64_t Size, unsigned Align) {
508     CommonSize = Size;
509     CommonAlign = Align;
510   }
511
512   /// getCommonSize - Return the size of a 'common' symbol.
513   uint64_t getCommonSize() const {
514     assert(isCommon() && "Not a 'common' symbol!");
515     return CommonSize;
516   }
517
518   /// getCommonAlignment - Return the alignment of a 'common' symbol.
519   unsigned getCommonAlignment() const {
520     assert(isCommon() && "Not a 'common' symbol!");
521     return CommonAlign;
522   }
523
524   /// getFlags - Get the (implementation defined) symbol flags.
525   uint32_t getFlags() const { return Flags; }
526
527   /// setFlags - Set the (implementation defined) symbol flags.
528   void setFlags(uint32_t Value) { Flags = Value; }
529   
530   /// getIndex - Get the (implementation defined) index.
531   uint64_t getIndex() const { return Index; }
532
533   /// setIndex - Set the (implementation defined) index.
534   void setIndex(uint64_t Value) { Index = Value; }
535   
536   /// @}  
537 };
538
539 // FIXME: This really doesn't belong here. See comments below.
540 struct IndirectSymbolData {
541   MCSymbol *Symbol;
542   MCSectionData *SectionData;
543 };
544
545 class MCAssembler {
546 public:
547   typedef iplist<MCSectionData> SectionDataListType;
548   typedef iplist<MCSymbolData> SymbolDataListType;
549
550   typedef SectionDataListType::const_iterator const_iterator;
551   typedef SectionDataListType::iterator iterator;
552
553   typedef SymbolDataListType::const_iterator const_symbol_iterator;
554   typedef SymbolDataListType::iterator symbol_iterator;
555
556   typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
557
558 private:
559   MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
560   void operator=(const MCAssembler&); // DO NOT IMPLEMENT
561
562   raw_ostream &OS;
563   
564   iplist<MCSectionData> Sections;
565
566   iplist<MCSymbolData> Symbols;
567
568   std::vector<IndirectSymbolData> IndirectSymbols;
569
570   unsigned SubsectionsViaSymbols : 1;
571
572 private:
573   /// LayoutSection - Assign offsets and sizes to the fragments in the section
574   /// \arg SD, and update the section size. The section file offset should
575   /// already have been computed.
576   void LayoutSection(MCSectionData &SD);
577
578 public:
579   /// Construct a new assembler instance.
580   ///
581   /// \arg OS - The stream to output to.
582   //
583   // FIXME: How are we going to parameterize this? Two obvious options are stay
584   // concrete and require clients to pass in a target like object. The other
585   // option is to make this abstract, and have targets provide concrete
586   // implementations as we do with AsmParser.
587   MCAssembler(raw_ostream &OS);
588   ~MCAssembler();
589
590   /// Finish - Do final processing and write the object to the output stream.
591   void Finish();
592
593   // FIXME: This does not belong here.
594   bool getSubsectionsViaSymbols() const {
595     return SubsectionsViaSymbols;
596   }
597   void setSubsectionsViaSymbols(bool Value) {
598     SubsectionsViaSymbols = Value;
599   }
600
601   /// @name Section List Access
602   /// @{
603
604   const SectionDataListType &getSectionList() const { return Sections; }
605   SectionDataListType &getSectionList() { return Sections; }  
606
607   iterator begin() { return Sections.begin(); }
608   const_iterator begin() const { return Sections.begin(); }
609
610   iterator end() { return Sections.end(); }
611   const_iterator end() const { return Sections.end(); }
612
613   size_t size() const { return Sections.size(); }
614
615   /// @}
616   /// @name Symbol List Access
617   /// @{
618
619   const SymbolDataListType &getSymbolList() const { return Symbols; }
620   SymbolDataListType &getSymbolList() { return Symbols; }
621
622   symbol_iterator symbol_begin() { return Symbols.begin(); }
623   const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
624
625   symbol_iterator symbol_end() { return Symbols.end(); }
626   const_symbol_iterator symbol_end() const { return Symbols.end(); }
627
628   size_t symbol_size() const { return Symbols.size(); }
629
630   /// @}
631   /// @name Indirect Symbol List Access
632   /// @{
633
634   // FIXME: This is a total hack, this should not be here. Once things are
635   // factored so that the streamer has direct access to the .o writer, it can
636   // disappear.
637   std::vector<IndirectSymbolData> &getIndirectSymbols() {
638     return IndirectSymbols;
639   }
640
641   indirect_symbol_iterator indirect_symbol_begin() {
642     return IndirectSymbols.begin();
643   }
644
645   indirect_symbol_iterator indirect_symbol_end() {
646     return IndirectSymbols.end();
647   }
648
649   size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
650
651   /// @}
652 };
653
654 } // end namespace llvm
655
656 #endif