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
MCWinCOFFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCCodeEmitter> CE,std::unique_ptr<MCObjectWriter> OW)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
getWriter()56*0fca6ea1SDimitry Andric WinCOFFObjectWriter &MCWinCOFFStreamer::getWriter() {
57*0fca6ea1SDimitry Andric return static_cast<WinCOFFObjectWriter &>(getAssembler().getWriter());
58*0fca6ea1SDimitry Andric }
590b57cec5SDimitry Andric
emitInstToData(const MCInst & Inst,const MCSubtargetInfo & STI)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
initSections(bool NoExecStack,const MCSubtargetInfo & STI)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
changeSection(MCSection * Section,uint32_t Subsection)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
emitLabel(MCSymbol * S,SMLoc Loc)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
emitAssemblerFlag(MCAssemblerFlag Flag)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
emitThumbFunc(MCSymbol * Func)1245ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitThumbFunc(MCSymbol *Func) {
1250b57cec5SDimitry Andric llvm_unreachable("not implemented");
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
emitSymbolAttribute(MCSymbol * S,MCSymbolAttr Attribute)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
emitSymbolDesc(MCSymbol * Symbol,unsigned DescValue)1555ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
1560b57cec5SDimitry Andric llvm_unreachable("not implemented");
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
beginCOFFSymbolDef(MCSymbol const * S)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
emitCOFFSymbolStorageClass(int StorageClass)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
emitCOFFSymbolType(int Type)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
endCOFFSymbolDef()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
emitCOFFSafeSEH(MCSymbol const * Symbol)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
emitCOFFSymbolIndex(MCSymbol const * Symbol)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
emitCOFFSectionIndex(const MCSymbol * Symbol)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
emitCOFFSecRel32(const MCSymbol * Symbol,uint64_t Offset)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
emitCOFFImgRel32(const MCSymbol * Symbol,int64_t Offset)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
emitCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)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
emitLocalCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)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
emitWeakReference(MCSymbol * AliasS,const MCSymbol * Symbol)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
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,Align ByteAlignment,SMLoc Loc)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
emitTBSSSymbol(MCSection * Section,MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)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.
emitIdent(StringRef IdentString)3505ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitIdent(StringRef IdentString) {
3510b57cec5SDimitry Andric llvm_unreachable("not implemented");
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric
emitWinEHHandlerData(SMLoc Loc)35481ad6265SDimitry Andric void MCWinCOFFStreamer::emitWinEHHandlerData(SMLoc Loc) {
3550b57cec5SDimitry Andric llvm_unreachable("not implemented");
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
emitCGProfileEntry(const MCSymbolRefExpr * From,const MCSymbolRefExpr * To,uint64_t Count)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
finalizeCGProfileEntry(const MCSymbolRefExpr * & SRE)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
finishImpl()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
Error(const Twine & Msg) const3910b57cec5SDimitry Andric void MCWinCOFFStreamer::Error(const Twine &Msg) const {
3920b57cec5SDimitry Andric getContext().reportError(SMLoc(), Msg);
3930b57cec5SDimitry Andric }
394