xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains an implementation of a Windows COFF object file streamer.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
14*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
17*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
18*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
19*0b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
20*0b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
21*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
22*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
23*0b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
24*0b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h"
25*0b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
26*0b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
27*0b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
28*0b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
29*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h"
30*0b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFStreamer.h"
31*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
32*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
33*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
34*0b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
35*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
36*0b57cec5SDimitry Andric #include <algorithm>
37*0b57cec5SDimitry Andric #include <cassert>
38*0b57cec5SDimitry Andric #include <cstdint>
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric using namespace llvm;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric #define DEBUG_TYPE "WinCOFFStreamer"
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
45*0b57cec5SDimitry Andric                                      std::unique_ptr<MCAsmBackend> MAB,
46*0b57cec5SDimitry Andric                                      std::unique_ptr<MCCodeEmitter> CE,
47*0b57cec5SDimitry Andric                                      std::unique_ptr<MCObjectWriter> OW)
48*0b57cec5SDimitry Andric     : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
49*0b57cec5SDimitry Andric       CurSymbol(nullptr) {}
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
52*0b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI) {
53*0b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   SmallVector<MCFixup, 4> Fixups;
56*0b57cec5SDimitry Andric   SmallString<256> Code;
57*0b57cec5SDimitry Andric   raw_svector_ostream VecOS(Code);
58*0b57cec5SDimitry Andric   getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric   // Add the fixups and data.
61*0b57cec5SDimitry Andric   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
62*0b57cec5SDimitry Andric     Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
63*0b57cec5SDimitry Andric     DF->getFixups().push_back(Fixups[i]);
64*0b57cec5SDimitry Andric   }
65*0b57cec5SDimitry Andric   DF->setHasInstructions(STI);
66*0b57cec5SDimitry Andric   DF->getContents().append(Code.begin(), Code.end());
67*0b57cec5SDimitry Andric }
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric void MCWinCOFFStreamer::InitSections(bool NoExecStack) {
70*0b57cec5SDimitry Andric   // FIXME: this is identical to the ELF one.
71*0b57cec5SDimitry Andric   // This emulates the same behavior of GNU as. This makes it easier
72*0b57cec5SDimitry Andric   // to compare the output as the major sections are in the same order.
73*0b57cec5SDimitry Andric   SwitchSection(getContext().getObjectFileInfo()->getTextSection());
74*0b57cec5SDimitry Andric   EmitCodeAlignment(4);
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric   SwitchSection(getContext().getObjectFileInfo()->getDataSection());
77*0b57cec5SDimitry Andric   EmitCodeAlignment(4);
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
80*0b57cec5SDimitry Andric   EmitCodeAlignment(4);
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric   SwitchSection(getContext().getObjectFileInfo()->getTextSection());
83*0b57cec5SDimitry Andric }
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
86*0b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
87*0b57cec5SDimitry Andric   MCObjectStreamer::EmitLabel(Symbol, Loc);
88*0b57cec5SDimitry Andric }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
91*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
92*0b57cec5SDimitry Andric }
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
95*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
96*0b57cec5SDimitry Andric }
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S,
99*0b57cec5SDimitry Andric                                             MCSymbolAttr Attribute) {
100*0b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
101*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric   switch (Attribute) {
104*0b57cec5SDimitry Andric   default: return false;
105*0b57cec5SDimitry Andric   case MCSA_WeakReference:
106*0b57cec5SDimitry Andric   case MCSA_Weak:
107*0b57cec5SDimitry Andric     Symbol->setIsWeakExternal();
108*0b57cec5SDimitry Andric     Symbol->setExternal(true);
109*0b57cec5SDimitry Andric     break;
110*0b57cec5SDimitry Andric   case MCSA_Global:
111*0b57cec5SDimitry Andric     Symbol->setExternal(true);
112*0b57cec5SDimitry Andric     break;
113*0b57cec5SDimitry Andric   case MCSA_AltEntry:
114*0b57cec5SDimitry Andric     llvm_unreachable("COFF doesn't support the .alt_entry attribute");
115*0b57cec5SDimitry Andric   }
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric   return true;
118*0b57cec5SDimitry Andric }
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
121*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
122*0b57cec5SDimitry Andric }
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) {
125*0b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
126*0b57cec5SDimitry Andric   if (CurSymbol)
127*0b57cec5SDimitry Andric     Error("starting a new symbol definition without completing the "
128*0b57cec5SDimitry Andric           "previous one");
129*0b57cec5SDimitry Andric   CurSymbol = Symbol;
130*0b57cec5SDimitry Andric }
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
133*0b57cec5SDimitry Andric   if (!CurSymbol) {
134*0b57cec5SDimitry Andric     Error("storage class specified outside of symbol definition");
135*0b57cec5SDimitry Andric     return;
136*0b57cec5SDimitry Andric   }
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric   if (StorageClass & ~COFF::SSC_Invalid) {
139*0b57cec5SDimitry Andric     Error("storage class value '" + Twine(StorageClass) +
140*0b57cec5SDimitry Andric                "' out of range");
141*0b57cec5SDimitry Andric     return;
142*0b57cec5SDimitry Andric   }
143*0b57cec5SDimitry Andric 
144*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*CurSymbol);
145*0b57cec5SDimitry Andric   cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass);
146*0b57cec5SDimitry Andric }
147*0b57cec5SDimitry Andric 
148*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) {
149*0b57cec5SDimitry Andric   if (!CurSymbol) {
150*0b57cec5SDimitry Andric     Error("symbol type specified outside of a symbol definition");
151*0b57cec5SDimitry Andric     return;
152*0b57cec5SDimitry Andric   }
153*0b57cec5SDimitry Andric 
154*0b57cec5SDimitry Andric   if (Type & ~0xffff) {
155*0b57cec5SDimitry Andric     Error("type value '" + Twine(Type) + "' out of range");
156*0b57cec5SDimitry Andric     return;
157*0b57cec5SDimitry Andric   }
158*0b57cec5SDimitry Andric 
159*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*CurSymbol);
160*0b57cec5SDimitry Andric   cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type);
161*0b57cec5SDimitry Andric }
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EndCOFFSymbolDef() {
164*0b57cec5SDimitry Andric   if (!CurSymbol)
165*0b57cec5SDimitry Andric     Error("ending symbol definition without starting one");
166*0b57cec5SDimitry Andric   CurSymbol = nullptr;
167*0b57cec5SDimitry Andric }
168*0b57cec5SDimitry Andric 
169*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
170*0b57cec5SDimitry Andric   // SafeSEH is a feature specific to 32-bit x86.  It does not exist (and is
171*0b57cec5SDimitry Andric   // unnecessary) on all platforms which use table-based exception dispatch.
172*0b57cec5SDimitry Andric   if (getContext().getObjectFileInfo()->getTargetTriple().getArch() !=
173*0b57cec5SDimitry Andric       Triple::x86)
174*0b57cec5SDimitry Andric     return;
175*0b57cec5SDimitry Andric 
176*0b57cec5SDimitry Andric   const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
177*0b57cec5SDimitry Andric   if (CSymbol->isSafeSEH())
178*0b57cec5SDimitry Andric     return;
179*0b57cec5SDimitry Andric 
180*0b57cec5SDimitry Andric   MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
181*0b57cec5SDimitry Andric   getAssembler().registerSection(*SXData);
182*0b57cec5SDimitry Andric   if (SXData->getAlignment() < 4)
183*0b57cec5SDimitry Andric     SXData->setAlignment(4);
184*0b57cec5SDimitry Andric 
185*0b57cec5SDimitry Andric   new MCSymbolIdFragment(Symbol, SXData);
186*0b57cec5SDimitry Andric 
187*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
188*0b57cec5SDimitry Andric   CSymbol->setIsSafeSEH();
189*0b57cec5SDimitry Andric 
190*0b57cec5SDimitry Andric   // The Microsoft linker requires that the symbol type of a handler be
191*0b57cec5SDimitry Andric   // function. Go ahead and oblige it here.
192*0b57cec5SDimitry Andric   CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
193*0b57cec5SDimitry Andric                    << COFF::SCT_COMPLEX_TYPE_SHIFT);
194*0b57cec5SDimitry Andric }
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
197*0b57cec5SDimitry Andric   MCSection *Sec = getCurrentSectionOnly();
198*0b57cec5SDimitry Andric   getAssembler().registerSection(*Sec);
199*0b57cec5SDimitry Andric   if (Sec->getAlignment() < 4)
200*0b57cec5SDimitry Andric     Sec->setAlignment(4);
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric   new MCSymbolIdFragment(Symbol, getCurrentSectionOnly());
203*0b57cec5SDimitry Andric 
204*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
205*0b57cec5SDimitry Andric }
206*0b57cec5SDimitry Andric 
207*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) {
208*0b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
209*0b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
210*0b57cec5SDimitry Andric   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
211*0b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
212*0b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
213*0b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 2, 0);
214*0b57cec5SDimitry Andric }
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol,
217*0b57cec5SDimitry Andric                                          uint64_t Offset) {
218*0b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
219*0b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
220*0b57cec5SDimitry Andric   // Create Symbol A for the relocation relative reference.
221*0b57cec5SDimitry Andric   const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
222*0b57cec5SDimitry Andric   // Add the constant offset, if given.
223*0b57cec5SDimitry Andric   if (Offset)
224*0b57cec5SDimitry Andric     MCE = MCBinaryExpr::createAdd(
225*0b57cec5SDimitry Andric         MCE, MCConstantExpr::create(Offset, getContext()), getContext());
226*0b57cec5SDimitry Andric   // Build the secrel32 relocation.
227*0b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
228*0b57cec5SDimitry Andric   // Record the relocation.
229*0b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
230*0b57cec5SDimitry Andric   // Emit 4 bytes (zeros) to the object file.
231*0b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
232*0b57cec5SDimitry Andric }
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
235*0b57cec5SDimitry Andric                                          int64_t Offset) {
236*0b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
237*0b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
238*0b57cec5SDimitry Andric   // Create Symbol A for the relocation relative reference.
239*0b57cec5SDimitry Andric   const MCExpr *MCE = MCSymbolRefExpr::create(
240*0b57cec5SDimitry Andric       Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
241*0b57cec5SDimitry Andric   // Add the constant offset, if given.
242*0b57cec5SDimitry Andric   if (Offset)
243*0b57cec5SDimitry Andric     MCE = MCBinaryExpr::createAdd(
244*0b57cec5SDimitry Andric         MCE, MCConstantExpr::create(Offset, getContext()), getContext());
245*0b57cec5SDimitry Andric   // Build the imgrel relocation.
246*0b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
247*0b57cec5SDimitry Andric   // Record the relocation.
248*0b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
249*0b57cec5SDimitry Andric   // Emit 4 bytes (zeros) to the object file.
250*0b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
251*0b57cec5SDimitry Andric }
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
254*0b57cec5SDimitry Andric                                          unsigned ByteAlignment) {
255*0b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric   const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
258*0b57cec5SDimitry Andric   if (T.isWindowsMSVCEnvironment()) {
259*0b57cec5SDimitry Andric     if (ByteAlignment > 32)
260*0b57cec5SDimitry Andric       report_fatal_error("alignment is limited to 32-bytes");
261*0b57cec5SDimitry Andric 
262*0b57cec5SDimitry Andric     // Round size up to alignment so that we will honor the alignment request.
263*0b57cec5SDimitry Andric     Size = std::max(Size, static_cast<uint64_t>(ByteAlignment));
264*0b57cec5SDimitry Andric   }
265*0b57cec5SDimitry Andric 
266*0b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
267*0b57cec5SDimitry Andric   Symbol->setExternal(true);
268*0b57cec5SDimitry Andric   Symbol->setCommon(Size, ByteAlignment);
269*0b57cec5SDimitry Andric 
270*0b57cec5SDimitry Andric   if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) {
271*0b57cec5SDimitry Andric     SmallString<128> Directive;
272*0b57cec5SDimitry Andric     raw_svector_ostream OS(Directive);
273*0b57cec5SDimitry Andric     const MCObjectFileInfo *MFI = getContext().getObjectFileInfo();
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric     OS << " -aligncomm:\"" << Symbol->getName() << "\","
276*0b57cec5SDimitry Andric        << Log2_32_Ceil(ByteAlignment);
277*0b57cec5SDimitry Andric 
278*0b57cec5SDimitry Andric     PushSection();
279*0b57cec5SDimitry Andric     SwitchSection(MFI->getDrectveSection());
280*0b57cec5SDimitry Andric     EmitBytes(Directive);
281*0b57cec5SDimitry Andric     PopSection();
282*0b57cec5SDimitry Andric   }
283*0b57cec5SDimitry Andric }
284*0b57cec5SDimitry Andric 
285*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
286*0b57cec5SDimitry Andric                                               unsigned ByteAlignment) {
287*0b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
288*0b57cec5SDimitry Andric 
289*0b57cec5SDimitry Andric   MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
290*0b57cec5SDimitry Andric   PushSection();
291*0b57cec5SDimitry Andric   SwitchSection(Section);
292*0b57cec5SDimitry Andric   EmitValueToAlignment(ByteAlignment, 0, 1, 0);
293*0b57cec5SDimitry Andric   EmitLabel(Symbol);
294*0b57cec5SDimitry Andric   Symbol->setExternal(false);
295*0b57cec5SDimitry Andric   EmitZeros(Size);
296*0b57cec5SDimitry Andric   PopSection();
297*0b57cec5SDimitry Andric }
298*0b57cec5SDimitry Andric 
299*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
300*0b57cec5SDimitry Andric                                      uint64_t Size, unsigned ByteAlignment,
301*0b57cec5SDimitry Andric                                      SMLoc Loc) {
302*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
303*0b57cec5SDimitry Andric }
304*0b57cec5SDimitry Andric 
305*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
306*0b57cec5SDimitry Andric                                        uint64_t Size, unsigned ByteAlignment) {
307*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
308*0b57cec5SDimitry Andric }
309*0b57cec5SDimitry Andric 
310*0b57cec5SDimitry Andric // TODO: Implement this if you want to emit .comment section in COFF obj files.
311*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) {
312*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
313*0b57cec5SDimitry Andric }
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
316*0b57cec5SDimitry Andric   llvm_unreachable("not implemented");
317*0b57cec5SDimitry Andric }
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric void MCWinCOFFStreamer::FinishImpl() {
320*0b57cec5SDimitry Andric   MCObjectStreamer::FinishImpl();
321*0b57cec5SDimitry Andric }
322*0b57cec5SDimitry Andric 
323*0b57cec5SDimitry Andric void MCWinCOFFStreamer::Error(const Twine &Msg) const {
324*0b57cec5SDimitry Andric   getContext().reportError(SMLoc(), Msg);
325*0b57cec5SDimitry Andric }
326