1//=- WebAssemblyInstPrinter.cpp - WebAssembly assembly instruction printing -=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// \brief Print MCInst instructions to wasm format. 12/// 13//===----------------------------------------------------------------------===// 14 15#include "InstPrinter/WebAssemblyInstPrinter.h" 16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 17#include "WebAssembly.h" 18#include "WebAssemblyMachineFunctionInfo.h" 19#include "llvm/MC/MCExpr.h" 20#include "llvm/MC/MCInst.h" 21#include "llvm/MC/MCInstrInfo.h" 22#include "llvm/MC/MCSubtargetInfo.h" 23#include "llvm/MC/MCSymbol.h" 24#include "llvm/Support/ErrorHandling.h" 25#include "llvm/Support/FormattedStream.h" 26#include "llvm/Target/TargetRegisterInfo.h" 27using namespace llvm; 28 29#define DEBUG_TYPE "asm-printer" 30 31#include "WebAssemblyGenAsmWriter.inc" 32 33WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI, 34 const MCInstrInfo &MII, 35 const MCRegisterInfo &MRI) 36 : MCInstPrinter(MAI, MII, MRI) {} 37 38void WebAssemblyInstPrinter::printRegName(raw_ostream &OS, 39 unsigned RegNo) const { 40 assert(RegNo != WebAssemblyFunctionInfo::UnusedReg); 41 // Note that there's an implicit get_local/set_local here! 42 OS << "$" << RegNo; 43} 44 45void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, 46 StringRef Annot, 47 const MCSubtargetInfo & /*STI*/) { 48 // Print the instruction (this uses the AsmStrings from the .td files). 49 printInstruction(MI, OS); 50 51 // Print any additional variadic operands. 52 const MCInstrDesc &Desc = MII.get(MI->getOpcode()); 53 if (Desc.isVariadic()) 54 for (auto i = Desc.getNumOperands(), e = MI->getNumOperands(); i < e; ++i) { 55 if (i != 0) 56 OS << ", "; 57 printOperand(MI, i, OS); 58 } 59 60 // Print any added annotation. 61 printAnnotation(OS, Annot); 62} 63 64static std::string toString(const APFloat &FP) { 65 static const size_t BufBytes = 128; 66 char buf[BufBytes]; 67 if (FP.isNaN()) 68 assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) || 69 FP.bitwiseIsEqual( 70 APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) && 71 "convertToHexString handles neither SNaN nor NaN payloads"); 72 // Use C99's hexadecimal floating-point representation. 73 auto Written = FP.convertToHexString( 74 buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven); 75 (void)Written; 76 assert(Written != 0); 77 assert(Written < BufBytes); 78 return buf; 79} 80 81void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 82 raw_ostream &O) { 83 const MCOperand &Op = MI->getOperand(OpNo); 84 if (Op.isReg()) { 85 unsigned WAReg = Op.getReg(); 86 if (int(WAReg) >= 0) 87 printRegName(O, WAReg); 88 else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs()) 89 O << "$pop" << (WAReg & INT32_MAX); 90 else if (WAReg != WebAssemblyFunctionInfo::UnusedReg) 91 O << "$push" << (WAReg & INT32_MAX); 92 else 93 O << "$discard"; 94 // Add a '=' suffix if this is a def. 95 if (OpNo < MII.get(MI->getOpcode()).getNumDefs()) 96 O << '='; 97 } else if (Op.isImm()) { 98 switch (MI->getOpcode()) { 99 case WebAssembly::PARAM: 100 case WebAssembly::RESULT: 101 case WebAssembly::LOCAL: 102 O << WebAssembly::TypeToString(MVT::SimpleValueType(Op.getImm())); 103 break; 104 default: 105 O << Op.getImm(); 106 break; 107 } 108 } else if (Op.isFPImm()) 109 O << toString(APFloat(Op.getFPImm())); 110 else { 111 assert(Op.isExpr() && "unknown operand kind in printOperand"); 112 Op.getExpr()->print(O, &MAI); 113 } 114} 115 116const char *llvm::WebAssembly::TypeToString(MVT Ty) { 117 switch (Ty.SimpleTy) { 118 case MVT::i32: 119 return "i32"; 120 case MVT::i64: 121 return "i64"; 122 case MVT::f32: 123 return "f32"; 124 case MVT::f64: 125 return "f64"; 126 default: 127 llvm_unreachable("unsupported type"); 128 } 129} 130