xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains an implementation of a Windows COFF object file streamer.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
1381ad6265SDimitry Andric #include "llvm/MC/MCWinCOFFStreamer.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
28*0fca6ea1SDimitry Andric #include "llvm/MC/MCSectionCOFF.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h"
30*0fca6ea1SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
31*0fca6ea1SDimitry Andric #include "llvm/MC/MCWinCOFFObjectWriter.h"
320b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
340b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
350b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
360b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3706c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
380b57cec5SDimitry Andric #include <algorithm>
390b57cec5SDimitry Andric #include <cstdint>
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #define DEBUG_TYPE "WinCOFFStreamer"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
460b57cec5SDimitry Andric                                      std::unique_ptr<MCAsmBackend> MAB,
470b57cec5SDimitry Andric                                      std::unique_ptr<MCCodeEmitter> CE,
480b57cec5SDimitry Andric                                      std::unique_ptr<MCObjectWriter> OW)
490b57cec5SDimitry Andric     : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
50*0fca6ea1SDimitry Andric       CurSymbol(nullptr) {
51*0fca6ea1SDimitry Andric   auto *TO = Context.getTargetOptions();
52*0fca6ea1SDimitry Andric   if (TO && TO->MCIncrementalLinkerCompatible)
53*0fca6ea1SDimitry Andric     getWriter().setIncrementalLinkerCompatible(true);
54*0fca6ea1SDimitry Andric }
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric WinCOFFObjectWriter &MCWinCOFFStreamer::getWriter() {
57*0fca6ea1SDimitry Andric   return static_cast<WinCOFFObjectWriter &>(getAssembler().getWriter());
58*0fca6ea1SDimitry Andric }
590b57cec5SDimitry Andric 
605ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst,
610b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI) {
620b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   SmallVector<MCFixup, 4> Fixups;
650b57cec5SDimitry Andric   SmallString<256> Code;
6606c3fb27SDimitry Andric   getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   // Add the fixups and data.
690b57cec5SDimitry Andric   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
700b57cec5SDimitry Andric     Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
710b57cec5SDimitry Andric     DF->getFixups().push_back(Fixups[i]);
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric   DF->setHasInstructions(STI);
740b57cec5SDimitry Andric   DF->getContents().append(Code.begin(), Code.end());
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
77349cc55cSDimitry Andric void MCWinCOFFStreamer::initSections(bool NoExecStack,
78349cc55cSDimitry Andric                                      const MCSubtargetInfo &STI) {
790b57cec5SDimitry Andric   // FIXME: this is identical to the ELF one.
800b57cec5SDimitry Andric   // This emulates the same behavior of GNU as. This makes it easier
810b57cec5SDimitry Andric   // to compare the output as the major sections are in the same order.
8281ad6265SDimitry Andric   switchSection(getContext().getObjectFileInfo()->getTextSection());
83bdd1243dSDimitry Andric   emitCodeAlignment(Align(4), &STI);
840b57cec5SDimitry Andric 
8581ad6265SDimitry Andric   switchSection(getContext().getObjectFileInfo()->getDataSection());
86bdd1243dSDimitry Andric   emitCodeAlignment(Align(4), &STI);
870b57cec5SDimitry Andric 
8881ad6265SDimitry Andric   switchSection(getContext().getObjectFileInfo()->getBSSSection());
89bdd1243dSDimitry Andric   emitCodeAlignment(Align(4), &STI);
900b57cec5SDimitry Andric 
9181ad6265SDimitry Andric   switchSection(getContext().getObjectFileInfo()->getTextSection());
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
94*0fca6ea1SDimitry Andric void MCWinCOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
95*0fca6ea1SDimitry Andric   changeSectionImpl(Section, Subsection);
96*0fca6ea1SDimitry Andric   // Ensure that the first and the second symbols relative to the section are
97*0fca6ea1SDimitry Andric   // the section symbol and the COMDAT symbol.
98*0fca6ea1SDimitry Andric   getAssembler().registerSymbol(*Section->getBeginSymbol());
99*0fca6ea1SDimitry Andric   if (auto *Sym = cast<MCSectionCOFF>(Section)->getCOMDATSymbol())
100*0fca6ea1SDimitry Andric     getAssembler().registerSymbol(*Sym);
101*0fca6ea1SDimitry Andric }
102*0fca6ea1SDimitry Andric 
1035ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
1040b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
1055ffd83dbSDimitry Andric   MCObjectStreamer::emitLabel(Symbol, Loc);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1085ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
1098bcb0991SDimitry Andric   // Let the target do whatever target specific stuff it needs to do.
1108bcb0991SDimitry Andric   getAssembler().getBackend().handleAssemblerFlag(Flag);
1118bcb0991SDimitry Andric 
1128bcb0991SDimitry Andric   switch (Flag) {
1138bcb0991SDimitry Andric   // None of these require COFF specific handling.
1148bcb0991SDimitry Andric   case MCAF_SyntaxUnified:
1158bcb0991SDimitry Andric   case MCAF_Code16:
1168bcb0991SDimitry Andric   case MCAF_Code32:
1178bcb0991SDimitry Andric   case MCAF_Code64:
1188bcb0991SDimitry Andric     break;
1198bcb0991SDimitry Andric   case MCAF_SubsectionsViaSymbols:
1208bcb0991SDimitry Andric     llvm_unreachable("COFF doesn't support .subsections_via_symbols");
1218bcb0991SDimitry Andric   }
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1245ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitThumbFunc(MCSymbol *Func) {
1250b57cec5SDimitry Andric   llvm_unreachable("not implemented");
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1285ffd83dbSDimitry Andric bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S,
1290b57cec5SDimitry Andric                                             MCSymbolAttr Attribute) {
1300b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
1310b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   switch (Attribute) {
1340b57cec5SDimitry Andric   default: return false;
1350b57cec5SDimitry Andric   case MCSA_WeakReference:
1360b57cec5SDimitry Andric   case MCSA_Weak:
13706c3fb27SDimitry Andric     Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS);
1380b57cec5SDimitry Andric     Symbol->setExternal(true);
1390b57cec5SDimitry Andric     break;
14006c3fb27SDimitry Andric   case MCSA_WeakAntiDep:
14106c3fb27SDimitry Andric     Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY);
14206c3fb27SDimitry Andric     Symbol->setExternal(true);
14306c3fb27SDimitry Andric     Symbol->setIsWeakExternal(true);
14406c3fb27SDimitry Andric     break;
1450b57cec5SDimitry Andric   case MCSA_Global:
1460b57cec5SDimitry Andric     Symbol->setExternal(true);
1470b57cec5SDimitry Andric     break;
1480b57cec5SDimitry Andric   case MCSA_AltEntry:
1490b57cec5SDimitry Andric     llvm_unreachable("COFF doesn't support the .alt_entry attribute");
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   return true;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1555ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
1560b57cec5SDimitry Andric   llvm_unreachable("not implemented");
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
15981ad6265SDimitry Andric void MCWinCOFFStreamer::beginCOFFSymbolDef(MCSymbol const *S) {
1600b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
1610b57cec5SDimitry Andric   if (CurSymbol)
1620b57cec5SDimitry Andric     Error("starting a new symbol definition without completing the "
1630b57cec5SDimitry Andric           "previous one");
1640b57cec5SDimitry Andric   CurSymbol = Symbol;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
16781ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
1680b57cec5SDimitry Andric   if (!CurSymbol) {
1690b57cec5SDimitry Andric     Error("storage class specified outside of symbol definition");
1700b57cec5SDimitry Andric     return;
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   if (StorageClass & ~COFF::SSC_Invalid) {
1740b57cec5SDimitry Andric     Error("storage class value '" + Twine(StorageClass) +
1750b57cec5SDimitry Andric                "' out of range");
1760b57cec5SDimitry Andric     return;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   getAssembler().registerSymbol(*CurSymbol);
1800b57cec5SDimitry Andric   cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
18381ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSymbolType(int Type) {
1840b57cec5SDimitry Andric   if (!CurSymbol) {
1850b57cec5SDimitry Andric     Error("symbol type specified outside of a symbol definition");
1860b57cec5SDimitry Andric     return;
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   if (Type & ~0xffff) {
1900b57cec5SDimitry Andric     Error("type value '" + Twine(Type) + "' out of range");
1910b57cec5SDimitry Andric     return;
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   getAssembler().registerSymbol(*CurSymbol);
1950b57cec5SDimitry Andric   cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
19881ad6265SDimitry Andric void MCWinCOFFStreamer::endCOFFSymbolDef() {
1990b57cec5SDimitry Andric   if (!CurSymbol)
2000b57cec5SDimitry Andric     Error("ending symbol definition without starting one");
2010b57cec5SDimitry Andric   CurSymbol = nullptr;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
20481ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {
2050b57cec5SDimitry Andric   // SafeSEH is a feature specific to 32-bit x86.  It does not exist (and is
2060b57cec5SDimitry Andric   // unnecessary) on all platforms which use table-based exception dispatch.
207fe6060f1SDimitry Andric   if (getContext().getTargetTriple().getArch() != Triple::x86)
2080b57cec5SDimitry Andric     return;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
2110b57cec5SDimitry Andric   if (CSymbol->isSafeSEH())
2120b57cec5SDimitry Andric     return;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
215*0fca6ea1SDimitry Andric   changeSection(SXData);
216bdd1243dSDimitry Andric   SXData->ensureMinAlignment(Align(4));
2170b57cec5SDimitry Andric 
218*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCSymbolIdFragment>(Symbol));
2190b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
2200b57cec5SDimitry Andric   CSymbol->setIsSafeSEH();
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   // The Microsoft linker requires that the symbol type of a handler be
2230b57cec5SDimitry Andric   // function. Go ahead and oblige it here.
2240b57cec5SDimitry Andric   CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
2250b57cec5SDimitry Andric                    << COFF::SCT_COMPLEX_TYPE_SHIFT);
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
22881ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
2290b57cec5SDimitry Andric   MCSection *Sec = getCurrentSectionOnly();
230bdd1243dSDimitry Andric   Sec->ensureMinAlignment(Align(4));
2310b57cec5SDimitry Andric 
232*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCSymbolIdFragment>(Symbol));
2330b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
23681ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) {
2370b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
2380b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
2390b57cec5SDimitry Andric   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
2400b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
2410b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
2420b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 2, 0);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
24581ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol,
2460b57cec5SDimitry Andric                                          uint64_t Offset) {
2470b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
2480b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
2490b57cec5SDimitry Andric   // Create Symbol A for the relocation relative reference.
2500b57cec5SDimitry Andric   const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
2510b57cec5SDimitry Andric   // Add the constant offset, if given.
2520b57cec5SDimitry Andric   if (Offset)
2530b57cec5SDimitry Andric     MCE = MCBinaryExpr::createAdd(
2540b57cec5SDimitry Andric         MCE, MCConstantExpr::create(Offset, getContext()), getContext());
2550b57cec5SDimitry Andric   // Build the secrel32 relocation.
2560b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
2570b57cec5SDimitry Andric   // Record the relocation.
2580b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
2590b57cec5SDimitry Andric   // Emit 4 bytes (zeros) to the object file.
2600b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
26381ad6265SDimitry Andric void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
2640b57cec5SDimitry Andric                                          int64_t Offset) {
2650b57cec5SDimitry Andric   visitUsedSymbol(*Symbol);
2660b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
2670b57cec5SDimitry Andric   // Create Symbol A for the relocation relative reference.
2680b57cec5SDimitry Andric   const MCExpr *MCE = MCSymbolRefExpr::create(
2690b57cec5SDimitry Andric       Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
2700b57cec5SDimitry Andric   // Add the constant offset, if given.
2710b57cec5SDimitry Andric   if (Offset)
2720b57cec5SDimitry Andric     MCE = MCBinaryExpr::createAdd(
2730b57cec5SDimitry Andric         MCE, MCConstantExpr::create(Offset, getContext()), getContext());
2740b57cec5SDimitry Andric   // Build the imgrel relocation.
2750b57cec5SDimitry Andric   MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
2760b57cec5SDimitry Andric   // Record the relocation.
2770b57cec5SDimitry Andric   DF->getFixups().push_back(Fixup);
2780b57cec5SDimitry Andric   // Emit 4 bytes (zeros) to the object file.
2790b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2825ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
283bdd1243dSDimitry Andric                                          Align ByteAlignment) {
2840b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
2850b57cec5SDimitry Andric 
286fe6060f1SDimitry Andric   const Triple &T = getContext().getTargetTriple();
2870b57cec5SDimitry Andric   if (T.isWindowsMSVCEnvironment()) {
2880b57cec5SDimitry Andric     if (ByteAlignment > 32)
2890b57cec5SDimitry Andric       report_fatal_error("alignment is limited to 32-bytes");
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     // Round size up to alignment so that we will honor the alignment request.
292bdd1243dSDimitry Andric     Size = std::max(Size, ByteAlignment.value());
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
2960b57cec5SDimitry Andric   Symbol->setExternal(true);
2970b57cec5SDimitry Andric   Symbol->setCommon(Size, ByteAlignment);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) {
3000b57cec5SDimitry Andric     SmallString<128> Directive;
3010b57cec5SDimitry Andric     raw_svector_ostream OS(Directive);
3020b57cec5SDimitry Andric     const MCObjectFileInfo *MFI = getContext().getObjectFileInfo();
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     OS << " -aligncomm:\"" << Symbol->getName() << "\","
305bdd1243dSDimitry Andric        << Log2_32_Ceil(ByteAlignment.value());
3060b57cec5SDimitry Andric 
30781ad6265SDimitry Andric     pushSection();
30881ad6265SDimitry Andric     switchSection(MFI->getDrectveSection());
3095ffd83dbSDimitry Andric     emitBytes(Directive);
31081ad6265SDimitry Andric     popSection();
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3145ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
315bdd1243dSDimitry Andric                                               Align ByteAlignment) {
3160b57cec5SDimitry Andric   auto *Symbol = cast<MCSymbolCOFF>(S);
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
31981ad6265SDimitry Andric   pushSection();
32081ad6265SDimitry Andric   switchSection(Section);
3215ffd83dbSDimitry Andric   emitValueToAlignment(ByteAlignment, 0, 1, 0);
3225ffd83dbSDimitry Andric   emitLabel(Symbol);
3230b57cec5SDimitry Andric   Symbol->setExternal(false);
3245ffd83dbSDimitry Andric   emitZeros(Size);
32581ad6265SDimitry Andric   popSection();
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
328e8d8bef9SDimitry Andric void MCWinCOFFStreamer::emitWeakReference(MCSymbol *AliasS,
329e8d8bef9SDimitry Andric                                           const MCSymbol *Symbol) {
330e8d8bef9SDimitry Andric   auto *Alias = cast<MCSymbolCOFF>(AliasS);
331e8d8bef9SDimitry Andric   emitSymbolAttribute(Alias, MCSA_Weak);
332e8d8bef9SDimitry Andric 
333e8d8bef9SDimitry Andric   getAssembler().registerSymbol(*Symbol);
334e8d8bef9SDimitry Andric   Alias->setVariableValue(MCSymbolRefExpr::create(
335e8d8bef9SDimitry Andric       Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()));
336e8d8bef9SDimitry Andric }
337e8d8bef9SDimitry Andric 
3385ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
339bdd1243dSDimitry Andric                                      uint64_t Size, Align ByteAlignment,
3400b57cec5SDimitry Andric                                      SMLoc Loc) {
3410b57cec5SDimitry Andric   llvm_unreachable("not implemented");
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
3445ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
345bdd1243dSDimitry Andric                                        uint64_t Size, Align ByteAlignment) {
3460b57cec5SDimitry Andric   llvm_unreachable("not implemented");
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric // TODO: Implement this if you want to emit .comment section in COFF obj files.
3505ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitIdent(StringRef IdentString) {
3510b57cec5SDimitry Andric   llvm_unreachable("not implemented");
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
35481ad6265SDimitry Andric void MCWinCOFFStreamer::emitWinEHHandlerData(SMLoc Loc) {
3550b57cec5SDimitry Andric   llvm_unreachable("not implemented");
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
3585ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
3595ffd83dbSDimitry Andric                                            const MCSymbolRefExpr *To,
3605ffd83dbSDimitry Andric                                            uint64_t Count) {
3615ffd83dbSDimitry Andric   // Ignore temporary symbols for now.
3625ffd83dbSDimitry Andric   if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
363*0fca6ea1SDimitry Andric     getWriter().getCGProfile().push_back({From, To, Count});
3645ffd83dbSDimitry Andric }
3655ffd83dbSDimitry Andric 
3665ffd83dbSDimitry Andric void MCWinCOFFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
3675ffd83dbSDimitry Andric   const MCSymbol *S = &SRE->getSymbol();
36806c3fb27SDimitry Andric   if (getAssembler().registerSymbol(*S))
3695ffd83dbSDimitry Andric     cast<MCSymbolCOFF>(S)->setExternal(true);
3705ffd83dbSDimitry Andric }
3715ffd83dbSDimitry Andric 
372*0fca6ea1SDimitry Andric void MCWinCOFFStreamer::finishImpl() {
373*0fca6ea1SDimitry Andric   MCAssembler &Asm = getAssembler();
374*0fca6ea1SDimitry Andric   if (Asm.getWriter().getEmitAddrsigSection()) {
375*0fca6ea1SDimitry Andric     // Register the section.
376*0fca6ea1SDimitry Andric     switchSection(Asm.getContext().getCOFFSection(".llvm_addrsig",
377*0fca6ea1SDimitry Andric                                                   COFF::IMAGE_SCN_LNK_REMOVE));
378*0fca6ea1SDimitry Andric   }
379*0fca6ea1SDimitry Andric   if (!Asm.getWriter().getCGProfile().empty()) {
380*0fca6ea1SDimitry Andric     for (auto &E : Asm.getWriter().getCGProfile()) {
3815ffd83dbSDimitry Andric       finalizeCGProfileEntry(E.From);
3825ffd83dbSDimitry Andric       finalizeCGProfileEntry(E.To);
3835ffd83dbSDimitry Andric     }
384*0fca6ea1SDimitry Andric     switchSection(Asm.getContext().getCOFFSection(".llvm.call-graph-profile",
385*0fca6ea1SDimitry Andric                                                   COFF::IMAGE_SCN_LNK_REMOVE));
3865ffd83dbSDimitry Andric   }
3875ffd83dbSDimitry Andric 
3885ffd83dbSDimitry Andric   MCObjectStreamer::finishImpl();
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric void MCWinCOFFStreamer::Error(const Twine &Msg) const {
3920b57cec5SDimitry Andric   getContext().reportError(SMLoc(), Msg);
3930b57cec5SDimitry Andric }
394