Skip to content

Commit 6caa2f7

Browse files
committed
[clang,WebAssembly] Support reference types in test_function_pointer_signature
1 parent d532d58 commit 6caa2f7

File tree

6 files changed

+51
-49
lines changed

6 files changed

+51
-49
lines changed

clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -253,28 +253,15 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
253253
Args.push_back(FuncRef);
254254

255255
// Add the type information
256-
auto addType = [this, &Args](llvm::Type *T) {
257-
if (T->isVoidTy()) {
258-
// Do nothing
259-
} else if (T->isFloatingPointTy()) {
260-
Args.push_back(ConstantFP::get(T, 0));
261-
} else if (T->isIntegerTy()) {
262-
Args.push_back(ConstantInt::get(T, 0));
263-
} else if (T->isPointerTy()) {
264-
Args.push_back(ConstantPointerNull::get(llvm::PointerType::get(
265-
getLLVMContext(), T->getPointerAddressSpace())));
266-
} else {
267-
// TODO: Handle reference types. For now, we reject them in Sema.
268-
llvm_unreachable("Unhandled type");
269-
}
270-
};
271-
272-
addType(LLVMFuncTy->getReturnType());
256+
llvm::Type *RetType = LLVMFuncTy->getReturnType();
257+
if (!RetType->isVoidTy()) {
258+
Args.push_back(PoisonValue::get(RetType));
259+
}
273260
// The token type indicates the boundary between return types and param
274261
// types.
275262
Args.push_back(PoisonValue::get(llvm::Type::getTokenTy(getLLVMContext())));
276263
for (unsigned i = 0; i < NParams; i++) {
277-
addType(LLVMFuncTy->getParamType(i));
264+
Args.push_back(PoisonValue::get(LLVMFuncTy->getParamType(i)));
278265
}
279266
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_test_func);
280267
return Builder.CreateCall(Callee, Args);

clang/lib/Sema/SemaWasm.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -250,24 +250,6 @@ bool SemaWasm::BuiltinWasmTestFunctionPointerSignature(CallExpr *TheCall) {
250250
<< ArgType << FuncPtrArg->getSourceRange();
251251
}
252252

253-
// Check that the function pointer doesn't use reference types
254-
if (FuncTy->getReturnType().isWebAssemblyReferenceType()) {
255-
return Diag(
256-
FuncPtrArg->getBeginLoc(),
257-
diag::err_wasm_builtin_test_fp_sig_cannot_include_reference_type)
258-
<< 0 << FuncTy->getReturnType() << FuncPtrArg->getSourceRange();
259-
}
260-
auto NParams = FuncTy->getNumParams();
261-
for (unsigned I = 0; I < NParams; I++) {
262-
if (FuncTy->getParamType(I).isWebAssemblyReferenceType()) {
263-
return Diag(
264-
FuncPtrArg->getBeginLoc(),
265-
diag::
266-
err_wasm_builtin_test_fp_sig_cannot_include_reference_type)
267-
<< 1 << FuncPtrArg->getSourceRange();
268-
}
269-
}
270-
271253
// Set return type to int (the result of the test)
272254
TheCall->setType(getASTContext().IntTy);
273255

