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 130b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 150b57cec5SDimitry Andric #include "llvm/ADT/Triple.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" 280b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFStreamer.h" 310b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 330b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 340b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 360b57cec5SDimitry Andric #include <algorithm> 370b57cec5SDimitry Andric #include <cassert> 380b57cec5SDimitry Andric #include <cstdint> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric using namespace llvm; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric #define DEBUG_TYPE "WinCOFFStreamer" 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, 450b57cec5SDimitry Andric std::unique_ptr<MCAsmBackend> MAB, 460b57cec5SDimitry Andric std::unique_ptr<MCCodeEmitter> CE, 470b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter> OW) 480b57cec5SDimitry Andric : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)), 490b57cec5SDimitry Andric CurSymbol(nullptr) {} 500b57cec5SDimitry Andric 51*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst, 520b57cec5SDimitry Andric const MCSubtargetInfo &STI) { 530b57cec5SDimitry Andric MCDataFragment *DF = getOrCreateDataFragment(); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 560b57cec5SDimitry Andric SmallString<256> Code; 570b57cec5SDimitry Andric raw_svector_ostream VecOS(Code); 580b57cec5SDimitry Andric getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Add the fixups and data. 610b57cec5SDimitry Andric for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 620b57cec5SDimitry Andric Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 630b57cec5SDimitry Andric DF->getFixups().push_back(Fixups[i]); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric DF->setHasInstructions(STI); 660b57cec5SDimitry Andric DF->getContents().append(Code.begin(), Code.end()); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void MCWinCOFFStreamer::InitSections(bool NoExecStack) { 700b57cec5SDimitry Andric // FIXME: this is identical to the ELF one. 710b57cec5SDimitry Andric // This emulates the same behavior of GNU as. This makes it easier 720b57cec5SDimitry Andric // to compare the output as the major sections are in the same order. 730b57cec5SDimitry Andric SwitchSection(getContext().getObjectFileInfo()->getTextSection()); 74*5ffd83dbSDimitry Andric emitCodeAlignment(4); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric SwitchSection(getContext().getObjectFileInfo()->getDataSection()); 77*5ffd83dbSDimitry Andric emitCodeAlignment(4); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); 80*5ffd83dbSDimitry Andric emitCodeAlignment(4); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric SwitchSection(getContext().getObjectFileInfo()->getTextSection()); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 85*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { 860b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolCOFF>(S); 87*5ffd83dbSDimitry Andric MCObjectStreamer::emitLabel(Symbol, Loc); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 90*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) { 918bcb0991SDimitry Andric // Let the target do whatever target specific stuff it needs to do. 928bcb0991SDimitry Andric getAssembler().getBackend().handleAssemblerFlag(Flag); 938bcb0991SDimitry Andric 948bcb0991SDimitry Andric switch (Flag) { 958bcb0991SDimitry Andric // None of these require COFF specific handling. 968bcb0991SDimitry Andric case MCAF_SyntaxUnified: 978bcb0991SDimitry Andric case MCAF_Code16: 988bcb0991SDimitry Andric case MCAF_Code32: 998bcb0991SDimitry Andric case MCAF_Code64: 1008bcb0991SDimitry Andric break; 1018bcb0991SDimitry Andric case MCAF_SubsectionsViaSymbols: 1028bcb0991SDimitry Andric llvm_unreachable("COFF doesn't support .subsections_via_symbols"); 1038bcb0991SDimitry Andric } 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 106*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitThumbFunc(MCSymbol *Func) { 1070b57cec5SDimitry Andric llvm_unreachable("not implemented"); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 110*5ffd83dbSDimitry Andric bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S, 1110b57cec5SDimitry Andric MCSymbolAttr Attribute) { 1120b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolCOFF>(S); 1130b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric switch (Attribute) { 1160b57cec5SDimitry Andric default: return false; 1170b57cec5SDimitry Andric case MCSA_WeakReference: 1180b57cec5SDimitry Andric case MCSA_Weak: 1190b57cec5SDimitry Andric Symbol->setIsWeakExternal(); 1200b57cec5SDimitry Andric Symbol->setExternal(true); 1210b57cec5SDimitry Andric break; 1220b57cec5SDimitry Andric case MCSA_Global: 1230b57cec5SDimitry Andric Symbol->setExternal(true); 1240b57cec5SDimitry Andric break; 1250b57cec5SDimitry Andric case MCSA_AltEntry: 1260b57cec5SDimitry Andric llvm_unreachable("COFF doesn't support the .alt_entry attribute"); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric return true; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 132*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 1330b57cec5SDimitry Andric llvm_unreachable("not implemented"); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { 1370b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolCOFF>(S); 1380b57cec5SDimitry Andric if (CurSymbol) 1390b57cec5SDimitry Andric Error("starting a new symbol definition without completing the " 1400b57cec5SDimitry Andric "previous one"); 1410b57cec5SDimitry Andric CurSymbol = Symbol; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 1450b57cec5SDimitry Andric if (!CurSymbol) { 1460b57cec5SDimitry Andric Error("storage class specified outside of symbol definition"); 1470b57cec5SDimitry Andric return; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (StorageClass & ~COFF::SSC_Invalid) { 1510b57cec5SDimitry Andric Error("storage class value '" + Twine(StorageClass) + 1520b57cec5SDimitry Andric "' out of range"); 1530b57cec5SDimitry Andric return; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric getAssembler().registerSymbol(*CurSymbol); 1570b57cec5SDimitry Andric cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { 1610b57cec5SDimitry Andric if (!CurSymbol) { 1620b57cec5SDimitry Andric Error("symbol type specified outside of a symbol definition"); 1630b57cec5SDimitry Andric return; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric if (Type & ~0xffff) { 1670b57cec5SDimitry Andric Error("type value '" + Twine(Type) + "' out of range"); 1680b57cec5SDimitry Andric return; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric getAssembler().registerSymbol(*CurSymbol); 1720b57cec5SDimitry Andric cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void MCWinCOFFStreamer::EndCOFFSymbolDef() { 1760b57cec5SDimitry Andric if (!CurSymbol) 1770b57cec5SDimitry Andric Error("ending symbol definition without starting one"); 1780b57cec5SDimitry Andric CurSymbol = nullptr; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { 1820b57cec5SDimitry Andric // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is 1830b57cec5SDimitry Andric // unnecessary) on all platforms which use table-based exception dispatch. 1840b57cec5SDimitry Andric if (getContext().getObjectFileInfo()->getTargetTriple().getArch() != 1850b57cec5SDimitry Andric Triple::x86) 1860b57cec5SDimitry Andric return; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol); 1890b57cec5SDimitry Andric if (CSymbol->isSafeSEH()) 1900b57cec5SDimitry Andric return; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); 1930b57cec5SDimitry Andric getAssembler().registerSection(*SXData); 1940b57cec5SDimitry Andric if (SXData->getAlignment() < 4) 1958bcb0991SDimitry Andric SXData->setAlignment(Align(4)); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric new MCSymbolIdFragment(Symbol, SXData); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 2000b57cec5SDimitry Andric CSymbol->setIsSafeSEH(); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // The Microsoft linker requires that the symbol type of a handler be 2030b57cec5SDimitry Andric // function. Go ahead and oblige it here. 2040b57cec5SDimitry Andric CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION 2050b57cec5SDimitry Andric << COFF::SCT_COMPLEX_TYPE_SHIFT); 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { 2090b57cec5SDimitry Andric MCSection *Sec = getCurrentSectionOnly(); 2100b57cec5SDimitry Andric getAssembler().registerSection(*Sec); 2110b57cec5SDimitry Andric if (Sec->getAlignment() < 4) 2128bcb0991SDimitry Andric Sec->setAlignment(Align(4)); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric new MCSymbolIdFragment(Symbol, getCurrentSectionOnly()); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) { 2200b57cec5SDimitry Andric visitUsedSymbol(*Symbol); 2210b57cec5SDimitry Andric MCDataFragment *DF = getOrCreateDataFragment(); 2220b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); 2230b57cec5SDimitry Andric MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); 2240b57cec5SDimitry Andric DF->getFixups().push_back(Fixup); 2250b57cec5SDimitry Andric DF->getContents().resize(DF->getContents().size() + 2, 0); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol, 2290b57cec5SDimitry Andric uint64_t Offset) { 2300b57cec5SDimitry Andric visitUsedSymbol(*Symbol); 2310b57cec5SDimitry Andric MCDataFragment *DF = getOrCreateDataFragment(); 2320b57cec5SDimitry Andric // Create Symbol A for the relocation relative reference. 2330b57cec5SDimitry Andric const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); 2340b57cec5SDimitry Andric // Add the constant offset, if given. 2350b57cec5SDimitry Andric if (Offset) 2360b57cec5SDimitry Andric MCE = MCBinaryExpr::createAdd( 2370b57cec5SDimitry Andric MCE, MCConstantExpr::create(Offset, getContext()), getContext()); 2380b57cec5SDimitry Andric // Build the secrel32 relocation. 2390b57cec5SDimitry Andric MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); 2400b57cec5SDimitry Andric // Record the relocation. 2410b57cec5SDimitry Andric DF->getFixups().push_back(Fixup); 2420b57cec5SDimitry Andric // Emit 4 bytes (zeros) to the object file. 2430b57cec5SDimitry Andric DF->getContents().resize(DF->getContents().size() + 4, 0); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol, 2470b57cec5SDimitry Andric int64_t Offset) { 2480b57cec5SDimitry Andric visitUsedSymbol(*Symbol); 2490b57cec5SDimitry Andric MCDataFragment *DF = getOrCreateDataFragment(); 2500b57cec5SDimitry Andric // Create Symbol A for the relocation relative reference. 2510b57cec5SDimitry Andric const MCExpr *MCE = MCSymbolRefExpr::create( 2520b57cec5SDimitry Andric Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); 2530b57cec5SDimitry Andric // Add the constant offset, if given. 2540b57cec5SDimitry Andric if (Offset) 2550b57cec5SDimitry Andric MCE = MCBinaryExpr::createAdd( 2560b57cec5SDimitry Andric MCE, MCConstantExpr::create(Offset, getContext()), getContext()); 2570b57cec5SDimitry Andric // Build the imgrel relocation. 2580b57cec5SDimitry Andric MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4); 2590b57cec5SDimitry Andric // Record the relocation. 2600b57cec5SDimitry Andric DF->getFixups().push_back(Fixup); 2610b57cec5SDimitry Andric // Emit 4 bytes (zeros) to the object file. 2620b57cec5SDimitry Andric DF->getContents().resize(DF->getContents().size() + 4, 0); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 265*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size, 2660b57cec5SDimitry Andric unsigned ByteAlignment) { 2670b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolCOFF>(S); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); 2700b57cec5SDimitry Andric if (T.isWindowsMSVCEnvironment()) { 2710b57cec5SDimitry Andric if (ByteAlignment > 32) 2720b57cec5SDimitry Andric report_fatal_error("alignment is limited to 32-bytes"); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // Round size up to alignment so that we will honor the alignment request. 2750b57cec5SDimitry Andric Size = std::max(Size, static_cast<uint64_t>(ByteAlignment)); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 2790b57cec5SDimitry Andric Symbol->setExternal(true); 2800b57cec5SDimitry Andric Symbol->setCommon(Size, ByteAlignment); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) { 2830b57cec5SDimitry Andric SmallString<128> Directive; 2840b57cec5SDimitry Andric raw_svector_ostream OS(Directive); 2850b57cec5SDimitry Andric const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric OS << " -aligncomm:\"" << Symbol->getName() << "\"," 2880b57cec5SDimitry Andric << Log2_32_Ceil(ByteAlignment); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric PushSection(); 2910b57cec5SDimitry Andric SwitchSection(MFI->getDrectveSection()); 292*5ffd83dbSDimitry Andric emitBytes(Directive); 2930b57cec5SDimitry Andric PopSection(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 297*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, 2980b57cec5SDimitry Andric unsigned ByteAlignment) { 2990b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolCOFF>(S); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); 3020b57cec5SDimitry Andric PushSection(); 3030b57cec5SDimitry Andric SwitchSection(Section); 304*5ffd83dbSDimitry Andric emitValueToAlignment(ByteAlignment, 0, 1, 0); 305*5ffd83dbSDimitry Andric emitLabel(Symbol); 3060b57cec5SDimitry Andric Symbol->setExternal(false); 307*5ffd83dbSDimitry Andric emitZeros(Size); 3080b57cec5SDimitry Andric PopSection(); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 311*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 3120b57cec5SDimitry Andric uint64_t Size, unsigned ByteAlignment, 3130b57cec5SDimitry Andric SMLoc Loc) { 3140b57cec5SDimitry Andric llvm_unreachable("not implemented"); 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 317*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 3180b57cec5SDimitry Andric uint64_t Size, unsigned ByteAlignment) { 3190b57cec5SDimitry Andric llvm_unreachable("not implemented"); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric // TODO: Implement this if you want to emit .comment section in COFF obj files. 323*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitIdent(StringRef IdentString) { 3240b57cec5SDimitry Andric llvm_unreachable("not implemented"); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) { 3280b57cec5SDimitry Andric llvm_unreachable("not implemented"); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 331*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, 332*5ffd83dbSDimitry Andric const MCSymbolRefExpr *To, 333*5ffd83dbSDimitry Andric uint64_t Count) { 334*5ffd83dbSDimitry Andric // Ignore temporary symbols for now. 335*5ffd83dbSDimitry Andric if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary()) 336*5ffd83dbSDimitry Andric getAssembler().CGProfile.push_back({From, To, Count}); 337*5ffd83dbSDimitry Andric } 338*5ffd83dbSDimitry Andric 339*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) { 340*5ffd83dbSDimitry Andric const MCSymbol *S = &SRE->getSymbol(); 341*5ffd83dbSDimitry Andric bool Created; 342*5ffd83dbSDimitry Andric getAssembler().registerSymbol(*S, &Created); 343*5ffd83dbSDimitry Andric if (Created) { 344*5ffd83dbSDimitry Andric cast<MCSymbolCOFF>(S)->setIsWeakExternal(); 345*5ffd83dbSDimitry Andric cast<MCSymbolCOFF>(S)->setExternal(true); 346*5ffd83dbSDimitry Andric } 347*5ffd83dbSDimitry Andric } 348*5ffd83dbSDimitry Andric 349*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::finalizeCGProfile() { 350*5ffd83dbSDimitry Andric for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) { 351*5ffd83dbSDimitry Andric finalizeCGProfileEntry(E.From); 352*5ffd83dbSDimitry Andric finalizeCGProfileEntry(E.To); 353*5ffd83dbSDimitry Andric } 354*5ffd83dbSDimitry Andric } 355*5ffd83dbSDimitry Andric 356*5ffd83dbSDimitry Andric void MCWinCOFFStreamer::finishImpl() { 357*5ffd83dbSDimitry Andric finalizeCGProfile(); 358*5ffd83dbSDimitry Andric 359*5ffd83dbSDimitry Andric MCObjectStreamer::finishImpl(); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric void MCWinCOFFStreamer::Error(const Twine &Msg) const { 3630b57cec5SDimitry Andric getContext().reportError(SMLoc(), Msg); 3640b57cec5SDimitry Andric } 365