10b57cec5SDimitry Andric //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// 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 assembles .s files and emits Wasm .o object files. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/MC/MCWasmStreamer.h" 1481ad6265SDimitry Andric #include "llvm/ADT/SmallString.h" 1581ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCFixup.h" 2181ad6265SDimitry Andric #include "llvm/MC/MCFragment.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCSectionWasm.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h" 27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 280b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 290b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 310b57cec5SDimitry Andric 3281ad6265SDimitry Andric namespace llvm { 3381ad6265SDimitry Andric class MCContext; 3481ad6265SDimitry Andric class MCStreamer; 3581ad6265SDimitry Andric class MCSubtargetInfo; 3681ad6265SDimitry Andric } // namespace llvm 3781ad6265SDimitry Andric 380b57cec5SDimitry Andric using namespace llvm; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric MCWasmStreamer::~MCWasmStreamer() = default; // anchor. 410b57cec5SDimitry Andric 42349cc55cSDimitry Andric void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { 43349cc55cSDimitry Andric auto *Symbol = cast<MCSymbolWasm>(S); 44349cc55cSDimitry Andric MCObjectStreamer::emitLabel(Symbol, Loc); 45349cc55cSDimitry Andric 46349cc55cSDimitry Andric const MCSectionWasm &Section = 47349cc55cSDimitry Andric static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); 48349cc55cSDimitry Andric if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) 49349cc55cSDimitry Andric Symbol->setTLS(); 50349cc55cSDimitry Andric } 51349cc55cSDimitry Andric 52*0fca6ea1SDimitry Andric void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, 53349cc55cSDimitry Andric uint64_t Offset) { 54349cc55cSDimitry Andric auto *Symbol = cast<MCSymbolWasm>(S); 55349cc55cSDimitry Andric MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); 56349cc55cSDimitry Andric 57349cc55cSDimitry Andric const MCSectionWasm &Section = 58349cc55cSDimitry Andric static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); 59349cc55cSDimitry Andric if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) 60349cc55cSDimitry Andric Symbol->setTLS(); 61349cc55cSDimitry Andric } 62349cc55cSDimitry Andric 635ffd83dbSDimitry Andric void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) { 640b57cec5SDimitry Andric // Let the target do whatever target specific stuff it needs to do. 650b57cec5SDimitry Andric getAssembler().getBackend().handleAssemblerFlag(Flag); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Do any generic stuff we need to do. 680b57cec5SDimitry Andric llvm_unreachable("invalid assembler flag!"); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 71*0fca6ea1SDimitry Andric void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) { 720b57cec5SDimitry Andric MCAssembler &Asm = getAssembler(); 730b57cec5SDimitry Andric auto *SectionWasm = cast<MCSectionWasm>(Section); 740b57cec5SDimitry Andric const MCSymbol *Grp = SectionWasm->getGroup(); 750b57cec5SDimitry Andric if (Grp) 760b57cec5SDimitry Andric Asm.registerSymbol(*Grp); 770b57cec5SDimitry Andric 785ffd83dbSDimitry Andric this->MCObjectStreamer::changeSection(Section, Subsection); 790b57cec5SDimitry Andric Asm.registerSymbol(*Section->getBeginSymbol()); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 825ffd83dbSDimitry Andric void MCWasmStreamer::emitWeakReference(MCSymbol *Alias, 830b57cec5SDimitry Andric const MCSymbol *Symbol) { 840b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 850b57cec5SDimitry Andric const MCExpr *Value = MCSymbolRefExpr::create( 860b57cec5SDimitry Andric Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); 870b57cec5SDimitry Andric Alias->setVariableValue(Value); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 905ffd83dbSDimitry Andric bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { 910b57cec5SDimitry Andric assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported"); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolWasm>(S); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // Adding a symbol attribute always introduces the symbol; note that an 960b57cec5SDimitry Andric // important side effect of calling registerSymbol here is to register the 970b57cec5SDimitry Andric // symbol with the assembler. 980b57cec5SDimitry Andric getAssembler().registerSymbol(*Symbol); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric switch (Attribute) { 1010b57cec5SDimitry Andric case MCSA_LazyReference: 1020b57cec5SDimitry Andric case MCSA_Reference: 1030b57cec5SDimitry Andric case MCSA_SymbolResolver: 1040b57cec5SDimitry Andric case MCSA_PrivateExtern: 1050b57cec5SDimitry Andric case MCSA_WeakDefinition: 1060b57cec5SDimitry Andric case MCSA_WeakDefAutoPrivate: 1070b57cec5SDimitry Andric case MCSA_Invalid: 1080b57cec5SDimitry Andric case MCSA_IndirectSymbol: 1090b57cec5SDimitry Andric case MCSA_Protected: 11081ad6265SDimitry Andric case MCSA_Exported: 1110b57cec5SDimitry Andric return false; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric case MCSA_Hidden: 1140b57cec5SDimitry Andric Symbol->setHidden(true); 1150b57cec5SDimitry Andric break; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric case MCSA_Weak: 1180b57cec5SDimitry Andric case MCSA_WeakReference: 1190b57cec5SDimitry Andric Symbol->setWeak(true); 1200b57cec5SDimitry Andric Symbol->setExternal(true); 1210b57cec5SDimitry Andric break; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric case MCSA_Global: 1240b57cec5SDimitry Andric Symbol->setExternal(true); 1250b57cec5SDimitry Andric break; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric case MCSA_ELF_TypeFunction: 1280b57cec5SDimitry Andric Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); 1290b57cec5SDimitry Andric break; 1300b57cec5SDimitry Andric 131349cc55cSDimitry Andric case MCSA_ELF_TypeTLS: 132349cc55cSDimitry Andric Symbol->setTLS(); 133349cc55cSDimitry Andric break; 134349cc55cSDimitry Andric 1350b57cec5SDimitry Andric case MCSA_ELF_TypeObject: 1360b57cec5SDimitry Andric case MCSA_Cold: 1370b57cec5SDimitry Andric break; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric case MCSA_NoDeadStrip: 1408bcb0991SDimitry Andric Symbol->setNoStrip(); 1410b57cec5SDimitry Andric break; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric default: 1440b57cec5SDimitry Andric // unrecognized directive 1450b57cec5SDimitry Andric llvm_unreachable("unexpected MCSymbolAttr"); 1460b57cec5SDimitry Andric return false; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric return true; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1525ffd83dbSDimitry Andric void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size, 153bdd1243dSDimitry Andric Align ByteAlignment) { 1540b57cec5SDimitry Andric llvm_unreachable("Common symbols are not yet implemented for Wasm"); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 1580b57cec5SDimitry Andric cast<MCSymbolWasm>(Symbol)->setSize(Value); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1615ffd83dbSDimitry Andric void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, 162bdd1243dSDimitry Andric Align ByteAlignment) { 1630b57cec5SDimitry Andric llvm_unreachable("Local common symbols are not yet implemented for Wasm"); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1665ffd83dbSDimitry Andric void MCWasmStreamer::emitIdent(StringRef IdentString) { 1670b57cec5SDimitry Andric // TODO(sbc): Add the ident section once we support mergable strings 1680b57cec5SDimitry Andric // sections in the object format 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1715ffd83dbSDimitry Andric void MCWasmStreamer::emitInstToFragment(const MCInst &Inst, 1720b57cec5SDimitry Andric const MCSubtargetInfo &STI) { 1735ffd83dbSDimitry Andric this->MCObjectStreamer::emitInstToFragment(Inst, STI); 174349cc55cSDimitry Andric MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); 175349cc55cSDimitry Andric 176349cc55cSDimitry Andric for (auto &Fixup : F.getFixups()) 177349cc55cSDimitry Andric fixSymbolsInTLSFixups(Fixup.getValue()); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1805ffd83dbSDimitry Andric void MCWasmStreamer::emitInstToData(const MCInst &Inst, 1810b57cec5SDimitry Andric const MCSubtargetInfo &STI) { 1820b57cec5SDimitry Andric MCAssembler &Assembler = getAssembler(); 1830b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 1840b57cec5SDimitry Andric SmallString<256> Code; 18506c3fb27SDimitry Andric Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI); 1860b57cec5SDimitry Andric 187349cc55cSDimitry Andric for (auto &Fixup : Fixups) 188349cc55cSDimitry Andric fixSymbolsInTLSFixups(Fixup.getValue()); 189349cc55cSDimitry Andric 1900b57cec5SDimitry Andric // Append the encoded instruction to the current data fragment (or create a 1910b57cec5SDimitry Andric // new such fragment if the current fragment is not a data fragment). 1920b57cec5SDimitry Andric MCDataFragment *DF = getOrCreateDataFragment(); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric // Add the fixups and data. 1950b57cec5SDimitry Andric for (unsigned I = 0, E = Fixups.size(); I != E; ++I) { 1960b57cec5SDimitry Andric Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size()); 1970b57cec5SDimitry Andric DF->getFixups().push_back(Fixups[I]); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric DF->setHasInstructions(STI); 2000b57cec5SDimitry Andric DF->getContents().append(Code.begin(), Code.end()); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2035ffd83dbSDimitry Andric void MCWasmStreamer::finishImpl() { 2045ffd83dbSDimitry Andric emitFrames(nullptr); 2050b57cec5SDimitry Andric 2065ffd83dbSDimitry Andric this->MCObjectStreamer::finishImpl(); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 209349cc55cSDimitry Andric void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { 210349cc55cSDimitry Andric switch (expr->getKind()) { 211349cc55cSDimitry Andric case MCExpr::Target: 212349cc55cSDimitry Andric case MCExpr::Constant: 213349cc55cSDimitry Andric break; 214349cc55cSDimitry Andric 215349cc55cSDimitry Andric case MCExpr::Binary: { 216349cc55cSDimitry Andric const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); 217349cc55cSDimitry Andric fixSymbolsInTLSFixups(be->getLHS()); 218349cc55cSDimitry Andric fixSymbolsInTLSFixups(be->getRHS()); 219349cc55cSDimitry Andric break; 220349cc55cSDimitry Andric } 221349cc55cSDimitry Andric 222349cc55cSDimitry Andric case MCExpr::SymbolRef: { 223349cc55cSDimitry Andric const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); 224349cc55cSDimitry Andric switch (symRef.getKind()) { 225349cc55cSDimitry Andric case MCSymbolRefExpr::VK_WASM_TLSREL: 226349cc55cSDimitry Andric case MCSymbolRefExpr::VK_WASM_GOT_TLS: 227349cc55cSDimitry Andric getAssembler().registerSymbol(symRef.getSymbol()); 228349cc55cSDimitry Andric cast<MCSymbolWasm>(symRef.getSymbol()).setTLS(); 229349cc55cSDimitry Andric break; 230349cc55cSDimitry Andric default: 231349cc55cSDimitry Andric break; 232349cc55cSDimitry Andric } 233349cc55cSDimitry Andric break; 234349cc55cSDimitry Andric } 235349cc55cSDimitry Andric 236349cc55cSDimitry Andric case MCExpr::Unary: 237349cc55cSDimitry Andric fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); 238349cc55cSDimitry Andric break; 239349cc55cSDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2425ffd83dbSDimitry Andric void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) { 2430b57cec5SDimitry Andric llvm_unreachable("Generic Wasm doesn't support this directive"); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2465ffd83dbSDimitry Andric void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 2470b57cec5SDimitry Andric llvm_unreachable("Wasm doesn't support this directive"); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2505ffd83dbSDimitry Andric void MCWasmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 251bdd1243dSDimitry Andric uint64_t Size, Align ByteAlignment, 2520b57cec5SDimitry Andric SMLoc Loc) { 2530b57cec5SDimitry Andric llvm_unreachable("Wasm doesn't support this directive"); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2565ffd83dbSDimitry Andric void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 257bdd1243dSDimitry Andric uint64_t Size, Align ByteAlignment) { 2580b57cec5SDimitry Andric llvm_unreachable("Wasm doesn't support this directive"); 2590b57cec5SDimitry Andric } 260349cc55cSDimitry Andric 261349cc55cSDimitry Andric MCStreamer *llvm::createWasmStreamer(MCContext &Context, 262349cc55cSDimitry Andric std::unique_ptr<MCAsmBackend> &&MAB, 263349cc55cSDimitry Andric std::unique_ptr<MCObjectWriter> &&OW, 264*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> &&CE) { 265349cc55cSDimitry Andric MCWasmStreamer *S = 266349cc55cSDimitry Andric new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); 267349cc55cSDimitry Andric return S; 268349cc55cSDimitry Andric } 269