Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/BuiltinsWebAssembly.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 <
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/SemaWasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 23 additions & 2 deletions clang/lib/Sema/SemaWasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,33 @@ 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) {
Expand Down Expand Up @@ -224,6 +243,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:
Expand Down
6 changes: 6 additions & 0 deletions clang/test/CodeGen/builtins-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Sema/builtins-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[]) {
Expand Down