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: {
71 if (
MI->getOperand(TableOperand).isExpr()) {
75 assert(
MI->getOperand(TableOperand).getImm() == 0);
78 if (
MI->getOpcode() == WebAssembly::CALL_INDIRECT)
90 if (
Desc.isVariadic()) {
91 if ((
Desc.getNumOperands() == 0 &&
MI->getNumOperands() > 0) ||
92 Desc.variadicOpsAreDefs())
94 unsigned Start =
Desc.getNumOperands();
95 unsigned NumVariadicDefs = 0;
96 if (
Desc.variadicOpsAreDefs()) {
98 NumVariadicDefs =
MI->getOperand(0).getImm();
101 bool NeedsComma =
Desc.getNumOperands() > 0 && !
Desc.variadicOpsAreDefs();
102 for (
auto I = Start, E =
MI->getNumOperands();
I < E; ++
I) {
103 if (
MI->getOpcode() == WebAssembly::CALL_INDIRECT &&
104 I - Start == NumVariadicDefs) {
119 auto PrintBranchAnnotation = [&](
const MCOperand &
Op,
122 if (!Printed.insert(
Depth).second)
124 if (
Depth >= ControlFlowStack.size()) {
127 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
129 " to label" +
utostr(Pair.first));
136 unsigned Opc =
MI->getOpcode();
141 case WebAssembly::LOOP:
142 case WebAssembly::LOOP_S:
144 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
true));
147 case WebAssembly::BLOCK:
148 case WebAssembly::BLOCK_S:
149 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
152 case WebAssembly::TRY:
153 case WebAssembly::TRY_S:
154 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter,
false));
155 TryStack.push_back(ControlFlowCounter++);
156 EHInstStack.push_back(TRY);
159 case WebAssembly::TRY_TABLE:
160 case WebAssembly::TRY_TABLE_S: {
164 unsigned NumCatches =
Op.getImm();
165 for (
unsigned I = 0;
I < NumCatches;
I++) {
166 int64_t CatchOpcode =
MI->getOperand(
OpIdx++).getImm();
170 PrintBranchAnnotation(
MI->getOperand(
OpIdx++), Printed);
172 ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++,
false));
176 case WebAssembly::END_LOOP:
177 case WebAssembly::END_LOOP_S:
178 if (ControlFlowStack.empty()) {
181 ControlFlowStack.pop_back();
185 case WebAssembly::END_BLOCK:
186 case WebAssembly::END_BLOCK_S:
187 case WebAssembly::END_TRY_TABLE:
188 case WebAssembly::END_TRY_TABLE_S:
189 if (ControlFlowStack.empty()) {
193 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
197 case WebAssembly::END_TRY:
198 case WebAssembly::END_TRY_S:
199 if (ControlFlowStack.empty() || EHInstStack.empty()) {
203 OS,
"label" +
utostr(ControlFlowStack.pop_back_val().first) +
':');
204 EHInstStack.pop_back();
208 case WebAssembly::CATCH_LEGACY:
209 case WebAssembly::CATCH_LEGACY_S:
210 case WebAssembly::CATCH_ALL_LEGACY:
211 case WebAssembly::CATCH_ALL_LEGACY_S:
214 if (EHInstStack.empty()) {
216 }
else if (EHInstStack.back() == CATCH_ALL_LEGACY) {
218 }
else if (EHInstStack.back() == TRY) {
219 if (TryStack.empty()) {
224 EHInstStack.pop_back();
225 if (
Opc == WebAssembly::CATCH_LEGACY ||
226 Opc == WebAssembly::CATCH_LEGACY_S) {
227 EHInstStack.push_back(CATCH_LEGACY);
229 EHInstStack.push_back(CATCH_ALL_LEGACY);
234 case WebAssembly::RETHROW:
235 case WebAssembly::RETHROW_S:
238 if (TryStack.empty()) {
245 case WebAssembly::DELEGATE:
246 case WebAssembly::DELEGATE_S:
247 if (ControlFlowStack.empty() || TryStack.empty() || EHInstStack.empty()) {
254 assert(ControlFlowStack.back().first == TryStack.back());
255 std::string Label =
"label/catch" +
256 utostr(ControlFlowStack.pop_back_val().first) +
259 EHInstStack.pop_back();
261 if (
Depth >= ControlFlowStack.size()) {
262 Label +=
"to caller";
264 const auto &Pair = ControlFlowStack.rbegin()[
Depth];
268 Label +=
"down to catch" +
utostr(Pair.first);
277 unsigned NumFixedOperands =
Desc.NumOperands;
279 for (
unsigned I = 0, E =
MI->getNumOperands();
I < E; ++
I) {
281 if (
I < NumFixedOperands) {
290 if (!
MI->getOperand(
I).isImm())
293 PrintBranchAnnotation(
MI->getOperand(
I), Printed);
303 APInt AI =
FP.bitcastToAPInt();
304 return std::string(AI.
isNegative() ?
"-" :
"") +
"nan:0x" +
307 : INT64_C(0x000fffffffffffff)),
312 static const size_t BufBytes = 128;
314 auto Written =
FP.convertToHexString(
318 assert(Written < BufBytes);
329 if (
int(WAReg.
id()) >= 0)
331 else if (OpNo >=
Desc.getNumDefs() && !IsVariadicDef)
338 if (OpNo <
MII.get(
MI->getOpcode()).getNumDefs() || IsVariadicDef)
340 }
else if (
Op.isImm()) {
342 }
else if (
Op.isSFPImm()) {
344 }
else if (
Op.isDFPImm()) {
347 assert(
Op.isExpr() &&
"unknown operand kind in printOperand");
353 auto &Sym =
static_cast<const MCSymbolWasm &
>(SRE->getSymbol());
356 MAI.printExpr(O, *
Op.getExpr());
365 for (
unsigned I = OpNo, E =
MI->getNumOperands();
I != E; ++
I) {
368 O <<
MI->getOperand(
I).getImm();
376 int64_t Imm =
MI->getOperand(OpNo).getImm();
379 O <<
":p2align=" << Imm;
385 int64_t Imm =
MI->getOperand(OpNo).getImm();
406 auto Imm =
static_cast<unsigned>(
Op.getImm());
411 auto *Sym =
static_cast<const MCSymbolWasm *
>(&Expr->getSymbol());
412 if (Sym->getSignature()) {
424 unsigned OpIdx = OpNo;
426 unsigned NumCatches =
Op.getImm();
438 O <<
Op.getImm() <<
" ";
442 for (
unsigned I = 0;
I < NumCatches;
I++) {
445 switch (
Op.getImm()) {
448 PrintTagOp(
MI->getOperand(
OpIdx++));
452 PrintTagOp(
MI->getOperand(
OpIdx++));
458 O <<
"catch_all_ref ";
461 O <<
MI->getOperand(
OpIdx++).getImm();
463 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 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...
StringRef - 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)
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.