10b57cec5SDimitry Andric //===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===// 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 /// \file 100b57cec5SDimitry Andric /// This file contains a printer that converts from our internal 110b57cec5SDimitry Andric /// representation of machine-dependent LLVM code to the WebAssembly assembly 120b57cec5SDimitry Andric /// language. 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "WebAssemblyAsmPrinter.h" 170b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyInstPrinter.h" 180b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 190b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyTargetStreamer.h" 200b57cec5SDimitry Andric #include "TargetInfo/WebAssemblyTargetInfo.h" 210b57cec5SDimitry Andric #include "WebAssembly.h" 220b57cec5SDimitry Andric #include "WebAssemblyMCInstLower.h" 230b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 240b57cec5SDimitry Andric #include "WebAssemblyRegisterInfo.h" 250b57cec5SDimitry Andric #include "WebAssemblyTargetMachine.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 270b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 280b57cec5SDimitry Andric #include "llvm/BinaryFormat/Wasm.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 340b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 350b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 360b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 370b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCSectionWasm.h" 400b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 410b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 420b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h" 430b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 440b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 450b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric using namespace llvm; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer" 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric extern cl::opt<bool> WasmKeepRegisters; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 540b57cec5SDimitry Andric // Helpers. 550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const { 580b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); 590b57cec5SDimitry Andric const TargetRegisterClass *TRC = MRI->getRegClass(RegNo); 600b57cec5SDimitry Andric for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16, 610b57cec5SDimitry Andric MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64}) 620b57cec5SDimitry Andric if (TRI->isTypeLegalForClass(*TRC, T)) 630b57cec5SDimitry Andric return T; 640b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo); 650b57cec5SDimitry Andric llvm_unreachable("Unknown register type"); 660b57cec5SDimitry Andric return MVT::Other; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) { 70*8bcb0991SDimitry Andric Register RegNo = MO.getReg(); 71*8bcb0991SDimitry Andric assert(Register::isVirtualRegister(RegNo) && 720b57cec5SDimitry Andric "Unlowered physical register encountered during assembly printing"); 730b57cec5SDimitry Andric assert(!MFI->isVRegStackified(RegNo)); 740b57cec5SDimitry Andric unsigned WAReg = MFI->getWAReg(RegNo); 750b57cec5SDimitry Andric assert(WAReg != WebAssemblyFunctionInfo::UnusedReg); 760b57cec5SDimitry Andric return '$' + utostr(WAReg); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric WebAssemblyTargetStreamer *WebAssemblyAsmPrinter::getTargetStreamer() { 800b57cec5SDimitry Andric MCTargetStreamer *TS = OutStreamer->getTargetStreamer(); 810b57cec5SDimitry Andric return static_cast<WebAssemblyTargetStreamer *>(TS); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 850b57cec5SDimitry Andric // WebAssemblyAsmPrinter Implementation. 860b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { 890b57cec5SDimitry Andric for (auto &It : OutContext.getSymbols()) { 900b57cec5SDimitry Andric // Emit a .globaltype and .eventtype declaration. 910b57cec5SDimitry Andric auto Sym = cast<MCSymbolWasm>(It.getValue()); 920b57cec5SDimitry Andric if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) 930b57cec5SDimitry Andric getTargetStreamer()->emitGlobalType(Sym); 940b57cec5SDimitry Andric else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT) 950b57cec5SDimitry Andric getTargetStreamer()->emitEventType(Sym); 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric for (const auto &F : M) { 990b57cec5SDimitry Andric // Emit function type info for all undefined functions 1000b57cec5SDimitry Andric if (F.isDeclarationForLinker() && !F.isIntrinsic()) { 1010b57cec5SDimitry Andric SmallVector<MVT, 4> Results; 1020b57cec5SDimitry Andric SmallVector<MVT, 4> Params; 1030b57cec5SDimitry Andric computeSignatureVTs(F.getFunctionType(), F, TM, Params, Results); 1040b57cec5SDimitry Andric auto *Sym = cast<MCSymbolWasm>(getSymbol(&F)); 1050b57cec5SDimitry Andric Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); 1060b57cec5SDimitry Andric if (!Sym->getSignature()) { 1070b57cec5SDimitry Andric auto Signature = signatureFromMVTs(Results, Params); 1080b57cec5SDimitry Andric Sym->setSignature(Signature.get()); 1090b57cec5SDimitry Andric addSignature(std::move(Signature)); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric // FIXME: this was originally intended for post-linking and was only used 1120b57cec5SDimitry Andric // for imports that were only called indirectly (i.e. s2wasm could not 1130b57cec5SDimitry Andric // infer the type from a call). With object files it applies to all 1140b57cec5SDimitry Andric // imports. so fix the names and the tests, or rethink how import 1150b57cec5SDimitry Andric // delcarations work in asm files. 1160b57cec5SDimitry Andric getTargetStreamer()->emitFunctionType(Sym); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric if (TM.getTargetTriple().isOSBinFormatWasm() && 1190b57cec5SDimitry Andric F.hasFnAttribute("wasm-import-module")) { 1200b57cec5SDimitry Andric StringRef Name = 1210b57cec5SDimitry Andric F.getFnAttribute("wasm-import-module").getValueAsString(); 1220b57cec5SDimitry Andric Sym->setImportModule(Name); 1230b57cec5SDimitry Andric getTargetStreamer()->emitImportModule(Sym, Name); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric if (TM.getTargetTriple().isOSBinFormatWasm() && 1260b57cec5SDimitry Andric F.hasFnAttribute("wasm-import-name")) { 1270b57cec5SDimitry Andric StringRef Name = 1280b57cec5SDimitry Andric F.getFnAttribute("wasm-import-name").getValueAsString(); 1290b57cec5SDimitry Andric Sym->setImportName(Name); 1300b57cec5SDimitry Andric getTargetStreamer()->emitImportName(Sym, Name); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric for (const auto &G : M.globals()) { 1360b57cec5SDimitry Andric if (!G.hasInitializer() && G.hasExternalLinkage()) { 1370b57cec5SDimitry Andric if (G.getValueType()->isSized()) { 1380b57cec5SDimitry Andric uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType()); 1390b57cec5SDimitry Andric OutStreamer->emitELFSize(getSymbol(&G), 1400b57cec5SDimitry Andric MCConstantExpr::create(Size, OutContext)); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) { 1460b57cec5SDimitry Andric for (const Metadata *MD : Named->operands()) { 1470b57cec5SDimitry Andric const auto *Tuple = dyn_cast<MDTuple>(MD); 1480b57cec5SDimitry Andric if (!Tuple || Tuple->getNumOperands() != 2) 1490b57cec5SDimitry Andric continue; 1500b57cec5SDimitry Andric const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0)); 1510b57cec5SDimitry Andric const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1)); 1520b57cec5SDimitry Andric if (!Name || !Contents) 1530b57cec5SDimitry Andric continue; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric OutStreamer->PushSection(); 1560b57cec5SDimitry Andric std::string SectionName = (".custom_section." + Name->getString()).str(); 1570b57cec5SDimitry Andric MCSectionWasm *MySection = 1580b57cec5SDimitry Andric OutContext.getWasmSection(SectionName, SectionKind::getMetadata()); 1590b57cec5SDimitry Andric OutStreamer->SwitchSection(MySection); 1600b57cec5SDimitry Andric OutStreamer->EmitBytes(Contents->getString()); 1610b57cec5SDimitry Andric OutStreamer->PopSection(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric EmitProducerInfo(M); 1660b57cec5SDimitry Andric EmitTargetFeatures(M); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) { 1700b57cec5SDimitry Andric llvm::SmallVector<std::pair<std::string, std::string>, 4> Languages; 1710b57cec5SDimitry Andric if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) { 1720b57cec5SDimitry Andric llvm::SmallSet<StringRef, 4> SeenLanguages; 1730b57cec5SDimitry Andric for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) { 1740b57cec5SDimitry Andric const auto *CU = cast<DICompileUnit>(Debug->getOperand(I)); 1750b57cec5SDimitry Andric StringRef Language = dwarf::LanguageString(CU->getSourceLanguage()); 1760b57cec5SDimitry Andric Language.consume_front("DW_LANG_"); 1770b57cec5SDimitry Andric if (SeenLanguages.insert(Language).second) 1780b57cec5SDimitry Andric Languages.emplace_back(Language.str(), ""); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric llvm::SmallVector<std::pair<std::string, std::string>, 4> Tools; 1830b57cec5SDimitry Andric if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) { 1840b57cec5SDimitry Andric llvm::SmallSet<StringRef, 4> SeenTools; 1850b57cec5SDimitry Andric for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) { 1860b57cec5SDimitry Andric const auto *S = cast<MDString>(Ident->getOperand(I)->getOperand(0)); 1870b57cec5SDimitry Andric std::pair<StringRef, StringRef> Field = S->getString().split("version"); 1880b57cec5SDimitry Andric StringRef Name = Field.first.trim(); 1890b57cec5SDimitry Andric StringRef Version = Field.second.trim(); 1900b57cec5SDimitry Andric if (SeenTools.insert(Name).second) 1910b57cec5SDimitry Andric Tools.emplace_back(Name.str(), Version.str()); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric int FieldCount = int(!Languages.empty()) + int(!Tools.empty()); 1960b57cec5SDimitry Andric if (FieldCount != 0) { 1970b57cec5SDimitry Andric MCSectionWasm *Producers = OutContext.getWasmSection( 1980b57cec5SDimitry Andric ".custom_section.producers", SectionKind::getMetadata()); 1990b57cec5SDimitry Andric OutStreamer->PushSection(); 2000b57cec5SDimitry Andric OutStreamer->SwitchSection(Producers); 2010b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(FieldCount); 2020b57cec5SDimitry Andric for (auto &Producers : {std::make_pair("language", &Languages), 2030b57cec5SDimitry Andric std::make_pair("processed-by", &Tools)}) { 2040b57cec5SDimitry Andric if (Producers.second->empty()) 2050b57cec5SDimitry Andric continue; 2060b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(strlen(Producers.first)); 2070b57cec5SDimitry Andric OutStreamer->EmitBytes(Producers.first); 2080b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(Producers.second->size()); 2090b57cec5SDimitry Andric for (auto &Producer : *Producers.second) { 2100b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(Producer.first.size()); 2110b57cec5SDimitry Andric OutStreamer->EmitBytes(Producer.first); 2120b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(Producer.second.size()); 2130b57cec5SDimitry Andric OutStreamer->EmitBytes(Producer.second); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric OutStreamer->PopSection(); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitTargetFeatures(Module &M) { 2210b57cec5SDimitry Andric struct FeatureEntry { 2220b57cec5SDimitry Andric uint8_t Prefix; 2230b57cec5SDimitry Andric StringRef Name; 2240b57cec5SDimitry Andric }; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // Read target features and linkage policies from module metadata 2270b57cec5SDimitry Andric SmallVector<FeatureEntry, 4> EmittedFeatures; 2280b57cec5SDimitry Andric for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) { 2290b57cec5SDimitry Andric std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str(); 2300b57cec5SDimitry Andric Metadata *Policy = M.getModuleFlag(MDKey); 2310b57cec5SDimitry Andric if (Policy == nullptr) 2320b57cec5SDimitry Andric continue; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric FeatureEntry Entry; 2350b57cec5SDimitry Andric Entry.Prefix = 0; 2360b57cec5SDimitry Andric Entry.Name = KV.Key; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric if (auto *MD = cast<ConstantAsMetadata>(Policy)) 2390b57cec5SDimitry Andric if (auto *I = cast<ConstantInt>(MD->getValue())) 2400b57cec5SDimitry Andric Entry.Prefix = I->getZExtValue(); 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric // Silently ignore invalid metadata 2430b57cec5SDimitry Andric if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED && 2440b57cec5SDimitry Andric Entry.Prefix != wasm::WASM_FEATURE_PREFIX_REQUIRED && 2450b57cec5SDimitry Andric Entry.Prefix != wasm::WASM_FEATURE_PREFIX_DISALLOWED) 2460b57cec5SDimitry Andric continue; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric EmittedFeatures.push_back(Entry); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric if (EmittedFeatures.size() == 0) 2520b57cec5SDimitry Andric return; 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric // Emit features and linkage policies into the "target_features" section 2550b57cec5SDimitry Andric MCSectionWasm *FeaturesSection = OutContext.getWasmSection( 2560b57cec5SDimitry Andric ".custom_section.target_features", SectionKind::getMetadata()); 2570b57cec5SDimitry Andric OutStreamer->PushSection(); 2580b57cec5SDimitry Andric OutStreamer->SwitchSection(FeaturesSection); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(EmittedFeatures.size()); 2610b57cec5SDimitry Andric for (auto &F : EmittedFeatures) { 2620b57cec5SDimitry Andric OutStreamer->EmitIntValue(F.Prefix, 1); 2630b57cec5SDimitry Andric OutStreamer->EmitULEB128IntValue(F.Name.size()); 2640b57cec5SDimitry Andric OutStreamer->EmitBytes(F.Name); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric OutStreamer->PopSection(); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitConstantPool() { 2710b57cec5SDimitry Andric assert(MF->getConstantPool()->getConstants().empty() && 2720b57cec5SDimitry Andric "WebAssembly disables constant pools"); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitJumpTableInfo() { 2760b57cec5SDimitry Andric // Nothing to do; jump tables are incorporated into the instruction stream. 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { 2800b57cec5SDimitry Andric const Function &F = MF->getFunction(); 2810b57cec5SDimitry Andric SmallVector<MVT, 1> ResultVTs; 2820b57cec5SDimitry Andric SmallVector<MVT, 4> ParamVTs; 2830b57cec5SDimitry Andric computeSignatureVTs(F.getFunctionType(), F, TM, ParamVTs, ResultVTs); 2840b57cec5SDimitry Andric auto Signature = signatureFromMVTs(ResultVTs, ParamVTs); 2850b57cec5SDimitry Andric auto *WasmSym = cast<MCSymbolWasm>(CurrentFnSym); 2860b57cec5SDimitry Andric WasmSym->setSignature(Signature.get()); 2870b57cec5SDimitry Andric addSignature(std::move(Signature)); 2880b57cec5SDimitry Andric WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // FIXME: clean up how params and results are emitted (use signatures) 2910b57cec5SDimitry Andric getTargetStreamer()->emitFunctionType(WasmSym); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric // Emit the function index. 2940b57cec5SDimitry Andric if (MDNode *Idx = F.getMetadata("wasm.index")) { 2950b57cec5SDimitry Andric assert(Idx->getNumOperands() == 1); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric getTargetStreamer()->emitIndIdx(AsmPrinter::lowerConstant( 2980b57cec5SDimitry Andric cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue())); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric SmallVector<wasm::ValType, 16> Locals; 3020b57cec5SDimitry Andric valTypesFromMVTs(MFI->getLocals(), Locals); 3030b57cec5SDimitry Andric getTargetStreamer()->emitLocal(Locals); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric AsmPrinter::EmitFunctionBodyStart(); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 3090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n'); 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric switch (MI->getOpcode()) { 3120b57cec5SDimitry Andric case WebAssembly::ARGUMENT_i32: 3130b57cec5SDimitry Andric case WebAssembly::ARGUMENT_i32_S: 3140b57cec5SDimitry Andric case WebAssembly::ARGUMENT_i64: 3150b57cec5SDimitry Andric case WebAssembly::ARGUMENT_i64_S: 3160b57cec5SDimitry Andric case WebAssembly::ARGUMENT_f32: 3170b57cec5SDimitry Andric case WebAssembly::ARGUMENT_f32_S: 3180b57cec5SDimitry Andric case WebAssembly::ARGUMENT_f64: 3190b57cec5SDimitry Andric case WebAssembly::ARGUMENT_f64_S: 3200b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v16i8: 3210b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v16i8_S: 3220b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v8i16: 3230b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v8i16_S: 3240b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v4i32: 3250b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v4i32_S: 3260b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v2i64: 3270b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v2i64_S: 3280b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v4f32: 3290b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v4f32_S: 3300b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v2f64: 3310b57cec5SDimitry Andric case WebAssembly::ARGUMENT_v2f64_S: 3320b57cec5SDimitry Andric // These represent values which are live into the function entry, so there's 3330b57cec5SDimitry Andric // no instruction to emit. 3340b57cec5SDimitry Andric break; 335*8bcb0991SDimitry Andric case WebAssembly::FALLTHROUGH_RETURN: { 3360b57cec5SDimitry Andric // These instructions represent the implicit return at the end of a 337*8bcb0991SDimitry Andric // function body. 3380b57cec5SDimitry Andric if (isVerbose()) { 339*8bcb0991SDimitry Andric OutStreamer->AddComment("fallthrough-return"); 3400b57cec5SDimitry Andric OutStreamer->AddBlankLine(); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric break; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric case WebAssembly::COMPILER_FENCE: 3450b57cec5SDimitry Andric // This is a compiler barrier that prevents instruction reordering during 3460b57cec5SDimitry Andric // backend compilation, and should not be emitted. 3470b57cec5SDimitry Andric break; 3480b57cec5SDimitry Andric case WebAssembly::EXTRACT_EXCEPTION_I32: 3490b57cec5SDimitry Andric case WebAssembly::EXTRACT_EXCEPTION_I32_S: 3500b57cec5SDimitry Andric // These are pseudo instructions that simulates popping values from stack. 3510b57cec5SDimitry Andric // We print these only when we have -wasm-keep-registers on for assembly 3520b57cec5SDimitry Andric // readability. 3530b57cec5SDimitry Andric if (!WasmKeepRegisters) 3540b57cec5SDimitry Andric break; 3550b57cec5SDimitry Andric LLVM_FALLTHROUGH; 3560b57cec5SDimitry Andric default: { 3570b57cec5SDimitry Andric WebAssemblyMCInstLower MCInstLowering(OutContext, *this); 3580b57cec5SDimitry Andric MCInst TmpInst; 3590b57cec5SDimitry Andric MCInstLowering.lower(MI, TmpInst); 3600b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 3610b57cec5SDimitry Andric break; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 3670b57cec5SDimitry Andric unsigned OpNo, 3680b57cec5SDimitry Andric const char *ExtraCode, 3690b57cec5SDimitry Andric raw_ostream &OS) { 3700b57cec5SDimitry Andric // First try the generic code, which knows about modifiers like 'c' and 'n'. 3710b57cec5SDimitry Andric if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) 3720b57cec5SDimitry Andric return false; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric if (!ExtraCode) { 3750b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 3760b57cec5SDimitry Andric switch (MO.getType()) { 3770b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 3780b57cec5SDimitry Andric OS << MO.getImm(); 3790b57cec5SDimitry Andric return false; 3800b57cec5SDimitry Andric case MachineOperand::MO_Register: 3810b57cec5SDimitry Andric // FIXME: only opcode that still contains registers, as required by 3820b57cec5SDimitry Andric // MachineInstr::getDebugVariable(). 3830b57cec5SDimitry Andric assert(MI->getOpcode() == WebAssembly::INLINEASM); 3840b57cec5SDimitry Andric OS << regToString(MO); 3850b57cec5SDimitry Andric return false; 3860b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 3870b57cec5SDimitry Andric PrintSymbolOperand(MO, OS); 3880b57cec5SDimitry Andric return false; 3890b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 3900b57cec5SDimitry Andric GetExternalSymbolSymbol(MO.getSymbolName())->print(OS, MAI); 3910b57cec5SDimitry Andric printOffset(MO.getOffset(), OS); 3920b57cec5SDimitry Andric return false; 3930b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 3940b57cec5SDimitry Andric MO.getMBB()->getSymbol()->print(OS, MAI); 3950b57cec5SDimitry Andric return false; 3960b57cec5SDimitry Andric default: 3970b57cec5SDimitry Andric break; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric return true; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 4050b57cec5SDimitry Andric unsigned OpNo, 4060b57cec5SDimitry Andric const char *ExtraCode, 4070b57cec5SDimitry Andric raw_ostream &OS) { 4080b57cec5SDimitry Andric // The current approach to inline asm is that "r" constraints are expressed 4090b57cec5SDimitry Andric // as local indices, rather than values on the operand stack. This simplifies 4100b57cec5SDimitry Andric // using "r" as it eliminates the need to push and pop the values in a 4110b57cec5SDimitry Andric // particular order, however it also makes it impossible to have an "m" 4120b57cec5SDimitry Andric // constraint. So we don't support it. 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // Force static initialization. 4180b57cec5SDimitry Andric extern "C" void LLVMInitializeWebAssemblyAsmPrinter() { 4190b57cec5SDimitry Andric RegisterAsmPrinter<WebAssemblyAsmPrinter> X(getTheWebAssemblyTarget32()); 4200b57cec5SDimitry Andric RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(getTheWebAssemblyTarget64()); 4210b57cec5SDimitry Andric } 422