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 77315cc068SJF Bastien // Untyped, lower-case version of the opcode's name matching the names 78315cc068SJF Bastien // WebAssembly opcodes are expected to have. The tablegen names are uppercase 79315cc068SJF Bastien // and suffixed with their type (after an underscore). 80315cc068SJF Bastien static SmallString<32> Name(const WebAssemblyInstrInfo *TII, 81315cc068SJF Bastien const MachineInstr *MI) { 82315cc068SJF Bastien std::string N(StringRef(TII->getName(MI->getOpcode())).lower()); 83315cc068SJF Bastien std::string::size_type End = N.find('_'); 84315cc068SJF Bastien End = std::string::npos == End ? N.length() : End; 85315cc068SJF Bastien return SmallString<32>(&N[0], &N[End]); 86315cc068SJF Bastien } 87315cc068SJF 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 1024a642256SJF Bastien OS << '(' << Name(TII, MI); 1034a642256SJF Bastien for (const MachineOperand &MO : MI->uses()) 1044a642256SJF Bastien switch (MO.getType()) { 105b9073fb2SJF Bastien default: 1064a642256SJF Bastien llvm_unreachable("unexpected machine operand type"); 1074a642256SJF Bastien case MachineOperand::MO_Register: { 1084a642256SJF Bastien if (MO.isImplicit()) 109600aee98SJF Bastien continue; 110600aee98SJF Bastien unsigned Reg = MO.getReg(); 111600aee98SJF Bastien OS << " @" << TargetRegisterInfo::virtReg2Index(Reg); 1124a642256SJF Bastien } break; 1134a642256SJF Bastien case MachineOperand::MO_Immediate: { 1144a642256SJF Bastien OS << ' ' << MO.getImm(); 1154a642256SJF Bastien } break; 1164a642256SJF Bastien case MachineOperand::MO_FPImmediate: { 1174a642256SJF Bastien static const size_t BufBytes = 128; 1184a642256SJF Bastien char buf[BufBytes]; 1194a642256SJF Bastien APFloat FP = MO.getFPImm()->getValueAPF(); 120*e73ce682SJF Bastien if (FP.isNaN()) 121*e73ce682SJF Bastien assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) || 122*e73ce682SJF Bastien FP.bitwiseIsEqual( 123*e73ce682SJF Bastien APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) && 124*e73ce682SJF Bastien "convertToHexString handles neither SNaN nor NaN payloads"); 1254a642256SJF Bastien // Use C99's hexadecimal floating-point representation. 1264a642256SJF Bastien auto Written = 1274a642256SJF Bastien FP.convertToHexString(buf, /*hexDigits=*/0, /*upperCase=*/false, 1284a642256SJF Bastien APFloat::rmNearestTiesToEven); 1294a642256SJF Bastien assert(Written != 0); 1304a642256SJF Bastien assert(Written < BufBytes); 1314a642256SJF Bastien OS << ' ' << buf; 1324a642256SJF Bastien } break; 133600aee98SJF Bastien } 134600aee98SJF Bastien OS << ')'; 135600aee98SJF Bastien 136600aee98SJF Bastien if (NumDefs != 0) 137600aee98SJF Bastien OS << ')'; 138600aee98SJF Bastien 139600aee98SJF Bastien OS << '\n'; 140600aee98SJF Bastien 141b9073fb2SJF Bastien OutStreamer->EmitRawText(OS.str()); 142b9073fb2SJF Bastien } 143b9073fb2SJF Bastien 144b9073fb2SJF Bastien // Force static initialization. 145b9073fb2SJF Bastien extern "C" void LLVMInitializeWebAssemblyAsmPrinter() { 146b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32); 147b9073fb2SJF Bastien RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64); 148b9073fb2SJF Bastien } 149