summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
-rw-r--r--llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp227
-rw-r--r--llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp3
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp7
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp36
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp40
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td8
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td10
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp409
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp77
9 files changed, 573 insertions, 244 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 0d591c04535..8e424f5d17b 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -34,29 +34,10 @@ using namespace llvm;
namespace {
-// We store register types as SimpleValueType to retain SIMD layout
-// information, but must also be able to supply them as the (unnamed)
-// register enum from WebAssemblyRegisterInfo.td/.inc.
-static unsigned MVTToWasmReg(MVT::SimpleValueType Type) {
- switch(Type) {
- case MVT::i32: return WebAssembly::I32_0;
- case MVT::i64: return WebAssembly::I64_0;
- case MVT::f32: return WebAssembly::F32_0;
- case MVT::f64: return WebAssembly::F64_0;
- case MVT::v16i8: return WebAssembly::V128_0;
- case MVT::v8i16: return WebAssembly::V128_0;
- case MVT::v4i32: return WebAssembly::V128_0;
- case MVT::v2i64: return WebAssembly::V128_0;
- case MVT::v4f32: return WebAssembly::V128_0;
- case MVT::v2f64: return WebAssembly::V128_0;
- default: return MVT::INVALID_SIMPLE_VALUE_TYPE;
- }
-}
-
/// WebAssemblyOperand - Instances of this class represent the operands in a
/// parsed WASM machine instruction.
struct WebAssemblyOperand : public MCParsedAsmOperand {
- enum KindTy { Token, Local, Stack, Integer, Float, Symbol } Kind;
+ enum KindTy { Token, Integer, Float, Symbol } Kind;
SMLoc StartLoc, EndLoc;
@@ -64,19 +45,6 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
StringRef Tok;
};
- struct RegOp {
- // This is a (virtual) local or stack register represented as 0..
- unsigned RegNo;
- // In most targets, the register number also encodes the type, but for
- // wasm we have to track that seperately since we have an unbounded
- // number of registers.
- // This has the unfortunate side effect that we supply a different value
- // to the table-gen matcher at different times in the process (when it
- // calls getReg() or addRegOperands().
- // TODO: While this works, it feels brittle. and would be nice to clean up.
- MVT::SimpleValueType Type;
- };
-
struct IntOp {
int64_t Val;
};
@@ -91,7 +59,6 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
union {
struct TokOp Tok;
- struct RegOp Reg;
struct IntOp Int;
struct FltOp Flt;
struct SymOp Sym;
@@ -99,8 +66,6 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
: Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
- WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, RegOp R)
- : Kind(K), StartLoc(Start), EndLoc(End), Reg(R) {}
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
: Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
@@ -112,14 +77,12 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
bool isImm() const override { return Kind == Integer ||
Kind == Float ||
Kind == Symbol; }
- bool isReg() const override { return Kind == Local || Kind == Stack; }
bool isMem() const override { return false; }
+ bool isReg() const override { return false; }
unsigned getReg() const override {
- assert(isReg());
- // This is called from the tablegen matcher (MatchInstructionImpl)
- // where it expects to match the type of register, see RegOp above.
- return MVTToWasmReg(Reg.Type);
+ llvm_unreachable("Assembly inspects a register operand");
+ return 0;
}
StringRef getToken() const {
@@ -130,19 +93,9 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
SMLoc getStartLoc() const override { return StartLoc; }
SMLoc getEndLoc() const override { return EndLoc; }
- void addRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- assert(isReg() && "Not a register operand!");
- // This is called from the tablegen matcher (MatchInstructionImpl)
- // where it expects to output the actual register index, see RegOp above.
- unsigned R = Reg.RegNo;
- if (Kind == Stack) {
- // A stack register is represented as a large negative number.
- // See WebAssemblyRegNumbering::runOnMachineFunction and
- // getWARegStackId for why this | is needed.
- R |= INT32_MIN;
- }
- Inst.addOperand(MCOperand::createReg(R));
+ void addRegOperands(MCInst &, unsigned) const {
+ // Required by the assembly matcher.
+ llvm_unreachable("Assembly matcher creates register operands");
}
void addImmOperands(MCInst &Inst, unsigned N) const {
@@ -162,12 +115,6 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
case Token:
OS << "Tok:" << Tok.Tok;
break;
- case Local:
- OS << "Loc:" << Reg.RegNo << ":" << static_cast<int>(Reg.Type);
- break;
- case Stack:
- OS << "Stk:" << Reg.RegNo << ":" << static_cast<int>(Reg.Type);
- break;
case Integer:
OS << "Int:" << Int.Val;
break;
@@ -184,11 +131,6 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
class WebAssemblyAsmParser final : public MCTargetAsmParser {
MCAsmParser &Parser;
MCAsmLexer &Lexer;
- // These are for the current function being parsed:
- // These are vectors since register assignments are so far non-sparse.
- // Replace by map if necessary.
- std::vector<MVT::SimpleValueType> LocalTypes;
- std::vector<MVT::SimpleValueType> StackTypes;
MCSymbol *LastLabel;
public:
@@ -245,68 +187,6 @@ public:
.Default(MVT::INVALID_SIMPLE_VALUE_TYPE);
}
- MVT::SimpleValueType &GetType(
- std::vector<MVT::SimpleValueType> &Types, size_t i) {
- Types.resize(std::max(i + 1, Types.size()), MVT::INVALID_SIMPLE_VALUE_TYPE);
- return Types[i];
- }
-
- bool ParseReg(OperandVector &Operands, StringRef TypePrefix) {
- if (Lexer.is(AsmToken::Integer)) {
- auto &Local = Lexer.getTok();
- // This is a reference to a local, turn it into a virtual register.
- auto LocalNo = static_cast<unsigned>(Local.getIntVal());
- Operands.push_back(make_unique<WebAssemblyOperand>(
- WebAssemblyOperand::Local, Local.getLoc(),
- Local.getEndLoc(),
- WebAssemblyOperand::RegOp{LocalNo,
- GetType(LocalTypes, LocalNo)}));
- Parser.Lex();
- } else if (Lexer.is(AsmToken::Identifier)) {
- auto &StackRegTok = Lexer.getTok();
- // These are push/pop/drop pseudo stack registers, which we turn
- // into virtual registers also. The stackify pass will later turn them
- // back into implicit stack references if possible.
- auto StackReg = StackRegTok.getString();
- auto StackOp = StackReg.take_while([](char c) { return isalpha(c); });
- auto Reg = StackReg.drop_front(StackOp.size());
- unsigned long long ParsedRegNo = 0;
- if (!Reg.empty() && getAsUnsignedInteger(Reg, 10, ParsedRegNo))
- return Error("Cannot parse stack register index: ", StackRegTok);
- unsigned RegNo = static_cast<unsigned>(ParsedRegNo);
- if (StackOp == "push") {
- // This defines a result, record register type.
- auto RegType = ParseRegType(TypePrefix);
- GetType(StackTypes, RegNo) = RegType;
- Operands.push_back(make_unique<WebAssemblyOperand>(
- WebAssemblyOperand::Stack,
- StackRegTok.getLoc(),
- StackRegTok.getEndLoc(),
- WebAssemblyOperand::RegOp{RegNo, RegType}));
- } else if (StackOp == "pop") {
- // This uses a previously defined stack value.
- auto RegType = GetType(StackTypes, RegNo);
- Operands.push_back(make_unique<WebAssemblyOperand>(
- WebAssemblyOperand::Stack,
- StackRegTok.getLoc(),
- StackRegTok.getEndLoc(),
- WebAssemblyOperand::RegOp{RegNo, RegType}));
- } else if (StackOp == "drop") {
- // This operand will be dropped, since it is part of an instruction
- // whose result is void.
- } else {
- return Error("Unknown stack register prefix: ", StackRegTok);
- }
- Parser.Lex();
- } else {
- return Error(
- "Expected identifier/integer following $, instead got: ",
- Lexer.getTok());
- }
- IsNext(AsmToken::Equal);
- return false;
- }
-
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
auto &Int = Lexer.getTok();
int64_t Val = Int.getIntVal();
@@ -319,36 +199,26 @@ public:
bool ParseOperandStartingWithInteger(bool IsNegative,
OperandVector &Operands,
- StringRef InstType) {
+ StringRef InstName) {
ParseSingleInteger(IsNegative, Operands);
- if (Lexer.is(AsmToken::LParen)) {
- // Parse load/store operands of the form: offset($reg)align
- auto &LParen = Lexer.getTok();
- Operands.push_back(
- make_unique<WebAssemblyOperand>(WebAssemblyOperand::Token,
- LParen.getLoc(),
- LParen.getEndLoc(),
- WebAssemblyOperand::TokOp{
- LParen.getString()}));
- Parser.Lex();
- if (Expect(AsmToken::Dollar, "register")) return true;
- if (ParseReg(Operands, InstType)) return true;
- auto &RParen = Lexer.getTok();
- Operands.push_back(
- make_unique<WebAssemblyOperand>(WebAssemblyOperand::Token,
- RParen.getLoc(),
- RParen.getEndLoc(),
- WebAssemblyOperand::TokOp{
- RParen.getString()}));
- if (Expect(AsmToken::RParen, ")")) return true;
- if (Lexer.is(AsmToken::Integer)) {
+ // FIXME: there is probably a cleaner way to do this.
+ auto IsLoadStore = InstName.startswith("load") ||
+ InstName.startswith("store") ||
+ InstName.startswith("atomic_load") ||
+ InstName.startswith("atomic_store");
+ if (IsLoadStore) {
+ // Parse load/store operands of the form: offset align
+ auto &Offset = Lexer.getTok();
+ if (Offset.is(AsmToken::Integer)) {
ParseSingleInteger(false, Operands);
} else {
// Alignment not specified.
// FIXME: correctly derive a default from the instruction.
+ // We can't just call WebAssembly::GetDefaultP2Align since we don't have
+ // an opcode until after the assembly matcher.
Operands.push_back(make_unique<WebAssemblyOperand>(
- WebAssemblyOperand::Integer, RParen.getLoc(),
- RParen.getEndLoc(), WebAssemblyOperand::IntOp{0}));
+ WebAssemblyOperand::Integer, Offset.getLoc(),
+ Offset.getEndLoc(), WebAssemblyOperand::IntOp{0}));
}
}
return false;
@@ -369,11 +239,6 @@ public:
while (Lexer.isNot(AsmToken::EndOfStatement)) {
auto &Tok = Lexer.getTok();
switch (Tok.getKind()) {
- case AsmToken::Dollar: {
- Parser.Lex();
- if (ParseReg(Operands, NamePair.first)) return true;
- break;
- }
case AsmToken::Identifier: {
auto &Id = Lexer.getTok();
const MCExpr *Val;
@@ -389,11 +254,11 @@ public:
Parser.Lex();
if (Lexer.isNot(AsmToken::Integer))
return Error("Expected integer instead got: ", Lexer.getTok());
- if (ParseOperandStartingWithInteger(true, Operands, NamePair.first))
+ if (ParseOperandStartingWithInteger(true, Operands, NamePair.second))
return true;
break;
case AsmToken::Integer:
- if (ParseOperandStartingWithInteger(false, Operands, NamePair.first))
+ if (ParseOperandStartingWithInteger(false, Operands, NamePair.second))
return true;
break;
case AsmToken::Real: {
@@ -414,35 +279,6 @@ public:
}
}
Parser.Lex();
- // Call instructions are vararg, but the tablegen matcher doesn't seem to
- // support that, so for now we strip these extra operands.
- // This is problematic if these arguments are not simple $pop stack
- // registers, since e.g. a local register would get lost, so we check for
- // this. This can be the case when using -disable-wasm-explicit-locals
- // which currently s2wasm requires.
- // TODO: Instead, we can move this code to MatchAndEmitInstruction below and
- // actually generate get_local instructions on the fly.
- // Or even better, improve the matcher to support vararg?
- auto IsIndirect = NamePair.second == "call_indirect";
- if (IsIndirect || NamePair.second == "call") {
- // Figure out number of fixed operands from the instruction.
- size_t CallOperands = 1; // The name token.
- if (!IsIndirect) CallOperands++; // The function index.
- if (!NamePair.first.empty()) CallOperands++; // The result register.
- if (Operands.size() > CallOperands) {
- // Ensure operands we drop are all $pop.
- for (size_t I = CallOperands; I < Operands.size(); I++) {
- auto Operand =
- reinterpret_cast<WebAssemblyOperand *>(Operands[I].get());
- if (Operand->Kind != WebAssemblyOperand::Stack)
- Parser.Error(NameLoc,
- "Call instruction has non-stack arguments, if this code was "
- "generated with -disable-wasm-explicit-locals please remove it");
- }
- // Drop unneeded operands.
- Operands.resize(CallOperands);
- }
- }
// Block instructions require a signature index, but these are missing in
// assembly, so we add a dummy one explicitly (since we have no control
// over signature tables here, we assume these will be regenerated when
@@ -452,17 +288,6 @@ public:
WebAssemblyOperand::Integer, NameLoc,
NameLoc, WebAssemblyOperand::IntOp{-1}));
}
- // These don't specify the type, which has to derived from the local index.
- if (NamePair.second == "get_local" || NamePair.second == "tee_local") {
- if (Operands.size() >= 3 && Operands[1]->isReg() &&
- Operands[2]->isImm()) {
- auto Op1 = reinterpret_cast<WebAssemblyOperand *>(Operands[1].get());
- auto Op2 = reinterpret_cast<WebAssemblyOperand *>(Operands[2].get());
- auto Type = GetType(LocalTypes, static_cast<size_t>(Op2->Int.Val));
- Op1->Reg.Type = Type;
- GetType(StackTypes, Op1->Reg.RegNo) = Type;
- }
- }
return false;
}
@@ -486,11 +311,6 @@ public:
IsNext(AsmToken::At) &&
Lexer.is(AsmToken::Identifier)))
return Error("Expected label,@type declaration, got: ", Lexer.getTok());
- if (Lexer.getTok().getString() == "function") {
- // Track locals from start of function.
- LocalTypes.clear();
- StackTypes.clear();
- }
Parser.Lex();
//Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
} else if (DirectiveID.getString() == ".param" ||
@@ -503,7 +323,6 @@ public:
while (Lexer.is(AsmToken::Identifier)) {
auto RegType = ParseRegType(Lexer.getTok().getString());
if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE) return true;
- LocalTypes.push_back(RegType);
if (DirectiveID.getString() == ".param") {
Params.push_back(RegType);
} else {
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
index 99c814612f7..b6a4bdd2957 100644
--- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
@@ -58,7 +58,8 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
// we have an extra flags operand which is not currently printed, for
// compatiblity reasons.
if (i != 0 &&
- (MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID ||
+ ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
+ MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
i != Desc.getNumOperands()))
OS << ", ";
printOperand(MI, i, OS);
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
index bff074d987c..3f24f93fe92 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -72,8 +72,11 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
}
// For br_table instructions, encode the size of the table. In the MCInst,
- // there's an index operand, one operand for each table entry, and the
- // default operand.
+ // there's an index operand (if not a stack instruction), one operand for
+ // each table entry, and the default operand.
+ if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
+ MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
+ encodeULEB128(MI.getNumOperands() - 1, OS);
if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
MI.getOpcode() == WebAssembly::BR_TABLE_I64)
encodeULEB128(MI.getNumOperands() - 2, OS);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 596264f0132..c6aa0a77fff 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -169,45 +169,62 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
case WebAssembly::ARGUMENT_I32:
+ case WebAssembly::ARGUMENT_I32_S:
case WebAssembly::ARGUMENT_I64:
+ case WebAssembly::ARGUMENT_I64_S:
case WebAssembly::ARGUMENT_F32:
+ case WebAssembly::ARGUMENT_F32_S:
case WebAssembly::ARGUMENT_F64:
+ case WebAssembly::ARGUMENT_F64_S:
case WebAssembly::ARGUMENT_v16i8:
+ case WebAssembly::ARGUMENT_v16i8_S:
case WebAssembly::ARGUMENT_v8i16:
+ case WebAssembly::ARGUMENT_v8i16_S:
case WebAssembly::ARGUMENT_v4i32:
+ case WebAssembly::ARGUMENT_v4i32_S:
case WebAssembly::ARGUMENT_v2i64:
+ case WebAssembly::ARGUMENT_v2i64_S:
case WebAssembly::ARGUMENT_v4f32:
+ case WebAssembly::ARGUMENT_v4f32_S:
case WebAssembly::ARGUMENT_v2f64:
+ case WebAssembly::ARGUMENT_v2f64_S:
// These represent values which are live into the function entry, so there's
// no instruction to emit.
break;
case WebAssembly::FALLTHROUGH_RETURN_I32:
+ case WebAssembly::FALLTHROUGH_RETURN_I32_S:
case WebAssembly::FALLTHROUGH_RETURN_I64:
+ case WebAssembly::FALLTHROUGH_RETURN_I64_S:
case WebAssembly::FALLTHROUGH_RETURN_F32:
+ case WebAssembly::FALLTHROUGH_RETURN_F32_S:
case WebAssembly::FALLTHROUGH_RETURN_F64:
+ case WebAssembly::FALLTHROUGH_RETURN_F64_S:
case WebAssembly::FALLTHROUGH_RETURN_v16i8:
+ case WebAssembly::FALLTHROUGH_RETURN_v16i8_S:
case WebAssembly::FALLTHROUGH_RETURN_v8i16:
+ case WebAssembly::FALLTHROUGH_RETURN_v8i16_S:
case WebAssembly::FALLTHROUGH_RETURN_v4i32:
+ case WebAssembly::FALLTHROUGH_RETURN_v4i32_S:
case WebAssembly::FALLTHROUGH_RETURN_v2i64:
+ case WebAssembly::FALLTHROUGH_RETURN_v2i64_S:
case WebAssembly::FALLTHROUGH_RETURN_v4f32:
- case WebAssembly::FALLTHROUGH_RETURN_v2f64: {
+ case WebAssembly::FALLTHROUGH_RETURN_v4f32_S:
+ case WebAssembly::FALLTHROUGH_RETURN_v2f64:
+ case WebAssembly::FALLTHROUGH_RETURN_v2f64_S: {
// These instructions represent the implicit return at the end of a
- // function body. The operand is always a pop.
- assert(MFI->isVRegStackified(MI->getOperand(0).getReg()));
-
+ // function body. Always pops one value off the stack.
if (isVerbose()) {
- OutStreamer->AddComment("fallthrough-return: $pop" +
- Twine(MFI->getWARegStackId(
- MFI->getWAReg(MI->getOperand(0).getReg()))));
+ OutStreamer->AddComment("fallthrough-return-value");
OutStreamer->AddBlankLine();
}
break;
}
case WebAssembly::FALLTHROUGH_RETURN_VOID:
+ case WebAssembly::FALLTHROUGH_RETURN_VOID_S:
// This instruction represents the implicit return at the end of a
// function body with no return value.
if (isVerbose()) {
- OutStreamer->AddComment("fallthrough-return");
+ OutStreamer->AddComment("fallthrough-return-void");
OutStreamer->AddBlankLine();
}
break;
@@ -248,6 +265,9 @@ bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
OS << MO.getImm();
return false;
case MachineOperand::MO_Register:
+ // FIXME: only opcode that still contains registers, as required by
+ // MachineInstr::getDebugVariable().
+ assert(MI->getOpcode() == WebAssembly::INLINEASM);
OS << regToString(MO);
return false;
case MachineOperand::MO_GlobalAddress:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index 8619cbdcb5e..c2fcb436f16 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -31,12 +31,14 @@ using namespace llvm;
#define DEBUG_TYPE "wasm-explicit-locals"
-// A command-line option to disable this pass. Note that this produces output
-// which is not valid WebAssembly, though it may be more convenient for writing
-// LLVM unit tests with.
-static cl::opt<bool> DisableWebAssemblyExplicitLocals(
- "disable-wasm-explicit-locals", cl::ReallyHidden,
- cl::desc("WebAssembly: Disable emission of get_local/set_local."),
+// A command-line option to disable this pass, and keep implicit locals
+// for the purpose of testing with lit/llc ONLY.
+// This produces output which is not valid WebAssembly, and is not supported
+// by assemblers/disassemblers and other MC based tools.
+static cl::opt<bool> WasmDisableExplicitLocals(
+ "wasm-disable-explicit-locals", cl::Hidden,
+ cl::desc("WebAssembly: output implicit locals in"
+ " instruction output for test purposes only."),
cl::init(false));
namespace {
@@ -162,7 +164,7 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) {
/// Given a MachineOperand of a stackified vreg, return the instruction at the
/// start of the expression tree.
-static MachineInstr *FindStartOfTree(MachineOperand &MO,
+static MachineInstr *findStartOfTree(MachineOperand &MO,
MachineRegisterInfo &MRI,
WebAssemblyFunctionInfo &MFI) {
unsigned Reg = MO.getReg();
@@ -173,7 +175,7 @@ static MachineInstr *FindStartOfTree(MachineOperand &MO,
for (MachineOperand &DefMO : Def->explicit_uses()) {
if (!DefMO.isReg())
continue;
- return FindStartOfTree(DefMO, MRI, MFI);
+ return findStartOfTree(DefMO, MRI, MFI);
}
// If there were no stackified uses, we've reached the start.
@@ -186,7 +188,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
<< MF.getName() << '\n');
// Disable this pass if directed to do so.
- if (DisableWebAssemblyExplicitLocals)
+ if (WasmDisableExplicitLocals)
return false;
bool Changed = false;
@@ -206,19 +208,19 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
break;
unsigned Reg = MI.getOperand(0).getReg();
assert(!MFI.isVRegStackified(Reg));
- Reg2Local[Reg] = MI.getOperand(1).getImm();
+ Reg2Local[Reg] = static_cast<unsigned>(MI.getOperand(1).getImm());
MI.eraseFromParent();
Changed = true;
}
// Start assigning local numbers after the last parameter.
- unsigned CurLocal = MFI.getParams().size();
+ unsigned CurLocal = static_cast<unsigned>(MFI.getParams().size());
// Precompute the set of registers that are unused, so that we can insert
// drops to their defs.
BitVector UseEmpty(MRI.getNumVirtRegs());
- for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i)
- UseEmpty[i] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(i));
+ for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I)
+ UseEmpty[I] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(I));
// Visit each instruction in the function.
for (MachineBasicBlock &MBB : MF) {
@@ -322,7 +324,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
// If we see a stackified register, prepare to insert subsequent
// get_locals before the start of its tree.
if (MFI.isVRegStackified(OldReg)) {
- InsertPt = FindStartOfTree(MO, MRI, MFI);
+ InsertPt = findStartOfTree(MO, MRI, MFI);
continue;
}
@@ -361,13 +363,13 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
// Define the locals.
// TODO: Sort the locals for better compression.
MFI.setNumLocals(CurLocal - MFI.getParams().size());
- for (size_t i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
- unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
- auto I = Reg2Local.find(Reg);
- if (I == Reg2Local.end() || I->second < MFI.getParams().size())
+ for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
+ unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
+ auto RL = Reg2Local.find(Reg);
+ if (RL == Reg2Local.end() || RL->second < MFI.getParams().size())
continue;
- MFI.setLocal(I->second - MFI.getParams().size(),
+ MFI.setLocal(RL->second - MFI.getParams().size(),
typeForRegClass(MRI.getRegClass(Reg)));
Changed = true;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
index a8fce89f203..d0d164fd381 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
@@ -53,9 +53,9 @@ def BR_TABLE_I32 : NI<(outs), (ins I32:$index, variable_ops),
let TSFlags{0} = 1;
let TSFlags{1} = 1;
}
-def BR_TABLE_I32_S : NI<(outs), (ins I32:$index),
+def BR_TABLE_I32_S : NI<(outs), (ins variable_ops),
[], 1,
- "br_table \t$index", 0x0e> {
+ "br_table", 0x0e> {
let TSFlags{0} = 1;
let TSFlags{1} = 1;
}
@@ -65,9 +65,9 @@ def BR_TABLE_I64 : NI<(outs), (ins I64:$index, variable_ops),
let TSFlags{0} = 1;
let TSFlags{1} = 1;
}
-def BR_TABLE_I64_S : NI<(outs), (ins I64:$index),
+def BR_TABLE_I64_S : NI<(outs), (ins variable_ops),
[], 1,
- "br_table \t$index"> {
+ "br_table"> {
let TSFlags{0} = 1;
let TSFlags{1} = 1;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
index fd574640a1a..76ef1461d22 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
@@ -57,11 +57,12 @@ let Defs = [ARGUMENTS] in {
// Defines atomic and non-atomic loads, regular and extending.
multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> {
+ let mayLoad = 1 in
defm "": I<(outs rc:$dst),
(ins P2Align:$p2align, offset32_op:$off, I32:$addr),
(outs), (ins P2Align:$p2align, offset32_op:$off),
[], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
- !strconcat(Name, "\t${off}, ${p2align}"), Opcode>;
+ !strconcat(Name, "\t${off}${p2align}"), Opcode>;
}
// Basic load.
@@ -307,12 +308,13 @@ let Defs = [ARGUMENTS] in {
// Defines atomic and non-atomic stores, regular and truncating
multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> {
+ let mayStore = 1 in
defm "" : I<(outs),
(ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
(outs),
(ins P2Align:$p2align, offset32_op:$off), [],
!strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
- !strconcat(Name, "\t${off}, ${p2align}"), Opcode>;
+ !strconcat(Name, "\t${off}${p2align}"), Opcode>;
}
// Basic store.
// Note: WebAssembly inverts SelectionDAG's usual operand order.
@@ -470,12 +472,12 @@ defm CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
// Grow memory.
defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
- (outs), (ins i32imm:$flags, I32:$delta),
+ (outs), (ins i32imm:$flags),
[(set I32:$dst,
(int_wasm_memory_grow (i32 imm:$flags),
I32:$delta))],
"memory.grow\t$dst, $flags, $delta",
- "memory.grow\t$flags, $delta", 0x40>,
+ "memory.grow\t$flags", 0x40>,
Requires<[HasAddr32]>;
defm MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
(outs), (ins i32imm:$flags),
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index 5a9e3c67176..54bb6805603 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -30,6 +30,17 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+// This disables the removal of registers when lowering into MC, as required
+// by some current tests.
+static cl::opt<bool> WasmKeepRegisters(
+ "wasm-keep-registers", cl::Hidden,
+ cl::desc("WebAssembly: output stack registers in"
+ " instruction output for test purposes only."),
+ cl::init(false));
+
+static unsigned regInstructionToStackInstruction(unsigned OpCode);
+static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
+
MCSymbol *
WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
const GlobalValue *Global = MO.getGlobal();
@@ -235,4 +246,402 @@ void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
OutMI.addOperand(MCOp);
}
+
+ if (!WasmKeepRegisters)
+ removeRegisterOperands(MI, OutMI);
+}
+
+static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) {
+ // Remove all uses of stackified registers to bring the instruction format
+ // into its final stack form used thruout MC, and transition opcodes to
+ // their _S variant.
+ // We do this seperate from the above code that still may need these
+ // registers for e.g. call_indirect signatures.
+ // See comments in lib/Target/WebAssembly/WebAssemblyInstrFormats.td for
+ // details.
+ // TODO: the code above creates new registers which are then removed here.
+ // That code could be slightly simplified by not doing that, though maybe
+ // it is simpler conceptually to keep the code above in "register mode"
+ // until this transition point.
+ // FIXME: we are not processing inline assembly, which contains register
+ // operands, because it is used by later target generic code.
+ if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm())
+ return;
+
+ // Transform to _S instruction.
+ auto RegOpcode = OutMI.getOpcode();
+ auto StackOpcode = regInstructionToStackInstruction(RegOpcode);
+ OutMI.setOpcode(StackOpcode);
+
+ // Remove register operands.
+ for (auto I = OutMI.getNumOperands(); I; --I) {
+ auto &MO = OutMI.getOperand(I - 1);
+ if (MO.isReg()) {
+ OutMI.erase(&MO);
+ }
+ }
+}
+
+static unsigned regInstructionToStackInstruction(unsigned OpCode) {
+ switch (OpCode) {
+ default:
+ // You may hit this if you add new instructions, please add them below.
+ // For most of these opcodes, this function could have been implemented
+ // as "return OpCode + 1", but since table-gen alphabetically sorts them,
+ // this cannot be guaranteed (see e.g. BR and BR_IF).
+ // The approach below is the same as what the x87 backend does.
+ // TODO(wvo): to make this code cleaner, create a custom tablegen
+ // code generator that emits the table below automatically.
+ llvm_unreachable(
+ "unknown WebAssembly instruction in Explicit Locals pass");
+ case WebAssembly::ABS_F32: return WebAssembly::ABS_F32_S;
+ case WebAssembly::ABS_F64: return WebAssembly::ABS_F64_S;
+ case WebAssembly::ADD_F32: return WebAssembly::ADD_F32_S;
+ case WebAssembly::ADD_F64: return WebAssembly::ADD_F64_S;
+ case WebAssembly::ADD_I32: return WebAssembly::ADD_I32_S;
+ case WebAssembly::ADD_I64: return WebAssembly::ADD_I64_S;
+ case WebAssembly::ADD_v16i8: return WebAssembly::ADD_v16i8_S;
+ case WebAssembly::ADD_v2f64: return WebAssembly::ADD_v2f64_S;
+ case WebAssembly::ADD_v2i64: return WebAssembly::ADD_v2i64_S;
+ case WebAssembly::ADD_v4f32: return WebAssembly::ADD_v4f32_S;
+ case WebAssembly::ADD_v4i32: return WebAssembly::ADD_v4i32_S;
+ case WebAssembly::ADD_v8i16: return WebAssembly::ADD_v8i16_S;
+ case WebAssembly::ADJCALLSTACKDOWN: return WebAssembly::ADJCALLSTACKDOWN_S;
+ case WebAssembly::ADJCALLSTACKUP: return WebAssembly::ADJCALLSTACKUP_S;
+ case WebAssembly::AND_I32: return WebAssembly::AND_I32_S;
+ case WebAssembly::AND_I64: return WebAssembly::AND_I64_S;
+ case WebAssembly::ARGUMENT_EXCEPT_REF: return WebAssembly::ARGUMENT_EXCEPT_REF_S;
+ case WebAssembly::ARGUMENT_F32: return WebAssembly::ARGUMENT_F32_S;
+ case WebAssembly::ARGUMENT_F64: return WebAssembly::ARGUMENT_F64_S;
+ case WebAssembly::ARGUMENT_I32: return WebAssembly::ARGUMENT_I32_S;
+ case WebAssembly::ARGUMENT_I64: return WebAssembly::ARGUMENT_I64_S;
+ case WebAssembly::ARGUMENT_v16i8: return WebAssembly::ARGUMENT_v16i8_S;
+ case WebAssembly::ARGUMENT_v4f32: return WebAssembly::ARGUMENT_v4f32_S;
+ case WebAssembly::ARGUMENT_v4i32: return WebAssembly::ARGUMENT_v4i32_S;
+ case WebAssembly::ARGUMENT_v8i16: return WebAssembly::ARGUMENT_v8i16_S;
+ case WebAssembly::ARGUMENT_v2f64: return WebAssembly::ARGUMENT_v2f64_S;
+ case WebAssembly::ARGUMENT_v2i64: return WebAssembly::ARGUMENT_v2i64_S;
+ case WebAssembly::ATOMIC_LOAD16_U_I32: return WebAssembly::ATOMIC_LOAD16_U_I32_S;
+ case WebAssembly::ATOMIC_LOAD16_U_I64: return WebAssembly::ATOMIC_LOAD16_U_I64_S;
+ case WebAssembly::ATOMIC_LOAD32_U_I64: return WebAssembly::ATOMIC_LOAD32_U_I64_S;
+ case WebAssembly::ATOMIC_LOAD8_U_I32: return WebAssembly::ATOMIC_LOAD8_U_I32_S;
+ case WebAssembly::ATOMIC_LOAD8_U_I64: return WebAssembly::ATOMIC_LOAD8_U_I64_S;
+ case WebAssembly::ATOMIC_LOAD_I32: return WebAssembly::ATOMIC_LOAD_I32_S;
+ case WebAssembly::ATOMIC_LOAD_I64: return WebAssembly::ATOMIC_LOAD_I64_S;
+ case WebAssembly::ATOMIC_STORE16_I32: return WebAssembly::ATOMIC_STORE16_I32_S;
+ case WebAssembly::ATOMIC_STORE16_I64: return WebAssembly::ATOMIC_STORE16_I64_S;
+ case WebAssembly::ATOMIC_STORE32_I64: return WebAssembly::ATOMIC_STORE32_I64_S;
+ case WebAssembly::ATOMIC_STORE8_I32: return WebAssembly::ATOMIC_STORE8_I32_S;
+ case WebAssembly::ATOMIC_STORE8_I64: return WebAssembly::ATOMIC_STORE8_I64_S;
+ case WebAssembly::ATOMIC_STORE_I32: return WebAssembly::ATOMIC_STORE_I32_S;
+ case WebAssembly::ATOMIC_STORE_I64: return WebAssembly::ATOMIC_STORE_I64_S;
+ case WebAssembly::BLOCK: return WebAssembly::BLOCK_S;
+ case WebAssembly::BR: return WebAssembly::BR_S;
+ case WebAssembly::BR_IF: return WebAssembly::BR_IF_S;
+ case WebAssembly::BR_TABLE_I32: return WebAssembly::BR_TABLE_I32_S;
+ case WebAssembly::BR_TABLE_I64: return WebAssembly::BR_TABLE_I64_S;
+ case WebAssembly::BR_UNLESS: return WebAssembly::BR_UNLESS_S;
+ case WebAssembly::CALL_EXCEPT_REF: return WebAssembly::CALL_EXCEPT_REF_S;
+ case WebAssembly::CALL_F32: return WebAssembly::CALL_F32_S;
+ case WebAssembly::CALL_F64: return WebAssembly::CALL_F64_S;
+ case WebAssembly::CALL_I32: return WebAssembly::CALL_I32_S;
+ case WebAssembly::CALL_I64: return WebAssembly::CALL_I64_S;
+ case WebAssembly::CALL_INDIRECT_EXCEPT_REF: return WebAssembly::CALL_INDIRECT_EXCEPT_REF_S;
+ case WebAssembly::CALL_INDIRECT_F32: return WebAssembly::CALL_INDIRECT_F32_S;
+ case WebAssembly::CALL_INDIRECT_F64: return WebAssembly::CALL_INDIRECT_F64_S;
+ case WebAssembly::CALL_INDIRECT_I32: return WebAssembly::CALL_INDIRECT_I32_S;
+ case WebAssembly::CALL_INDIRECT_I64: return WebAssembly::CALL_INDIRECT_I64_S;
+ case WebAssembly::CALL_INDIRECT_VOID: return WebAssembly::CALL_INDIRECT_VOID_S;
+ case WebAssembly::CALL_INDIRECT_v16i8: return WebAssembly::CALL_INDIRECT_v16i8_S;
+ case WebAssembly::CALL_INDIRECT_v4f32: return WebAssembly::CALL_INDIRECT_v4f32_S;
+ case WebAssembly::CALL_INDIRECT_v4i32: return WebAssembly::CALL_INDIRECT_v4i32_S;
+ case WebAssembly::CALL_INDIRECT_v8i16: return WebAssembly::CALL_INDIRECT_v8i16_S;
+ case WebAssembly::CALL_VOID: return WebAssembly::CALL_VOID_S;
+ case WebAssembly::CALL_v16i8: return WebAssembly::CALL_v16i8_S;
+ case WebAssembly::CALL_v4f32: return WebAssembly::CALL_v4f32_S;
+ case WebAssembly::CALL_v4i32: return WebAssembly::CALL_v4i32_S;
+ case WebAssembly::CALL_v8i16: return WebAssembly::CALL_v8i16_S;
+ case WebAssembly::CATCHRET: return WebAssembly::CATCHRET_S;
+ case WebAssembly::CATCH_ALL: return WebAssembly::CATCH_ALL_S;
+ case WebAssembly::CATCH_I32: return WebAssembly::CATCH_I32_S;
+ case WebAssembly::CATCH_I64: return WebAssembly::CATCH_I64_S;
+ case WebAssembly::CEIL_F32: return WebAssembly::CEIL_F32_S;
+ case WebAssembly::CEIL_F64: return WebAssembly::CEIL_F64_S;
+ case WebAssembly::CLEANUPRET: return WebAssembly::CLEANUPRET_S;
+ case WebAssembly::CLZ_I32: return WebAssembly::CLZ_I32_S;
+ case WebAssembly::CLZ_I64: return WebAssembly::CLZ_I64_S;
+ case WebAssembly::CONST_F32: return WebAssembly::CONST_F32_S;
+ case WebAssembly::CONST_F64: return WebAssembly::CONST_F64_S;
+ case WebAssembly::CONST_I32: return WebAssembly::CONST_I32_S;
+ case WebAssembly::CONST_I64: return WebAssembly::CONST_I64_S;
+ case WebAssembly::COPYSIGN_F32: return WebAssembly::COPYSIGN_F32_S;
+ case WebAssembly::COPYSIGN_F64: return WebAssembly::COPYSIGN_F64_S;
+ case WebAssembly::COPY_EXCEPT_REF: return WebAssembly::COPY_EXCEPT_REF_S;
+ case WebAssembly::COPY_F32: return WebAssembly::COPY_F32_S;
+ case WebAssembly::COPY_F64: return WebAssembly::COPY_F64_S;
+ case WebAssembly::COPY_I32: return WebAssembly::COPY_I32_S;
+ case WebAssembly::COPY_I64: return WebAssembly::COPY_I64_S;
+ case WebAssembly::COPY_V128: return WebAssembly::COPY_V128_S;
+ case WebAssembly::CTZ_I32: return WebAssembly::CTZ_I32_S;
+ case WebAssembly::CTZ_I64: return WebAssembly::CTZ_I64_S;
+ case WebAssembly::CURRENT_MEMORY_I32: return WebAssembly::CURRENT_MEMORY_I32_S;
+ case WebAssembly::DIV_F32: return WebAssembly::DIV_F32_S;
+ case WebAssembly::DIV_F64: return WebAssembly::DIV_F64_S;
+ case WebAssembly::DIV_S_I32: return WebAssembly::DIV_S_I32_S;
+ case WebAssembly::DIV_S_I64: return WebAssembly::DIV_S_I64_S;
+ case WebAssembly::DIV_U_I32: return WebAssembly::DIV_U_I32_S;
+ case WebAssembly::DIV_U_I64: return WebAssembly::DIV_U_I64_S;
+ case WebAssembly::DROP_EXCEPT_REF: return WebAssembly::DROP_EXCEPT_REF_S;
+ case WebAssembly::DROP_F32: return WebAssembly::DROP_F32_S;
+ case WebAssembly::DROP_F64: return WebAssembly::DROP_F64_S;
+ case WebAssembly::DROP_I32: return WebAssembly::DROP_I32_S;
+ case WebAssembly::DROP_I64: return WebAssembly::DROP_I64_S;
+ case WebAssembly::DROP_V128: return WebAssembly::DROP_V128_S;
+ case WebAssembly::END_BLOCK: return WebAssembly::END_BLOCK_S;
+ case WebAssembly::END_FUNCTION: return WebAssembly::END_FUNCTION_S;
+ case WebAssembly::END_LOOP: return WebAssembly::END_LOOP_S;
+ case WebAssembly::END_TRY: return WebAssembly::END_TRY_S;
+ case WebAssembly::EQZ_I32: return WebAssembly::EQZ_I32_S;
+ case WebAssembly::EQZ_I64: return WebAssembly::EQZ_I64_S;
+ case WebAssembly::EQ_F32: return WebAssembly::EQ_F32_S;
+ case WebAssembly::EQ_F64: return WebAssembly::EQ_F64_S;
+ case WebAssembly::EQ_I32: return WebAssembly::EQ_I32_S;
+ case WebAssembly::EQ_I64: return WebAssembly::EQ_I64_S;
+ case WebAssembly::F32_CONVERT_S_I32: return WebAssembly::F32_CONVERT_S_I32_S;
+ case WebAssembly::F32_CONVERT_S_I64: return WebAssembly::F32_CONVERT_S_I64_S;
+ case WebAssembly::F32_CONVERT_U_I32: return WebAssembly::F32_CONVERT_U_I32_S;
+ case WebAssembly::F32_CONVERT_U_I64: return WebAssembly::F32_CONVERT_U_I64_S;
+ case WebAssembly::F32_DEMOTE_F64: return WebAssembly::F32_DEMOTE_F64_S;
+ case WebAssembly::F32_REINTERPRET_I32: return WebAssembly::F32_REINTERPRET_I32_S;
+ case WebAssembly::F64_CONVERT_S_I32: return WebAssembly::F64_CONVERT_S_I32_S;
+ case WebAssembly::F64_CONVERT_S_I64: return WebAssembly::F64_CONVERT_S_I64_S;
+ case WebAssembly::F64_CONVERT_U_I32: return WebAssembly::F64_CONVERT_U_I32_S;
+ case WebAssembly::F64_CONVERT_U_I64: return WebAssembly::F64_CONVERT_U_I64_S;
+ case WebAssembly::F64_PROMOTE_F32: return WebAssembly::F64_PROMOTE_F32_S;
+ case WebAssembly::F64_REINTERPRET_I64: return WebAssembly::F64_REINTERPRET_I64_S;
+ case WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF: return WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF_S;
+ case WebAssembly::FALLTHROUGH_RETURN_F32: return WebAssembly::FALLTHROUGH_RETURN_F32_S;
+ case WebAssembly::FALLTHROUGH_RETURN_F64: return WebAssembly::FALLTHROUGH_RETURN_F64_S;
+ case WebAssembly::FALLTHROUGH_RETURN_I32: return WebAssembly::FALLTHROUGH_RETURN_I32_S;
+ case WebAssembly::FALLTHROUGH_RETURN_I64: return WebAssembly::FALLTHROUGH_RETURN_I64_S;
+ case WebAssembly::FALLTHROUGH_RETURN_VOID: return WebAssembly::FALLTHROUGH_RETURN_VOID_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v16i8: return WebAssembly::FALLTHROUGH_RETURN_v16i8_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v4f32: return WebAssembly::FALLTHROUGH_RETURN_v4f32_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v4i32: return WebAssembly::FALLTHROUGH_RETURN_v4i32_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v8i16: return WebAssembly::FALLTHROUGH_RETURN_v8i16_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v2f64: return WebAssembly::FALLTHROUGH_RETURN_v2f64_S;
+ case WebAssembly::FALLTHROUGH_RETURN_v2i64: return WebAssembly::FALLTHROUGH_RETURN_v2i64_S;
+ case WebAssembly::FLOOR_F32: return WebAssembly::FLOOR_F32_S;
+ case WebAssembly::FLOOR_F64: return WebAssembly::FLOOR_F64_S;
+ case WebAssembly::FP_TO_SINT_I32_F32: return WebAssembly::FP_TO_SINT_I32_F32_S;
+ case WebAssembly::FP_TO_SINT_I32_F64: return WebAssembly::FP_TO_SINT_I32_F64_S;
+ case WebAssembly::FP_TO_SINT_I64_F32: return WebAssembly::FP_TO_SINT_I64_F32_S;
+ case WebAssembly::FP_TO_SINT_I64_F64: return WebAssembly::FP_TO_SINT_I64_F64_S;
+ case WebAssembly::FP_TO_UINT_I32_F32: return WebAssembly::FP_TO_UINT_I32_F32_S;
+ case WebAssembly::FP_TO_UINT_I32_F64: return WebAssembly::FP_TO_UINT_I32_F64_S;
+ case WebAssembly::FP_TO_UINT_I64_F32: return WebAssembly::FP_TO_UINT_I64_F32_S;
+ case WebAssembly::FP_TO_UINT_I64_F64: return WebAssembly::FP_TO_UINT_I64_F64_S;
+ case WebAssembly::GET_GLOBAL_EXCEPT_REF: return WebAssembly::GET_GLOBAL_EXCEPT_REF_S;
+ case WebAssembly::GET_GLOBAL_F32: return WebAssembly::GET_GLOBAL_F32_S;
+ case WebAssembly::GET_GLOBAL_F64: return WebAssembly::GET_GLOBAL_F64_S;
+ case WebAssembly::GET_GLOBAL_I32: return WebAssembly::GET_GLOBAL_I32_S;
+ case WebAssembly::GET_GLOBAL_I64: return WebAssembly::GET_GLOBAL_I64_S;
+ case WebAssembly::GET_GLOBAL_V128: return WebAssembly::GET_GLOBAL_V128_S;
+ case WebAssembly::GET_LOCAL_EXCEPT_REF: return WebAssembly::GET_LOCAL_EXCEPT_REF_S;
+ case WebAssembly::GET_LOCAL_F32: return WebAssembly::GET_LOCAL_F32_S;
+ case WebAssembly::GET_LOCAL_F64: return WebAssembly::GET_LOCAL_F64_S;
+ case WebAssembly::GET_LOCAL_I32: return WebAssembly::GET_LOCAL_I32_S;
+ case WebAssembly::GET_LOCAL_I64: return WebAssembly::GET_LOCAL_I64_S;
+ case WebAssembly::GET_LOCAL_V128: return WebAssembly::GET_LOCAL_V128_S;
+ case WebAssembly::GE_F32: return WebAssembly::GE_F32_S;
+ case WebAssembly::GE_F64: return WebAssembly::GE_F64_S;
+ case WebAssembly::GE_S_I32: return WebAssembly::GE_S_I32_S;
+ case WebAssembly::GE_S_I64: return WebAssembly::GE_S_I64_S;
+ case WebAssembly::GE_U_I32: return WebAssembly::GE_U_I32_S;
+ case WebAssembly::GE_U_I64: return WebAssembly::GE_U_I64_S;
+ case WebAssembly::GROW_MEMORY_I32: return WebAssembly::GROW_MEMORY_I32_S;
+ case WebAssembly::GT_F32: return WebAssembly::GT_F32_S;
+ case WebAssembly::GT_F64: return WebAssembly::GT_F64_S;
+ case WebAssembly::GT_S_I32: return WebAssembly::GT_S_I32_S;
+ case WebAssembly::GT_S_I64: return WebAssembly::GT_S_I64_S;
+ case WebAssembly::GT_U_I32: return WebAssembly::GT_U_I32_S;
+ case WebAssembly::GT_U_I64: return WebAssembly::GT_U_I64_S;
+ case WebAssembly::I32_EXTEND16_S_I32: return WebAssembly::I32_EXTEND16_S_I32_S;
+ case WebAssembly::I32_EXTEND8_S_I32: return WebAssembly::I32_EXTEND8_S_I32_S;
+ case WebAssembly::I32_REINTERPRET_F32: return WebAssembly::I32_REINTERPRET_F32_S;
+ case WebAssembly::I32_TRUNC_S_F32: return WebAssembly::I32_TRUNC_S_F32_S;
+ case WebAssembly::I32_TRUNC_S_F64: return WebAssembly::I32_TRUNC_S_F64_S;
+ case WebAssembly::I32_TRUNC_S_SAT_F32: return WebAssembly::I32_TRUNC_S_SAT_F32_S;
+ case WebAssembly::I32_TRUNC_S_SAT_F64: return WebAssembly::I32_TRUNC_S_SAT_F64_S;
+ case WebAssembly::I32_TRUNC_U_F32: return WebAssembly::I32_TRUNC_U_F32_S;
+ case WebAssembly::I32_TRUNC_U_F64: return WebAssembly::I32_TRUNC_U_F64_S;
+ case WebAssembly::I32_TRUNC_U_SAT_F32: return WebAssembly::I32_TRUNC_U_SAT_F32_S;
+ case WebAssembly::I32_TRUNC_U_SAT_F64: return WebAssembly::I32_TRUNC_U_SAT_F64_S;
+ case WebAssembly::I32_WRAP_I64: return WebAssembly::I32_WRAP_I64_S;
+ case WebAssembly::I64_EXTEND16_S_I64: return WebAssembly::I64_EXTEND16_S_I64_S;
+ case WebAssembly::I64_EXTEND32_S_I64: return WebAssembly::I64_EXTEND32_S_I64_S;
+ case WebAssembly::I64_EXTEND8_S_I64: return WebAssembly::I64_EXTEND8_S_I64_S;
+ case WebAssembly::I64_EXTEND_S_I32: return WebAssembly::I64_EXTEND_S_I32_S;
+ case WebAssembly::I64_EXTEND_U_I32: return WebAssembly::I64_EXTEND_U_I32_S;
+ case WebAssembly::I64_REINTERPRET_F64: return WebAssembly::I64_REINTERPRET_F64_S;
+ case WebAssembly::I64_TRUNC_S_F32: return WebAssembly::I64_TRUNC_S_F32_S;
+ case WebAssembly::I64_TRUNC_S_F64: return WebAssembly::I64_TRUNC_S_F64_S;
+ case WebAssembly::I64_TRUNC_S_SAT_F32: return WebAssembly::I64_TRUNC_S_SAT_F32_S;
+ case WebAssembly::I64_TRUNC_S_SAT_F64: return WebAssembly::I64_TRUNC_S_SAT_F64_S;
+ case WebAssembly::I64_TRUNC_U_F32: return WebAssembly::I64_TRUNC_U_F32_S;
+ case WebAssembly::I64_TRUNC_U_F64: return WebAssembly::I64_TRUNC_U_F64_S;
+ case WebAssembly::I64_TRUNC_U_SAT_F32: return WebAssembly::I64_TRUNC_U_SAT_F32_S;
+ case WebAssembly::I64_TRUNC_U_SAT_F64: return WebAssembly::I64_TRUNC_U_SAT_F64_S;
+ case WebAssembly::LE_F32: return WebAssembly::LE_F32_S;
+ case WebAssembly::LE_F64: return WebAssembly::LE_F64_S;
+ case WebAssembly::LE_S_I32: return WebAssembly::LE_S_I32_S;
+ case WebAssembly::LE_S_I64: return WebAssembly::LE_S_I64_S;
+ case WebAssembly::LE_U_I32: return WebAssembly::LE_U_I32_S;
+ case WebAssembly::LE_U_I64: return WebAssembly::LE_U_I64_S;
+ case WebAssembly::LOAD16_S_I32: return WebAssembly::LOAD16_S_I32_S;
+ case WebAssembly::LOAD16_S_I64: return WebAssembly::LOAD16_S_I64_S;
+ case WebAssembly::LOAD16_U_I32: return WebAssembly::LOAD16_U_I32_S;
+ case WebAssembly::LOAD16_U_I64: return WebAssembly::LOAD16_U_I64_S;
+ case WebAssembly::LOAD32_S_I64: return WebAssembly::LOAD32_S_I64_S;
+ case WebAssembly::LOAD32_U_I64: return WebAssembly::LOAD32_U_I64_S;
+ case WebAssembly::LOAD8_S_I32: return WebAssembly::LOAD8_S_I32_S;
+ case WebAssembly::LOAD8_S_I64: return WebAssembly::LOAD8_S_I64_S;
+ case WebAssembly::LOAD8_U_I32: return WebAssembly::LOAD8_U_I32_S;
+ case WebAssembly::LOAD8_U_I64: return WebAssembly::LOAD8_U_I64_S;
+ case WebAssembly::LOAD_F32: return WebAssembly::LOAD_F32_S;
+ case WebAssembly::LOAD_F64: return WebAssembly::LOAD_F64_S;
+ case WebAssembly::LOAD_I32: return WebAssembly::LOAD_I32_S;
+ case WebAssembly::LOAD_I64: return WebAssembly::LOAD_I64_S;
+ case WebAssembly::LOOP: return WebAssembly::LOOP_S;
+ case WebAssembly::LT_F32: return WebAssembly::LT_F32_S;
+ case WebAssembly::LT_F64: return WebAssembly::LT_F64_S;
+ case WebAssembly::LT_S_I32: return WebAssembly::LT_S_I32_S;
+ case WebAssembly::LT_S_I64: return WebAssembly::LT_S_I64_S;
+ case WebAssembly::LT_U_I32: return WebAssembly::LT_U_I32_S;
+ case WebAssembly::LT_U_I64: return WebAssembly::LT_U_I64_S;
+ case WebAssembly::MAX_F32: return WebAssembly::MAX_F32_S;
+ case WebAssembly::MAX_F64: return WebAssembly::MAX_F64_S;
+ case WebAssembly::MEMORY_GROW_I32: return WebAssembly::MEMORY_GROW_I32_S;
+ case WebAssembly::MEMORY_SIZE_I32: return WebAssembly::MEMORY_SIZE_I32_S;
+ case WebAssembly::MEM_GROW_I32: return WebAssembly::MEM_GROW_I32_S;
+ case WebAssembly::MEM_SIZE_I32: return WebAssembly::MEM_SIZE_I32_S;
+ case WebAssembly::MIN_F32: return WebAssembly::MIN_F32_S;
+ case WebAssembly::MIN_F64: return WebAssembly::MIN_F64_S;
+ case WebAssembly::MUL_F32: return WebAssembly::MUL_F32_S;
+ case WebAssembly::MUL_F64: return WebAssembly::MUL_F64_S;
+ case WebAssembly::MUL_I32: return WebAssembly::MUL_I32_S;
+ case WebAssembly::MUL_I64: return WebAssembly::MUL_I64_S;
+ case WebAssembly::MUL_v16i8: return WebAssembly::MUL_v16i8_S;
+ case WebAssembly::MUL_v2f64: return WebAssembly::MUL_v2f64_S;
+ case WebAssembly::MUL_v4f32: return WebAssembly::MUL_v4f32_S;
+ case WebAssembly::MUL_v4i32: return WebAssembly::MUL_v4i32_S;
+ case WebAssembly::MUL_v8i16: return WebAssembly::MUL_v8i16_S;
+ case WebAssembly::NEAREST_F32: return WebAssembly::NEAREST_F32_S;
+ case WebAssembly::NEAREST_F64: return WebAssembly::NEAREST_F64_S;
+ case WebAssembly::NEG_F32: return WebAssembly::NEG_F32_S;
+ case WebAssembly::NEG_F64: return WebAssembly::NEG_F64_S;
+ case WebAssembly::NE_F32: return WebAssembly::NE_F32_S;
+ case WebAssembly::NE_F64: return WebAssembly::NE_F64_S;
+ case WebAssembly::NE_I32: return WebAssembly::NE_I32_S;
+ case WebAssembly::NE_I64: return WebAssembly::NE_I64_S;
+ case WebAssembly::NOP: return WebAssembly::NOP_S;
+ case WebAssembly::OR_I32: return WebAssembly::OR_I32_S;
+ case WebAssembly::OR_I64: return WebAssembly::OR_I64_S;
+ case WebAssembly::PCALL_INDIRECT_EXCEPT_REF: return WebAssembly::PCALL_INDIRECT_EXCEPT_REF_S;
+ case WebAssembly::PCALL_INDIRECT_F32: return WebAssembly::PCALL_INDIRECT_F32_S;
+ case WebAssembly::PCALL_INDIRECT_F64: return WebAssembly::PCALL_INDIRECT_F64_S;
+ case WebAssembly::PCALL_INDIRECT_I32: return WebAssembly::PCALL_INDIRECT_I32_S;
+ case WebAssembly::PCALL_INDIRECT_I64: return WebAssembly::PCALL_INDIRECT_I64_S;
+ case WebAssembly::PCALL_INDIRECT_VOID: return WebAssembly::PCALL_INDIRECT_VOID_S;
+ case WebAssembly::PCALL_INDIRECT_v16i8: return WebAssembly::PCALL_INDIRECT_v16i8_S;
+ case WebAssembly::PCALL_INDIRECT_v4f32: return WebAssembly::PCALL_INDIRECT_v4f32_S;
+ case WebAssembly::PCALL_INDIRECT_v4i32: return WebAssembly::PCALL_INDIRECT_v4i32_S;
+ case WebAssembly::PCALL_INDIRECT_v8i16: return WebAssembly::PCALL_INDIRECT_v8i16_S;
+ case WebAssembly::POPCNT_I32: return WebAssembly::POPCNT_I32_S;
+ case WebAssembly::POPCNT_I64: return WebAssembly::POPCNT_I64_S;
+ case WebAssembly::REM_S_I32: return WebAssembly::REM_S_I32_S;
+ case WebAssembly::REM_S_I64: return WebAssembly::REM_S_I64_S;
+ case WebAssembly::REM_U_I32: return WebAssembly::REM_U_I32_S;
+ case WebAssembly::REM_U_I64: return WebAssembly::REM_U_I64_S;
+ case WebAssembly::RETHROW: return WebAssembly::RETHROW_S;
+ case WebAssembly::RETHROW_TO_CALLER: return WebAssembly::RETHROW_TO_CALLER_S;
+ case WebAssembly::RETURN_EXCEPT_REF: return WebAssembly::RETURN_EXCEPT_REF_S;
+ case WebAssembly::RETURN_F32: return WebAssembly::RETURN_F32_S;
+ case WebAssembly::RETURN_F64: return WebAssembly::RETURN_F64_S;
+ case WebAssembly::RETURN_I32: return WebAssembly::RETURN_I32_S;
+ case WebAssembly::RETURN_I64: return WebAssembly::RETURN_I64_S;
+ case WebAssembly::RETURN_VOID: return WebAssembly::RETURN_VOID_S;
+ case WebAssembly::RETURN_v16i8: return WebAssembly::RETURN_v16i8_S;
+ case WebAssembly::RETURN_v4f32: return WebAssembly::RETURN_v4f32_S;
+ case WebAssembly::RETURN_v4i32: return WebAssembly::RETURN_v4i32_S;
+ case WebAssembly::RETURN_v8i16: return WebAssembly::RETURN_v8i16_S;
+ case WebAssembly::ROTL_I32: return WebAssembly::ROTL_I32_S;
+ case WebAssembly::ROTL_I64: return WebAssembly::ROTL_I64_S;
+ case WebAssembly::ROTR_I32: return WebAssembly::ROTR_I32_S;
+ case WebAssembly::ROTR_I64: return WebAssembly::ROTR_I64_S;
+ case WebAssembly::SELECT_EXCEPT_REF: return WebAssembly::SELECT_EXCEPT_REF_S;
+ case WebAssembly::SELECT_F32: return WebAssembly::SELECT_F32_S;
+ case WebAssembly::SELECT_F64: return WebAssembly::SELECT_F64_S;
+ case WebAssembly::SELECT_I32: return WebAssembly::SELECT_I32_S;
+ case WebAssembly::SELECT_I64: return WebAssembly::SELECT_I64_S;
+ case WebAssembly::SET_GLOBAL_EXCEPT_REF: return WebAssembly::SET_GLOBAL_EXCEPT_REF_S;
+ case WebAssembly::SET_GLOBAL_F32: return WebAssembly::SET_GLOBAL_F32_S;
+ case WebAssembly::SET_GLOBAL_F64: return WebAssembly::SET_GLOBAL_F64_S;
+ case WebAssembly::SET_GLOBAL_I32: return WebAssembly::SET_GLOBAL_I32_S;
+ case WebAssembly::SET_GLOBAL_I64: return WebAssembly::SET_GLOBAL_I64_S;
+ case WebAssembly::SET_GLOBAL_V128: return WebAssembly::SET_GLOBAL_V128_S;
+ case WebAssembly::SET_LOCAL_EXCEPT_REF: return WebAssembly::SET_LOCAL_EXCEPT_REF_S;
+ case WebAssembly::SET_LOCAL_F32: return WebAssembly::SET_LOCAL_F32_S;
+ case WebAssembly::SET_LOCAL_F64: return WebAssembly::SET_LOCAL_F64_S;
+ case WebAssembly::SET_LOCAL_I32: return WebAssembly::SET_LOCAL_I32_S;
+ case WebAssembly::SET_LOCAL_I64: return WebAssembly::SET_LOCAL_I64_S;
+ case WebAssembly::SET_LOCAL_V128: return WebAssembly::SET_LOCAL_V128_S;
+ case WebAssembly::SHL_I32: return WebAssembly::SHL_I32_S;
+ case WebAssembly::SHL_I64: return WebAssembly::SHL_I64_S;
+ case WebAssembly::SHR_S_I32: return WebAssembly::SHR_S_I32_S;
+ case WebAssembly::SHR_S_I64: return WebAssembly::SHR_S_I64_S;
+ case WebAssembly::SHR_U_I32: return WebAssembly::SHR_U_I32_S;
+ case WebAssembly::SHR_U_I64: return WebAssembly::SHR_U_I64_S;
+ case WebAssembly::SQRT_F32: return WebAssembly::SQRT_F32_S;
+ case WebAssembly::SQRT_F64: return WebAssembly::SQRT_F64_S;
+ case WebAssembly::STORE16_I32: return WebAssembly::STORE16_I32_S;
+ case WebAssembly::STORE16_I64: return WebAssembly::STORE16_I64_S;
+ case WebAssembly::STORE32_I64: return WebAssembly::STORE32_I64_S;
+ case WebAssembly::STORE8_I32: return WebAssembly::STORE8_I32_S;
+ case WebAssembly::STORE8_I64: return WebAssembly::STORE8_I64_S;
+ case WebAssembly::STORE_F32: return WebAssembly::STORE_F32_S;
+ case WebAssembly::STORE_F64: return WebAssembly::STORE_F64_S;
+ case WebAssembly::STORE_I32: return WebAssembly::STORE_I32_S;
+ case WebAssembly::STORE_I64: return WebAssembly::STORE_I64_S;
+ case WebAssembly::SUB_F32: return WebAssembly::SUB_F32_S;
+ case WebAssembly::SUB_F64: return WebAssembly::SUB_F64_S;
+ case WebAssembly::SUB_I32: return WebAssembly::SUB_I32_S;
+ case WebAssembly::SUB_I64: return WebAssembly::SUB_I64_S;
+ case WebAssembly::SUB_v16i8: return WebAssembly::SUB_v16i8_S;
+ case WebAssembly::SUB_v2f64: return WebAssembly::SUB_v2f64_S;
+ case WebAssembly::SUB_v2i64: return WebAssembly::SUB_v2i64_S;
+ case WebAssembly::SUB_v4f32: return WebAssembly::SUB_v4f32_S;
+ case WebAssembly::SUB_v4i32: return WebAssembly::SUB_v4i32_S;
+ case WebAssembly::SUB_v8i16: return WebAssembly::SUB_v8i16_S;
+ case WebAssembly::TEE_EXCEPT_REF: return WebAssembly::TEE_EXCEPT_REF_S;
+ case WebAssembly::TEE_F32: return WebAssembly::TEE_F32_S;
+ case WebAssembly::TEE_F64: return WebAssembly::TEE_F64_S;
+ case WebAssembly::TEE_I32: return WebAssembly::TEE_I32_S;
+ case WebAssembly::TEE_I64: return WebAssembly::TEE_I64_S;
+ case WebAssembly::TEE_LOCAL_EXCEPT_REF: return WebAssembly::TEE_LOCAL_EXCEPT_REF_S;
+ case WebAssembly::TEE_LOCAL_F32: return WebAssembly::TEE_LOCAL_F32_S;
+ case WebAssembly::TEE_LOCAL_F64: return WebAssembly::TEE_LOCAL_F64_S;
+ case WebAssembly::TEE_LOCAL_I32: return WebAssembly::TEE_LOCAL_I32_S;
+ case WebAssembly::TEE_LOCAL_I64: return WebAssembly::TEE_LOCAL_I64_S;
+ case WebAssembly::TEE_LOCAL_V128: return WebAssembly::TEE_LOCAL_V128_S;
+ case WebAssembly::TEE_V128: return WebAssembly::TEE_V128_S;
+ case WebAssembly::THROW_I32: return WebAssembly::THROW_I32_S;
+ case WebAssembly::THROW_I64: return WebAssembly::THROW_I64_S;
+ case WebAssembly::TRUNC_F32: return WebAssembly::TRUNC_F32_S;
+ case WebAssembly::TRUNC_F64: return WebAssembly::TRUNC_F64_S;
+ case WebAssembly::TRY: return WebAssembly::TRY_S;
+ case WebAssembly::UNREACHABLE: return WebAssembly::UNREACHABLE_S;
+ case WebAssembly::XOR_I32: return WebAssembly::XOR_I32_S;
+ case WebAssembly::XOR_I64: return WebAssembly::XOR_I64_S;
+ }
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
index f4884de5844..eed91e70aaa 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
@@ -28,15 +28,25 @@ const char *const WebAssembly::PersonalityWrapperFn =
bool WebAssembly::isArgument(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::ARGUMENT_I32:
+ case WebAssembly::ARGUMENT_I32_S:
case WebAssembly::ARGUMENT_I64:
+ case WebAssembly::ARGUMENT_I64_S:
case WebAssembly::ARGUMENT_F32:
+ case WebAssembly::ARGUMENT_F32_S:
case WebAssembly::ARGUMENT_F64:
+ case WebAssembly::ARGUMENT_F64_S:
case WebAssembly::ARGUMENT_v16i8:
+ case WebAssembly::ARGUMENT_v16i8_S:
case WebAssembly::ARGUMENT_v8i16:
+ case WebAssembly::ARGUMENT_v8i16_S:
case WebAssembly::ARGUMENT_v4i32:
+ case WebAssembly::ARGUMENT_v4i32_S:
case WebAssembly::ARGUMENT_v2i64:
+ case WebAssembly::ARGUMENT_v2i64_S:
case WebAssembly::ARGUMENT_v4f32:
+ case WebAssembly::ARGUMENT_v4f32_S:
case WebAssembly::ARGUMENT_v2f64:
+ case WebAssembly::ARGUMENT_v2f64_S:
return true;
default:
return false;
@@ -46,9 +56,13 @@ bool WebAssembly::isArgument(const MachineInstr &MI) {
bool WebAssembly::isCopy(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::COPY_I32:
+ case WebAssembly::COPY_I32_S:
case WebAssembly::COPY_I64:
+ case WebAssembly::COPY_I64_S:
case WebAssembly::COPY_F32:
+ case WebAssembly::COPY_F32_S:
case WebAssembly::COPY_F64:
+ case WebAssembly::COPY_F64_S:
return true;
default:
return false;
@@ -58,9 +72,13 @@ bool WebAssembly::isCopy(const MachineInstr &MI) {
bool WebAssembly::isTee(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::TEE_I32:
+ case WebAssembly::TEE_I32_S:
case WebAssembly::TEE_I64:
+ case WebAssembly::TEE_I64_S:
case WebAssembly::TEE_F32:
+ case WebAssembly::TEE_F32_S:
case WebAssembly::TEE_F64:
+ case WebAssembly::TEE_F64_S:
return true;
default:
return false;
@@ -83,17 +101,29 @@ bool WebAssembly::isChild(const MachineInstr &MI,
bool WebAssembly::isCallDirect(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::CALL_VOID:
+ case WebAssembly::CALL_VOID_S:
case WebAssembly::CALL_I32:
+ case WebAssembly::CALL_I32_S:
case WebAssembly::CALL_I64:
+ case WebAssembly::CALL_I64_S:
case WebAssembly::CALL_F32:
+ case WebAssembly::CALL_F32_S:
case WebAssembly::CALL_F64:
+ case WebAssembly::CALL_F64_S:
case WebAssembly::CALL_v16i8:
+ case WebAssembly::CALL_v16i8_S:
case WebAssembly::CALL_v8i16:
+ case WebAssembly::CALL_v8i16_S:
case WebAssembly::CALL_v4i32:
+ case WebAssembly::CALL_v4i32_S:
case WebAssembly::CALL_v2i64:
+ case WebAssembly::CALL_v2i64_S:
case WebAssembly::CALL_v4f32:
+ case WebAssembly::CALL_v4f32_S:
case WebAssembly::CALL_v2f64:
+ case WebAssembly::CALL_v2f64_S:
case WebAssembly::CALL_EXCEPT_REF:
+ case WebAssembly::CALL_EXCEPT_REF_S:
return true;
default:
return false;
@@ -103,17 +133,29 @@ bool WebAssembly::isCallDirect(const MachineInstr &MI) {
bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::CALL_INDIRECT_VOID:
+ case WebAssembly::CALL_INDIRECT_VOID_S:
case WebAssembly::CALL_INDIRECT_I32:
+ case WebAssembly::CALL_INDIRECT_I32_S:
case WebAssembly::CALL_INDIRECT_I64:
+ case WebAssembly::CALL_INDIRECT_I64_S:
case WebAssembly::CALL_INDIRECT_F32:
+ case WebAssembly::CALL_INDIRECT_F32_S:
case WebAssembly::CALL_INDIRECT_F64:
+ case WebAssembly::CALL_INDIRECT_F64_S:
case WebAssembly::CALL_INDIRECT_v16i8:
+ case WebAssembly::CALL_INDIRECT_v16i8_S:
case WebAssembly::CALL_INDIRECT_v8i16:
+ case WebAssembly::CALL_INDIRECT_v8i16_S:
case WebAssembly::CALL_INDIRECT_v4i32:
+ case WebAssembly::CALL_INDIRECT_v4i32_S:
case WebAssembly::CALL_INDIRECT_v2i64:
+ case WebAssembly::CALL_INDIRECT_v2i64_S:
case WebAssembly::CALL_INDIRECT_v4f32:
+ case WebAssembly::CALL_INDIRECT_v4f32_S:
case WebAssembly::CALL_INDIRECT_v2f64:
+ case WebAssembly::CALL_INDIRECT_v2f64_S:
case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
+ case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
return true;
default:
return false;
@@ -123,18 +165,30 @@ bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::CALL_VOID:
+ case WebAssembly::CALL_VOID_S:
case WebAssembly::CALL_INDIRECT_VOID:
+ case WebAssembly::CALL_INDIRECT_VOID_S:
return 0;
case WebAssembly::CALL_I32:
+ case WebAssembly::CALL_I32_S:
case WebAssembly::CALL_I64:
+ case WebAssembly::CALL_I64_S:
case WebAssembly::CALL_F32:
+ case WebAssembly::CALL_F32_S:
case WebAssembly::CALL_F64:
+ case WebAssembly::CALL_F64_S:
case WebAssembly::CALL_EXCEPT_REF:
+ case WebAssembly::CALL_EXCEPT_REF_S:
case WebAssembly::CALL_INDIRECT_I32:
+ case WebAssembly::CALL_INDIRECT_I32_S:
case WebAssembly::CALL_INDIRECT_I64:
+ case WebAssembly::CALL_INDIRECT_I64_S:
case WebAssembly::CALL_INDIRECT_F32:
+ case WebAssembly::CALL_INDIRECT_F32_S:
case WebAssembly::CALL_INDIRECT_F64:
+ case WebAssembly::CALL_INDIRECT_F64_S:
case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
+ case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
return 1;
default:
llvm_unreachable("Not a call instruction");
@@ -144,11 +198,17 @@ unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
bool WebAssembly::isMarker(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::BLOCK:
+ case WebAssembly::BLOCK_S:
case WebAssembly::END_BLOCK:
+ case WebAssembly::END_BLOCK_S:
case WebAssembly::LOOP:
+ case WebAssembly::LOOP_S:
case WebAssembly::END_LOOP:
+ case WebAssembly::END_LOOP_S:
case WebAssembly::TRY:
+ case WebAssembly::TRY_S:
case WebAssembly::END_TRY:
+ case WebAssembly::END_TRY_S:
return true;
default:
return false;
@@ -158,7 +218,9 @@ bool WebAssembly::isMarker(const MachineInstr &MI) {
bool WebAssembly::isThrow(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::THROW_I32:
+ case WebAssembly::THROW_I32_S:
case WebAssembly::THROW_I64:
+ case WebAssembly::THROW_I64_S:
return true;
default:
return false;
@@ -168,7 +230,9 @@ bool WebAssembly::isThrow(const MachineInstr &MI) {
bool WebAssembly::isRethrow(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::RETHROW:
+ case WebAssembly::RETHROW_S:
case WebAssembly::RETHROW_TO_CALLER:
+ case WebAssembly::RETHROW_TO_CALLER_S:
return true;
default:
return false;
@@ -178,8 +242,11 @@ bool WebAssembly::isRethrow(const MachineInstr &MI) {
bool WebAssembly::isCatch(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::CATCH_I32:
+ case WebAssembly::CATCH_I32_S:
case WebAssembly::CATCH_I64:
+ case WebAssembly::CATCH_I64_S:
case WebAssembly::CATCH_ALL:
+ case WebAssembly::CATCH_ALL_S:
return true;
default:
return false;
@@ -189,8 +256,11 @@ bool WebAssembly::isCatch(const MachineInstr &MI) {
bool WebAssembly::mayThrow(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::THROW_I32:
+ case WebAssembly::THROW_I32_S:
case WebAssembly::THROW_I64:
+ case WebAssembly::THROW_I64_S:
case WebAssembly::RETHROW:
+ case WebAssembly::RETHROW_S:
return true;
}
if (isCallIndirect(MI))
@@ -218,7 +288,9 @@ bool WebAssembly::isCatchTerminatePad(const MachineBasicBlock &MBB) {
bool SeenCatch = false;
for (auto &MI : MBB) {
if (MI.getOpcode() == WebAssembly::CATCH_I32 ||
- MI.getOpcode() == WebAssembly::CATCH_I64)
+ MI.getOpcode() == WebAssembly::CATCH_I64 ||
+ MI.getOpcode() == WebAssembly::CATCH_I32_S ||
+ MI.getOpcode() == WebAssembly::CATCH_I64_S)
SeenCatch = true;
if (SeenCatch && MI.isCall()) {
const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
@@ -235,7 +307,8 @@ bool WebAssembly::isCatchAllTerminatePad(const MachineBasicBlock &MBB) {
return false;
bool SeenCatchAll = false;
for (auto &MI : MBB) {
- if (MI.getOpcode() == WebAssembly::CATCH_ALL)
+ if (MI.getOpcode() == WebAssembly::CATCH_ALL ||
+ MI.getOpcode() == WebAssembly::CATCH_ALL_S)
SeenCatchAll = true;
if (SeenCatchAll && MI.isCall()) {
const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
OpenPOWER on IntegriCloud