1b9073fb2SJF Bastien //===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===// 2b9073fb2SJF Bastien // 3b9073fb2SJF Bastien // The LLVM Compiler Infrastructure 4b9073fb2SJF Bastien // 5b9073fb2SJF Bastien // This file is distributed under the University of Illinois Open Source 6b9073fb2SJF Bastien // License. See LICENSE.TXT for details. 7b9073fb2SJF Bastien // 8b9073fb2SJF Bastien //===----------------------------------------------------------------------===// 9b9073fb2SJF Bastien /// 10b9073fb2SJF Bastien /// \file 11b9073fb2SJF Bastien /// \brief This file contains a printer that converts from our internal 12b9073fb2SJF Bastien /// representation of machine-dependent LLVM code to the WebAssembly assembly 13b9073fb2SJF Bastien /// language. 14b9073fb2SJF Bastien /// 15b9073fb2SJF Bastien //===----------------------------------------------------------------------===// 16b9073fb2SJF Bastien 17b9073fb2SJF Bastien #include "WebAssembly.h" 18b9073fb2SJF Bastien #include "WebAssemblyMachineFunctionInfo.h" 19b9073fb2SJF Bastien #include "WebAssemblyRegisterInfo.h" 20b9073fb2SJF Bastien #include "WebAssemblySubtarget.h" 21b9073fb2SJF Bastien #include "InstPrinter/WebAssemblyInstPrinter.h" 22b9073fb2SJF Bastien #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 23b9073fb2SJF Bastien 24b9073fb2SJF Bastien #include "llvm/ADT/SmallString.h" 25b9073fb2SJF Bastien #include "llvm/CodeGen/AsmPrinter.h" 26b9073fb2SJF Bastien #include "llvm/CodeGen/MachineInstr.h" 27b9073fb2SJF Bastien #include "llvm/IR/DataLayout.h" 28b9073fb2SJF Bastien #include "llvm/IR/DebugInfo.h" 29b9073fb2SJF Bastien #include "llvm/MC/MCStreamer.h" 30b9073fb2SJF Bastien #include "llvm/Support/Debug.h" 31b9073fb2SJF Bastien #include "llvm/Support/TargetRegistry.h" 32b9073fb2SJF Bastien #include "llvm/Support/raw_ostream.h" 33b9073fb2SJF Bastien 34b9073fb2SJF Bastien using namespace llvm; 35b9073fb2SJF Bastien 36b9073fb2SJF Bastien #define DEBUG_TYPE "asm-printer" 37b9073fb2SJF Bastien 38b9073fb2SJF Bastien namespace { 39b9073fb2SJF Bastien 40b9073fb2SJF Bastien class WebAssemblyAsmPrinter final : public AsmPrinter { 41600aee98SJF Bastien const WebAssemblyInstrInfo *TII; 42600aee98SJF Bastien 43b9073fb2SJF Bastien public: 44b9073fb2SJF Bastien WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) 45600aee98SJF Bastien : AsmPrinter(TM, std::move(Streamer)), TII(nullptr) {} 46b9073fb2SJF Bastien 47b9073fb2SJF Bastien private: 48b9073fb2SJF Bastien const char *getPassName() const override { 49b9073fb2SJF Bastien return "WebAssembly Assembly Printer"; 50b9073fb2SJF Bastien } 51b9073fb2SJF Bastien 52b9073fb2SJF Bastien //===------------------------------------------------------------------===// 53b9073fb2SJF Bastien // MachineFunctionPass Implementation. 54b9073fb2SJF Bastien //===------------------------------------------------------------------===// 55b9073fb2SJF Bastien 56b9073fb2SJF Bastien void getAnalysisUsage(AnalysisUsage &AU) const override { 57b9073fb2SJF Bastien AsmPrinter::getAnalysisUsage(AU); 58b9073fb2SJF Bastien } 59b9073fb2SJF Bastien 60600aee98SJF Bastien bool runOnMachineFunction(MachineFunction &MF) override { 61600aee98SJF Bastien TII = static_cast<const WebAssemblyInstrInfo *>( 62600aee98SJF Bastien MF.getSubtarget().getInstrInfo()); 63600aee98SJF Bastien return AsmPrinter::runOnMachineFunction(MF); 64b9073fb2SJF Bastien } 65b9073fb2SJF Bastien 66b9073fb2SJF Bastien //===------------------------------------------------------------------===// 67b9073fb2SJF Bastien // AsmPrinter Implementation. 68b9073fb2SJF Bastien //===------------------------------------------------------------------===// 69b9073fb2SJF Bastien 70b9073fb2SJF Bastien void EmitInstruction(const MachineInstr *MI) override; 71b9073fb2SJF Bastien }; 72b9073fb2SJF Bastien 73b9073fb2SJF Bastien } // end anonymous namespace 74b9073fb2SJF Bastien 75b9073fb2SJF Bastien //===----------------------------------------------------------------------===// 76b9073fb2SJF Bastien 77b9073fb2SJF Bastien void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 78b9073fb2SJF Bastien SmallString<128> Str; 79b9073fb2SJF Bastien raw_svector_ostream OS(Str); 80b9073fb2SJF Bastien 81600aee98SJF Bastien unsigned NumDefs = MI->getDesc().getNumDefs(); 82600aee98SJF Bastien assert(NumDefs <= 1 && 83600aee98SJF Bastien "Instructions with multiple result values not implemented"); 84600aee98SJF Bastien 85600aee98SJF Bastien if (NumDefs != 0) { 86600aee98SJF Bastien const MachineOperand &MO = MI->getOperand(0); 87600aee98SJF Bastien unsigned Reg = MO.getReg(); 88600aee98SJF Bastien OS << "(setlocal @" << TargetRegisterInfo::virtReg2Index(Reg) << ' '; 89600aee98SJF Bastien } 90600aee98SJF Bastien 91600aee98SJF Bastien OS << '('; 92600aee98SJF Bastien 93600aee98SJF Bastien bool PrintOperands = true; 94b9073fb2SJF Bastien switch (MI->getOpcode()) { 95*8f9aea08SJF Bastien case WebAssembly::ARGUMENT_Int32: 96*8f9aea08SJF Bastien case WebAssembly::ARGUMENT_Int64: 97*8f9aea08SJF Bastien case WebAssembly::ARGUMENT_Float32: 98*8f9aea08SJF Bastien case WebAssembly::ARGUMENT_Float64: 99600aee98SJF Bastien OS << "argument " << MI->getOperand(1).getImm(); 100600aee98SJF Bastien PrintOperands = false; 101600aee98SJF Bastien break; 102*8f9aea08SJF Bastien case WebAssembly::RETURN_Int32: 103*8f9aea08SJF Bastien case WebAssembly::RETURN_Int64: 104*8f9aea08SJF Bastien case WebAssembly::RETURN_Float32: 105*8f9aea08SJF Bastien case WebAssembly::RETURN_Float64: 106*8f9aea08SJF Bastien case WebAssembly::RETURN_VOID: 107*8f9aea08SJF Bastien // FIXME This is here only so "return" prints nicely, instead of printing 108*8f9aea08SJF Bastien // the isel name. Other operations have the same problem, fix this in 109*8f9aea08SJF Bastien // a generic way instead. 110*8f9aea08SJF Bastien OS << "return"; 111*8f9aea08SJF Bastien break; 112b9073fb2SJF Bastien default: 113600aee98SJF Bastien OS << TII->getName(MI->getOpcode()); 114b9073fb2SJF Bastien break; 115b9073fb2SJF Bastien } 116b9073fb2SJF Bastien 117600aee98SJF Bastien if (PrintOperands) 118600aee98SJF Bastien for (const MachineOperand &MO : MI->uses()) { 119600aee98SJF Bastien if (MO.isReg() && MO.isImplicit()) 120600aee98SJF Bastien continue; 121600aee98SJF Bastien unsigned Reg = MO.getReg(); 122600aee98SJF Bastien OS << " @" << TargetRegisterInfo::virtReg2Index(Reg); 123600aee98SJF Bastien } 124600aee98SJF Bastien OS << ')'; 125600aee98SJF Bastien 126600aee98SJF Bastien if (NumDefs != 0) 127600aee98SJF Bastien OS << ')'; 128600aee98SJF Bastien 129600aee98SJF Bastien OS << '\n'; 130600aee98SJF Bastien 131b9073fb2SJF Bastien OutStreamer->EmitRawText(OS.str()); 132b9073fb2SJF Bastien } 133b9073fb2SJF Bastien 134b9073fb2SJF Bastien // Force static initialization. 135b9073fb2SJF Bastien extern "C" void LLVMInitializeWebAssemblyAsmPrinter() { 136b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32); 137b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64); 138b9073fb2SJF Bastien } 139