diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
16 files changed, 126 insertions, 131 deletions
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 9b59c7554bd..1b52bed0abe 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -154,22 +154,11 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, (Desc.TSFlags & WebAssemblyII::VariableOpIsImmediate)) && "WebAssemblyII::VariableOpIsImmediate should be set for " "variable_ops immediate ops"); - - if (Desc.TSFlags & WebAssemblyII::VariableOpImmediateIsType) { - switch (Op.getImm()) { - case int64_t(WebAssembly::ValType::I32): O << "i32"; break; - case int64_t(WebAssembly::ValType::I64): O << "i64"; break; - case int64_t(WebAssembly::ValType::F32): O << "f32"; break; - case int64_t(WebAssembly::ValType::F64): O << "f64"; break; - default: llvm_unreachable("unknown local type"); - } - } else { - // TODO: (MII.get(MI->getOpcode()).TSFlags & - // WebAssemblyII::VariableOpImmediateIsLabel) - // can tell us whether this is an immediate referencing a label in the - // control flow stack, and it may be nice to pretty-print. - O << Op.getImm(); - } + // TODO: (MII.get(MI->getOpcode()).TSFlags & + // WebAssemblyII::VariableOpImmediateIsLabel) + // can tell us whether this is an immediate referencing a label in the + // control flow stack, and it may be nice to pretty-print. + O << Op.getImm(); } else if (Op.isFPImm()) { const MCInstrDesc &Desc = MII.get(MI->getOpcode()); assert(OpNo < Desc.getNumOperands() && @@ -220,9 +209,10 @@ WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI, case WebAssembly::ExprType::I8x16: O << "i8x16"; break; case WebAssembly::ExprType::I16x8: O << "i16x8"; break; case WebAssembly::ExprType::I32x4: O << "i32x4"; break; - case WebAssembly::ExprType::I64x2: O << "i32x4"; break; case WebAssembly::ExprType::F32x4: O << "f32x4"; break; - case WebAssembly::ExprType::F64x2: O << "f64x2"; break; + case WebAssembly::ExprType::B8x16: O << "b8x16"; break; + case WebAssembly::ExprType::B16x8: O << "b16x8"; break; + case WebAssembly::ExprType::B32x4: O << "b32x4"; break; } } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp index df6fb8968d5..97454a824a3 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -66,8 +66,10 @@ bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, if (Count == 0) return true; - // FIXME: Do something. - return false; + for (uint64_t i = 0; i < Count; ++i) + OW->write8(WebAssembly::Nop); + + return true; } void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp index d740b0adc7a..f7183241f9f 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -60,7 +60,8 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( uint64_t Start = OS.tell(); uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); - encodeULEB128(Binary, OS); + assert(Binary < UINT8_MAX && "Multi-byte opcodes not supported yet"); + OS << uint8_t(Binary); const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { @@ -68,16 +69,20 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( if (MO.isReg()) { /* nothing to encode */ } else if (MO.isImm()) { - assert(i < Desc.getNumOperands() && - "Unexpected integer immediate as a non-fixed operand"); - assert(Desc.TSFlags == 0 && - "WebAssembly variable_ops integer ops don't use TSFlags"); - const MCOperandInfo &Info = Desc.OpInfo[i]; - if (Info.OperandType == WebAssembly::OPERAND_I32IMM) { - encodeSLEB128(int32_t(MO.getImm()), OS); - } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) { - encodeSLEB128(int64_t(MO.getImm()), OS); + if (i < Desc.getNumOperands()) { + assert(Desc.TSFlags == 0 && + "WebAssembly non-variable_ops don't use TSFlags"); + const MCOperandInfo &Info = Desc.OpInfo[i]; + if (Info.OperandType == WebAssembly::OPERAND_I32IMM) { + encodeSLEB128(int32_t(MO.getImm()), OS); + } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) { + encodeSLEB128(int64_t(MO.getImm()), OS); + } else { + encodeULEB128(uint64_t(MO.getImm()), OS); + } } else { + assert(Desc.TSFlags == (WebAssemblyII::VariableOpIsImmediate | + WebAssemblyII::VariableOpImmediateIsLabel)); encodeULEB128(uint64_t(MO.getImm()), OS); } } else if (MO.isFPImm()) { diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp index 5d7a0f82062..3dc1ded1711 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -134,3 +134,13 @@ extern "C" void LLVMInitializeWebAssemblyTargetMC() { TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer); } } + +WebAssembly::ValType WebAssembly::toValType(const MVT &Ty) { + switch (Ty.SimpleTy) { + case MVT::i32: return WebAssembly::ValType::I32; + case MVT::i64: return WebAssembly::ValType::I64; + case MVT::f32: return WebAssembly::ValType::F32; + case MVT::f64: return WebAssembly::ValType::F64; + default: llvm_unreachable("unexpected type"); + } +} diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 5fa277324d6..ae3fb7bfd13 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -26,6 +26,7 @@ class MCContext; class MCInstrInfo; class MCObjectWriter; class MCSubtargetInfo; +class MVT; class Target; class Triple; class raw_pwrite_stream; @@ -59,17 +60,6 @@ enum OperandType { /// signature immediate for block/loop. OPERAND_SIGNATURE }; - -/// WebAssembly-specific directive identifiers. -enum Directive { - // FIXME: This is not the real binary encoding. - DotParam = UINT64_MAX - 0, ///< .param - DotResult = UINT64_MAX - 1, ///< .result - DotLocal = UINT64_MAX - 2, ///< .local - DotEndFunc = UINT64_MAX - 3, ///< .endfunc - DotIndIdx = UINT64_MAX - 4, ///< .indidx -}; - } // end namespace WebAssembly namespace WebAssemblyII { @@ -79,10 +69,7 @@ enum { VariableOpIsImmediate = (1 << 0), // For immediate values in the variable_ops range, this flag indicates // whether the value represents a control-flow label. - VariableOpImmediateIsLabel = (1 << 1), - // For immediate values in the variable_ops range, this flag indicates - // whether the value represents a ValType. - VariableOpImmediateIsType = (1 << 2), + VariableOpImmediateIsLabel = (1 << 1) }; } // end namespace WebAssemblyII @@ -150,33 +137,41 @@ static const unsigned StoreP2AlignOperandNo = 2; /// This is used to indicate block signatures. enum class ExprType { - Void = 0, - I32 = 1, - I64 = 2, - F32 = 3, - F64 = 4, - I8x16 = 5, - I16x8 = 6, - I32x4 = 7, - I64x2 = 8, - F32x4 = 9, - F64x2 = 10 + Void = 0x40, + I32 = 0x7f, + I64 = 0x7e, + F32 = 0x7d, + F64 = 0x7c, + I8x16 = 0x7b, + I16x8 = 0x7a, + I32x4 = 0x79, + F32x4 = 0x78, + B8x16 = 0x77, + B16x8 = 0x76, + B32x4 = 0x75 }; /// This is used to indicate local types. enum class ValType { - I32 = 1, - I64 = 2, - F32 = 3, - F64 = 4, - I8x16 = 5, - I16x8 = 6, - I32x4 = 7, - I64x2 = 8, - F32x4 = 9, - F64x2 = 10 + I32 = 0x7f, + I64 = 0x7e, + F32 = 0x7d, + F64 = 0x7c, + I8x16 = 0x7b, + I16x8 = 0x7a, + I32x4 = 0x79, + F32x4 = 0x78, + B8x16 = 0x77, + B16x8 = 0x76, + B32x4 = 0x75 }; +/// Instruction opcodes emitted via means other than CodeGen. +static const unsigned Nop = 0x01; +static const unsigned End = 0x0b; + +ValType toValType(const MVT &Ty); + } // end namespace WebAssembly } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 9934b119cb6..f0886880802 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -58,8 +58,10 @@ void WebAssemblyTargetAsmStreamer::emitResult(ArrayRef<MVT> Types) { } void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) { - OS << "\t.local \t"; - PrintTypes(OS, Types); + if (!Types.empty()) { + OS << "\t.local \t"; + PrintTypes(OS, Types); + } } void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } @@ -82,34 +84,30 @@ void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } -// FIXME: What follows is not the real binary encoding. - -static void EncodeTypes(MCStreamer &Streamer, ArrayRef<MVT> Types) { - Streamer.EmitIntValue(Types.size(), sizeof(uint64_t)); - for (MVT Type : Types) - Streamer.EmitIntValue(Type.SimpleTy, sizeof(uint64_t)); -} - void WebAssemblyTargetELFStreamer::emitParam(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotParam, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + // Nothing to emit; params are declared as part of the function signature. } void WebAssemblyTargetELFStreamer::emitResult(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotResult, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + // Nothing to emit; results are declared as part of the function signature. } void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotLocal, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + Streamer.EmitULEB128IntValue(Types.size()); + for (MVT Type : Types) + Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1); } void WebAssemblyTargetELFStreamer::emitEndFunc() { - Streamer.EmitIntValue(WebAssembly::DotEndFunc, sizeof(uint64_t)); + Streamer.EmitIntValue(WebAssembly::End, 1); } void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) { - Streamer.EmitIntValue(WebAssembly::DotIndIdx, sizeof(uint64_t)); - Streamer.EmitValue(Value, sizeof(uint64_t)); + llvm_unreachable(".indidx encoding not yet implemented"); +} + +void WebAssemblyTargetELFStreamer::emitIndirectFunctionType( + StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) { + // Nothing to emit here. TODO: Re-design how linking works and re-evaluate + // whether it's necessary for .o files to declare indirect function types. } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 15f67164bee..cf164ca5924 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -73,6 +73,9 @@ public: void emitResult(ArrayRef<MVT> Types) override; void emitLocal(ArrayRef<MVT> Types) override; void emitEndFunc() override; + void emitIndirectFunctionType(StringRef name, + SmallVectorImpl<MVT> &Params, + SmallVectorImpl<MVT> &Results) override; void emitIndIdx(const MCExpr *Value) override; }; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 85ff1b80e3c..f53cfca9db3 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -42,7 +42,7 @@ namespace { class WebAssemblyAsmPrinter final : public AsmPrinter { const MachineRegisterInfo *MRI; - const WebAssemblyFunctionInfo *MFI; + WebAssemblyFunctionInfo *MFI; public: WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) @@ -166,8 +166,8 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { if (ResultVTs.size() == 1) getTargetStreamer()->emitResult(ResultVTs); - bool AnyWARegs = false; - SmallVector<MVT, 16> LocalTypes; + // FIXME: When ExplicitLocals is enabled by default, we won't need + // to define the locals here (and MFI can go back to being pointer-to-const). for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) { unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx); unsigned WAReg = MFI->getWAReg(VReg); @@ -180,11 +180,10 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { // Don't declare stackified registers. if (int(WAReg) < 0) continue; - LocalTypes.push_back(getRegType(VReg)); - AnyWARegs = true; + MFI->addLocal(getRegType(VReg)); } - if (AnyWARegs) - getTargetStreamer()->emitLocal(LocalTypes); + + getTargetStreamer()->emitLocal(MFI->getLocals()); AsmPrinter::EmitFunctionBodyStart(); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 18b6f932081..49b9754e6b6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -466,9 +466,7 @@ static void FixEndsAtEndOfFunction( case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break; case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break; case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break; - case MVT::v2i64: retType = WebAssembly::ExprType::I64x2; break; case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break; - case MVT::v2f64: retType = WebAssembly::ExprType::F64x2; break; default: llvm_unreachable("unexpected return type"); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp index 3b527922419..56b0f4fb684 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -109,15 +109,15 @@ static unsigned getTeeLocalOpcode(const TargetRegisterClass *RC) { } /// Get the type associated with the given register class. -static WebAssembly::ValType typeForRegClass(const TargetRegisterClass *RC) { +static MVT typeForRegClass(const TargetRegisterClass *RC) { if (RC == &WebAssembly::I32RegClass) - return WebAssembly::ValType::I32; + return MVT::i32; if (RC == &WebAssembly::I64RegClass) - return WebAssembly::ValType::I64; + return MVT::i64; if (RC == &WebAssembly::F32RegClass) - return WebAssembly::ValType::F32; + return MVT::f32; if (RC == &WebAssembly::F64RegClass) - return WebAssembly::ValType::F64; + return MVT::f64; llvm_unreachable("unrecognized register class"); } @@ -272,21 +272,15 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { } } - // Insert a .locals directive to declare the locals. - MachineInstrBuilder DeclareLocals; + // Define the locals. 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()) continue; - if (!DeclareLocals) { - DeclareLocals = BuildMI(*MF.begin(), MF.begin()->begin(), DebugLoc(), - TII->get(WebAssembly::DECLARE_LOCALS)); - Changed = true; - } - - DeclareLocals.addImm(int64_t(typeForRegClass(MRI.getRegClass(Reg)))); + MFI.addLocal(typeForRegClass(MRI.getRegClass(Reg))); + Changed = true; } #ifndef NDEBUG diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 47459f85a16..f4906e9fca2 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -28,7 +28,8 @@ def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt, i32imm:$amt2), multiclass CALL<WebAssemblyRegClass vt, string prefix> { def CALL_#vt : I<(outs vt:$dst), (ins i32imm:$callee, variable_ops), [(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))], - !strconcat(prefix, "call\t$dst, $callee")>; + !strconcat(prefix, "call\t$dst, $callee"), + 0x10>; let isCodeGenOnly = 1 in { def PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops), [(set vt:$dst, (WebAssemblycall1 I32:$callee))], @@ -36,14 +37,16 @@ multiclass CALL<WebAssemblyRegClass vt, string prefix> { } // isCodeGenOnly = 1 def CALL_INDIRECT_#vt : I<(outs vt:$dst), (ins variable_ops), [], - !strconcat(prefix, "call_indirect\t$dst")>; + !strconcat(prefix, "call_indirect\t$dst"), + 0x11>; } multiclass SIMD_CALL<ValueType vt, string prefix> { def CALL_#vt : SIMD_I<(outs V128:$dst), (ins i32imm:$callee, variable_ops), [(set (vt V128:$dst), (WebAssemblycall1 (i32 imm:$callee)))], - !strconcat(prefix, "call\t$dst, $callee")>; + !strconcat(prefix, "call\t$dst, $callee"), + 0x10>; let isCodeGenOnly = 1 in { def PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), (ins I32:$callee, variable_ops), @@ -54,7 +57,8 @@ multiclass SIMD_CALL<ValueType vt, string prefix> { def CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), (ins variable_ops), [], - !strconcat(prefix, "call_indirect\t$dst")>; + !strconcat(prefix, "call_indirect\t$dst"), + 0x11>; } let Uses = [SP32, SP64], isCall = 1 in { @@ -69,7 +73,7 @@ let Uses = [SP32, SP64], isCall = 1 in { def CALL_VOID : I<(outs), (ins i32imm:$callee, variable_ops), [(WebAssemblycall0 (i32 imm:$callee))], - "call \t$callee">; + "call \t$callee", 0x10>; let isCodeGenOnly = 1 in { def PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops), [(WebAssemblycall0 I32:$callee)], @@ -77,7 +81,7 @@ let Uses = [SP32, SP64], isCall = 1 in { } // isCodeGenOnly = 1 def CALL_INDIRECT_VOID : I<(outs), (ins variable_ops), [], - "call_indirect\t">; + "call_indirect\t", 0x11>; } // Uses = [SP32,SP64], isCall = 1 } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td index 7ff5bbdcd48..1146431e6b7 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -65,13 +65,13 @@ def BLOCK : I<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; def LOOP : I<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>; // END_BLOCK and END_LOOP are represented with the same opcode in wasm. -def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0f>; -def END_LOOP : I<(outs), (ins), [], "end_loop", 0x0f>; +def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0b>; +def END_LOOP : I<(outs), (ins), [], "end_loop", 0x0b>; } // Uses = [VALUE_STACK], Defs = [VALUE_STACK] multiclass RETURN<WebAssemblyRegClass vt> { def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)], - "return \t$val">; + "return \t$val", 0x0f>; // Equivalent to RETURN_#vt, for use at the end of a function when wasm // semantics return by falling off the end of the block. let isCodeGenOnly = 1 in @@ -81,7 +81,7 @@ multiclass RETURN<WebAssemblyRegClass vt> { multiclass SIMD_RETURN<ValueType vt> { def RETURN_#vt : SIMD_I<(outs), (ins V128:$val), [(WebAssemblyreturn (vt V128:$val))], - "return \t$val">; + "return \t$val", 0x0f>; // Equivalent to RETURN_#vt, for use at the end of a function when wasm // semantics return by falling off the end of the block. let isCodeGenOnly = 1 in @@ -100,14 +100,14 @@ let isReturn = 1 in { defm : SIMD_RETURN<v4i32>; defm : SIMD_RETURN<v4f32>; - def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return">; + def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>; // This is to RETURN_VOID what FALLTHROUGH_RETURN_#vt is to RETURN_#vt. let isCodeGenOnly = 1 in def FALLTHROUGH_RETURN_VOID : I<(outs), (ins), []>; } // isReturn = 1 -def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">; +def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable", 0x00>; } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td index a67fd676013..030be0862a5 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td @@ -79,10 +79,10 @@ let Defs = [ARGUMENTS] in { def SELECT_F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs, I32:$cond), [(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))], - "f32.select\t$dst, $lhs, $rhs, $cond">; + "f32.select\t$dst, $lhs, $rhs, $cond", 0x1b>; def SELECT_F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs, I32:$cond), [(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))], - "f64.select\t$dst, $lhs, $rhs, $cond">; + "f64.select\t$dst, $lhs, $rhs, $cond", 0x1b>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index f094aae9c90..b38dd2070ce 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -180,13 +180,6 @@ defm : LOCAL<F32>; defm : LOCAL<F64>; defm : LOCAL<V128>, Requires<[HasSIMD128]>; -// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates. -// Set TSFlags{2} to 1 to indicate that the immediates are ValTypes. -def DECLARE_LOCALS : I<(outs), (ins variable_ops), [], ".local \t"> { - let TSFlags{0} = 1; - let TSFlags{2} = 1; -} - let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), [(set I32:$res, imm:$imm)], diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td index ab28dd3e1c7..7cdeb397be9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td @@ -75,10 +75,10 @@ let Defs = [ARGUMENTS] in { def SELECT_I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs, I32:$cond), [(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))], - "i32.select\t$dst, $lhs, $rhs, $cond">; + "i32.select\t$dst, $lhs, $rhs, $cond", 0x1b>; def SELECT_I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs, I32:$cond), [(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))], - "i64.select\t$dst, $lhs, $rhs, $cond">; + "i64.select\t$dst, $lhs, $rhs, $cond", 0x1b>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index 61382cd0640..c5702ce11ad 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -28,6 +28,7 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo { std::vector<MVT> Params; std::vector<MVT> Results; + std::vector<MVT> Locals; /// A mapping from CodeGen vreg index to WebAssembly register number. std::vector<unsigned> WARegs; @@ -55,6 +56,9 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo { void addResult(MVT VT) { Results.push_back(VT); } const std::vector<MVT> &getResults() const { return Results; } + void addLocal(MVT VT) { Locals.push_back(VT); } + const std::vector<MVT> &getLocals() const { return Locals; } + unsigned getVarargBufferVreg() const { assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); return VarargVreg; |