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