[clang] [WebAssembly][Clang] Add __builtin_wasm_ref_is_null_extern (PR #139580)
Hood Chatham via cfe-commits
cfe-commits at lists.llvm.org
Tue May 13 15:35:24 PDT 2025
https://github.com/hoodmane updated https://github.com/llvm/llvm-project/pull/139580
>From 2ca282f0a20088bef15289a8ce5167d1e23595c3 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham at gmail.com>
Date: Fri, 9 May 2025 00:16:26 -0400
Subject: [PATCH 1/3] [Wasm][Clang] Add __builtin_wasm_ref_is_null_extern
I also fixed __builtin_wasm_ref_null_extern() to generate a diagnostic
when it gets an argument. It seems like `SemaRef.checkArgCount()` has a
bug that makes it unable to check for 0 args.
---
.../clang/Basic/BuiltinsWebAssembly.def | 1 +
.../clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/include/clang/Sema/SemaWasm.h | 1 +
.../CodeGen/TargetBuiltins/WebAssembly.cpp | 5 ++++
clang/lib/Sema/SemaWasm.cpp | 26 +++++++++++++++++--
clang/test/CodeGen/builtins-wasm.c | 6 +++++
clang/test/Sema/builtins-wasm.c | 4 +++
7 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def
index ab480369b3820..e2afcc08064b2 100644
--- a/clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -192,6 +192,7 @@ TARGET_BUILTIN(__builtin_wasm_replace_lane_f16x8, "V8hV8hIif", "nc", "fp16")
// in which case the argument spec (second argument) is unused.
TARGET_BUILTIN(__builtin_wasm_ref_null_extern, "i", "nct", "reference-types")
+TARGET_BUILTIN(__builtin_wasm_ref_is_null_extern, "ii", "nct", "reference-types")
// A funcref represented as a function pointer with the funcref attribute
// attached to the type, therefore SemaChecking will check for the right
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e5a7cdc14a737..d4abc46ae58ee 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12991,6 +12991,8 @@ def err_wasm_reftype_multidimensional_array : Error<
"multi-dimensional arrays of WebAssembly references are not allowed">;
def err_wasm_builtin_arg_must_be_table_type : Error <
"%ordinal0 argument must be a WebAssembly table">;
+def err_wasm_builtin_arg_must_be_externref_type : Error <
+ "%ordinal0 argument must be an externref">;
def err_wasm_builtin_arg_must_match_table_element_type : Error <
"%ordinal0 argument must match the element type of the WebAssembly table in the %ordinal1 argument">;
def err_wasm_builtin_arg_must_be_integer_type : Error <
diff --git a/clang/include/clang/Sema/SemaWasm.h b/clang/include/clang/Sema/SemaWasm.h
index 8841fdff23035..2123e073516cb 100644
--- a/clang/include/clang/Sema/SemaWasm.h
+++ b/clang/include/clang/Sema/SemaWasm.h
@@ -29,6 +29,7 @@ class SemaWasm : public SemaBase {
CallExpr *TheCall);
bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
+ bool BuiltinWasmRefIsNullExtern(CallExpr *TheCall);
bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
bool BuiltinWasmTableGet(CallExpr *TheCall);
bool BuiltinWasmTableSet(CallExpr *TheCall);
diff --git a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp
index 698f43215a1be..b7fd70e855d40 100644
--- a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp
@@ -209,6 +209,11 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_extern);
return Builder.CreateCall(Callee);
}
+ case WebAssembly::BI__builtin_wasm_ref_is_null_extern: {
+ Value *Src = EmitScalarExpr(E->getArg(0));
+ Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_is_null_extern);
+ return Builder.CreateCall(Callee, {Src});
+ }
case WebAssembly::BI__builtin_wasm_ref_null_func: {
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func);
return Builder.CreateCall(Callee);
diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp
index c0fa05bc17609..4157e179c97d6 100644
--- a/clang/lib/Sema/SemaWasm.cpp
+++ b/clang/lib/Sema/SemaWasm.cpp
@@ -52,14 +52,34 @@ static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
}
bool SemaWasm::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
- if (TheCall->getNumArgs() != 0)
+ if (TheCall->getNumArgs() != 0) {
+ Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
+ << /*is non object*/ 0;
return true;
-
+ }
TheCall->setType(getASTContext().getWebAssemblyExternrefType());
return false;
}
+bool SemaWasm::BuiltinWasmRefIsNullExtern(CallExpr *TheCall) {
+ if (SemaRef.checkArgCount(TheCall, 1)) {
+ return true;
+ }
+
+ Expr *ArgExpr = TheCall->getArg(0);
+ if (!ArgExpr->getType().isWebAssemblyExternrefType()) {
+ SemaRef.Diag(ArgExpr->getBeginLoc(),
+ diag::err_wasm_builtin_arg_must_be_externref_type)
+ << 1 << ArgExpr->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
+
bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
ASTContext &Context = getASTContext();
if (TheCall->getNumArgs() != 0) {
@@ -224,6 +244,8 @@ bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
return BuiltinWasmRefNullExtern(TheCall);
case WebAssembly::BI__builtin_wasm_ref_null_func:
return BuiltinWasmRefNullFunc(TheCall);
+ case WebAssembly::BI__builtin_wasm_ref_is_null_extern:
+ return BuiltinWasmRefIsNullExtern(TheCall);
case WebAssembly::BI__builtin_wasm_table_get:
return BuiltinWasmTableGet(TheCall);
case WebAssembly::BI__builtin_wasm_table_set:
diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c
index 263cfd3ab4c69..4a44a9a88df11 100644
--- a/clang/test/CodeGen/builtins-wasm.c
+++ b/clang/test/CodeGen/builtins-wasm.c
@@ -741,6 +741,12 @@ __externref_t externref_null() {
// WEBASSEMBLY-NEXT: ret
}
+int externref_is_null(__externref_t arg) {
+ return __builtin_wasm_ref_is_null_extern(arg);
+ // WEBASSEMBLY: tail call i32 @llvm.wasm.ref.is_null.extern(ptr addrspace(10) %arg)
+ // WEBASSEMBLY-NEXT: ret
+}
+
void *tp (void) {
return __builtin_thread_pointer ();
// WEBASSEMBLY: call {{.*}} @llvm.thread.pointer()
diff --git a/clang/test/Sema/builtins-wasm.c b/clang/test/Sema/builtins-wasm.c
index beb430616233a..31e5291d3ae5e 100644
--- a/clang/test/Sema/builtins-wasm.c
+++ b/clang/test/Sema/builtins-wasm.c
@@ -7,6 +7,10 @@ static __externref_t table[0];
typedef void (*__funcref funcref_t)();
void test_ref_null() {
funcref_t func = __builtin_wasm_ref_null_func(0); // expected-error {{too many arguments to function call, expected 0, have 1}}
+ __externref_t ref = __builtin_wasm_ref_null_extern(0); // expected-error {{too many arguments to function call, expected 0, have 1}}
+ __builtin_wasm_ref_is_null_extern(ref, 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
+ __builtin_wasm_ref_is_null_extern(); // expected-error {{too few arguments to function call, expected 1, have 0}}
+ __builtin_wasm_ref_is_null_extern(1); // expected-error {{1st argument must be an externref}}
}
void test_table_size(__externref_t ref, void *ptr, int arr[]) {
>From cfb8e469532c5bffa2b65fb4bc83cc7573b70977 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham at gmail.com>
Date: Mon, 12 May 2025 13:09:01 -0400
Subject: [PATCH 2/3] Apply clang-format
---
clang/lib/Sema/SemaWasm.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp
index 4157e179c97d6..3842674cd9a2d 100644
--- a/clang/lib/Sema/SemaWasm.cpp
+++ b/clang/lib/Sema/SemaWasm.cpp
@@ -71,15 +71,14 @@ bool SemaWasm::BuiltinWasmRefIsNullExtern(CallExpr *TheCall) {
Expr *ArgExpr = TheCall->getArg(0);
if (!ArgExpr->getType().isWebAssemblyExternrefType()) {
SemaRef.Diag(ArgExpr->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_be_externref_type)
- << 1 << ArgExpr->getSourceRange();
+ diag::err_wasm_builtin_arg_must_be_externref_type)
+ << 1 << ArgExpr->getSourceRange();
return true;
}
return false;
}
-
bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
ASTContext &Context = getASTContext();
if (TheCall->getNumArgs() != 0) {
>From 0258c51ca35c7bb21dc484bf9c9ca42330ab537b Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham at gmail.com>
Date: Mon, 12 May 2025 17:53:59 -0400
Subject: [PATCH 3/3] Fix Sema::checkArgCount with 0 args
---
clang/lib/Sema/SemaChecking.cpp | 2 +-
clang/lib/Sema/SemaWasm.cpp | 10 ++--------
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 97f623f61a405..5d0d5861d4026 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -168,7 +168,7 @@ bool Sema::checkArgCount(CallExpr *Call, unsigned DesiredArgCount) {
return Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args)
<< 0 /*function call*/ << DesiredArgCount << ArgCount
- << /*is non object*/ 0 << Call->getArg(1)->getSourceRange();
+ << /*is non object*/ 0 << Range;
}
static bool checkBuiltinVerboseTrap(CallExpr *Call, Sema &S) {
diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp
index 3842674cd9a2d..6e949290c1ca2 100644
--- a/clang/lib/Sema/SemaWasm.cpp
+++ b/clang/lib/Sema/SemaWasm.cpp
@@ -52,10 +52,7 @@ static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
}
bool SemaWasm::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
- if (TheCall->getNumArgs() != 0) {
- Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
- << /*is non object*/ 0;
+ if (SemaRef.checkArgCount(TheCall, 0)) {
return true;
}
TheCall->setType(getASTContext().getWebAssemblyExternrefType());
@@ -81,10 +78,7 @@ bool SemaWasm::BuiltinWasmRefIsNullExtern(CallExpr *TheCall) {
bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
ASTContext &Context = getASTContext();
- if (TheCall->getNumArgs() != 0) {
- Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
- << /*is non object*/ 0;
+ if (SemaRef.checkArgCount(TheCall, 0)) {
return true;
}
More information about the cfe-commits
mailing list