blob: f92a9d0c6615f2e99bfec7f408ebde2a8463d556 [file] [log] [blame]
Dan Gohman10e730a2015-06-29 23:51:55 +00001//=- 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"
Dan Gohman7a6b9822015-11-29 22:32:02 +000016#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Dan Gohman10e730a2015-06-29 23:51:55 +000017#include "WebAssembly.h"
Dan Gohman058fce52015-11-13 00:21:05 +000018#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohman10e730a2015-06-29 23:51:55 +000019#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"
Dan Gohmane9361d52015-11-05 19:28:16 +000026#include "llvm/Target/TargetRegisterInfo.h"
Dan Gohman10e730a2015-06-29 23:51:55 +000027using namespace llvm;
28
29#define DEBUG_TYPE "asm-printer"
30
JF Bastienb9073fb2015-07-22 21:28:15 +000031#include "WebAssemblyGenAsmWriter.inc"
32
Dan Gohman10e730a2015-06-29 23:51:55 +000033WebAssemblyInstPrinter::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 {
Dan Gohman058fce52015-11-13 00:21:05 +000040 assert(RegNo != WebAssemblyFunctionInfo::UnusedReg);
Dan Gohman4ba48162015-11-18 16:12:01 +000041 // Note that there's an implicit get_local/set_local here!
42 OS << "$" << RegNo;
Dan Gohman10e730a2015-06-29 23:51:55 +000043}
44
45void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
46 StringRef Annot,
Dan Gohman7a6b9822015-11-29 22:32:02 +000047 const MCSubtargetInfo & /*STI*/) {
Dan Gohmandd20c702015-12-21 16:50:41 +000048 // Print the instruction (this uses the AsmStrings from the .td files).
JF Bastienb9073fb2015-07-22 21:28:15 +000049 printInstruction(MI, OS);
Dan Gohmancf4748f2015-11-12 17:04:33 +000050
Dan Gohmandd20c702015-12-21 16:50:41 +000051 // Print any additional variadic operands.
Dan Gohmancf4748f2015-11-12 17:04:33 +000052 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
53 if (Desc.isVariadic())
Dan Gohmandd20c702015-12-21 16:50:41 +000054 for (auto i = Desc.getNumOperands(), e = MI->getNumOperands(); i < e; ++i) {
Dan Gohman53828fd2015-11-23 16:50:18 +000055 if (i != 0)
56 OS << ", ";
Dan Gohmancf4748f2015-11-12 17:04:33 +000057 printOperand(MI, i, OS);
58 }
59
Dan Gohmandd20c702015-12-21 16:50:41 +000060 // Print any added annotation.
JF Bastienb9073fb2015-07-22 21:28:15 +000061 printAnnotation(OS, Annot);
Dan Gohmancf4748f2015-11-12 17:04:33 +000062}
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;
Dan Gohman10e730a2015-06-29 23:51:55 +000079}
JF Bastienaf111db2015-08-24 22:16:48 +000080
81void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
82 raw_ostream &O) {
83 const MCOperand &Op = MI->getOperand(OpNo);
Dan Gohmane9361d52015-11-05 19:28:16 +000084 if (Op.isReg()) {
Dan Gohman85159ca2016-01-12 01:45:12 +000085 assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
86 MII.get(MI->getOpcode()).TSFlags == 0) &&
87 "WebAssembly variable_ops register ops don't use TSFlags");
Dan Gohman4ba48162015-11-18 16:12:01 +000088 unsigned WAReg = Op.getReg();
89 if (int(WAReg) >= 0)
90 printRegName(O, WAReg);
91 else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs())
92 O << "$pop" << (WAReg & INT32_MAX);
93 else if (WAReg != WebAssemblyFunctionInfo::UnusedReg)
94 O << "$push" << (WAReg & INT32_MAX);
95 else
96 O << "$discard";
Dan Gohman700515f2015-11-23 21:55:57 +000097 // Add a '=' suffix if this is a def.
98 if (OpNo < MII.get(MI->getOpcode()).getNumDefs())
99 O << '=';
Dan Gohman53828fd2015-11-23 16:50:18 +0000100 } else if (Op.isImm()) {
Dan Gohman85159ca2016-01-12 01:45:12 +0000101 assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
102 (MII.get(MI->getOpcode()).TSFlags &
103 WebAssemblyII::VariableOpIsImmediate)) &&
104 "WebAssemblyII::VariableOpIsImmediate should be set for "
105 "variable_ops immediate ops");
106 if (MII.get(MI->getOpcode()).TSFlags &
107 WebAssemblyII::VariableOpImmediateIsType)
108 // The immediates represent types.
Dan Gohman5e0886b2015-12-06 19:42:29 +0000109 O << WebAssembly::TypeToString(MVT::SimpleValueType(Op.getImm()));
Dan Gohman85159ca2016-01-12 01:45:12 +0000110 else
Dan Gohman53828fd2015-11-23 16:50:18 +0000111 O << Op.getImm();
Dan Gohman85159ca2016-01-12 01:45:12 +0000112 } else if (Op.isFPImm()) {
113 assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
114 MII.get(MI->getOpcode()).TSFlags == 0) &&
115 "WebAssembly variable_ops floating point ops don't use TSFlags");
Dan Gohmancf4748f2015-11-12 17:04:33 +0000116 O << toString(APFloat(Op.getFPImm()));
Dan Gohman85159ca2016-01-12 01:45:12 +0000117 } else {
118 assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
119 (MII.get(MI->getOpcode()).TSFlags &
120 WebAssemblyII::VariableOpIsImmediate)) &&
121 "WebAssemblyII::VariableOpIsImmediate should be set for "
122 "variable_ops expr ops");
JF Bastienaf111db2015-08-24 22:16:48 +0000123 assert(Op.isExpr() && "unknown operand kind in printOperand");
124 Op.getExpr()->print(O, &MAI);
125 }
126}
Dan Gohman5e0886b2015-12-06 19:42:29 +0000127
128const char *llvm::WebAssembly::TypeToString(MVT Ty) {
129 switch (Ty.SimpleTy) {
130 case MVT::i32:
131 return "i32";
132 case MVT::i64:
133 return "i64";
134 case MVT::f32:
135 return "f32";
136 case MVT::f64:
137 return "f64";
138 default:
139 llvm_unreachable("unsupported type");
140 }
141}