32#define DEBUG_TYPE "asm-printer"
34#include "WebAssemblyGenAsmWriter.inc"
44 OS <<
"$" << Reg.id();
51 unsigned TypeOperand = 0;
52 unsigned TableOperand = 1;
53 switch (
MI->getOpcode()) {
54 case WebAssembly::CALL_INDIRECT: {
55 unsigned NumDefs =
MI->getOperand(0).getImm();
56 TypeOperand = NumDefs + 1;
57 TableOperand = NumDefs + 2;
60 case WebAssembly::RET_CALL_INDIRECT:
61 case WebAssembly::CALL_INDIRECT_S:
62 case WebAssembly::RET_CALL_INDIRECT_S: {
73 const MCOperand &TableOp =
MI->getOperand(TableOperand);
79 if (
MI->getOpcode() == WebAssembly::CALL_INDIRECT)
91 if (
Desc.isVariadic()) {
92 if ((
Desc.getNumOperands() == 0 &&
MI->getNumOperands() > 0) ||
93 Desc.variadicOpsAreDefs())
95 unsigned Start =
Desc.getNumOperands();
96 unsigned NumVariadicDefs = 0;
97 if (
Desc.variadicOpsAreDefs()) {
99 NumVariadicDefs =
MI->getOperand(0).getImm();
102 bool NeedsComma =
Desc.getNumOperands() > 0 && !
Desc.variadicOpsAreDefs();
103 for (
auto I = Start, E =
MI->getNumOperands();
I < E; ++
I) {
104 if (
MI->getOpcode() == WebAssembly::CALL_INDIRECT &&
105 I - Start == NumVariadicDefs) {
120 auto PrintBranchAnnotation = [&](
const MCOperand &
Op,
123 if (!Printed.insert(
Depth).second)
125 if (
Depth >= ControlFlowStack.size()) {
128 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
130 " to label" +
utostr(Pair.first));
137 unsigned Opc =
MI->getOpcode();
142 case WebAssembly::LOOP:
143 case WebAssembly::LOOP_S:
145 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
true));
148 case WebAssembly::BLOCK:
149 case WebAssembly::BLOCK_S:
150 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
153 case WebAssembly::TRY:
154 case WebAssembly::TRY_S:
155 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter,
false));
156 TryStack.push_back(ControlFlowCounter++);
157 EHInstStack.push_back(TRY);
160 case WebAssembly::TRY_TABLE:
161 case WebAssembly::TRY_TABLE_S: {
165 unsigned NumCatches =
Op.getImm();
166 for (
unsigned I = 0;
I < NumCatches;
I++) {
167 int64_t CatchOpcode =
MI->getOperand(
OpIdx++).getImm();
171 PrintBranchAnnotation(
MI->getOperand(
OpIdx++), Printed);
173 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
177 case WebAssembly::SELECT_T:
178 case WebAssembly::SELECT_T_S:
183 case WebAssembly::END_LOOP:
184 case WebAssembly::END_LOOP_S:
185 if (ControlFlowStack.empty()) {
188 ControlFlowStack.pop_back();
192 case WebAssembly::END_BLOCK:
193 case WebAssembly::END_BLOCK_S:
194 case WebAssembly::END_TRY_TABLE:
195 case WebAssembly::END_TRY_TABLE_S:
196 if (ControlFlowStack.empty()) {
200 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
204 case WebAssembly::END_TRY:
205 case WebAssembly::END_TRY_S:
206 if (ControlFlowStack.empty() || EHInstStack.empty()) {
210 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
211 EHInstStack.pop_back();
215 case WebAssembly::CATCH_LEGACY:
216 case WebAssembly::CATCH_LEGACY_S:
217 case WebAssembly::CATCH_ALL_LEGACY:
218 case WebAssembly::CATCH_ALL_LEGACY_S:
221 if (EHInstStack.empty()) {
223 }
else if (EHInstStack.back() == CATCH_ALL_LEGACY) {
225 }
else if (EHInstStack.back() == TRY) {
226 if (TryStack.empty()) {
231 EHInstStack.pop_back();
232 if (
Opc == WebAssembly::CATCH_LEGACY ||
233 Opc == WebAssembly::CATCH_LEGACY_S) {
234 EHInstStack.push_back(CATCH_LEGACY);
236 EHInstStack.push_back(CATCH_ALL_LEGACY);
241 case WebAssembly::RETHROW:
242 case WebAssembly::RETHROW_S:
245 if (TryStack.empty()) {
252 case WebAssembly::DELEGATE:
253 case WebAssembly::DELEGATE_S:
254 if (ControlFlowStack.empty() || TryStack.empty() || EHInstStack.empty()) {
261 assert(ControlFlowStack.back().first == TryStack.back());
262 std::string Label =
"label/catch" +
263 utostr(ControlFlowStack.pop_back_val().first) +
266 EHInstStack.pop_back();
268 if (
Depth >= ControlFlowStack.size()) {
269 Label +=
"to caller";
271 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
275 Label +=
"down to catch" +
utostr(Pair.first);
284 unsigned NumFixedOperands =
Desc.NumOperands;
286 for (
unsigned I = 0, E =
MI->getNumOperands();
I < E; ++
I) {
288 if (
I < NumFixedOperands) {
297 if (!
MI->getOperand(
I).isImm())
300 PrintBranchAnnotation(
MI->getOperand(
I), Printed);
310 APInt AI =
FP.bitcastToAPInt();
311 return std::string(AI.
isNegative() ?
"-" :
"") +
"nan:0x" +
314 : INT64_C(0x000fffffffffffff)),
319 static const size_t BufBytes = 128;
321 auto Written =
FP.convertToHexString(
325 assert(Written < BufBytes);
336 if (
int(WAReg.
id()) >= 0)
338 else if (OpNo >=
Desc.getNumDefs() && !IsVariadicDef)
345 if (OpNo <
MII.get(
MI->getOpcode()).getNumDefs() || IsVariadicDef)
347 }
else if (
Op.isImm()) {
349 }
else if (
Op.isSFPImm()) {
351 }
else if (
Op.isDFPImm()) {
354 assert(
Op.isExpr() &&
"unknown operand kind in printOperand");
360 auto &Sym =
static_cast<const MCSymbolWasm &
>(SRE->getSymbol());
363 MAI.printExpr(O, *
Op.getExpr());
372 for (
unsigned I = OpNo, E =
MI->getNumOperands();
I != E; ++
I) {
375 O <<
MI->getOperand(
I).getImm();
383 int64_t Imm =
MI->getOperand(OpNo).getImm();
386 O <<
":p2align=" << Imm;
392 int64_t Imm =
MI->getOperand(OpNo).getImm();
413 auto Imm =
static_cast<unsigned>(
Op.getImm());
418 auto *Sym =
static_cast<const MCSymbolWasm *
>(&Expr->getSymbol());
419 if (Sym->getSignature()) {
431 unsigned OpIdx = OpNo;
433 unsigned NumCatches =
Op.getImm();
445 O <<
Op.getImm() <<
" ";
449 for (
unsigned I = 0;
I < NumCatches;
I++) {
452 switch (
Op.getImm()) {
455 PrintTagOp(
MI->getOperand(
OpIdx++));
459 PrintTagOp(
MI->getOperand(
OpIdx++));
465 O <<
"catch_all_ref ";
468 O <<
MI->getOperand(
OpIdx++).getImm();
470 if (
I < NumCatches - 1)
478 unsigned OpIdx = OpNo;
481 if (NumTypes > Remaining)
482 NumTypes = Remaining;
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.
const FeatureBitset & getFeatureBits() const
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...
Represent a constant reference to a string, i.e.
void printCatchList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O, bool IsVariadicDef=false)
void printWebAssemblyMemOrderOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, 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 printBrList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
void printInstruction(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O)
void printTypeList(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O)
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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
@ WASM_MEM_ORDER_RMW_ACQ_REL
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.