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 77*315cc068SJF Bastien // Untyped, lower-case version of the opcode's name matching the names 78*315cc068SJF Bastien // WebAssembly opcodes are expected to have. The tablegen names are uppercase 79*315cc068SJF Bastien // and suffixed with their type (after an underscore). 80*315cc068SJF Bastien static SmallString<32> Name(const WebAssemblyInstrInfo *TII, 81*315cc068SJF Bastien const MachineInstr *MI) { 82*315cc068SJF Bastien std::string N(StringRef(TII->getName(MI->getOpcode())).lower()); 83*315cc068SJF Bastien std::string::size_type End = N.find('_'); 84*315cc068SJF Bastien End = std::string::npos == End ? N.length() : End; 85*315cc068SJF Bastien return SmallString<32>(&N[0], &N[End]); 86*315cc068SJF Bastien } 87*315cc068SJF Bastien 88b9073fb2SJF Bastien void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 89b9073fb2SJF Bastien SmallString<128> Str; 90b9073fb2SJF Bastien raw_svector_ostream OS(Str); 91b9073fb2SJF Bastien 92600aee98SJF Bastien unsigned NumDefs = MI->getDesc().getNumDefs(); 93600aee98SJF Bastien assert(NumDefs <= 1 && 94600aee98SJF Bastien "Instructions with multiple result values not implemented"); 95600aee98SJF Bastien 96600aee98SJF Bastien if (NumDefs != 0) { 97600aee98SJF Bastien const MachineOperand &MO = MI->getOperand(0); 98600aee98SJF Bastien unsigned Reg = MO.getReg(); 99600aee98SJF Bastien OS << "(setlocal @" << TargetRegisterInfo::virtReg2Index(Reg) << ' '; 100600aee98SJF Bastien } 101600aee98SJF Bastien 102600aee98SJF Bastien OS << '('; 103600aee98SJF Bastien 104600aee98SJF Bastien bool PrintOperands = true; 105b9073fb2SJF Bastien switch (MI->getOpcode()) { 1068f9aea08SJF Bastien case WebAssembly::ARGUMENT_Int32: 1078f9aea08SJF Bastien case WebAssembly::ARGUMENT_Int64: 1088f9aea08SJF Bastien case WebAssembly::ARGUMENT_Float32: 1098f9aea08SJF Bastien case WebAssembly::ARGUMENT_Float64: 110*315cc068SJF Bastien OS << Name(TII, MI) << ' ' << MI->getOperand(1).getImm(); 111600aee98SJF Bastien PrintOperands = false; 112600aee98SJF Bastien break; 113b9073fb2SJF Bastien default: 114*315cc068SJF Bastien OS << Name(TII, MI); 115b9073fb2SJF Bastien break; 116b9073fb2SJF Bastien } 117b9073fb2SJF Bastien 118600aee98SJF Bastien if (PrintOperands) 119600aee98SJF Bastien for (const MachineOperand &MO : MI->uses()) { 120600aee98SJF Bastien if (MO.isReg() && MO.isImplicit()) 121600aee98SJF Bastien continue; 122600aee98SJF Bastien unsigned Reg = MO.getReg(); 123600aee98SJF Bastien OS << " @" << TargetRegisterInfo::virtReg2Index(Reg); 124600aee98SJF Bastien } 125600aee98SJF Bastien OS << ')'; 126600aee98SJF Bastien 127600aee98SJF Bastien if (NumDefs != 0) 128600aee98SJF Bastien OS << ')'; 129600aee98SJF Bastien 130600aee98SJF Bastien OS << '\n'; 131600aee98SJF Bastien 132b9073fb2SJF Bastien OutStreamer->EmitRawText(OS.str()); 133b9073fb2SJF Bastien } 134b9073fb2SJF Bastien 135b9073fb2SJF Bastien // Force static initialization. 136b9073fb2SJF Bastien extern "C" void LLVMInitializeWebAssemblyAsmPrinter() { 137b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32); 138b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64); 139b9073fb2SJF Bastien } 140