1 //===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains an implementation of a Win32 COFF object file streamer.
12 //===----------------------------------------------------------------------===//
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"
36 #define DEBUG_TYPE "WinCOFFStreamer"
39 class WinCOFFStreamer : public MCObjectStreamer {
41 MCSymbol const *CurSymbol;
43 WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE,
46 // MCStreamer interface
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;
76 void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override {
77 MCDataFragment *DF = getOrCreateDataFragment();
79 SmallVector<MCFixup, 4> Fixups;
80 SmallString<256> Code;
81 raw_svector_ostream VecOS(Code);
82 getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI);
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]);
90 DF->getContents().append(Code.begin(), Code.end());
93 } // end anonymous namespace.
95 WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
96 MCCodeEmitter &CE, raw_ostream &OS)
97 : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {}
99 // MCStreamer interface
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);
108 SwitchSection(getContext().getObjectFileInfo()->getDataSection());
109 EmitCodeAlignment(4);
111 SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
112 EmitCodeAlignment(4);
114 SwitchSection(getContext().getObjectFileInfo()->getTextSection());
117 void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
118 assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
119 MCObjectStreamer::EmitLabel(Symbol);
122 void WinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) {
126 void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
127 llvm_unreachable("not implemented");
130 void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
131 llvm_unreachable("not implemented");
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!");
141 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
144 default: return false;
145 case MCSA_WeakReference:
147 SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
148 SD.setExternal(true);
151 SD.setExternal(true);
158 void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
159 llvm_unreachable("not implemented");
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");
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!");
175 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol);
176 SD.modifyFlags(StorageClass << COFF::SF_ClassShift, COFF::SF_ClassMask);
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");
184 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol);
185 SD.modifyFlags(Type << COFF::SF_TypeShift, COFF::SF_TypeMask);
188 void WinCOFFStreamer::EndCOFFSymbolDef() {
189 assert(CurSymbol && "ending symbol definition without beginning one");
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);
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);
209 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
210 llvm_unreachable("not supported");
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!");
219 if (ByteAlignment > 32)
220 report_fatal_error("alignment is limited to 32-bytes");
222 AssignSection(Symbol, nullptr);
224 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
225 SD.setExternal(true);
226 SD.setCommon(Size, ByteAlignment);
229 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
230 unsigned ByteAlignment) {
231 assert(!Symbol->isInSection() && "Symbol must not already have a section!");
233 const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
234 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
235 if (SectionData.getAlignment() < ByteAlignment)
236 SectionData.setAlignment(ByteAlignment);
238 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
239 SD.setExternal(false);
241 AssignSection(Symbol, Section);
243 if (ByteAlignment != 1)
244 new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0,
245 ByteAlignment, &SectionData);
247 MCFillFragment *Fragment =
248 new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData);
249 SD.setFragment(Fragment);
252 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
253 uint64_t Size, unsigned ByteAlignment) {
254 llvm_unreachable("not implemented");
257 void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
258 uint64_t Size, unsigned ByteAlignment) {
259 llvm_unreachable("not implemented");
262 void WinCOFFStreamer::EmitFileDirective(StringRef Filename) {
263 getAssembler().addFileName(Filename);
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");
271 void WinCOFFStreamer::EmitWin64EHHandlerData() {
272 MCStreamer::EmitWin64EHHandlerData();
274 // We have to emit the unwind info now, because this directive
275 // actually switches to the .xdata section!
276 MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo());
279 void WinCOFFStreamer::FinishImpl() {
280 EmitFrames(nullptr, true);
282 MCObjectStreamer::FinishImpl();
286 MCStreamer *createWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
287 MCCodeEmitter &CE, raw_ostream &OS,
289 WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS);
290 S->getAssembler().setRelaxAll(RelaxAll);