https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121624
--- Comment #8 from Kaloian Doganov <kaloian at doganov dot org> --- It turns out, this trick with clear_fp_result_register works for every target Yavor Doganov can get his hands on, but doesn't work on x86. That's due to the peculiar x87 register stack that needs to be empty when calling a function. So the effect of clear_fp_result_register is nullified on x86. Still, the patch improves things everywhere else so perhaps it shouldn't be thrown away. It would provide more correct behavior for programs already compiled and dynamically linked with libobjc. The only solution I can think of to support x86 (without resorting to assembly in libobjc) is to patch objc-gnu-runtime-abi-01.cc. After all, the compiler is in a better position than the runtime to know what type is expected to be returned, so it can provide the proper zero value when the receiver is nil. Moreover, this would work with any C type, not just integers and floats. The new patch with this solution is heavily inspired by NeXT runtime's -fobjc-nilcheck, but without the evaluation order problems I strongly suspect it exhibits. I think the Objective-C message passing semantics requires the arguments to be evaluated regardless whether the receiver is nil or not. This is exactly what would happen if the nil check is implemented in the runtime, so a compiler-inlined nil check needs to preserve that exact semantics. Speaking of evaluation order, I wrote a test (pr121624-4.m) to make sure that my patch doesn't regress the expected evaluation order. The new implementation needs to evaluate the method arguments before the nil check and lookup/call to the IMP, and do that in the same order as a call to a "plain" runtime function (a-la obj_msgSend) would. To my surprise, this test fails on x86 and x86-64 without the patch applied. There must be something wrong with the current GCC if [recv a: arg1 () b: arg2 ()] leads to calling arg2 before arg1 on those targets. My patch fixes that, but I am still worried there is some underlying problem down the line that just gets masked away.
