17d523365SDimitry Andric //===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric //                     The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric ///
107d523365SDimitry Andric /// \file
114ba319b5SDimitry Andric /// This file contains a printer that converts from our internal
127d523365SDimitry Andric /// representation of machine-dependent LLVM code to the WebAssembly assembly
137d523365SDimitry Andric /// language.
147d523365SDimitry Andric ///
157d523365SDimitry Andric //===----------------------------------------------------------------------===//
167d523365SDimitry Andric 
177a7e6055SDimitry Andric #include "WebAssemblyAsmPrinter.h"
187d523365SDimitry Andric #include "InstPrinter/WebAssemblyInstPrinter.h"
197d523365SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
20444ed5c5SDimitry Andric #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
21d88c1a5aSDimitry Andric #include "WebAssembly.h"
227d523365SDimitry Andric #include "WebAssemblyMCInstLower.h"
237d523365SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
247d523365SDimitry Andric #include "WebAssemblyRegisterInfo.h"
257d523365SDimitry Andric #include "llvm/ADT/StringExtras.h"
267d523365SDimitry Andric #include "llvm/CodeGen/Analysis.h"
277d523365SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
287d523365SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
297d523365SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
307a7e6055SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
317d523365SDimitry Andric #include "llvm/IR/DataLayout.h"
327a7e6055SDimitry Andric #include "llvm/IR/GlobalVariable.h"
337d523365SDimitry Andric #include "llvm/MC/MCContext.h"
344ba319b5SDimitry Andric #include "llvm/MC/MCSectionWasm.h"
357d523365SDimitry Andric #include "llvm/MC/MCStreamer.h"
367d523365SDimitry Andric #include "llvm/MC/MCSymbol.h"
3724d58133SDimitry Andric #include "llvm/MC/MCSymbolWasm.h"
387d523365SDimitry Andric #include "llvm/Support/Debug.h"
397d523365SDimitry Andric #include "llvm/Support/TargetRegistry.h"
407d523365SDimitry Andric #include "llvm/Support/raw_ostream.h"
417d523365SDimitry Andric using namespace llvm;
427d523365SDimitry Andric 
437d523365SDimitry Andric #define DEBUG_TYPE "asm-printer"
447d523365SDimitry Andric 
457d523365SDimitry Andric //===----------------------------------------------------------------------===//
467d523365SDimitry Andric // Helpers.
477d523365SDimitry Andric //===----------------------------------------------------------------------===//
487d523365SDimitry Andric 
getRegType(unsigned RegNo) const497d523365SDimitry Andric MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const {
5051690af2SDimitry Andric   const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
513ca95b02SDimitry Andric   const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
52d88c1a5aSDimitry Andric   for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16,
53*b5893f02SDimitry Andric                 MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64})
5451690af2SDimitry Andric     if (TRI->isTypeLegalForClass(*TRC, T))
557d523365SDimitry Andric       return T;
564ba319b5SDimitry Andric   LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo);
577d523365SDimitry Andric   llvm_unreachable("Unknown register type");
587d523365SDimitry Andric   return MVT::Other;
597d523365SDimitry Andric }
607d523365SDimitry Andric 
regToString(const MachineOperand & MO)617d523365SDimitry Andric std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) {
627d523365SDimitry Andric   unsigned RegNo = MO.getReg();
637d523365SDimitry Andric   assert(TargetRegisterInfo::isVirtualRegister(RegNo) &&
647d523365SDimitry Andric          "Unlowered physical register encountered during assembly printing");
657d523365SDimitry Andric   assert(!MFI->isVRegStackified(RegNo));
667d523365SDimitry Andric   unsigned WAReg = MFI->getWAReg(RegNo);
677d523365SDimitry Andric   assert(WAReg != WebAssemblyFunctionInfo::UnusedReg);
687d523365SDimitry Andric   return '$' + utostr(WAReg);
697d523365SDimitry Andric }
707d523365SDimitry Andric 
getTargetStreamer()713ca95b02SDimitry Andric WebAssemblyTargetStreamer *WebAssemblyAsmPrinter::getTargetStreamer() {
72444ed5c5SDimitry Andric   MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
73444ed5c5SDimitry Andric   return static_cast<WebAssemblyTargetStreamer *>(TS);
747d523365SDimitry Andric }
757d523365SDimitry Andric 
767d523365SDimitry Andric //===----------------------------------------------------------------------===//
777d523365SDimitry Andric // WebAssemblyAsmPrinter Implementation.
787d523365SDimitry Andric //===----------------------------------------------------------------------===//
797d523365SDimitry Andric 
EmitEndOfAsmFile(Module & M)803ca95b02SDimitry Andric void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
81*b5893f02SDimitry Andric   for (auto &It : OutContext.getSymbols()) {
82*b5893f02SDimitry Andric     // Emit a .globaltype and .eventtype declaration.
83*b5893f02SDimitry Andric     auto Sym = cast<MCSymbolWasm>(It.getValue());
84*b5893f02SDimitry Andric     if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL)
85*b5893f02SDimitry Andric       getTargetStreamer()->emitGlobalType(Sym);
86*b5893f02SDimitry Andric     else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT)
87*b5893f02SDimitry Andric       getTargetStreamer()->emitEventType(Sym);
88*b5893f02SDimitry Andric   }
89*b5893f02SDimitry Andric 
903ca95b02SDimitry Andric   for (const auto &F : M) {
913ca95b02SDimitry Andric     // Emit function type info for all undefined functions
923ca95b02SDimitry Andric     if (F.isDeclarationForLinker() && !F.isIntrinsic()) {
93d88c1a5aSDimitry Andric       SmallVector<MVT, 4> Results;
94d88c1a5aSDimitry Andric       SmallVector<MVT, 4> Params;
95*b5893f02SDimitry Andric       ComputeSignatureVTs(F.getFunctionType(), F, TM, Params, Results);
96*b5893f02SDimitry Andric       auto *Sym = cast<MCSymbolWasm>(getSymbol(&F));
97*b5893f02SDimitry Andric       Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
98*b5893f02SDimitry Andric       if (!Sym->getSignature()) {
99*b5893f02SDimitry Andric         auto Signature = SignatureFromMVTs(Results, Params);
100*b5893f02SDimitry Andric         Sym->setSignature(Signature.get());
101*b5893f02SDimitry Andric         addSignature(std::move(Signature));
102*b5893f02SDimitry Andric       }
103*b5893f02SDimitry Andric       // FIXME: this was originally intended for post-linking and was only used
104*b5893f02SDimitry Andric       // for imports that were only called indirectly (i.e. s2wasm could not
105*b5893f02SDimitry Andric       // infer the type from a call). With object files it applies to all
106*b5893f02SDimitry Andric       // imports. so fix the names and the tests, or rethink how import
107*b5893f02SDimitry Andric       // delcarations work in asm files.
108*b5893f02SDimitry Andric       getTargetStreamer()->emitFunctionType(Sym);
1094ba319b5SDimitry Andric 
1104ba319b5SDimitry Andric       if (TM.getTargetTriple().isOSBinFormatWasm() &&
1114ba319b5SDimitry Andric           F.hasFnAttribute("wasm-import-module")) {
112*b5893f02SDimitry Andric         StringRef Name =
113*b5893f02SDimitry Andric             F.getFnAttribute("wasm-import-module").getValueAsString();
114*b5893f02SDimitry Andric         Sym->setImportModule(Name);
115*b5893f02SDimitry Andric         getTargetStreamer()->emitImportModule(Sym, Name);
116*b5893f02SDimitry Andric       }
117*b5893f02SDimitry Andric       if (TM.getTargetTriple().isOSBinFormatWasm() &&
118*b5893f02SDimitry Andric           F.hasFnAttribute("wasm-import-name")) {
119*b5893f02SDimitry Andric         StringRef Name =
120*b5893f02SDimitry Andric             F.getFnAttribute("wasm-import-name").getValueAsString();
121*b5893f02SDimitry Andric         Sym->setImportName(Name);
122*b5893f02SDimitry Andric         getTargetStreamer()->emitImportName(Sym, Name);
1234ba319b5SDimitry Andric       }
1243ca95b02SDimitry Andric     }
1253ca95b02SDimitry Andric   }
126*b5893f02SDimitry Andric 
127d88c1a5aSDimitry Andric   for (const auto &G : M.globals()) {
128d88c1a5aSDimitry Andric     if (!G.hasInitializer() && G.hasExternalLinkage()) {
1292cab237bSDimitry Andric       if (G.getValueType()->isSized()) {
1307a7e6055SDimitry Andric         uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType());
1317a7e6055SDimitry Andric         OutStreamer->emitELFSize(getSymbol(&G),
1327a7e6055SDimitry Andric                                  MCConstantExpr::create(Size, OutContext));
1333ca95b02SDimitry Andric       }
1343ca95b02SDimitry Andric     }
1353ca95b02SDimitry Andric   }
1364ba319b5SDimitry Andric 
1374ba319b5SDimitry Andric   if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
1384ba319b5SDimitry Andric     for (const Metadata *MD : Named->operands()) {
1394ba319b5SDimitry Andric       const MDTuple *Tuple = dyn_cast<MDTuple>(MD);
1404ba319b5SDimitry Andric       if (!Tuple || Tuple->getNumOperands() != 2)
1414ba319b5SDimitry Andric         continue;
1424ba319b5SDimitry Andric       const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
1434ba319b5SDimitry Andric       const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
1444ba319b5SDimitry Andric       if (!Name || !Contents)
1454ba319b5SDimitry Andric         continue;
1464ba319b5SDimitry Andric 
1474ba319b5SDimitry Andric       OutStreamer->PushSection();
1484ba319b5SDimitry Andric       std::string SectionName = (".custom_section." + Name->getString()).str();
1494ba319b5SDimitry Andric       MCSectionWasm *mySection =
1504ba319b5SDimitry Andric           OutContext.getWasmSection(SectionName, SectionKind::getMetadata());
1514ba319b5SDimitry Andric       OutStreamer->SwitchSection(mySection);
1524ba319b5SDimitry Andric       OutStreamer->EmitBytes(Contents->getString());
1534ba319b5SDimitry Andric       OutStreamer->PopSection();
1544ba319b5SDimitry Andric     }
1554ba319b5SDimitry Andric   }
1562cab237bSDimitry Andric }
1573ca95b02SDimitry Andric 
EmitConstantPool()1583ca95b02SDimitry Andric void WebAssemblyAsmPrinter::EmitConstantPool() {
1593ca95b02SDimitry Andric   assert(MF->getConstantPool()->getConstants().empty() &&
1603ca95b02SDimitry Andric          "WebAssembly disables constant pools");
1613ca95b02SDimitry Andric }
1623ca95b02SDimitry Andric 
EmitJumpTableInfo()1633ca95b02SDimitry Andric void WebAssemblyAsmPrinter::EmitJumpTableInfo() {
1643ca95b02SDimitry Andric   // Nothing to do; jump tables are incorporated into the instruction stream.
1653ca95b02SDimitry Andric }
1663ca95b02SDimitry Andric 
EmitFunctionBodyStart()1677d523365SDimitry Andric void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
1682cab237bSDimitry Andric   const Function &F = MF->getFunction();
169*b5893f02SDimitry Andric   SmallVector<MVT, 1> ResultVTs;
170*b5893f02SDimitry Andric   SmallVector<MVT, 4> ParamVTs;
171*b5893f02SDimitry Andric   ComputeSignatureVTs(F.getFunctionType(), F, TM, ParamVTs, ResultVTs);
172*b5893f02SDimitry Andric   auto Signature = SignatureFromMVTs(ResultVTs, ParamVTs);
173*b5893f02SDimitry Andric   auto *WasmSym = cast<MCSymbolWasm>(CurrentFnSym);
174*b5893f02SDimitry Andric   WasmSym->setSignature(Signature.get());
175*b5893f02SDimitry Andric   addSignature(std::move(Signature));
176*b5893f02SDimitry Andric   WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
177*b5893f02SDimitry Andric 
178*b5893f02SDimitry Andric   // FIXME: clean up how params and results are emitted (use signatures)
179*b5893f02SDimitry Andric   getTargetStreamer()->emitFunctionType(WasmSym);
180d88c1a5aSDimitry Andric 
181d88c1a5aSDimitry Andric   // Emit the function index.
182d88c1a5aSDimitry Andric   if (MDNode *Idx = F.getMetadata("wasm.index")) {
183d88c1a5aSDimitry Andric     assert(Idx->getNumOperands() == 1);
184d88c1a5aSDimitry Andric 
185d88c1a5aSDimitry Andric     getTargetStreamer()->emitIndIdx(AsmPrinter::lowerConstant(
186d88c1a5aSDimitry Andric         cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue()));
187d88c1a5aSDimitry Andric   }
188d88c1a5aSDimitry Andric 
189*b5893f02SDimitry Andric   SmallVector<wasm::ValType, 16> Locals;
190*b5893f02SDimitry Andric   ValTypesFromMVTs(MFI->getLocals(), Locals);
191*b5893f02SDimitry Andric   getTargetStreamer()->emitLocal(Locals);
1927d523365SDimitry Andric 
1937d523365SDimitry Andric   AsmPrinter::EmitFunctionBodyStart();
1947d523365SDimitry Andric }
1957d523365SDimitry Andric 
EmitInstruction(const MachineInstr * MI)1967d523365SDimitry Andric void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1974ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
1987d523365SDimitry Andric 
1997d523365SDimitry Andric   switch (MI->getOpcode()) {
200*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_i32:
201*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_i32_S:
202*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_i64:
203*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_i64_S:
204*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_f32:
205*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_f32_S:
206*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_f64:
207*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_f64_S:
208d88c1a5aSDimitry Andric   case WebAssembly::ARGUMENT_v16i8:
209*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v16i8_S:
210d88c1a5aSDimitry Andric   case WebAssembly::ARGUMENT_v8i16:
211*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v8i16_S:
212d88c1a5aSDimitry Andric   case WebAssembly::ARGUMENT_v4i32:
213*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v4i32_S:
214*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v2i64:
215*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v2i64_S:
216d88c1a5aSDimitry Andric   case WebAssembly::ARGUMENT_v4f32:
217*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v4f32_S:
218*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v2f64:
219*b5893f02SDimitry Andric   case WebAssembly::ARGUMENT_v2f64_S:
2207d523365SDimitry Andric     // These represent values which are live into the function entry, so there's
2217d523365SDimitry Andric     // no instruction to emit.
2227d523365SDimitry Andric     break;
2233ca95b02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_I32:
224*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_I32_S:
2253ca95b02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_I64:
226*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_I64_S:
2273ca95b02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_F32:
228*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_F32_S:
229d88c1a5aSDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_F64:
230*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_F64_S:
231d88c1a5aSDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v16i8:
232*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v16i8_S:
233d88c1a5aSDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v8i16:
234*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v8i16_S:
235d88c1a5aSDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v4i32:
236*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v4i32_S:
237*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v2i64:
238*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v2i64_S:
239*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v4f32:
240*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v4f32_S:
241*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v2f64:
242*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_v2f64_S: {
2433ca95b02SDimitry Andric     // These instructions represent the implicit return at the end of a
244*b5893f02SDimitry Andric     // function body. Always pops one value off the stack.
2453ca95b02SDimitry Andric     if (isVerbose()) {
246*b5893f02SDimitry Andric       OutStreamer->AddComment("fallthrough-return-value");
2473ca95b02SDimitry Andric       OutStreamer->AddBlankLine();
2483ca95b02SDimitry Andric     }
2493ca95b02SDimitry Andric     break;
2503ca95b02SDimitry Andric   }
2513ca95b02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_VOID:
252*b5893f02SDimitry Andric   case WebAssembly::FALLTHROUGH_RETURN_VOID_S:
2533ca95b02SDimitry Andric     // This instruction represents the implicit return at the end of a
2543ca95b02SDimitry Andric     // function body with no return value.
2553ca95b02SDimitry Andric     if (isVerbose()) {
256*b5893f02SDimitry Andric       OutStreamer->AddComment("fallthrough-return-void");
2573ca95b02SDimitry Andric       OutStreamer->AddBlankLine();
2583ca95b02SDimitry Andric     }
2593ca95b02SDimitry Andric     break;
2607d523365SDimitry Andric   default: {
2617d523365SDimitry Andric     WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
2627d523365SDimitry Andric     MCInst TmpInst;
2637d523365SDimitry Andric     MCInstLowering.Lower(MI, TmpInst);
2647d523365SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
2657d523365SDimitry Andric     break;
2667d523365SDimitry Andric   }
2677d523365SDimitry Andric   }
2687d523365SDimitry Andric }
2697d523365SDimitry Andric 
lowerConstant(const Constant * CV)270444ed5c5SDimitry Andric const MCExpr *WebAssemblyAsmPrinter::lowerConstant(const Constant *CV) {
271444ed5c5SDimitry Andric   if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
27224d58133SDimitry Andric     if (GV->getValueType()->isFunctionTy()) {
273444ed5c5SDimitry Andric       return MCSymbolRefExpr::create(
274c4394386SDimitry Andric           getSymbol(GV), MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext);
27524d58133SDimitry Andric     }
276444ed5c5SDimitry Andric   return AsmPrinter::lowerConstant(CV);
277444ed5c5SDimitry Andric }
278444ed5c5SDimitry Andric 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & OS)2797d523365SDimitry Andric bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
2807d523365SDimitry Andric                                             unsigned OpNo, unsigned AsmVariant,
2817d523365SDimitry Andric                                             const char *ExtraCode,
2827d523365SDimitry Andric                                             raw_ostream &OS) {
2837d523365SDimitry Andric   if (AsmVariant != 0)
2847d523365SDimitry Andric     report_fatal_error("There are no defined alternate asm variants");
2857d523365SDimitry Andric 
2867d523365SDimitry Andric   // First try the generic code, which knows about modifiers like 'c' and 'n'.
2877d523365SDimitry Andric   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS))
2887d523365SDimitry Andric     return false;
2897d523365SDimitry Andric 
2907d523365SDimitry Andric   if (!ExtraCode) {
2917d523365SDimitry Andric     const MachineOperand &MO = MI->getOperand(OpNo);
2927d523365SDimitry Andric     switch (MO.getType()) {
2937d523365SDimitry Andric     case MachineOperand::MO_Immediate:
2947d523365SDimitry Andric       OS << MO.getImm();
2957d523365SDimitry Andric       return false;
2967d523365SDimitry Andric     case MachineOperand::MO_Register:
297*b5893f02SDimitry Andric       // FIXME: only opcode that still contains registers, as required by
298*b5893f02SDimitry Andric       // MachineInstr::getDebugVariable().
299*b5893f02SDimitry Andric       assert(MI->getOpcode() == WebAssembly::INLINEASM);
3007d523365SDimitry Andric       OS << regToString(MO);
3017d523365SDimitry Andric       return false;
3027d523365SDimitry Andric     case MachineOperand::MO_GlobalAddress:
3037d523365SDimitry Andric       getSymbol(MO.getGlobal())->print(OS, MAI);
3047d523365SDimitry Andric       printOffset(MO.getOffset(), OS);
3057d523365SDimitry Andric       return false;
3067d523365SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
3077d523365SDimitry Andric       GetExternalSymbolSymbol(MO.getSymbolName())->print(OS, MAI);
3087d523365SDimitry Andric       printOffset(MO.getOffset(), OS);
3097d523365SDimitry Andric       return false;
3107d523365SDimitry Andric     case MachineOperand::MO_MachineBasicBlock:
3117d523365SDimitry Andric       MO.getMBB()->getSymbol()->print(OS, MAI);
3127d523365SDimitry Andric       return false;
3137d523365SDimitry Andric     default:
3147d523365SDimitry Andric       break;
3157d523365SDimitry Andric     }
3167d523365SDimitry Andric   }
3177d523365SDimitry Andric 
3187d523365SDimitry Andric   return true;
3197d523365SDimitry Andric }
3207d523365SDimitry Andric 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & OS)3217d523365SDimitry Andric bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
3227d523365SDimitry Andric                                                   unsigned OpNo,
3237d523365SDimitry Andric                                                   unsigned AsmVariant,
3247d523365SDimitry Andric                                                   const char *ExtraCode,
3257d523365SDimitry Andric                                                   raw_ostream &OS) {
3267d523365SDimitry Andric   if (AsmVariant != 0)
3277d523365SDimitry Andric     report_fatal_error("There are no defined alternate asm variants");
3287d523365SDimitry Andric 
3292cab237bSDimitry Andric   // The current approach to inline asm is that "r" constraints are expressed
3302cab237bSDimitry Andric   // as local indices, rather than values on the operand stack. This simplifies
3312cab237bSDimitry Andric   // using "r" as it eliminates the need to push and pop the values in a
3322cab237bSDimitry Andric   // particular order, however it also makes it impossible to have an "m"
3332cab237bSDimitry Andric   // constraint. So we don't support it.
3347d523365SDimitry Andric 
3357d523365SDimitry Andric   return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant, ExtraCode, OS);
3367d523365SDimitry Andric }
3377d523365SDimitry Andric 
3387d523365SDimitry Andric // Force static initialization.
LLVMInitializeWebAssemblyAsmPrinter()3397d523365SDimitry Andric extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {
340d88c1a5aSDimitry Andric   RegisterAsmPrinter<WebAssemblyAsmPrinter> X(getTheWebAssemblyTarget32());
341d88c1a5aSDimitry Andric   RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(getTheWebAssemblyTarget64());
3427d523365SDimitry Andric }
343