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