Skip to content

Commit 2247121

Browse files
committed
Add scaffolding and drafting support for nonnull_extern_ref type
1 parent 44582c9 commit 2247121

File tree

13 files changed

+147
-2
lines changed

13 files changed

+147
-2
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
16751675
/// Return a WebAssembly externref type.
16761676
QualType getWebAssemblyExternrefType() const;
16771677

1678+
/// Return a WebAssembly non null externref type.
1679+
QualType getWebAssemblyNonNullExternrefType() const;
1680+
16781681
/// Return the unique reference to a vector type of the specified
16791682
/// element type and size.
16801683
///

clang/include/clang/AST/Type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,9 @@ class QualType {
11451145
/// Returns true if it is a WebAssembly Externref Type.
11461146
bool isWebAssemblyExternrefType() const;
11471147

1148+
/// Returns true if it is a WebAssembly non null Externref Type.
1149+
bool isWebAssemblyNonNullExternrefType() const;
1150+
11481151
/// Returns true if it is a WebAssembly Funcref Type.
11491152
bool isWebAssemblyFuncrefType() const;
11501153

@@ -2402,6 +2405,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
24022405
/// Check if this is a WebAssembly Externref Type.
24032406
bool isWebAssemblyExternrefType() const;
24042407

2408+
/// Check if this is a WebAssembly non null Externref Type.
2409+
bool isWebAssemblyNonNullExternrefType() const;
2410+
24052411
/// Returns true if this is a WebAssembly table type: either an array of
24062412
/// reference types, or a pointer to a reference type (which can only be
24072413
/// created by array to pointer decay).

clang/include/clang/Basic/WebAssemblyReferenceTypes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,7 @@
3636

3737
WASM_REF_TYPE("__externref_t", "externref_t", WasmExternRef, WasmExternRefTy, 10)
3838

39+
WASM_REF_TYPE("__non_null_externref_t", "non_null_externref_t", WasmNonNullExternRef, WasmNonNullExternRefTy, 10)
40+
3941
#undef WASM_TYPE
4042
#undef WASM_REF_TYPE

clang/lib/AST/ASTContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3550,6 +3550,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
35503550
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
35513551
#include "clang/Basic/AMDGPUTypes.def"
35523552
case BuiltinType::WasmExternRef:
3553+
case BuiltinType::WasmNonNullExternRef:
35533554
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
35543555
#include "clang/Basic/RISCVVTypes.def"
35553556
llvm_unreachable("not yet implemented");
@@ -4584,7 +4585,8 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const {
45844585
QualType ASTContext::getWebAssemblyExternrefType() const {
45854586
if (Target->getTriple().isWasm() && Target->hasFeature("reference-types")) {
45864587
#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \
4587-
if (BuiltinType::Id == BuiltinType::WasmExternRef) \
4588+
if (BuiltinType::Id == BuiltinType::WasmExternRef || \
4589+
BuiltinType::Id == BuiltinType::WasmNonNullExternRef) \
45884590
return SingletonId;
45894591
#include "clang/Basic/WebAssemblyReferenceTypes.def"
45904592
}

clang/lib/AST/Type.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,12 @@ bool Type::isWebAssemblyExternrefType() const {
25532553
return false;
25542554
}
25552555

2556+
bool Type::isWebAssemblyNonNullExternrefType() const {
2557+
if (const auto *BT = getAs<BuiltinType>())
2558+
return BT->getKind() == BuiltinType::WasmNonNullExternRef;
2559+
return false;
2560+
}
2561+
25562562
bool Type::isWebAssemblyTableType() const {
25572563
if (const auto *ATy = dyn_cast<ArrayType>(this))
25582564
return ATy->getElementType().isWebAssemblyReferenceType();
@@ -2922,13 +2928,18 @@ bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
29222928
}
29232929

29242930
bool QualType::isWebAssemblyReferenceType() const {
2925-
return isWebAssemblyExternrefType() || isWebAssemblyFuncrefType();
2931+
return isWebAssemblyExternrefType() || isWebAssemblyNonNullExternrefType() ||
2932+
isWebAssemblyFuncrefType();
29262933
}
29272934

29282935
bool QualType::isWebAssemblyExternrefType() const {
29292936
return getTypePtr()->isWebAssemblyExternrefType();
29302937
}
29312938

2939+
bool QualType::isWebAssemblyNonNullExternrefType() const {
2940+
return getTypePtr()->isWebAssemblyNonNullExternrefType();
2941+
}
2942+
29322943
bool QualType::isWebAssemblyFuncrefType() const {
29332944
return getTypePtr()->isFunctionPointerType() &&
29342945
getAddressSpace() == LangAS::wasm_funcref;

clang/lib/CodeGen/CodeGenTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
569569
case BuiltinType::Id: { \
570570
if (BuiltinType::Id == BuiltinType::WasmExternRef) \
571571
ResultType = CGM.getTargetCodeGenInfo().getWasmExternrefReferenceType(); \
572+
else if (BuiltinType::Id == BuiltinType::WasmNonNullExternRef) \
573+
ResultType = \
574+
CGM.getTargetCodeGenInfo().getWasmNonNullExternrefReferenceType(); \
572575
else \
573576
llvm_unreachable("Unexpected wasm reference builtin type!"); \
574577
} break;

clang/lib/CodeGen/TargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,10 @@ class TargetCodeGenInfo {
418418
/// Return the WebAssembly externref reference type.
419419
virtual llvm::Type *getWasmExternrefReferenceType() const { return nullptr; }
420420

421+
/// Return the WebAssembly externref reference type.
422+
virtual llvm::Type *getWasmNonNullExternrefReferenceType() const {
423+
return nullptr;
424+
}
421425
/// Return the WebAssembly funcref reference type.
422426
virtual llvm::Type *getWasmFuncrefReferenceType() const { return nullptr; }
423427

clang/lib/CodeGen/Targets/WebAssembly.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
8989
virtual llvm::Type *getWasmExternrefReferenceType() const override {
9090
return llvm::Type::getWasm_ExternrefTy(getABIInfo().getVMContext());
9191
}
92+
virtual llvm::Type *getWasmNonNullExternrefReferenceType() const override {
93+
return llvm::Type::getWasm_NonNullExternrefTy(getABIInfo().getVMContext());
94+
}
9295
/// Return the WebAssembly funcref reference type.
9396
virtual llvm::Type *getWasmFuncrefReferenceType() const override {
9497
return llvm::Type::getWasm_FuncrefTy(getABIInfo().getVMContext());

clang/test/CodeGen/WebAssembly/wasm-externref.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s
33

44
typedef __externref_t externref_t;
5+
typedef __non_null_externref_t nn_externref_t;
56

67
void helper(externref_t);
8+
void helper_2(nn_externref_t);
79

810
// CHECK-LABEL: @handle(
911
// CHECK-NEXT: entry:
@@ -16,3 +18,48 @@ void helper(externref_t);
1618
void handle(externref_t obj) {
1719
helper(obj);
1820
}
21+
22+
23+
// CHECK-LABEL: @handle_2(
24+
// CHECK-NEXT: entry:
25+
// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca ptr addrspace(10), align 1
26+
// CHECK-NEXT: store ptr addrspace(10) [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1
27+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr [[OBJ_ADDR]], align 1
28+
// CHECK-NEXT: call void @helper_2(ptr addrspace(10) [[TMP0]])
29+
// CHECK-NEXT: ret void
30+
//
31+
void handle_2(nn_externref_t obj) {
32+
helper_2(obj);
33+
}
34+
35+
36+
nn_externref_t socketpair_js_concat(nn_externref_t, nn_externref_t)
37+
__attribute__((import_module("wasm:js-string"), import_name("concat")));
38+
39+
nn_externref_t get_string_ref(const char *s);
40+
void print_string_ref(nn_externref_t);
41+
42+
// CHECK-LABEL: @socketpair_example(
43+
// CHECK-NEXT: entry:
44+
// CHECK-NEXT: [[STR1:%.*]] = alloca ptr addrspace(10), align 1
45+
// CHECK-NEXT: [[STR2:%.*]] = alloca ptr addrspace(10), align 1
46+
// CHECK-NEXT: [[RESULT:%.*]] = alloca ptr addrspace(10), align 1
47+
// CHECK-NEXT: [[CALL:%.*]] = call ptr addrspace(10) @get_string_ref(ptr noundef @.str)
48+
// CHECK-NEXT: store ptr addrspace(10) [[CALL]], ptr [[STR1]], align 1
49+
// CHECK-NEXT: [[CALL1:%.*]] = call ptr addrspace(10) @get_string_ref(ptr noundef @.str.1)
50+
// CHECK-NEXT: store ptr addrspace(10) [[CALL1]], ptr [[STR2]], align 1
51+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr [[STR1]], align 1
52+
// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(10), ptr [[STR2]], align 1
53+
// CHECK-NEXT: [[CALL2:%.*]] = call ptr addrspace(10) @socketpair_js_concat(ptr addrspace(10) [[TMP0]], ptr addrspace(10) [[TMP1]])
54+
// CHECK-NEXT: store ptr addrspace(10) [[CALL2]], ptr [[RESULT]], align 1
55+
// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(10), ptr [[RESULT]], align 1
56+
// CHECK-NEXT: call void @print_string_ref(ptr addrspace(10) [[TMP2]])
57+
// CHECK-NEXT: ret void
58+
//
59+
void socketpair_example() {
60+
nn_externref_t str1 = get_string_ref("Hello, ");
61+
nn_externref_t str2 = get_string_ref("world!");
62+
nn_externref_t result = socketpair_js_concat(str1, str2);
63+
print_string_ref(result);
64+
}
65+

clang/test/Sema/wasm-refs-and-tables.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ __externref_t r1;
99
extern __externref_t r2;
1010
static __externref_t r3;
1111

12+
__non_null_externref_t nn_r1;
13+
extern __non_null_externref_t nn_r2;
14+
static __non_null_externref_t nn_r3;
15+
1216
__externref_t *t1; // expected-error {{pointer to WebAssembly reference type is not allowed}}
1317
__externref_t **t2; // expected-error {{pointer to WebAssembly reference type is not allowed}}
1418
__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
1923
static __externref_t t8[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
2024
static __externref_t (*t9)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
2125

26+
__non_null_externref_t *nn_t1; // expected-error {{pointer to WebAssembly reference type is not allowed}}
27+
__non_null_externref_t **nn_t2; // expected-error {{pointer to WebAssembly reference type is not allowed}}
28+
__non_null_externref_t ******nn_t3; // expected-error {{pointer to WebAssembly reference type is not allowed}}
29+
static __non_null_externref_t nn_t4[3]; // expected-error {{only zero-length WebAssembly tables are currently supported}}
30+
static __non_null_externref_t nn_t5[]; // expected-error {{only zero-length WebAssembly tables are currently supported}}
31+
static __non_null_externref_t nn_t6[] = {0}; // expected-error {{only zero-length WebAssembly tables are currently supported}}
32+
__non_null_externref_t nn_t7[0]; // expected-error {{WebAssembly table must be static}}
33+
static __non_null_externref_t nn_t8[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
34+
static __non_null_externref_t (*nn_t9)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
35+
2236
static __externref_t table[0];
2337
static __externref_t other_table[0] = {};
2438
static __externref_t another_table[] = {}; // expected-error {{only zero-length WebAssembly tables are currently supported}}
2539

40+
static __non_null_externref_t nn_table[0];
41+
static __non_null_externref_t nn_other_table[0] = {};
42+
static __non_null_externref_t nn_another_table[] = {}; // expected-error {{only zero-length WebAssembly tables are currently supported}}
43+
2644
struct s {
2745
__externref_t f1; // expected-error {{field has sizeless type '__externref_t'}}
2846
__externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}}
@@ -33,6 +51,17 @@ struct s {
3351
__externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
3452
};
3553

54+
55+
struct nn_s {
56+
__externref_t nn_f1; // expected-error {{field has sizeless type '__externref_t'}}
57+
__externref_t nn_f2[0]; // expected-error {{field has sizeless type '__externref_t'}}
58+
__externref_t nn_f3[]; // expected-error {{field has sizeless type '__externref_t'}}
59+
__externref_t nn_f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
60+
__externref_t *nn_f5; // expected-error {{pointer to WebAssembly reference type is not allowed}}
61+
__externref_t ****nn_f6; // expected-error {{pointer to WebAssembly reference type is not allowed}}
62+
__externref_t (*nn_f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
63+
};
64+
3665
union u {
3766
__externref_t f1; // expected-error {{field has sizeless type '__externref_t'}}
3867
__externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}}
@@ -43,16 +72,38 @@ union u {
4372
__externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
4473
};
4574

75+
76+
union nn_u {
77+
__externref_t nn_f1; // expected-error {{field has sizeless type '__externref_t'}}
78+
__externref_t nn_f2[0]; // expected-error {{field has sizeless type '__externref_t'}}
79+
__externref_t nn_f3[]; // expected-error {{field has sizeless type '__externref_t'}}
80+
__externref_t nn_f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
81+
__externref_t *nn_f5; // expected-error {{pointer to WebAssembly reference type is not allowed}}
82+
__externref_t ****nn_f6; // expected-error {{pointer to WebAssembly reference type is not allowed}}
83+
__externref_t (*f7)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
84+
};
85+
4686
void illegal_argument_1(__externref_t table[]); // expected-error {{cannot use WebAssembly table as a function parameter}}
4787
void illegal_argument_2(__externref_t table[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
4888
void illegal_argument_3(__externref_t *table); // expected-error {{pointer to WebAssembly reference type is not allowed}}
4989
void illegal_argument_4(__externref_t ***table); // expected-error {{pointer to WebAssembly reference type is not allowed}}
5090
void illegal_argument_5(__externref_t (*table)[0]); // expected-error {{cannot form a pointer to a WebAssembly table}}
5191
void illegal_argument_6(__externref_t table[0]); // expected-error {{cannot use WebAssembly table as a function parameter}}
92+
93+
void illegal_nn_argument_1(__non_null_externref_t table[]); // expected-error {{cannot use WebAssembly table as a function parameter}}
94+
void illegal_nn_argument_2(__non_null_externref_t table[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
95+
void illegal_nn_argument_3(__non_null_externref_t *table); // expected-error {{pointer to WebAssembly reference type is not allowed}}
96+
void illegal_nn_argument_4(__non_null_externref_t ***table); // expected-error {{pointer to WebAssembly reference type is not allowed}}
97+
void illegal_nn_argument_5(__non_null_externref_t (*table)[0]); // expected-error {{cannot form a pointer to a WebAssembly table}}
98+
void illegal_nn_argument_6(__non_null_externref_t table[0]); // expected-error {{cannot use WebAssembly table as a function parameter}}
5299

53100
__externref_t *illegal_return_1(); // expected-error {{pointer to WebAssembly reference type is not allowed}}
54101
__externref_t ***illegal_return_2(); // expected-error {{pointer to WebAssembly reference type is not allowed}}
55102
__externref_t (*illegal_return_3())[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
103+
104+
__non_null_externref_t *illegal_nn_return_1(); // expected-error {{pointer to WebAssembly reference type is not allowed}}
105+
__non_null_externref_t ***illegal_nn_return_2(); // expected-error {{pointer to WebAssembly reference type is not allowed}}
106+
__non_null_externref_t (*illegal_nn_return_3())[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
56107

57108
void varargs(int, ...);
58109
typedef void (*__funcref funcref_t)();

0 commit comments

Comments
 (0)