LLVM  7.0.0svn
WebAssemblyInstPrinter.cpp
Go to the documentation of this file.
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 /// Print MCInst instructions to wasm format.
12 ///
13 //===----------------------------------------------------------------------===//
14 
17 #include "WebAssembly.h"
19 #include "llvm/ADT/SmallSet.h"
20 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCSymbol.h"
29 using namespace llvm;
30 
31 #define DEBUG_TYPE "asm-printer"
32 
33 #include "WebAssemblyGenAsmWriter.inc"
34 
36  const MCInstrInfo &MII,
37  const MCRegisterInfo &MRI)
38  : MCInstPrinter(MAI, MII, MRI), ControlFlowCounter(0) {}
39 
41  unsigned RegNo) const {
43  // Note that there's an implicit get_local/set_local here!
44  OS << "$" << RegNo;
45 }
46 
48  StringRef Annot,
49  const MCSubtargetInfo &STI) {
50  // Print the instruction (this uses the AsmStrings from the .td files).
51  printInstruction(MI, OS);
52 
53  // Print any additional variadic operands.
54  const MCInstrDesc &Desc = MII.get(MI->getOpcode());
55  if (Desc.isVariadic())
56  for (auto i = Desc.getNumOperands(), e = MI->getNumOperands(); i < e; ++i) {
57  // FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because
58  // we have an extra flags operand which is not currently printed, for
59  // compatiblity reasons.
60  if (i != 0 &&
61  (MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID ||
62  i != Desc.getNumOperands()))
63  OS << ", ";
64  printOperand(MI, i, OS);
65  }
66 
67  // Print any added annotation.
68  printAnnotation(OS, Annot);
69 
70  if (CommentStream) {
71  // Observe any effects on the control flow stack, for use in annotating
72  // control flow label references.
73  switch (MI->getOpcode()) {
74  default:
75  break;
76  case WebAssembly::LOOP: {
77  printAnnotation(OS, "label" + utostr(ControlFlowCounter) + ':');
78  ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, true));
79  break;
80  }
81  case WebAssembly::BLOCK:
82  ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false));
83  break;
84  case WebAssembly::END_LOOP:
85  // Have to guard against an empty stack, in case of mismatched pairs
86  // in assembly parsing.
87  if (!ControlFlowStack.empty()) ControlFlowStack.pop_back();
88  break;
90  if (!ControlFlowStack.empty()) printAnnotation(
91  OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
92  break;
93  }
94 
95  // Annotate any control flow label references.
96  unsigned NumFixedOperands = Desc.NumOperands;
97  SmallSet<uint64_t, 8> Printed;
98  for (unsigned i = 0, e = MI->getNumOperands(); i < e; ++i) {
99  if (!(i < NumFixedOperands
100  ? (Desc.OpInfo[i].OperandType ==
103  continue;
104  uint64_t Depth = MI->getOperand(i).getImm();
105  if (!Printed.insert(Depth).second)
106  continue;
107  const auto &Pair = ControlFlowStack.rbegin()[Depth];
108  printAnnotation(OS, utostr(Depth) + ": " + (Pair.second ? "up" : "down") +
109  " to label" + utostr(Pair.first));
110  }
111  }
112 }
113 
114 static std::string toString(const APFloat &FP) {
115  // Print NaNs with custom payloads specially.
116  if (FP.isNaN() &&
118  !FP.bitwiseIsEqual(
119  APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) {
120  APInt AI = FP.bitcastToAPInt();
121  return
122  std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
123  utohexstr(AI.getZExtValue() &
124  (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) :
125  INT64_C(0x000fffffffffffff)),
126  /*LowerCase=*/true);
127  }
128 
129  // Use C99's hexadecimal floating-point representation.
130  static const size_t BufBytes = 128;
131  char buf[BufBytes];
132  auto Written = FP.convertToHexString(
133  buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven);
134  (void)Written;
135  assert(Written != 0);
136  assert(Written < BufBytes);
137  return buf;
138 }
139 
140 void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
141  raw_ostream &O) {
142  const MCOperand &Op = MI->getOperand(OpNo);
143  if (Op.isReg()) {
144  assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
145  MII.get(MI->getOpcode()).TSFlags == 0) &&
146  "WebAssembly variable_ops register ops don't use TSFlags");
147  unsigned WAReg = Op.getReg();
148  if (int(WAReg) >= 0)
149  printRegName(O, WAReg);
150  else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs())
151  O << "$pop" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
152  else if (WAReg != WebAssemblyFunctionInfo::UnusedReg)
153  O << "$push" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
154  else
155  O << "$drop";
156  // Add a '=' suffix if this is a def.
157  if (OpNo < MII.get(MI->getOpcode()).getNumDefs())
158  O << '=';
159  } else if (Op.isImm()) {
160  const MCInstrDesc &Desc = MII.get(MI->getOpcode());
161  assert((OpNo < Desc.getNumOperands() ||
163  "WebAssemblyII::VariableOpIsImmediate should be set for "
164  "variable_ops immediate ops");
165  (void)Desc;
166  // TODO: (MII.get(MI->getOpcode()).TSFlags &
167  // WebAssemblyII::VariableOpImmediateIsLabel)
168  // can tell us whether this is an immediate referencing a label in the
169  // control flow stack, and it may be nice to pretty-print.
170  O << Op.getImm();
171  } else if (Op.isFPImm()) {
172  const MCInstrDesc &Desc = MII.get(MI->getOpcode());
173  assert(OpNo < Desc.getNumOperands() &&
174  "Unexpected floating-point immediate as a non-fixed operand");
175  assert(Desc.TSFlags == 0 &&
176  "WebAssembly variable_ops floating point ops don't use TSFlags");
177  const MCOperandInfo &Info = Desc.OpInfo[OpNo];
179  // TODO: MC converts all floating point immediate operands to double.
180  // This is fine for numeric values, but may cause NaNs to change bits.
181  O << ::toString(APFloat(float(Op.getFPImm())));
182  } else {
184  O << ::toString(APFloat(Op.getFPImm()));
185  }
186  } else {
187  assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() ||
188  (MII.get(MI->getOpcode()).TSFlags &
190  "WebAssemblyII::VariableOpIsImmediate should be set for "
191  "variable_ops expr ops");
192  assert(Op.isExpr() && "unknown operand kind in printOperand");
193  Op.getExpr()->print(O, &MAI);
194  }
195 }
196 
198  const MCInst *MI, unsigned OpNo, raw_ostream &O) {
199  int64_t Imm = MI->getOperand(OpNo).getImm();
200  if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode()))
201  return;
202  O << ":p2align=" << Imm;
203 }
204 
206  const MCInst *MI, unsigned OpNo, raw_ostream &O) {
207  int64_t Imm = MI->getOperand(OpNo).getImm();
208  switch (WebAssembly::ExprType(Imm)) {
209  case WebAssembly::ExprType::Void: break;
210  case WebAssembly::ExprType::I32: O << "i32"; break;
211  case WebAssembly::ExprType::I64: O << "i64"; break;
212  case WebAssembly::ExprType::F32: O << "f32"; break;
213  case WebAssembly::ExprType::F64: O << "f64"; break;
214  case WebAssembly::ExprType::I8x16: O << "i8x16"; break;
215  case WebAssembly::ExprType::I16x8: O << "i16x8"; break;
216  case WebAssembly::ExprType::I32x4: O << "i32x4"; break;
217  case WebAssembly::ExprType::F32x4: O << "f32x4"; break;
218  case WebAssembly::ExprType::B8x16: O << "b8x16"; break;
219  case WebAssembly::ExprType::B16x8: O << "b16x8"; break;
220  case WebAssembly::ExprType::B32x4: O << "b32x4"; break;
221  case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break;
222  }
223 }
224 
226  switch (Ty.SimpleTy) {
227  case MVT::i32:
228  return "i32";
229  case MVT::i64:
230  return "i64";
231  case MVT::f32:
232  return "f32";
233  case MVT::f64:
234  return "f64";
235  case MVT::v16i8:
236  case MVT::v8i16:
237  case MVT::v4i32:
238  case MVT::v4f32:
239  return "v128";
240  case MVT::ExceptRef:
241  return "except_ref";
242  default:
243  llvm_unreachable("unsupported type");
244  }
245 }
246 
248  switch (Type) {
249  case wasm::ValType::I32:
250  return "i32";
251  case wasm::ValType::I64:
252  return "i64";
253  case wasm::ValType::F32:
254  return "f32";
255  case wasm::ValType::F64:
256  return "f64";
258  return "except_ref";
259  }
260  llvm_unreachable("unsupported type");
261 }
32-bit floating-point immediates.
void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void push_back(const T &Elt)
Definition: SmallVector.h:212
bool isImm() const
Definition: MCInst.h:59
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1547
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
const char * TypeToString(MVT Ty)
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
This class prints an WebAssembly MCInst to wasm file syntax.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:160
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
bool isReg() const
Definition: MCInst.h:58
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
Basic block label in a branch construct.
const fltSemantics & getSemantics() const
Definition: APFloat.h:1155
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1493
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:947
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:207
SimpleValueType SimpleTy
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:65
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:79
const MCExpr * getExpr() const
Definition: MCInst.h:96
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
unsigned short NumOperands
Definition: MCInstrDesc.h:163
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
int64_t getImm() const
Definition: MCInst.h:76
bool isNegative() const
Determine sign of this APInt.
Definition: APInt.h:357
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:41
unsigned const MachineRegisterInfo * MRI
Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
Definition: MCInstrDesc.h:231
bool isNaN() const
Definition: APFloat.h:1145
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:36
bool isFPImm() const
Definition: MCInst.h:60
This file provides WebAssembly-specific target descriptions.
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
bool isExpr() const
Definition: MCInst.h:61
unsigned getNumOperands() const
Definition: MCInst.h:184
unsigned GetDefaultP2Align(unsigned Opcode)
Return the default p2align value for a load or store with the given opcode.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn&#39;t already there.
Definition: SmallSet.h:81
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, const MCSubtargetInfo &STI) override
Print the specified MCInst to the specified raw_ostream.
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:182
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:383
ExprType
This is used to indicate block signatures.
raw_ostream * CommentStream
A stream that comments can be emitted to if desired.
Definition: MCInstPrinter.h:46
std::string utostr(uint64_t X, bool isNeg=false)
Definition: StringExtras.h:193
Class for arbitrary precision integers.
Definition: APInt.h:69
64-bit floating-point immediates.
unsigned int convertToHexString(char *DST, unsigned int HexDigits, bool UpperCase, roundingMode RM) const
Definition: APFloat.h:1137
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:47
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:41
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:61
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
This file declares WebAssembly-specific per-machine-function information.
Generic base class for all target subtargets.
const MCInstrInfo & MII
Definition: MCInstPrinter.h:48
void printInstruction(const MCInst *MI, raw_ostream &O)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
bool bitwiseIsEqual(const APFloat &RHS) const
Definition: APFloat.h:1112
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:171
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
APInt bitcastToAPInt() const
Definition: APFloat.h:1094
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:67
unsigned getOpcode() const
Definition: MCInst.h:174
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Definition: APFloat.h:886
double getFPImm() const
Definition: MCInst.h:86
std::string utohexstr(uint64_t X, bool LowerCase=false)
Definition: StringExtras.h:95
static unsigned getWARegStackId(unsigned Reg)