diff options
Diffstat (limited to 'llvm/lib')
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)); |