LLVM: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
30using namespace llvm;
31
32#define DEBUG_TYPE "asm-printer"
33
34#include "WebAssemblyGenAsmWriter.inc"
35
40
43
44 OS << "$" << Reg.id();
45}
46
51 switch (MI->getOpcode()) {
52 case WebAssembly::CALL_INDIRECT_S:
53 case WebAssembly::RET_CALL_INDIRECT_S: {
54
55
56
57
58
59 OS << "\t";
61 OS << " ";
62
63 assert(MI->getNumOperands() == 2);
64 const unsigned TypeOperand = 0;
65 const unsigned TableOperand = 1;
66 if (MI->getOperand(TableOperand).isExpr()) {
68 OS << ", ";
69 } else {
70 assert(MI->getOperand(TableOperand).getImm() == 0);
71 }
73 break;
74 }
75 default:
76
78 break;
79 }
80
81
83 if (Desc.isVariadic()) {
84 if ((Desc.getNumOperands() == 0 && MI->getNumOperands() > 0) ||
85 Desc.variadicOpsAreDefs())
86 OS << "\t";
87 unsigned Start = Desc.getNumOperands();
88 unsigned NumVariadicDefs = 0;
89 if (Desc.variadicOpsAreDefs()) {
90
91 NumVariadicDefs = MI->getOperand(0).getImm();
92 Start = 1;
93 }
94 bool NeedsComma = Desc.getNumOperands() > 0 && .variadicOpsAreDefs();
95 for (auto I = Start, E = MI->getNumOperands(); I < E; ++I) {
96 if (MI->getOpcode() == WebAssembly::CALL_INDIRECT &&
97 I - Start == NumVariadicDefs) {
98
99 ++I;
100 continue;
101 }
102 if (NeedsComma)
103 OS << ", ";
105 NeedsComma = true;
106 }
107 }
108
109
111
112 auto PrintBranchAnnotation = [&](const MCOperand &Op,
115 if (!Printed.insert(Depth).second)
116 return;
117 if (Depth >= ControlFlowStack.size()) {
119 } else {
120 const auto &Pair = ControlFlowStack.rbegin()[Depth];
122 " to label" + utostr(Pair.first));
123 }
124 };
125
127
128
129 unsigned Opc = MI->getOpcode();
130 switch (Opc) {
131 default:
132 break;
133
134 case WebAssembly::LOOP:
135 case WebAssembly::LOOP_S:
137 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, true));
138 return;
139
140 case WebAssembly::BLOCK:
141 case WebAssembly::BLOCK_S:
142 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false));
143 return;
144
145 case WebAssembly::TRY:
146 case WebAssembly::TRY_S:
147 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter, false));
148 TryStack.push_back(ControlFlowCounter++);
149 EHInstStack.push_back(TRY);
150 return;
151
152 case WebAssembly::TRY_TABLE:
153 case WebAssembly::TRY_TABLE_S: {
155 unsigned OpIdx = 1;
157 unsigned NumCatches = Op.getImm();
158 for (unsigned I = 0; I < NumCatches; I++) {
159 int64_t CatchOpcode = MI->getOperand(OpIdx++).getImm();
162 OpIdx++;
163 PrintBranchAnnotation(MI->getOperand(OpIdx++), Printed);
164 }
165 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false));
166 return;
167 }
168
169 case WebAssembly::END_LOOP:
170 case WebAssembly::END_LOOP_S:
171 if (ControlFlowStack.empty()) {
173 } else {
174 ControlFlowStack.pop_back();
175 }
176 return;
177
178 case WebAssembly::END_BLOCK:
179 case WebAssembly::END_BLOCK_S:
180 case WebAssembly::END_TRY_TABLE:
181 case WebAssembly::END_TRY_TABLE_S:
182 if (ControlFlowStack.empty()) {
184 } else {
186 OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
187 }
188 return;
189
190 case WebAssembly::END_TRY:
191 case WebAssembly::END_TRY_S:
192 if (ControlFlowStack.empty() || EHInstStack.empty()) {
194 } else {
196 OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
197 EHInstStack.pop_back();
198 }
199 return;
200
201 case WebAssembly::CATCH_LEGACY:
202 case WebAssembly::CATCH_LEGACY_S:
203 case WebAssembly::CATCH_ALL_LEGACY:
204 case WebAssembly::CATCH_ALL_LEGACY_S:
205
206
207 if (EHInstStack.empty()) {
209 } else if (EHInstStack.back() == CATCH_ALL_LEGACY) {
210 printAnnotation(OS, "catch/catch_all cannot occur after catch_all");
211 } else if (EHInstStack.back() == TRY) {
212 if (TryStack.empty()) {
214 } else {
216 }
217 EHInstStack.pop_back();
218 if (Opc == WebAssembly::CATCH_LEGACY ||
219 Opc == WebAssembly::CATCH_LEGACY_S) {
220 EHInstStack.push_back(CATCH_LEGACY);
221 } else {
222 EHInstStack.push_back(CATCH_ALL_LEGACY);
223 }
224 }
225 return;
226
227 case WebAssembly::RETHROW:
228 case WebAssembly::RETHROW_S:
229
230
231 if (TryStack.empty()) {
233 } else {
235 }
236 return;
237
238 case WebAssembly::DELEGATE:
239 case WebAssembly::DELEGATE_S:
240 if (ControlFlowStack.empty() || TryStack.empty() || EHInstStack.empty()) {
242 } else {
243
244
245
246
247 assert(ControlFlowStack.back().first == TryStack.back());
248 std::string Label = "label/catch" +
249 utostr(ControlFlowStack.pop_back_val().first) +
250 ": ";
251 TryStack.pop_back();
252 EHInstStack.pop_back();
254 if (Depth >= ControlFlowStack.size()) {
255 Label += "to caller";
256 } else {
257 const auto &Pair = ControlFlowStack.rbegin()[Depth];
258 if (Pair.second)
260 else
261 Label += "down to catch" + utostr(Pair.first);
262 }
264 }
265 return;
266 }
267
268
269
270 unsigned NumFixedOperands = Desc.NumOperands;
272 for (unsigned I = 0, E = MI->getNumOperands(); I < E; ++I) {
273
274 if (I < NumFixedOperands) {
275
277 continue;
278 } else {
279
280
281
282
283 if (->getOperand(I).isImm())
284 continue;
285 }
286 PrintBranchAnnotation(MI->getOperand(I), Printed);
287 }
288 }
289}
290
292
294 .bitwiseIsEqual(
296 APInt AI = FP.bitcastToAPInt();
297 return std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
299 (AI.getBitWidth() == 32 ? INT64_C(0x007fffff)
300 : INT64_C(0x000fffffffffffff)),
301 true);
302 }
303
304
305 static const size_t BufBytes = 128;
306 char Buf[BufBytes];
307 auto Written = FP.convertToHexString(
309 (void)Written;
310 assert(Written != 0);
311 assert(Written < BufBytes);
312 return Buf;
313}
314
318 if (Op.isReg()) {
321 if (int(WAReg.id()) >= 0)
323 else if (OpNo >= Desc.getNumDefs() && !IsVariadicDef)
327 else
328 O << "$drop";
329
330 if (OpNo < MII.get(MI->getOpcode()).getNumDefs() || IsVariadicDef)
331 O << '=';
332 } else if (Op.isImm()) {
333 O << Op.getImm();
334 } else if (Op.isSFPImm()) {
336 } else if (Op.isDFPImm()) {
338 } else {
339 assert(Op.isExpr() && "unknown operand kind in printOperand");
340
341
342
345 auto &Sym = static_cast<const MCSymbolWasm &>(SRE->getSymbol());
347 } else {
348 MAI.printExpr(O, *Op.getExpr());
349 }
350 }
351}
352
355 O << "{";
356 for (unsigned I = OpNo, E = MI->getNumOperands(); I != E; ++I) {
357 if (I != OpNo)
358 O << ", ";
359 O << MI->getOperand(I).getImm();
360 }
361 O << "}";
362}
363
365 unsigned OpNo,
367 int64_t Imm = MI->getOperand(OpNo).getImm();
369 return;
370 O << ":p2align=" << Imm;
371}
372
374 unsigned OpNo,
377 if (Op.isImm()) {
378 auto Imm = static_cast<unsigned>(Op.getImm());
381 } else {
383 auto *Sym = static_cast<const MCSymbolWasm *>(&Expr->getSymbol());
384 if (Sym->getSignature()) {
386 } else {
387
388 O << "unknown_type";
389 }
390 }
391}
392
395 unsigned OpIdx = OpNo;
397 unsigned NumCatches = Op.getImm();
398
399 auto PrintTagOp = [&](const MCOperand &Op) {
401 const MCSymbol *TagSym = nullptr;
402 if (Op.isExpr()) {
405 O << TagSym->getName() << " ";
406 } else {
407
408
409 O << Op.getImm() << " ";
410 }
411 };
412
413 for (unsigned I = 0; I < NumCatches; I++) {
415 O << "(";
416 switch (Op.getImm()) {
418 O << "catch ";
419 PrintTagOp(MI->getOperand(OpIdx++));
420 break;
422 O << "catch_ref ";
423 PrintTagOp(MI->getOperand(OpIdx++));
424 break;
426 O << "catch_all ";
427 break;
429 O << "catch_all_ref ";
430 break;
431 }
432 O << MI->getOperand(OpIdx++).getImm();
433 O << ")";
434 if (I < NumCatches - 1)
435 O << " ";
436 }
437}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
MachineInstr unsigned OpIdx
This file defines the SmallSet class.
This class prints an WebAssembly MCInst to wasm file syntax.
This file contains the declaration of the WebAssemblyMCAsmInfo class.
This file provides WebAssembly-specific target descriptions.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
This class is intended to be used as a base class for asm properties and features specific to the tar...
raw_ostream * CommentStream
A stream that comments can be emitted to if desired.
const MCRegisterInfo & MRI
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri)
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
Instances of this class represent operands of the MCInst class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
StringRef getName() const
getName - Get the symbol name.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
StringRef - Represent a constant reference to a string, i.e.
void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
Definition WebAssemblyInstPrinter.cpp:373
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
Definition WebAssemblyInstPrinter.cpp:41
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
std::pair< const char *, uint64_t > getMnemonic(const MCInst &MI) const override
Returns a pair containing the mnemonic for MI and the number of bits left for further processing by p...
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &OS) override
Print the specified MCInst to the specified raw_ostream.
Definition WebAssemblyInstPrinter.cpp:47
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool IsVariadicDef=false)
Definition WebAssemblyInstPrinter.cpp:315
void printBrList(const MCInst *MI, unsigned OpNo, raw_ostream &O)
Definition WebAssemblyInstPrinter.cpp:353
void printCatchList(const MCInst *MI, unsigned OpNo, raw_ostream &O)
Definition WebAssemblyInstPrinter.cpp:393
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
Definition WebAssemblyInstPrinter.cpp:364
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
Definition WebAssemblyInstPrinter.cpp:36
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned GetDefaultP2Align(unsigned Opc)
static const unsigned UnusedReg
@ OPERAND_BASIC_BLOCK
Basic block label in a branch construct.
std::string signatureToString(const wasm::WasmSignature *Sig)
unsigned getWARegStackId(MCRegister Reg)
const char * anyTypeToString(unsigned Type)
@ WASM_OPCODE_CATCH_ALL_REF
This is an optimization pass for GlobalISel generic memory operations.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
std::string utostr(uint64_t X, bool isNeg=false)
DWARFExpression::Operation Op
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.