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