From 0de587296ebdc071086d35e888aa850c0c97340d Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 8 Mar 2018 04:05:37 +0000 Subject: [PATCH] [WebAssembly] Add except_ref as a first-class type Summary: Add except_ref as a first-class type, according to the [[https://github.com/WebAssembly/exception-handling/blob/master/proposals/Level-1.md | Level 1 exception handling proposal ]]. Reviewers: dschuff Subscribers: jfb, sbc100, llvm-commits Differential Revision: https://reviews.llvm.org/D43706 llvm-svn: 326985 --- llvm/include/llvm/BinaryFormat/Wasm.h | 2 ++ llvm/include/llvm/CodeGen/MachineValueType.h | 5 +++- llvm/include/llvm/CodeGen/ValueTypes.td | 1 + .../InstPrinter/WebAssemblyInstPrinter.cpp | 5 ++++ .../MCTargetDesc/WebAssemblyMCTargetDesc.cpp | 1 + .../MCTargetDesc/WebAssemblyMCTargetDesc.h | 25 ++++++++++--------- .../Target/WebAssembly/WebAssemblyCFGStackify.cpp | 1 + .../WebAssembly/WebAssemblyExplicitLocals.cpp | 10 ++++++++ .../lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 17 +++++++++++++ .../lib/Target/WebAssembly/WebAssemblyInstrCall.td | 7 ++++++ .../Target/WebAssembly/WebAssemblyInstrControl.td | 1 + .../WebAssembly/WebAssemblyInstrExceptRef.td | 29 ++++++++++++++++++++++ .../lib/Target/WebAssembly/WebAssemblyInstrInfo.td | 3 +++ .../Target/WebAssembly/WebAssemblyRegisterInfo.td | 4 +-- llvm/utils/TableGen/CodeGenTarget.cpp | 1 + 15 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h index 893eab8..eab1a54 100644 --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -185,6 +185,7 @@ enum : unsigned { WASM_TYPE_F32 = 0x7D, WASM_TYPE_F64 = 0x7C, WASM_TYPE_ANYFUNC = 0x70, + WASM_TYPE_EXCEPT_REF = 0x68, WASM_TYPE_FUNC = 0x60, WASM_TYPE_NORESULT = 0x40, // for blocks with no result values }; @@ -217,6 +218,7 @@ enum class ValType { I64 = WASM_TYPE_I64, F32 = WASM_TYPE_F32, F64 = WASM_TYPE_F64, + EXCEPT_REF = WASM_TYPE_EXCEPT_REF, }; // Kind codes used in the custom "name" section diff --git a/llvm/include/llvm/CodeGen/MachineValueType.h b/llvm/include/llvm/CodeGen/MachineValueType.h index b452684..f1a77d2 100644 --- a/llvm/include/llvm/CodeGen/MachineValueType.h +++ b/llvm/include/llvm/CodeGen/MachineValueType.h @@ -191,8 +191,10 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + ExceptRef = 113, // WebAssembly's except_ref type + FIRST_VALUETYPE = 1, // This is always the beginning of the list. - LAST_VALUETYPE = 113, // This always remains at the end of the list. + LAST_VALUETYPE = 114, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -746,6 +748,7 @@ namespace llvm { case v64i32: case v32i64: case nxv32i64: return 2048; + case ExceptRef: return 0; // opaque type } } diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td index 73c7fb4..845dc92 100644 --- a/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/llvm/include/llvm/CodeGen/ValueTypes.td @@ -145,6 +145,7 @@ def x86mmx : ValueType<64 , 109>; // X86 MMX value def FlagVT : ValueType<0 , 110>; // Pre-RA sched glue def isVoid : ValueType<0 , 111>; // Produces no value def untyped: ValueType<8 , 112>; // Produces an untyped value +def ExceptRef: ValueType<0, 113>; // WebAssembly's except_ref type def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 73d9b3d..639dd63 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -220,6 +220,7 @@ WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI, case WebAssembly::ExprType::B8x16: O << "b8x16"; break; case WebAssembly::ExprType::B16x8: O << "b16x8"; break; case WebAssembly::ExprType::B32x4: O << "b32x4"; break; + case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break; } } @@ -238,6 +239,8 @@ const char *llvm::WebAssembly::TypeToString(MVT Ty) { case MVT::v4i32: case MVT::v4f32: return "v128"; + case MVT::ExceptRef: + return "except_ref"; default: llvm_unreachable("unsupported type"); } @@ -253,6 +256,8 @@ const char *llvm::WebAssembly::TypeToString(wasm::ValType Type) { return "f32"; case wasm::ValType::F64: return "f64"; + case wasm::ValType::EXCEPT_REF: + return "except_ref"; } llvm_unreachable("unsupported type"); } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp index e7c8809..a51fb92 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -135,6 +135,7 @@ wasm::ValType WebAssembly::toValType(const MVT &Ty) { case MVT::i64: return wasm::ValType::I64; case MVT::f32: return wasm::ValType::F32; case MVT::f64: return wasm::ValType::F64; + case MVT::ExceptRef: return wasm::ValType::EXCEPT_REF; default: llvm_unreachable("unexpected type"); } } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index e27a740..364aac3 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -159,18 +159,19 @@ static const unsigned StoreP2AlignOperandNo = 0; /// This is used to indicate block signatures. enum class ExprType : unsigned { - Void = 0x40, - I32 = 0x7F, - I64 = 0x7E, - F32 = 0x7D, - F64 = 0x7C, - I8x16 = 0x7B, - I16x8 = 0x7A, - I32x4 = 0x79, - F32x4 = 0x78, - B8x16 = 0x77, - B16x8 = 0x76, - B32x4 = 0x75 + Void = 0x40, + I32 = 0x7F, + I64 = 0x7E, + F32 = 0x7D, + F64 = 0x7C, + I8x16 = 0x7B, + I16x8 = 0x7A, + I32x4 = 0x79, + F32x4 = 0x78, + B8x16 = 0x77, + B16x8 = 0x76, + B32x4 = 0x75, + ExceptRef = 0x68 }; /// Instruction opcodes emitted via means other than CodeGen. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 21e0f6b..cab2100 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -249,6 +249,7 @@ static void FixEndsAtEndOfFunction( case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break; case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break; case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break; + case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break; default: llvm_unreachable("unexpected return type"); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp index e2edb92..e6229b9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -86,6 +86,8 @@ static unsigned getDropOpcode(const TargetRegisterClass *RC) { return WebAssembly::DROP_F64; if (RC == &WebAssembly::V128RegClass) return WebAssembly::DROP_V128; + if (RC == &WebAssembly::EXCEPT_REFRegClass) + return WebAssembly::DROP_EXCEPT_REF; llvm_unreachable("Unexpected register class"); } @@ -101,6 +103,8 @@ static unsigned getGetLocalOpcode(const TargetRegisterClass *RC) { return WebAssembly::GET_LOCAL_F64; if (RC == &WebAssembly::V128RegClass) return WebAssembly::GET_LOCAL_V128; + if (RC == &WebAssembly::EXCEPT_REFRegClass) + return WebAssembly::GET_LOCAL_EXCEPT_REF; llvm_unreachable("Unexpected register class"); } @@ -116,6 +120,8 @@ static unsigned getSetLocalOpcode(const TargetRegisterClass *RC) { return WebAssembly::SET_LOCAL_F64; if (RC == &WebAssembly::V128RegClass) return WebAssembly::SET_LOCAL_V128; + if (RC == &WebAssembly::EXCEPT_REFRegClass) + return WebAssembly::SET_LOCAL_EXCEPT_REF; llvm_unreachable("Unexpected register class"); } @@ -131,6 +137,8 @@ static unsigned getTeeLocalOpcode(const TargetRegisterClass *RC) { return WebAssembly::TEE_LOCAL_F64; if (RC == &WebAssembly::V128RegClass) return WebAssembly::TEE_LOCAL_V128; + if (RC == &WebAssembly::EXCEPT_REFRegClass) + return WebAssembly::TEE_LOCAL_EXCEPT_REF; llvm_unreachable("Unexpected register class"); } @@ -144,6 +152,8 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) { return MVT::f32; if (RC == &WebAssembly::F64RegClass) return MVT::f64; + if (RC == &WebAssembly::EXCEPT_REFRegClass) + return MVT::ExceptRef; llvm_unreachable("unrecognized register class"); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 59bf1ad..f3ee6e7 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -127,6 +127,7 @@ private: case MVT::i64: case MVT::f32: case MVT::f64: + case MVT::ExceptRef: return VT; case MVT::f16: return MVT::f32; @@ -681,6 +682,10 @@ bool WebAssemblyFastISel::fastLowerArguments() { Opc = WebAssembly::ARGUMENT_v4f32; RC = &WebAssembly::V128RegClass; break; + case MVT::ExceptRef: + Opc = WebAssembly::ARGUMENT_EXCEPT_REF; + RC = &WebAssembly::EXCEPT_REFRegClass; + break; default: return false; } @@ -770,6 +775,11 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32; ResultReg = createResultReg(&WebAssembly::V128RegClass); break; + case MVT::ExceptRef: + Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF + : WebAssembly::PCALL_INDIRECT_EXCEPT_REF; + ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass); + break; default: return false; } @@ -868,6 +878,10 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) { Opc = WebAssembly::SELECT_F64; RC = &WebAssembly::F64RegClass; break; + case MVT::ExceptRef: + Opc = WebAssembly::SELECT_EXCEPT_REF; + RC = &WebAssembly::EXCEPT_REFRegClass; + break; default: return false; } @@ -1274,6 +1288,9 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) { case MVT::v4f32: Opc = WebAssembly::RETURN_v4f32; break; + case MVT::ExceptRef: + Opc = WebAssembly::RETURN_EXCEPT_REF; + break; default: return false; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 6b45839..8874fe5 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -72,6 +72,7 @@ let Uses = [SP32, SP64], isCall = 1 in { defm : CALL; defm : CALL; defm : CALL; + defm : CALL; defm : SIMD_CALL; defm : SIMD_CALL; defm : SIMD_CALL; @@ -112,6 +113,9 @@ def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_v4i32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(ExceptRef + (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), + (CALL_EXCEPT_REF tglobaladdr:$callee)>; def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)), (CALL_VOID tglobaladdr:$callee)>; @@ -132,5 +136,8 @@ def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (CALL_v4i32 texternalsym:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(ExceptRef + (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), + (CALL_EXCEPT_REF texternalsym:$callee)>; def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)), (CALL_VOID texternalsym:$callee)>; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td index 1f1d438..18ffba7 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -98,6 +98,7 @@ let isReturn = 1 in { defm : RETURN; defm : RETURN; defm : RETURN; + defm : RETURN; defm : SIMD_RETURN; defm : SIMD_RETURN; defm : SIMD_RETURN; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td new file mode 100644 index 0000000..921e7ab --- /dev/null +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td @@ -0,0 +1,29 @@ +// WebAssemblyInstrExceptRef.td-WebAssembly except_ref codegen --*- tablegen -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief WebAssembly except_ref operand code-gen constructs. +/// +//===----------------------------------------------------------------------===// + +let Defs = [ARGUMENTS] in { + +def SELECT_EXCEPT_REF : I<(outs EXCEPT_REF:$dst), + (ins EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond), + [(set EXCEPT_REF:$dst, + (select I32:$cond, EXCEPT_REF:$lhs, + EXCEPT_REF:$rhs))], + "except_ref.select\t$dst, $lhs, $rhs, $cond", 0x1b>; + +} // Defs = [ARGUMENTS] + +def : Pat<(select (i32 (setne I32:$cond, 0)), EXCEPT_REF:$lhs, EXCEPT_REF:$rhs), + (SELECT_EXCEPT_REF EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond)>; +def : Pat<(select (i32 (seteq I32:$cond, 0)), EXCEPT_REF:$lhs, EXCEPT_REF:$rhs), + (SELECT_EXCEPT_REF EXCEPT_REF:$rhs, EXCEPT_REF:$lhs, I32:$cond)>; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index f5a1be1..64695fb 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -166,6 +166,7 @@ defm : ARGUMENT; defm : ARGUMENT; defm : ARGUMENT; defm : ARGUMENT; +defm : ARGUMENT; defm : SIMD_ARGUMENT; defm : SIMD_ARGUMENT; defm : SIMD_ARGUMENT; @@ -232,6 +233,7 @@ defm : LOCAL; defm : LOCAL; defm : LOCAL; defm : LOCAL, Requires<[HasSIMD128]>; +defm : LOCAL, Requires<[HasExceptionHandling]>; let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), @@ -267,3 +269,4 @@ include "WebAssemblyInstrConv.td" include "WebAssemblyInstrFloat.td" include "WebAssemblyInstrAtomics.td" include "WebAssemblyInstrSIMD.td" +include "WebAssemblyInstrExceptRef.td" diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td index 9088810..2110872 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td @@ -38,8 +38,8 @@ def SP64 : WebAssemblyReg<"%SP64">; // since we otherwise don't need a physical register in those classes. def F32_0 : WebAssemblyReg<"%f32.0">; def F64_0 : WebAssemblyReg<"%f64.0">; - def V128_0: WebAssemblyReg<"%v128">; +def EXCEPT_REF_0 : WebAssemblyReg<"%except_ref.0">; // The value stack "register". This is an opaque entity which serves to order // uses and defs that must remain in LIFO order. @@ -59,4 +59,4 @@ def I64 : WebAssemblyRegClass<[i64], 64, (add FP64, SP64)>; def F32 : WebAssemblyRegClass<[f32], 32, (add F32_0)>; def F64 : WebAssemblyRegClass<[f64], 64, (add F64_0)>; def V128 : WebAssemblyRegClass<[v4f32, v4i32, v16i8, v8i16], 128, (add V128_0)>; - +def EXCEPT_REF : WebAssemblyRegClass<[ExceptRef], 0, (add EXCEPT_REF_0)>; diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index 451d305..41f0e04 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -174,6 +174,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) { case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; case MVT::Untyped: return "MVT::Untyped"; + case MVT::ExceptRef: return "MVT::ExceptRef"; default: llvm_unreachable("ILLEGAL VALUE TYPE!"); } } -- 2.7.4