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