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 { 61e419a7c3SDan Gohman TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 62600aee98SJF Bastien return AsmPrinter::runOnMachineFunction(MF); 63b9073fb2SJF Bastien } 64b9073fb2SJF Bastien 65b9073fb2SJF Bastien //===------------------------------------------------------------------===// 66b9073fb2SJF Bastien // AsmPrinter Implementation. 67b9073fb2SJF Bastien //===------------------------------------------------------------------===// 68b9073fb2SJF Bastien 69b9073fb2SJF Bastien void EmitInstruction(const MachineInstr *MI) override; 70b9073fb2SJF Bastien }; 71b9073fb2SJF Bastien 72b9073fb2SJF Bastien } // end anonymous namespace 73b9073fb2SJF Bastien 74b9073fb2SJF Bastien //===----------------------------------------------------------------------===// 75b9073fb2SJF Bastien 76315cc068SJF Bastien // Untyped, lower-case version of the opcode's name matching the names 77315cc068SJF Bastien // WebAssembly opcodes are expected to have. The tablegen names are uppercase 78315cc068SJF Bastien // and suffixed with their type (after an underscore). 79315cc068SJF Bastien static SmallString<32> Name(const WebAssemblyInstrInfo *TII, 80315cc068SJF Bastien const MachineInstr *MI) { 81315cc068SJF Bastien std::string N(StringRef(TII->getName(MI->getOpcode())).lower()); 8269c4c763SDan Gohman std::string::size_type End = N.rfind('_'); 83315cc068SJF Bastien End = std::string::npos == End ? N.length() : End; 84315cc068SJF Bastien return SmallString<32>(&N[0], &N[End]); 85315cc068SJF Bastien } 86315cc068SJF Bastien 87*af111db8SJF Bastien static std::string toSymbol(StringRef S) { return ("$" + S).str(); } 88*af111db8SJF Bastien 89b9073fb2SJF Bastien void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 90*af111db8SJF Bastien DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n'); 91b9073fb2SJF Bastien SmallString<128> Str; 92b9073fb2SJF Bastien raw_svector_ostream OS(Str); 93b9073fb2SJF Bastien 94600aee98SJF Bastien unsigned NumDefs = MI->getDesc().getNumDefs(); 95600aee98SJF Bastien assert(NumDefs <= 1 && 96600aee98SJF Bastien "Instructions with multiple result values not implemented"); 97600aee98SJF Bastien 9812e1997eSDan Gohman OS << '\t'; 9912e1997eSDan Gohman 100600aee98SJF Bastien if (NumDefs != 0) { 101600aee98SJF Bastien const MachineOperand &MO = MI->getOperand(0); 102600aee98SJF Bastien unsigned Reg = MO.getReg(); 103600aee98SJF Bastien OS << "(setlocal @" << TargetRegisterInfo::virtReg2Index(Reg) << ' '; 104600aee98SJF Bastien } 105600aee98SJF Bastien 1064a642256SJF Bastien OS << '(' << Name(TII, MI); 1074a642256SJF Bastien for (const MachineOperand &MO : MI->uses()) 1084a642256SJF Bastien switch (MO.getType()) { 109b9073fb2SJF Bastien default: 1104a642256SJF Bastien llvm_unreachable("unexpected machine operand type"); 1114a642256SJF Bastien case MachineOperand::MO_Register: { 1124a642256SJF Bastien if (MO.isImplicit()) 113600aee98SJF Bastien continue; 114600aee98SJF Bastien unsigned Reg = MO.getReg(); 115600aee98SJF Bastien OS << " @" << TargetRegisterInfo::virtReg2Index(Reg); 1164a642256SJF Bastien } break; 1174a642256SJF Bastien case MachineOperand::MO_Immediate: { 1184a642256SJF Bastien OS << ' ' << MO.getImm(); 1194a642256SJF Bastien } break; 1204a642256SJF Bastien case MachineOperand::MO_FPImmediate: { 1214a642256SJF Bastien static const size_t BufBytes = 128; 1224a642256SJF Bastien char buf[BufBytes]; 1234a642256SJF Bastien APFloat FP = MO.getFPImm()->getValueAPF(); 124e73ce682SJF Bastien if (FP.isNaN()) 125e73ce682SJF Bastien assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) || 126e73ce682SJF Bastien FP.bitwiseIsEqual( 127e73ce682SJF Bastien APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) && 128e73ce682SJF Bastien "convertToHexString handles neither SNaN nor NaN payloads"); 1294a642256SJF Bastien // Use C99's hexadecimal floating-point representation. 1304a642256SJF Bastien auto Written = 1314a642256SJF Bastien FP.convertToHexString(buf, /*hexDigits=*/0, /*upperCase=*/false, 1324a642256SJF Bastien APFloat::rmNearestTiesToEven); 13311bf0da0SJF Bastien (void)Written; 1344a642256SJF Bastien assert(Written != 0); 1354a642256SJF Bastien assert(Written < BufBytes); 1364a642256SJF Bastien OS << ' ' << buf; 1374a642256SJF Bastien } break; 138*af111db8SJF Bastien case MachineOperand::MO_GlobalAddress: { 139*af111db8SJF Bastien OS << ' ' << toSymbol(MO.getGlobal()->getName()); 140*af111db8SJF Bastien } break; 141600aee98SJF Bastien } 142600aee98SJF Bastien OS << ')'; 143600aee98SJF Bastien 144600aee98SJF Bastien if (NumDefs != 0) 145600aee98SJF Bastien OS << ')'; 146600aee98SJF Bastien 147600aee98SJF Bastien OS << '\n'; 148600aee98SJF Bastien 149b9073fb2SJF Bastien OutStreamer->EmitRawText(OS.str()); 150b9073fb2SJF Bastien } 151b9073fb2SJF Bastien 152b9073fb2SJF Bastien // Force static initialization. 153b9073fb2SJF Bastien extern "C" void LLVMInitializeWebAssemblyAsmPrinter() { 154b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32); 155b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64); 156b9073fb2SJF Bastien } 157