32#define DEBUG_TYPE "asm-printer"
34#include "WebAssemblyGenAsmWriter.inc"
44 OS <<
"$" << Reg.id();
51 switch (
MI->getOpcode()) {
52 case WebAssembly::CALL_INDIRECT_S:
53 case WebAssembly::RET_CALL_INDIRECT_S: {
64 const unsigned TypeOperand = 0;
65 const unsigned TableOperand = 1;
66 if (
MI->getOperand(TableOperand).isExpr()) {
70 assert(
MI->getOperand(TableOperand).getImm() == 0);
83 if (
Desc.isVariadic()) {
84 if ((
Desc.getNumOperands() == 0 &&
MI->getNumOperands() > 0) ||
85 Desc.variadicOpsAreDefs())
87 unsigned Start =
Desc.getNumOperands();
88 unsigned NumVariadicDefs = 0;
89 if (
Desc.variadicOpsAreDefs()) {
91 NumVariadicDefs =
MI->getOperand(0).getImm();
94 bool NeedsComma =
Desc.getNumOperands() > 0 && !
Desc.variadicOpsAreDefs();
95 for (
auto I = Start, E =
MI->getNumOperands();
I < E; ++
I) {
96 if (
MI->getOpcode() == WebAssembly::CALL_INDIRECT &&
97 I - Start == NumVariadicDefs) {
112 auto PrintBranchAnnotation = [&](
const MCOperand &
Op,
115 if (!Printed.insert(
Depth).second)
117 if (
Depth >= ControlFlowStack.size()) {
120 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
122 " to label" +
utostr(Pair.first));
129 unsigned Opc =
MI->getOpcode();
134 case WebAssembly::LOOP:
135 case WebAssembly::LOOP_S:
137 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
true));
140 case WebAssembly::BLOCK:
141 case WebAssembly::BLOCK_S:
142 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
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);
152 case WebAssembly::TRY_TABLE:
153 case WebAssembly::TRY_TABLE_S: {
157 unsigned NumCatches =
Op.getImm();
158 for (
unsigned I = 0;
I < NumCatches;
I++) {
159 int64_t CatchOpcode =
MI->getOperand(
OpIdx++).getImm();
163 PrintBranchAnnotation(
MI->getOperand(
OpIdx++), Printed);
165 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
169 case WebAssembly::END_LOOP:
170 case WebAssembly::END_LOOP_S:
171 if (ControlFlowStack.empty()) {
174 ControlFlowStack.pop_back();
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()) {
186 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
190 case WebAssembly::END_TRY:
191 case WebAssembly::END_TRY_S:
192 if (ControlFlowStack.empty() || EHInstStack.empty()) {
196 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
197 EHInstStack.pop_back();
201 case WebAssembly::CATCH_LEGACY:
202 case WebAssembly::CATCH_LEGACY_S:
203 case WebAssembly::CATCH_ALL_LEGACY:
204 case WebAssembly::CATCH_ALL_LEGACY_S:
207 if (EHInstStack.empty()) {
209 }
else if (EHInstStack.back() == CATCH_ALL_LEGACY) {
211 }
else if (EHInstStack.back() == TRY) {
212 if (TryStack.empty()) {
217 EHInstStack.pop_back();
218 if (
Opc == WebAssembly::CATCH_LEGACY ||
219 Opc == WebAssembly::CATCH_LEGACY_S) {
220 EHInstStack.push_back(CATCH_LEGACY);
222 EHInstStack.push_back(CATCH_ALL_LEGACY);
227 case WebAssembly::RETHROW:
228 case WebAssembly::RETHROW_S:
231 if (TryStack.empty()) {
238 case WebAssembly::DELEGATE:
239 case WebAssembly::DELEGATE_S:
240 if (ControlFlowStack.empty() || TryStack.empty() || EHInstStack.empty()) {
247 assert(ControlFlowStack.back().first == TryStack.back());
248 std::string Label =
"label/catch" +
249 utostr(ControlFlowStack.pop_back_val().first) +
252 EHInstStack.pop_back();
254 if (
Depth >= ControlFlowStack.size()) {
255 Label +=
"to caller";
257 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
261 Label +=
"down to catch" +
utostr(Pair.first);
270 unsigned NumFixedOperands =
Desc.NumOperands;
272 for (
unsigned I = 0, E =
MI->getNumOperands();
I < E; ++
I) {
274 if (
I < NumFixedOperands) {
283 if (!
MI->getOperand(
I).isImm())
286 PrintBranchAnnotation(
MI->getOperand(
I), Printed);
296 APInt AI =
FP.bitcastToAPInt();
297 return std::string(AI.
isNegative() ?
"-" :
"") +
"nan:0x" +
300 : INT64_C(0x000fffffffffffff)),
305 static const size_t BufBytes = 128;
307 auto Written =
FP.convertToHexString(
311 assert(Written < BufBytes);
320 unsigned WAReg =
Op.getReg();
323 else if (OpNo >=
Desc.getNumDefs() && !IsVariadicDef)
330 if (OpNo <
MII.get(
MI->getOpcode()).getNumDefs() || IsVariadicDef)
332 }
else if (
Op.isImm()) {
334 }
else if (
Op.isSFPImm()) {
336 }
else if (
Op.isDFPImm()) {
339 assert(
Op.isExpr() &&
"unknown operand kind in printOperand");
345 auto &Sym =
static_cast<const MCSymbolWasm &
>(SRE->getSymbol());
348 MAI.printExpr(O, *
Op.getExpr());
356 for (
unsigned I = OpNo, E =
MI->getNumOperands();
I != E; ++
I) {
359 O <<
MI->getOperand(
I).getImm();
367 int64_t Imm =
MI->getOperand(OpNo).getImm();
370 O <<
":p2align=" << Imm;
378 auto Imm =
static_cast<unsigned>(
Op.getImm());
383 auto *Sym =
static_cast<const MCSymbolWasm *
>(&Expr->getSymbol());
384 if (Sym->getSignature()) {
395 unsigned OpIdx = OpNo;
397 unsigned NumCatches =
Op.getImm();
409 O <<
Op.getImm() <<
" ";
413 for (
unsigned I = 0;
I < NumCatches;
I++) {
416 switch (
Op.getImm()) {
419 PrintTagOp(
MI->getOperand(
OpIdx++));
423 PrintTagOp(
MI->getOperand(
OpIdx++));
429 O <<
"catch_all_ref ";
432 O <<
MI->getOperand(
OpIdx++).getImm();
434 if (
I < NumCatches - 1)
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 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.
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)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
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.
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool IsVariadicDef=false)
void printBrList(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printCatchList(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
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)
const char * anyTypeToString(unsigned Type)
unsigned getWARegStackId(unsigned Reg)
@ 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<X> - Return the argument parameter cast to the specified type.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE