https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/215920
From 88a907d96e17f14a22d8101194aea786e30824fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <[email protected]> Date: Thu, 13 Aug 2026 01:19:46 +0200 Subject: [PATCH 1/2] [Objective-C][WebAssembly] Always emit nil-check for indirect calls --- clang/lib/CodeGen/CGObjCGNU.cpp | 10 +++++ clang/test/CodeGenObjC/gnustep2-wasm32-nil.m | 44 ++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 clang/test/CodeGenObjC/gnustep2-wasm32-nil.m diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 32a1afe310629..e2ebca6bff1ce 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2968,11 +2968,21 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, Class, Receiver)) return false; + // If there's a consumed argument, we need a nil check. if (Method && Method->hasParamDestroyedInCallee()) { hasParamDestroyedInCallee = true; } + // WebAssembly indirect calls require an exact function type match. + // Therfore, we cannot use libobjc2's nil-IMP stubs for WebAssembly + // and must always emit a null check and optionally zero the result. + if (CGM.getTriple().isWasm() && !isDirect) { + requiresExplicitZeroResult = + !Return.isUnused() && !ResultType->isVoidType(); + return true; + } + // If the return value isn't flagged as unused, and the result // type isn't in our narrow set where we assume compatibility, // we need a nil check to ensure a nil value. diff --git a/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m b/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m new file mode 100644 index 0000000000000..093cdfaa8366b --- /dev/null +++ b/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -emit-llvm -fobjc-runtime=gnustep-2.2 -o - %s | FileCheck %s + + +typedef struct { + int x; + int y; + int z; +} S; + +@interface Object +- (int)value; +- (S)s; +@end + +// We expect generated nil-checks and zeroing of the result for WASM. + +int sendToPossiblyNil(Object *object) { + // CHECK-LABEL: define{{.*}} i32 @sendToPossiblyNil + // CHECK: icmp eq ptr %{{.*}}, null + // CHECK: br i1 %{{.*}}, label %[[CONTINUE:.*]], label %[[SEND:.*]] + // CHECK: [[SEND]]: + // CHECK: call ptr @objc_msg_lookup_sender + // CHECK: br label %[[CONTINUE]] + // CHECK: [[CONTINUE]]: + // CHECK: phi i32 [ %{{.*}}, %[[SEND]] ], [ 0, %{{.*}} ] + return [object value]; +} + +Triple sendStructToPossiblyNil(Object *object) { + // CHECK-LABEL: define{{.*}} void @sendStructToPossiblyNil + // CHECK: [[ISNIL:%.*]] = icmp eq ptr %{{.*}}, null + // CHECK: br i1 [[ISNIL]], label %[[NIL_CLEANUP:.*]], label %[[STRUCT_SEND:.*]] + // CHECK: [[STRUCT_SEND]]: + // CHECK: call ptr @objc_msg_lookup_sender + // CHECK: call void %{{.*}}(ptr{{.*}} sret(%struct.Triple){{.*}} + // CHECK: br label %[[STRUCT_CONTINUE:.*]] + // CHECK: [[NIL_CLEANUP]]: + // CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 %agg.result, i8 0, i32 12, i1 false) + // CHECK-NEXT: br label %[[STRUCT_CONTINUE]] + // CHECK: [[STRUCT_CONTINUE]]: + // CHECK: ret void + return [object s]; +} + From 97fcbd083a18d7131d4444562f728d66ce0e377d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <[email protected]> Date: Thu, 13 Aug 2026 09:15:30 +0200 Subject: [PATCH 2/2] fix --- clang/lib/CodeGen/CGObjCGNU.cpp | 1 - clang/test/CodeGenObjC/gnustep2-wasm32-nil.m | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index e2ebca6bff1ce..ff79b0aacb96d 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2968,7 +2968,6 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, Class, Receiver)) return false; - // If there's a consumed argument, we need a nil check. if (Method && Method->hasParamDestroyedInCallee()) { hasParamDestroyedInCallee = true; diff --git a/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m b/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m index 093cdfaa8366b..ae66f3ffbf9a9 100644 --- a/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m +++ b/clang/test/CodeGenObjC/gnustep2-wasm32-nil.m @@ -26,13 +26,13 @@ int sendToPossiblyNil(Object *object) { return [object value]; } -Triple sendStructToPossiblyNil(Object *object) { +S sendStructToPossiblyNil(Object *object) { // CHECK-LABEL: define{{.*}} void @sendStructToPossiblyNil // CHECK: [[ISNIL:%.*]] = icmp eq ptr %{{.*}}, null // CHECK: br i1 [[ISNIL]], label %[[NIL_CLEANUP:.*]], label %[[STRUCT_SEND:.*]] // CHECK: [[STRUCT_SEND]]: // CHECK: call ptr @objc_msg_lookup_sender - // CHECK: call void %{{.*}}(ptr{{.*}} sret(%struct.Triple){{.*}} + // CHECK: call void %{{.*}}(ptr{{.*}} sret(%struct.S){{.*}} // CHECK: br label %[[STRUCT_CONTINUE:.*]] // CHECK: [[NIL_CLEANUP]]: // CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 %agg.result, i8 0, i32 12, i1 false) @@ -41,4 +41,3 @@ Triple sendStructToPossiblyNil(Object *object) { // CHECK: ret void return [object s]; } - _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
