[Sparc] Lowering of Complex number for ABI compliance

Hi all,

The Sparc LLVM compiler is not lowering the return value of complex numbers according to the Sparc ABI.

I’ll try to describe the problem as succinctly as I can.

I’ve looked at the updated Sparc ABI (6.3 Parameter Passing - SPARC Assembly Language Reference Manual)

This document states that complex numbers should be returned from functions using two registers - in the case of the problem I’m addressing, two floating point registers.

LLVM treats complex numbers as a structure of two floating point values. It therefore attempts to return a complex number as a structure (of two floats).

When there is a cross-system call (such as where LLVM code calls into GCC’s runtime library), the LLVM code is calling usingthe Sparc ABI structure return convention, whereas GCC is correctly using registers for the ABI return. The mismatch causes an error. Note, the relevant change to ensure GCC handled this correctly happened here: SPARC ABI Changes in GCC 3.4 - GNU Project

The problem I’ve come to realise is that the information that the value passed was originally a complex number is discarded by the LLVM clang front-end. By the time the back-end sees the code, it can no longer distinguish between what was originally a complex number and what could reasonably have simply been a structure of two floating point values. The two are indistinguishable from each other to the back-end. See the following IR fragment declaring a function taking two complex numbers and returning one complex number.

define void @complex_op({ float, float }* noalias nocapture sret %agg.result, { float, float }* byval nocapture readonly align 4 %a, { float, float }* byval nocapture readonly align 4 %b) #0 {

This means that every attempt I’ve made to fix this problem has resulted in breaking something else in the ABI - specifically, normal structure-return ABI implementation.

The fix can only possibly be implemented by a combination of changes in both the front-end and back-end of LLVM.

I’ve only implemented changes in the back-end of the system so far, so I don’t even know if it’s possible to mark a value as being originally of “complex” type in the front-end before it’s passed to the back-end.

Ultimately, the question is: What changes would need to be made to
(a) the front-end, to propagate this information into the back-end.
(b) the back-end, to be able to detect this information and treat the function call ABI differently?

I can’t find any comparable situation in other processors to copy. If any can point to comparable piece(s) of code, that would be most welcome.

Best Regards,
Chris Dewhurst
University of Limerick,

It looks like LLVM already returns {double, double} in float
registers, doesn't it? If so, you ought to be able to just make Clang
emit complex returns as that instead of an sret parameter. Roughly: in
lib/CodeGen/TargetInfo.cpp, SparcV9ABIInfo::computeInfo check for a
complex type and return getDirect for it.