MC/Mach-O: Add MCSymbolData::getAddress() utility.
[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   uint64_t getAddress() const {
511     assert(getFragment() && "Invalid getAddress() on undefined symbol!");
512     return getFragment()->getAddress() + getOffset();
513   }
514
515   /// @}
516   /// @name Symbol Attributes
517   /// @{
518
519   bool isExternal() const { return IsExternal; }
520   void setExternal(bool Value) { IsExternal = Value; }
521
522   bool isPrivateExtern() const { return IsPrivateExtern; }
523   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
524
525   /// isCommon - Is this a 'common' symbol.
526   bool isCommon() const { return CommonSize != 0; }
527
528   /// setCommon - Mark this symbol as being 'common'.
529   ///
530   /// \param Size - The size of the symbol.
531   /// \param Align - The alignment of the symbol.
532   void setCommon(uint64_t Size, unsigned Align) {
533     CommonSize = Size;
534     CommonAlign = Align;
535   }
536
537   /// getCommonSize - Return the size of a 'common' symbol.
538   uint64_t getCommonSize() const {
539     assert(isCommon() && "Not a 'common' symbol!");
540     return CommonSize;
541   }
542
543   /// getCommonAlignment - Return the alignment of a 'common' symbol.
544   unsigned getCommonAlignment() const {
545     assert(isCommon() && "Not a 'common' symbol!");
546     return CommonAlign;
547   }
548
549   /// getFlags - Get the (implementation defined) symbol flags.
550   uint32_t getFlags() const { return Flags; }
551
552   /// setFlags - Set the (implementation defined) symbol flags.
553   void setFlags(uint32_t Value) { Flags = Value; }
554
555   /// getIndex - Get the (implementation defined) index.
556   uint64_t getIndex() const { return Index; }
557
558   /// setIndex - Set the (implementation defined) index.
559   void setIndex(uint64_t Value) { Index = Value; }
560
561   /// @}
562
563   void dump();
564 };
565
566 // FIXME: This really doesn't belong here. See comments below.
567 struct IndirectSymbolData {
568   MCSymbol *Symbol;
569   MCSectionData *SectionData;
570 };
571
572 class MCAssembler {
573 public:
574   typedef iplist<MCSectionData> SectionDataListType;
575   typedef iplist<MCSymbolData> SymbolDataListType;
576
577   typedef SectionDataListType::const_iterator const_iterator;
578   typedef SectionDataListType::iterator iterator;
579
580   typedef SymbolDataListType::const_iterator const_symbol_iterator;
581   typedef SymbolDataListType::iterator symbol_iterator;
582
583   typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
584
585 private:
586   MCAssembler(const MCAssembler&);    // DO NOT IMPLEMENT
587   void operator=(const MCAssembler&); // DO NOT IMPLEMENT
588
589   MCContext &Context;
590
591   TargetAsmBackend &Backend;
592
593   raw_ostream &OS;
594
595   iplist<MCSectionData> Sections;
596
597   iplist<MCSymbolData> Symbols;
598
599   /// The map of sections to their associated assembler backend data.
600   //
601   // FIXME: Avoid this indirection?
602   DenseMap<const MCSection*, MCSectionData*> SectionMap;
603
604   /// The map of symbols to their associated assembler backend data.
605   //
606   // FIXME: Avoid this indirection?
607   DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap;
608
609   std::vector<IndirectSymbolData> IndirectSymbols;
610
611   unsigned SubsectionsViaSymbols : 1;
612
613 private:
614   /// LayoutSection - Assign offsets and sizes to the fragments in the section
615   /// \arg SD, and update the section size. The section file offset should
616   /// already have been computed.
617   void LayoutSection(MCSectionData &SD);
618
619 public:
620   /// Construct a new assembler instance.
621   ///
622   /// \arg OS - The stream to output to.
623   //
624   // FIXME: How are we going to parameterize this? Two obvious options are stay
625   // concrete and require clients to pass in a target like object. The other
626   // option is to make this abstract, and have targets provide concrete
627   // implementations as we do with AsmParser.
628   MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS);
629   ~MCAssembler();
630
631   MCContext &getContext() const { return Context; }
632
633   TargetAsmBackend &getBackend() const { return Backend; }
634
635   /// Finish - Do final processing and write the object to the output stream.
636   void Finish();
637
638   // FIXME: This does not belong here.
639   bool getSubsectionsViaSymbols() const {
640     return SubsectionsViaSymbols;
641   }
642   void setSubsectionsViaSymbols(bool Value) {
643     SubsectionsViaSymbols = Value;
644   }
645
646   /// @name Section List Access
647   /// @{
648
649   const SectionDataListType &getSectionList() const { return Sections; }
650   SectionDataListType &getSectionList() { return Sections; }
651
652   iterator begin() { return Sections.begin(); }
653   const_iterator begin() const { return Sections.begin(); }
654
655   iterator end() { return Sections.end(); }
656   const_iterator end() const { return Sections.end(); }
657
658   size_t size() const { return Sections.size(); }
659
660   /// @}
661   /// @name Symbol List Access
662   /// @{
663
664   const SymbolDataListType &getSymbolList() const { return Symbols; }
665   SymbolDataListType &getSymbolList() { return Symbols; }
666
667   symbol_iterator symbol_begin() { return Symbols.begin(); }
668   const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
669
670   symbol_iterator symbol_end() { return Symbols.end(); }
671   const_symbol_iterator symbol_end() const { return Symbols.end(); }
672
673   size_t symbol_size() const { return Symbols.size(); }
674
675   /// @}
676   /// @name Indirect Symbol List Access
677   /// @{
678
679   // FIXME: This is a total hack, this should not be here. Once things are
680   // factored so that the streamer has direct access to the .o writer, it can
681   // disappear.
682   std::vector<IndirectSymbolData> &getIndirectSymbols() {
683     return IndirectSymbols;
684   }
685
686   indirect_symbol_iterator indirect_symbol_begin() {
687     return IndirectSymbols.begin();
688   }
689
690   indirect_symbol_iterator indirect_symbol_end() {
691     return IndirectSymbols.end();
692   }
693
694   size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
695
696   /// @}
697   /// @name Backend Data Access
698   /// @{
699
700   MCSectionData &getSectionData(const MCSection &Section) {
701     MCSectionData *&Entry = SectionMap[&Section];
702     assert(Entry && "Missing section data!");
703     return *Entry;
704   }
705
706   MCSectionData &getOrCreateSectionData(const MCSection &Section,
707                                         bool *Created = 0) {
708     MCSectionData *&Entry = SectionMap[&Section];
709
710     if (Created) *Created = !Entry;
711     if (!Entry)
712       Entry = new MCSectionData(Section, this);
713
714     return *Entry;
715   }
716
717   MCSymbolData &getSymbolData(const MCSymbol &Symbol) {
718     MCSymbolData *&Entry = SymbolMap[&Symbol];
719     assert(Entry && "Missing symbol data!");
720     return *Entry;
721   }
722
723   MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol,
724                                       bool *Created = 0) {
725     MCSymbolData *&Entry = SymbolMap[&Symbol];
726
727     if (Created) *Created = !Entry;
728     if (!Entry)
729       Entry = new MCSymbolData(Symbol, 0, 0, this);
730
731     return *Entry;
732   }
733
734   /// @}
735
736   void dump();
737 };
738
739 } // end namespace llvm
740
741 #endif