1 //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file assembles .s files and emits Wasm .o object files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/MC/MCWasmStreamer.h" 14 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/MC/MCAsmBackend.h" 17 #include "llvm/MC/MCAssembler.h" 18 #include "llvm/MC/MCCodeEmitter.h" 19 #include "llvm/MC/MCExpr.h" 20 #include "llvm/MC/MCFixup.h" 21 #include "llvm/MC/MCFragment.h" 22 #include "llvm/MC/MCObjectStreamer.h" 23 #include "llvm/MC/MCSection.h" 24 #include "llvm/MC/MCSectionWasm.h" 25 #include "llvm/MC/MCSymbol.h" 26 #include "llvm/MC/MCSymbolWasm.h" 27 #include "llvm/MC/TargetRegistry.h" 28 #include "llvm/Support/Casting.h" 29 #include "llvm/Support/ErrorHandling.h" 30 31 namespace llvm { 32 class MCContext; 33 class MCStreamer; 34 class MCSubtargetInfo; 35 } // namespace llvm 36 37 using namespace llvm; 38 39 MCWasmStreamer::~MCWasmStreamer() = default; // anchor. 40 41 void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { 42 auto *Symbol = cast<MCSymbolWasm>(S); 43 MCObjectStreamer::emitLabel(Symbol, Loc); 44 45 const MCSectionWasm &Section = 46 static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); 47 if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) 48 Symbol->setTLS(); 49 } 50 51 void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, 52 uint64_t Offset) { 53 auto *Symbol = cast<MCSymbolWasm>(S); 54 MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); 55 56 const MCSectionWasm &Section = 57 static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); 58 if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) 59 Symbol->setTLS(); 60 } 61 62 void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) { 63 // Let the target do whatever target specific stuff it needs to do. 64 getAssembler().getBackend().handleAssemblerFlag(Flag); 65 66 // Do any generic stuff we need to do. 67 llvm_unreachable("invalid assembler flag!"); 68 } 69 70 void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) { 71 MCAssembler &Asm = getAssembler(); 72 auto *SectionWasm = cast<MCSectionWasm>(Section); 73 const MCSymbol *Grp = SectionWasm->getGroup(); 74 if (Grp) 75 Asm.registerSymbol(*Grp); 76 77 this->MCObjectStreamer::changeSection(Section, Subsection); 78 Asm.registerSymbol(*Section->getBeginSymbol()); 79 } 80 81 void MCWasmStreamer::emitWeakReference(MCSymbol *Alias, 82 const MCSymbol *Symbol) { 83 getAssembler().registerSymbol(*Symbol); 84 const MCExpr *Value = MCSymbolRefExpr::create( 85 Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); 86 Alias->setVariableValue(Value); 87 } 88 89 bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { 90 assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported"); 91 92 auto *Symbol = cast<MCSymbolWasm>(S); 93 94 // Adding a symbol attribute always introduces the symbol; note that an 95 // important side effect of calling registerSymbol here is to register the 96 // symbol with the assembler. 97 getAssembler().registerSymbol(*Symbol); 98 99 switch (Attribute) { 100 case MCSA_LazyReference: 101 case MCSA_Reference: 102 case MCSA_SymbolResolver: 103 case MCSA_PrivateExtern: 104 case MCSA_WeakDefinition: 105 case MCSA_WeakDefAutoPrivate: 106 case MCSA_Invalid: 107 case MCSA_IndirectSymbol: 108 case MCSA_Protected: 109 case MCSA_Exported: 110 return false; 111 112 case MCSA_Hidden: 113 Symbol->setHidden(true); 114 break; 115 116 case MCSA_Weak: 117 case MCSA_WeakReference: 118 Symbol->setWeak(true); 119 Symbol->setExternal(true); 120 break; 121 122 case MCSA_Global: 123 Symbol->setExternal(true); 124 break; 125 126 case MCSA_ELF_TypeFunction: 127 Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); 128 break; 129 130 case MCSA_ELF_TypeTLS: 131 Symbol->setTLS(); 132 break; 133 134 case MCSA_ELF_TypeObject: 135 case MCSA_Cold: 136 break; 137 138 case MCSA_NoDeadStrip: 139 Symbol->setNoStrip(); 140 break; 141 142 default: 143 // unrecognized directive 144 llvm_unreachable("unexpected MCSymbolAttr"); 145 return false; 146 } 147 148 return true; 149 } 150 151 void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size, 152 Align ByteAlignment) { 153 llvm_unreachable("Common symbols are not yet implemented for Wasm"); 154 } 155 156 void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 157 cast<MCSymbolWasm>(Symbol)->setSize(Value); 158 } 159 160 void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, 161 Align ByteAlignment) { 162 llvm_unreachable("Local common symbols are not yet implemented for Wasm"); 163 } 164 165 void MCWasmStreamer::emitIdent(StringRef IdentString) { 166 // TODO(sbc): Add the ident section once we support mergable strings 167 // sections in the object format 168 } 169 170 void MCWasmStreamer::emitInstToFragment(const MCInst &Inst, 171 const MCSubtargetInfo &STI) { 172 this->MCObjectStreamer::emitInstToFragment(Inst, STI); 173 MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); 174 175 for (auto &Fixup : F.getFixups()) 176 fixSymbolsInTLSFixups(Fixup.getValue()); 177 } 178 179 void MCWasmStreamer::emitInstToData(const MCInst &Inst, 180 const MCSubtargetInfo &STI) { 181 MCAssembler &Assembler = getAssembler(); 182 SmallVector<MCFixup, 4> Fixups; 183 SmallString<256> Code; 184 Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI); 185 186 for (auto &Fixup : Fixups) 187 fixSymbolsInTLSFixups(Fixup.getValue()); 188 189 // Append the encoded instruction to the current data fragment (or create a 190 // new such fragment if the current fragment is not a data fragment). 191 MCDataFragment *DF = getOrCreateDataFragment(); 192 193 // Add the fixups and data. 194 for (unsigned I = 0, E = Fixups.size(); I != E; ++I) { 195 Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size()); 196 DF->getFixups().push_back(Fixups[I]); 197 } 198 DF->setHasInstructions(STI); 199 DF->appendContents(Code); 200 } 201 202 void MCWasmStreamer::finishImpl() { 203 emitFrames(nullptr); 204 205 this->MCObjectStreamer::finishImpl(); 206 } 207 208 void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { 209 switch (expr->getKind()) { 210 case MCExpr::Target: 211 case MCExpr::Constant: 212 break; 213 214 case MCExpr::Binary: { 215 const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); 216 fixSymbolsInTLSFixups(be->getLHS()); 217 fixSymbolsInTLSFixups(be->getRHS()); 218 break; 219 } 220 221 case MCExpr::SymbolRef: { 222 const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); 223 switch (symRef.getKind()) { 224 case MCSymbolRefExpr::VK_WASM_TLSREL: 225 case MCSymbolRefExpr::VK_WASM_GOT_TLS: 226 getAssembler().registerSymbol(symRef.getSymbol()); 227 cast<MCSymbolWasm>(symRef.getSymbol()).setTLS(); 228 break; 229 default: 230 break; 231 } 232 break; 233 } 234 235 case MCExpr::Unary: 236 fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); 237 break; 238 } 239 } 240 241 void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) { 242 llvm_unreachable("Generic Wasm doesn't support this directive"); 243 } 244 245 void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 246 llvm_unreachable("Wasm doesn't support this directive"); 247 } 248 249 void MCWasmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 250 uint64_t Size, Align ByteAlignment, 251 SMLoc Loc) { 252 llvm_unreachable("Wasm doesn't support this directive"); 253 } 254 255 void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 256 uint64_t Size, Align ByteAlignment) { 257 llvm_unreachable("Wasm doesn't support this directive"); 258 } 259 260 MCStreamer *llvm::createWasmStreamer(MCContext &Context, 261 std::unique_ptr<MCAsmBackend> &&MAB, 262 std::unique_ptr<MCObjectWriter> &&OW, 263 std::unique_ptr<MCCodeEmitter> &&CE) { 264 MCWasmStreamer *S = 265 new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); 266 return S; 267 } 268