clang/test/CodeGen/builtins-wasm.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ void *tp (void) {
755755
typedef void (*Fvoid)(void);
756756
typedef float (*Ffloats)(float, double, int);
757757
typedef void (*Fpointers)(Fvoid, Ffloats, void*, int*, int***, char[5]);
758+
typedef __externref_t (*FExternRef)(__externref_t, __externref_t);
759+
typedef __funcref Fpointers (*FFuncRef)(__funcref Fvoid, __funcref Ffloats);
758760

759761
void use(int);
760762

@@ -764,11 +766,21 @@ void test_function_pointer_signature_void(Fvoid func) {
764766
}
765767

766768
void test_function_pointer_signature_floats(Ffloats func) {
767-
// WEBASSEMBLY: tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, float 0.000000e+00, token poison, float 0.000000e+00, double 0.000000e+00, i32 0)
769+
// WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, float poison, token poison, float poison, double poison, i32 poison)
768770
use(__builtin_wasm_test_function_pointer_signature(func));
769771
}
770772

771773
void test_function_pointer_signature_pointers(Fpointers func) {
772-
// WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null)
774+
// WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison, ptr poison, ptr poison, ptr poison, ptr poison, ptr poison, ptr poison)
775+
use(__builtin_wasm_test_function_pointer_signature(func));
776+
}
777+
778+
void test_function_pointer_externref(FExternRef func) {
779+
// WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, ptr addrspace(10) poison, token poison, ptr addrspace(10) poison, ptr addrspace(10) poison)
780+
use(__builtin_wasm_test_function_pointer_signature(func));
781+
}
782+
783+
void test_function_pointer_funcref(FFuncRef func) {
784+
// WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, ptr addrspace(20) poison, token poison, ptr addrspace(20) poison, ptr addrspace(20) poison)
773785
use(__builtin_wasm_test_function_pointer_signature(func));
774786
}

clang/test/Sema/builtins-wasm.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ void test_table_copy(int dst_idx, int src_idx, int nelem) {
5757

5858
typedef void (*F1)(void);
5959
typedef int (*F2)(int);
60-
typedef int (*F3)(__externref_t);
61-
typedef __externref_t (*F4)(int);
6260

6361
void test_function_pointer_signature() {
6462
// Test argument count validation
@@ -68,8 +66,6 @@ void test_function_pointer_signature() {
6866
// // Test argument type validation - should require function pointer
6967
(void)__builtin_wasm_test_function_pointer_signature((void*)0); // expected-error {{used type 'void *' where function pointer is required}}
7068
(void)__builtin_wasm_test_function_pointer_signature((int)0); // expected-error {{used type 'int' where function pointer is required}}
71-
(void)__builtin_wasm_test_function_pointer_signature((F3)0); // expected-error {{not supported for function pointers with a reference type parameter}}
72-
(void)__builtin_wasm_test_function_pointer_signature((F4)0); // expected-error {{not supported for function pointers with a reference type return value}}
7369

7470
// // Test valid usage
7571
int res = __builtin_wasm_test_function_pointer_signature((F1)0);

llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ static APInt encodeFunctionSignature(SelectionDAG *DAG, SDLoc &DL,
136136
if (VT == MVT::f64) {
137137
return wasm::ValType::F64;
138138
}
139+
if (VT == MVT::externref) {
140+
return wasm::ValType::EXTERNREF;
141+
}
142+
if (VT == MVT::funcref) {
143+
return wasm::ValType::FUNCREF;
144+
}
145+
if (VT == MVT::exnref) {
146+
return wasm::ValType::EXNREF;
147+
}
139148
LLVM_DEBUG(errs() << "Unhandled type for llvm.wasm.ref.test.func: " << VT
140149
<< "\n");
141150
llvm_unreachable("Unhandled type for llvm.wasm.ref.test.func");

llvm/test/CodeGen/WebAssembly/ref-test-func.ll

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ define void @test_fpsig_return_i32(ptr noundef %func) local_unnamed_addr #0 {
3131
; CHECK-NEXT: call use
3232
; CHECK-NEXT: # fallthrough-return
3333
entry:
34-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i32 0)
34+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i32 poison)
3535
tail call void @use(i32 noundef %res) #3
3636
ret void
3737
}
@@ -48,7 +48,7 @@ define void @test_fpsig_return_i64(ptr noundef %func) local_unnamed_addr #0 {
4848
; CHECK-NEXT: call use
4949
; CHECK-NEXT: # fallthrough-return
5050
entry:
51-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i64 0)
51+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i64 poison)
5252
tail call void @use(i32 noundef %res) #3
5353
ret void
5454
}
@@ -65,7 +65,7 @@ define void @test_fpsig_return_f32(ptr noundef %func) local_unnamed_addr #0 {
6565
; CHECK-NEXT: call use
6666
; CHECK-NEXT: # fallthrough-return
6767
entry:
68-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, float 0.)
68+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, float poison)
6969
tail call void @use(i32 noundef %res) #3
7070
ret void
7171
}
@@ -82,7 +82,7 @@ define void @test_fpsig_return_f64(ptr noundef %func) local_unnamed_addr #0 {
8282
; CHECK-NEXT: call use
8383
; CHECK-NEXT: # fallthrough-return
8484
entry:
85-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, double 0.)
85+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, double poison)
8686
tail call void @use(i32 noundef %res) #3
8787
ret void
8888
}
@@ -100,7 +100,7 @@ define void @test_fpsig_param_i32(ptr noundef %func) local_unnamed_addr #0 {
100100
; CHECK-NEXT: call use
101101
; CHECK-NEXT: # fallthrough-return
102102
entry:
103-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison, double 0.)
103+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison, double poison)
104104
tail call void @use(i32 noundef %res) #3
105105
ret void
106106
}
@@ -118,7 +118,7 @@ define void @test_fpsig_multiple_params_and_returns(ptr noundef %func) local_unn
118118
; CHECK-NEXT: call use
119119
; CHECK-NEXT: # fallthrough-return
120120
entry:
121-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i32 0, i64 0, float 0., double 0., token poison, i64 0, float 0., i64 0)
121+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, i32 poison, i64 poison, float poison, double poison, token poison, i64 poison, float poison, i64 poison)
122122
tail call void @use(i32 noundef %res) #3
123123
ret void
124124
}
@@ -137,10 +137,26 @@ define void @test_fpsig_ptrs(ptr noundef %func) local_unnamed_addr #0 {
137137
; CHECK-NEXT: call use
138138
; CHECK-NEXT: # fallthrough-return
139139
entry:
140-
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, ptr null, token poison, ptr null, ptr null)
140+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, ptr poison, token poison, ptr poison, ptr poison)
141141
tail call void @use(i32 noundef %res) #3
142142
ret void
143143
}
144144

145+
define void @test_reference_types(ptr noundef %func) local_unnamed_addr #0 {
146+
; CHECK-LABEL: test_reference_types:
147+
; CHK32: .functype test_reference_types (i32) -> ()
148+
; CHK64: .functype test_reference_types (i64) -> ()
149+
; CHECK-NEXT: # %bb.0: # %entry
150+
; CHECK-NEXT: local.get 0
151+
; CHK64-NEXT: i32.wrap_i64
152+
; CHECK-NEXT: table.get __indirect_function_table
153+
; CHECK-NEXT: ref.test (funcref, externref) -> (externref)
154+
; CHECK-NEXT: call use
155+
; CHECK-NEXT: # fallthrough-return
156+
entry:
157+
%res = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, ptr addrspace(10) poison, token poison, ptr addrspace(20) poison, ptr addrspace(10) poison)
158+
tail call void @use(i32 noundef %res) #3
159+
ret void
160+
}
145161

146162
declare void @use(i32 noundef) local_unnamed_addr #1

0 commit comments

Comments
 (0)