diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 78220d4d8ff5b..5ef92d2dd5953 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1725,6 +1725,9 @@ class ASTContext : public RefCountedBase { /// Return a WebAssembly externref type. QualType getWebAssemblyExternrefType() const; + /// Return a WebAssembly non null externref type. + QualType getWebAssemblyNonNullExternrefType() const; + /// Return the unique reference to a vector type of the specified /// element type and size. /// diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 625cc77dc1f08..b6ff06dd32eab 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -1146,6 +1146,9 @@ class QualType { /// Returns true if it is a WebAssembly Externref Type. bool isWebAssemblyExternrefType() const; + /// Check if this is a WebAssembly non null Externref Type. + bool isWebAssemblyNonNullExternrefType() const; + /// Returns true if it is a WebAssembly Funcref Type. bool isWebAssemblyFuncrefType() const; @@ -2438,6 +2441,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { /// Check if this is a WebAssembly Externref Type. bool isWebAssemblyExternrefType() const; + /// Returns true if it is a WebAssembly non null Externref Type. + bool isWebAssemblyNonNullExternrefType() const; + /// Returns true if this is a WebAssembly table type: either an array of /// reference types, or a pointer to a reference type (which can only be /// created by array to pointer decay). diff --git a/clang/include/clang/Basic/WebAssemblyReferenceTypes.def b/clang/include/clang/Basic/WebAssemblyReferenceTypes.def index 7c83da15150ce..296bc45cff4c9 100644 --- a/clang/include/clang/Basic/WebAssemblyReferenceTypes.def +++ b/clang/include/clang/Basic/WebAssemblyReferenceTypes.def @@ -36,5 +36,7 @@ WASM_REF_TYPE("__externref_t", "externref_t", WasmExternRef, WasmExternRefTy, 10) +WASM_REF_TYPE("__non_null_externref_t", "non_null_externref_t", WasmNonNullExternRef, WasmNonNullExternRefTy, 11) + #undef WASM_TYPE #undef WASM_REF_TYPE diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index a8b41ba18fa01..ed50b7c88a23d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3462,6 +3462,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, #define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id: #include "clang/Basic/AMDGPUTypes.def" case BuiltinType::WasmExternRef: + case BuiltinType::WasmNonNullExternRef: #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" llvm_unreachable("not yet implemented"); @@ -4488,7 +4489,8 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const { QualType ASTContext::getWebAssemblyExternrefType() const { if (Target->getTriple().isWasm() && Target->hasFeature("reference-types")) { #define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ - if (BuiltinType::Id == BuiltinType::WasmExternRef) \ + if (BuiltinType::Id == BuiltinType::WasmExternRef || \ + BuiltinType::Id == BuiltinType::WasmNonNullExternRef) \ return SingletonId; #include "clang/Basic/WebAssemblyReferenceTypes.def" } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index ee7a68ee8ba7e..a9801db03f3fc 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2555,6 +2555,12 @@ bool Type::isWebAssemblyExternrefType() const { return false; } +bool Type::isWebAssemblyNonNullExternrefType() const { + if (const auto *BT = getAs()) + return BT->getKind() == BuiltinType::WasmNonNullExternRef; + return false; +} + bool Type::isWebAssemblyTableType() const { if (const auto *ATy = dyn_cast(this)) return ATy->getElementType().isWebAssemblyReferenceType(); @@ -2938,13 +2944,18 @@ bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) { } bool QualType::isWebAssemblyReferenceType() const { - return isWebAssemblyExternrefType() || isWebAssemblyFuncrefType(); + return isWebAssemblyExternrefType() || isWebAssemblyNonNullExternrefType() || + isWebAssemblyFuncrefType(); } bool QualType::isWebAssemblyExternrefType() const { return getTypePtr()->isWebAssemblyExternrefType(); } +bool QualType::isWebAssemblyNonNullExternrefType() const { + return getTypePtr()->isWebAssemblyNonNullExternrefType(); +} + bool QualType::isWebAssemblyFuncrefType() const { return getTypePtr()->isFunctionPointerType() && getAddressSpace() == LangAS::wasm_funcref; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 3ffe999d01178..7197dbcdfc5a1 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -570,6 +570,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case BuiltinType::Id: { \ if (BuiltinType::Id == BuiltinType::WasmExternRef) \ ResultType = CGM.getTargetCodeGenInfo().getWasmExternrefReferenceType(); \ + else if (BuiltinType::Id == BuiltinType::WasmNonNullExternRef) \ + ResultType = \ + CGM.getTargetCodeGenInfo().getWasmNonNullExternrefReferenceType(); \ else \ llvm_unreachable("Unexpected wasm reference builtin type!"); \ } break; diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index d0edae1295094..b31a993cfe495 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -418,6 +418,10 @@ class TargetCodeGenInfo { /// Return the WebAssembly externref reference type. virtual llvm::Type *getWasmExternrefReferenceType() const { return nullptr; } + /// Return the WebAssembly externref reference type. + virtual llvm::Type *getWasmNonNullExternrefReferenceType() const { + return nullptr; + } /// Return the WebAssembly funcref reference type. virtual llvm::Type *getWasmFuncrefReferenceType() const { return nullptr; } diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index ebe996a4edd8d..2ae6e690e21af 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -89,6 +89,9 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { virtual llvm::Type *getWasmExternrefReferenceType() const override { return llvm::Type::getWasm_ExternrefTy(getABIInfo().getVMContext()); } + virtual llvm::Type *getWasmNonNullExternrefReferenceType() const override { + return llvm::Type::getWasm_NonNullExternrefTy(getABIInfo().getVMContext()); + } /// Return the WebAssembly funcref reference type. virtual llvm::Type *getWasmFuncrefReferenceType() const override { return llvm::Type::getWasm_FuncrefTy(getABIInfo().getVMContext()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0e83c20b27c22..9576ce8e54913 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13766,6 +13766,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { return; } + if (VDecl->getType().isWebAssemblyExternrefType() && + Init->getType()->isWebAssemblyNonNullExternrefType()) { + VDecl->setInit(Init); + return; + } + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (VDecl->getType()->isUndeducedType()) { if (Init->containsErrors()) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 01abc1fb2cd37..f424058d4727f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9714,6 +9714,12 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType, return AssignConvertType::Compatible; } + if (LHSType->isWebAssemblyExternrefType() && + RHSType->isWebAssemblyNonNullExternrefType()) { + Kind = CK_NoOp; + return AssignConvertType::Compatible; + } + return AssignConvertType::Incompatible; } diff --git a/clang/test/CodeGen/WebAssembly/wasm-externref.c b/clang/test/CodeGen/WebAssembly/wasm-externref.c index 788438bb4a86a..1bc9f74f46074 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-externref.c +++ b/clang/test/CodeGen/WebAssembly/wasm-externref.c @@ -2,8 +2,10 @@ // RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s typedef __externref_t externref_t; +typedef __non_null_externref_t nn_externref_t; void helper(externref_t); +void helper_2(nn_externref_t); // CHECK-LABEL: @handle( // CHECK-NEXT: entry: @@ -16,3 +18,48 @@ void helper(externref_t); void handle(externref_t obj) { helper(obj); } + + +// CHECK-LABEL: @handle_2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca ptr addrspace(11), align 1 +// CHECK-NEXT: store ptr addrspace(11) [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(11), ptr [[OBJ_ADDR]], align 1 +// CHECK-NEXT: call void @helper_2(ptr addrspace(11) [[TMP0]]) +// CHECK-NEXT: ret void +// +void handle_2(nn_externref_t obj) { + helper_2(obj); +} + + +nn_externref_t socketpair_js_concat(nn_externref_t, nn_externref_t) +__attribute__((import_module("wasm:js-string"), import_name("concat"))); + +nn_externref_t get_string_ref(const char *s); +void print_string_ref(nn_externref_t); + +// CHECK-LABEL: @socketpair_example( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[STR1:%.*]] = alloca ptr addrspace(11), align 1 +// CHECK-NEXT: [[STR2:%.*]] = alloca ptr addrspace(11), align 1 +// CHECK-NEXT: [[RESULT:%.*]] = alloca ptr addrspace(11), align 1 +// CHECK-NEXT: [[CALL:%.*]] = call ptr addrspace(11) @get_string_ref(ptr noundef @.str) +// CHECK-NEXT: store ptr addrspace(11) [[CALL]], ptr [[STR1]], align 1 +// CHECK-NEXT: [[CALL1:%.*]] = call ptr addrspace(11) @get_string_ref(ptr noundef @.str.1) +// CHECK-NEXT: store ptr addrspace(11) [[CALL1]], ptr [[STR2]], align 1 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(11), ptr [[STR1]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(11), ptr [[STR2]], align 1 +// CHECK-NEXT: [[CALL2:%.*]] = call ptr addrspace(11) @socketpair_js_concat(ptr addrspace(11) [[TMP0]], ptr addrspace(11) [[TMP1]]) +// CHECK-NEXT: store ptr addrspace(11) [[CALL2]], ptr [[RESULT]], align 1 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(11), ptr [[RESULT]], align 1 +// CHECK-NEXT: call void @print_string_ref(ptr addrspace(11) [[TMP2]]) +// CHECK-NEXT: ret void +// +void socketpair_example() { + nn_externref_t str1 = get_string_ref("Hello, "); + nn_externref_t str2 = get_string_ref("world!"); + nn_externref_t result = socketpair_js_concat(str1, str2); + print_string_ref(result); +} + diff --git a/clang/test/Sema/wasm-refs-and-tables.c b/clang/test/Sema/wasm-refs-and-tables.c index dd8536c52cd03..2c5b8307998b1 100644 --- a/clang/test/Sema/wasm-refs-and-tables.c +++ b/clang/test/Sema/wasm-refs-and-tables.c @@ -9,6 +9,10 @@ __externref_t r1; extern __externref_t r2; static __externref_t r3; +__non_null_externref_t nn_r1; +extern __non_null_externref_t nn_r2; +static __non_null_externref_t nn_r3; + __externref_t *t1; // expected-error {{pointer to WebAssembly reference type is not allowed}} __externref_t **t2; // expected-error {{pointer to WebAssembly reference type is not allowed}} __externref_t ******t3; // expected-error {{pointer to WebAssembly reference type is not allowed}} @@ -19,10 +23,24 @@ __externref_t t7[0]; // expected-error {{WebAssembly table must be s static __externref_t t8[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} static __externref_t (*t9)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} +__non_null_externref_t *nn_t1; // expected-error {{pointer to WebAssembly reference type is not allowed}} +__non_null_externref_t **nn_t2; // expected-error {{pointer to WebAssembly reference type is not allowed}} +__non_null_externref_t ******nn_t3; // expected-error {{pointer to WebAssembly reference type is not allowed}} +static __non_null_externref_t nn_t4[3]; // expected-error {{only zero-length WebAssembly tables are currently supported}} +static __non_null_externref_t nn_t5[]; // expected-error {{only zero-length WebAssembly tables are currently supported}} +static __non_null_externref_t nn_t6[] = {0}; // expected-error {{only zero-length WebAssembly tables are currently supported}} +__non_null_externref_t nn_t7[0]; // expected-error {{WebAssembly table must be static}} +static __non_null_externref_t nn_t8[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} +static __non_null_externref_t (*nn_t9)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} + static __externref_t table[0]; static __externref_t other_table[0] = {}; static __externref_t another_table[] = {}; // expected-error {{only zero-length WebAssembly tables are currently supported}} +static __non_null_externref_t nn_table[0]; +static __non_null_externref_t nn_other_table[0] = {}; +static __non_null_externref_t nn_another_table[] = {}; // expected-error {{only zero-length WebAssembly tables are currently supported}} + struct s { __externref_t f1; // expected-error {{field has sizeless type '__externref_t'}} __externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}} @@ -33,6 +51,17 @@ struct s { __externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} }; + +struct nn_s { + __non_null_externref_t nn_f1; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f2[0]; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f3[]; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} + __non_null_externref_t *nn_f5; // expected-error {{pointer to WebAssembly reference type is not allowed}} + __non_null_externref_t ****nn_f6; // expected-error {{pointer to WebAssembly reference type is not allowed}} + __non_null_externref_t (*nn_f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} +}; + union u { __externref_t f1; // expected-error {{field has sizeless type '__externref_t'}} __externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}} @@ -43,16 +72,38 @@ union u { __externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} }; + +union nn_u { + __non_null_externref_t nn_f1; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f2[0]; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f3[]; // expected-error {{field has sizeless type '__non_null_externref_t'}} + __non_null_externref_t nn_f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} + __non_null_externref_t *nn_f5; // expected-error {{pointer to WebAssembly reference type is not allowed}} + __non_null_externref_t ****nn_f6; // expected-error {{pointer to WebAssembly reference type is not allowed}} + __non_null_externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} +}; + void illegal_argument_1(__externref_t table[]); // expected-error {{cannot use WebAssembly table as a function parameter}} void illegal_argument_2(__externref_t table[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} void illegal_argument_3(__externref_t *table); // expected-error {{pointer to WebAssembly reference type is not allowed}} void illegal_argument_4(__externref_t ***table); // expected-error {{pointer to WebAssembly reference type is not allowed}} void illegal_argument_5(__externref_t (*table)[0]); // expected-error {{cannot form a pointer to a WebAssembly table}} void illegal_argument_6(__externref_t table[0]); // expected-error {{cannot use WebAssembly table as a function parameter}} + +void illegal_nn_argument_1(__non_null_externref_t table[]); // expected-error {{cannot use WebAssembly table as a function parameter}} +void illegal_nn_argument_2(__non_null_externref_t table[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}} +void illegal_nn_argument_3(__non_null_externref_t *table); // expected-error {{pointer to WebAssembly reference type is not allowed}} +void illegal_nn_argument_4(__non_null_externref_t ***table); // expected-error {{pointer to WebAssembly reference type is not allowed}} +void illegal_nn_argument_5(__non_null_externref_t (*table)[0]); // expected-error {{cannot form a pointer to a WebAssembly table}} +void illegal_nn_argument_6(__non_null_externref_t table[0]); // expected-error {{cannot use WebAssembly table as a function parameter}} __externref_t *illegal_return_1(); // expected-error {{pointer to WebAssembly reference type is not allowed}} __externref_t ***illegal_return_2(); // expected-error {{pointer to WebAssembly reference type is not allowed}} __externref_t (*illegal_return_3())[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} + +__non_null_externref_t *illegal_nn_return_1(); // expected-error {{pointer to WebAssembly reference type is not allowed}} +__non_null_externref_t ***illegal_nn_return_2(); // expected-error {{pointer to WebAssembly reference type is not allowed}} +__non_null_externref_t (*illegal_nn_return_3())[0]; // expected-error {{cannot form a pointer to a WebAssembly table}} void varargs(int, ...); typedef void (*__funcref funcref_t)(); @@ -133,3 +184,15 @@ void foo() { void *ret_void_ptr() { return table; // expected-error {{cannot return a WebAssembly table}} } + +// checks all related assignment from extern ref to non null extern ref and vice versa +void externref_assignment(__externref_t er, __non_null_externref_t nn_er) { + __externref_t asg_1 = er; + __externref_t asg_2 = nn_er; + + __non_null_externref_t nn_asg_1 = er; // conly-error {{initializing '__non_null_externref_t' with an expression of incompatible type '__externref_t'}} \ + // cpp-error {{cannot initialize a variable of type '__non_null_externref_t' with an lvalue of type '__externref_t'}} + __non_null_externref_t nn_asg_2 = nn_er; + + +} diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td index 300addd7d4daf..5200a573d40c5 100644 --- a/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/llvm/include/llvm/CodeGen/ValueTypes.td @@ -347,25 +347,26 @@ def untyped : ValueType<8, 243> { // Produces an untyped value } def funcref : ValueType<0, 244>; // WebAssembly's funcref type def externref : ValueType<0, 245>; // WebAssembly's externref type -def exnref : ValueType<0, 246>; // WebAssembly's exnref type -def x86amx : ValueType<8192, 247>; // X86 AMX value -def i64x8 : ValueType<512, 248>; // 8 Consecutive GPRs (AArch64) +def externref_nn : ValueType<0, 246>; // WebAssembly's nonnull externref type +def exnref : ValueType<0, 247>; // WebAssembly's exnref type +def x86amx : ValueType<8192, 248>; // X86 AMX value +def i64x8 : ValueType<512, 249>; // 8 Consecutive GPRs (AArch64) def aarch64svcount - : ValueType<16, 249>; // AArch64 predicate-as-counter -def spirvbuiltin : ValueType<0, 250>; // SPIR-V's builtin type + : ValueType<16, 250>; // AArch64 predicate-as-counter +def spirvbuiltin : ValueType<0, 251>; // SPIR-V's builtin type // AMDGPU buffer fat pointer, buffer rsrc + offset, rewritten before MIR translation. // FIXME: Remove this and the getPointerType() override if MVT::i160 is added. -def amdgpuBufferFatPointer : ValueType<160, 251>; +def amdgpuBufferFatPointer : ValueType<160, 252>; // AMDGPU buffer strided pointer, buffer rsrc + index + offset, doesn't reach MIR. // FIXME: Remove this and the getPointerType() override if MVT::i82 is added. -def amdgpuBufferStridedPointer : ValueType<192, 252>; +def amdgpuBufferStridedPointer : ValueType<192, 253>; -def aarch64mfp8 : ValueType<8, 253>; // 8-bit value in FPR (AArch64) +def aarch64mfp8 : ValueType<8, 254>; // 8-bit value in FPR (AArch64) // CHERI capabilities. Pointer-like values that carry additional metadata // for enforcing safety guarantees on CHERI-enabled targets. -def c64 : VTCheriCapability<64, 254>; // 64-bit CHERI capability value -def c128 : VTCheriCapability<128, 255>; // 128-bit CHERI capability value +def c64 : VTCheriCapability<64, 255>; // 64-bit CHERI capability value +def c128 : VTCheriCapability<128, 256>; // 128-bit CHERI capability value let isNormalValueType = false in { // Pseudo valuetype mapped to the current CHERI capability pointer size. diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 8856eda250ed6..e05eb3e0b9ca6 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -596,6 +596,7 @@ def llvm_v16f64_ty : LLVMType; // 16 x double def llvm_vararg_ty : LLVMType; // this means vararg here def llvm_externref_ty : LLVMType; +def llvm_externref_nn_ty : LLVMType; def llvm_funcref_ty : LLVMType; def llvm_exnref_ty : LLVMType; diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index c1e4b97e96bc8..d5f1b1b9f8dc4 100644 --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -29,6 +29,11 @@ def int_wasm_memory_grow : //===----------------------------------------------------------------------===// def int_wasm_ref_null_extern : DefaultAttrsIntrinsic<[llvm_externref_ty], [], [IntrNoMem]>; + +// TODO: Is this correct? +def int_wasm_ref_nonnull_extern + : DefaultAttrsIntrinsic<[llvm_externref_nn_ty], [], [IntrNoMem]>; + def int_wasm_ref_null_func : DefaultAttrsIntrinsic<[llvm_funcref_ty], [], [IntrNoMem]>; def int_wasm_ref_null_exn: diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h index 1c042500ba8ec..8c6b629d10f27 100644 --- a/llvm/include/llvm/IR/Type.h +++ b/llvm/include/llvm/IR/Type.h @@ -479,6 +479,7 @@ class Type { // Convenience methods for getting pointer types. // LLVM_ABI static Type *getWasm_ExternrefTy(LLVMContext &C); + LLVM_ABI static Type *getWasm_NonNullExternrefTy(LLVMContext &C); LLVM_ABI static Type *getWasm_FuncrefTy(LLVMContext &C); /// Return a pointer to the current type. This is equivalent to diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index 9db48e8f6a96b..95f7c3c33275c 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -307,6 +307,12 @@ Type *Type::getWasm_ExternrefTy(LLVMContext &C) { return PointerType::get(C, 10); } +Type *Type::getWasm_NonNullExternrefTy(LLVMContext &C) { + // opaque pointer in addrspace(11) + static PointerType *Ty = PointerType::get(C, 11); + return Ty; +} + Type *Type::getWasm_FuncrefTy(LLVMContext &C) { // opaque pointer in addrspace(20) return PointerType::get(C, 20);