9666ce6daf2bd0da2d75577cffc8e502e6d2eafb
[oota-llvm.git] / lib / MC / WinCOFFStreamer.cpp
1 //===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- 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 // This file contains an implementation of a Win32 COFF object file streamer.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCAsmLayout.h"
17 #include "llvm/MC/MCAssembler.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCObjectFileInfo.h"
22 #include "llvm/MC/MCObjectStreamer.h"
23 #include "llvm/MC/MCSection.h"
24 #include "llvm/MC/MCSectionCOFF.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/MCValue.h"
27 #include "llvm/MC/MCWin64EH.h"
28 #include "llvm/Support/COFF.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/TargetRegistry.h"
32 #include "llvm/Support/raw_ostream.h"
33
34 using namespace llvm;
35
36 #define DEBUG_TYPE "WinCOFFStreamer"
37
38 namespace {
39 class WinCOFFStreamer : public MCObjectStreamer {
40 public:
41   MCSymbol const *CurSymbol;
42
43   WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE,
44                   raw_ostream &OS);
45
46   // MCStreamer interface
47
48   void InitSections() override;
49   void EmitLabel(MCSymbol *Symbol) override;
50   void EmitDebugLabel(MCSymbol *Symbol) override;
51   void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
52   void EmitThumbFunc(MCSymbol *Func) override;
53   bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
54   void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
55   void BeginCOFFSymbolDef(MCSymbol const *Symbol) override;
56   void EmitCOFFSymbolStorageClass(int StorageClass) override;
57   void EmitCOFFSymbolType(int Type) override;
58   void EndCOFFSymbolDef() override;
59   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
60   void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
61   void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
62   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
63                         unsigned ByteAlignment) override;
64   void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
65                              unsigned ByteAlignment) override;
66   void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size,
67                     unsigned ByteAlignment) override;
68   void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size,
69                       unsigned ByteAlignment) override;
70   void EmitFileDirective(StringRef Filename) override;
71   void EmitIdent(StringRef IdentString) override;
72   void EmitWin64EHHandlerData() override;
73   void FinishImpl() override;
74
75 private:
76   void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override {
77     MCDataFragment *DF = getOrCreateDataFragment();
78
79     SmallVector<MCFixup, 4> Fixups;
80     SmallString<256> Code;
81     raw_svector_ostream VecOS(Code);
82     getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI);
83     VecOS.flush();
84
85     // Add the fixups and data.
86     for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
87       Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
88       DF->getFixups().push_back(Fixups[i]);
89     }
90     DF->getContents().append(Code.begin(), Code.end());
91   }
92 };
93 } // end anonymous namespace.
94
95 WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
96                                  MCCodeEmitter &CE, raw_ostream &OS)
97     : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {}
98
99 // MCStreamer interface
100
101 void WinCOFFStreamer::InitSections() {
102   // FIXME: this is identical to the ELF one.
103   // This emulates the same behavior of GNU as. This makes it easier
104   // to compare the output as the major sections are in the same order.
105   SwitchSection(getContext().getObjectFileInfo()->getTextSection());
106   EmitCodeAlignment(4);
107
108   SwitchSection(getContext().getObjectFileInfo()->getDataSection());
109   EmitCodeAlignment(4);
110
111   SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
112   EmitCodeAlignment(4);
113
114   SwitchSection(getContext().getObjectFileInfo()->getTextSection());
115 }
116
117 void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
118   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
119   MCObjectStreamer::EmitLabel(Symbol);
120 }
121
122 void WinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) {
123   EmitLabel(Symbol);
124 }
125
126 void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
127   llvm_unreachable("not implemented");
128 }
129
130 void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
131   llvm_unreachable("not implemented");
132 }
133
134 bool WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
135                                           MCSymbolAttr Attribute) {
136   assert(Symbol && "Symbol must be non-null!");
137   assert((!Symbol->isInSection() ||
138           Symbol->getSection().getVariant() == MCSection::SV_COFF) &&
139          "Got non-COFF section in the COFF backend!");
140
141   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
142
143   switch (Attribute) {
144   default: return false;
145   case MCSA_WeakReference:
146   case MCSA_Weak:
147     SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
148     SD.setExternal(true);
149     break;
150   case MCSA_Global:
151     SD.setExternal(true);
152     break;
153   }
154
155   return true;
156 }
157
158 void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
159   llvm_unreachable("not implemented");
160 }
161
162 void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) {
163   assert((!Symbol->isInSection() ||
164           Symbol->getSection().getVariant() == MCSection::SV_COFF) &&
165          "Got non-COFF section in the COFF backend!");
166   assert(!CurSymbol && "starting new symbol definition in a symbol definition");
167   CurSymbol = Symbol;
168 }
169
170 void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
171   assert(CurSymbol && "StorageClass specified outside of symbol definition");
172   assert((StorageClass & ~0xFF) == 0 &&
173          "StorageClass must only have data in the first byte!");
174
175   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol);
176   SD.modifyFlags(StorageClass << COFF::SF_ClassShift, COFF::SF_ClassMask);
177 }
178
179 void WinCOFFStreamer::EmitCOFFSymbolType(int Type) {
180   assert(CurSymbol && "SymbolType specified outside of a symbol definition");
181   assert((Type & ~0xFFFF) == 0 &&
182          "Type must only have data in the first 2 bytes");
183
184   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol);
185   SD.modifyFlags(Type << COFF::SF_TypeShift, COFF::SF_TypeMask);
186 }
187
188 void WinCOFFStreamer::EndCOFFSymbolDef() {
189   assert(CurSymbol && "ending symbol definition without beginning one");
190   CurSymbol = nullptr;
191 }
192
193 void WinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
194   MCDataFragment *DF = getOrCreateDataFragment();
195   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext());
196   MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_2);
197   DF->getFixups().push_back(Fixup);
198   DF->getContents().resize(DF->getContents().size() + 4, 0);
199 }
200
201 void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
202   MCDataFragment *DF = getOrCreateDataFragment();
203   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext());
204   MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_4);
205   DF->getFixups().push_back(Fixup);
206   DF->getContents().resize(DF->getContents().size() + 4, 0);
207 }
208
209 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
210   llvm_unreachable("not supported");
211 }
212
213 void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
214                                        unsigned ByteAlignment) {
215   assert((!Symbol->isInSection() ||
216           Symbol->getSection().getVariant() == MCSection::SV_COFF) &&
217          "Got non-COFF section in the COFF backend!");
218
219   if (ByteAlignment > 32)
220     report_fatal_error("alignment is limited to 32-bytes");
221
222   AssignSection(Symbol, nullptr);
223
224   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
225   SD.setExternal(true);
226   SD.setCommon(Size, ByteAlignment);
227 }
228
229 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
230                                             unsigned ByteAlignment) {
231   assert(!Symbol->isInSection() && "Symbol must not already have a section!");
232
233   const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
234   MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
235   if (SectionData.getAlignment() < ByteAlignment)
236     SectionData.setAlignment(ByteAlignment);
237
238   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
239   SD.setExternal(false);
240
241   AssignSection(Symbol, Section);
242
243   if (ByteAlignment != 1)
244     new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0,
245                         ByteAlignment, &SectionData);
246
247   MCFillFragment *Fragment =
248       new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData);
249   SD.setFragment(Fragment);
250 }
251
252 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
253                                    uint64_t Size, unsigned ByteAlignment) {
254   llvm_unreachable("not implemented");
255 }
256
257 void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
258                                      uint64_t Size, unsigned ByteAlignment) {
259   llvm_unreachable("not implemented");
260 }
261
262 void WinCOFFStreamer::EmitFileDirective(StringRef Filename) {
263   getAssembler().addFileName(Filename);
264 }
265
266 // TODO: Implement this if you want to emit .comment section in COFF obj files.
267 void WinCOFFStreamer::EmitIdent(StringRef IdentString) {
268   llvm_unreachable("not implemented");
269 }
270
271 void WinCOFFStreamer::EmitWin64EHHandlerData() {
272   MCStreamer::EmitWin64EHHandlerData();
273
274   // We have to emit the unwind info now, because this directive
275   // actually switches to the .xdata section!
276   MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo());
277 }
278
279 void WinCOFFStreamer::FinishImpl() {
280   EmitFrames(nullptr, true);
281   EmitW64Tables();
282   MCObjectStreamer::FinishImpl();
283 }
284
285 namespace llvm {
286 MCStreamer *createWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
287                                   MCCodeEmitter &CE, raw_ostream &OS,
288                                   bool RelaxAll) {
289   WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS);
290   S->getAssembler().setRelaxAll(RelaxAll);
291   return S;
292 }
293 }
294