Page MenuHomePhabricator

[WIP][Sparc] Fix long double on 32-bit Solaris/SPARC
Needs ReviewPublic

Authored by ro on Oct 9 2020, 7:03 AM.



The SysVr4 SPARC psABI prescribes 128-bit long double on 32-bit Sparc, and Solaris follows that as do some other OSes. However, clang doesn't support that.

This is not yet complete, but I need guidance in some points and believe it's easier to do so here than in the corresponding Bug 42493

There are several noteworthy issues:

  • long double is 128-bit IEEEquad format, but with 64-bit alignment unlike SPARC V9 which uses 128-bit alignment.
  • long double is passed and returned by reference, just like structures and unions.
  • long double _Complex, a Sun extension not in the psABI, is always returned in registers.
  • compiler-rt uses __uint128_t for long double support which isn't available for 32-bit compilations by default. It's currently enabled with -fforce-enable-int128 which gcc doesn't support.

Right now the basic long double support seems to work (need to double-check with GCC's gcc.dg/compat testsuite), but compiling compiler-rt/lib/builtins/divtc3.c fails:

Assertion failed: isRegLoc(), file /vol/llvm/src/llvm-project/local/llvm/include/llvm/CodeGen/CallingConvLower.h, line 150

11 0xffffffff7edfb158 _assert + 104
12 clang-12  0x00000001038fdf90 llvm::SparcTargetLowering::LowerCall_32(llvm::TargetLowering::CallLoweringInfo&, llvm::SmallVectorImpl<llvm::SDValue>&) const + 11888
13 clang-12  0x00000001038f9010 llvm::SparcTargetLowering::LowerCall(llvm::TargetLowering::CallLoweringInfo&, llvm::SmallVectorImpl<llvm::SDValue>&) const + 60
14 clang-12  0x0000000106062f54 llvm::TargetLowering::LowerCallTo(llvm::TargetLowering::CallLoweringInfo&) const + 7724
15 clang-12  0x0000000106039704 (anonymous namespace)::SelectionDAGLegalize::ExpandLibCall(llvm::RTLIB::Libcall, llvm::SDNode*, bool) + 1896

Besides, something will have to be done about the __uint128_t requirement on 32-bit targets, probably using a union with uint64_t members.

I'm currently lost here and will need some guidance how to proceed.

Diff Detail

Unit TestsFailed

120 mslinux > Clang.CodeGen::sparcv8-abi.c
Script: -- : 'RUN: at line 1'; /mnt/disks/ssd0/agent/llvm-project/build/bin/clang -cc1 -internal-isystem /mnt/disks/ssd0/agent/llvm-project/build/lib/clang/12.0.0/include -nostdsysteminc -triple sparc-unknown-unknown -emit-llvm /mnt/disks/ssd0/agent/llvm-project/clang/test/CodeGen/sparcv8-abi.c -o - | /mnt/disks/ssd0/agent/llvm-project/build/bin/FileCheck /mnt/disks/ssd0/agent/llvm-project/clang/test/CodeGen/sparcv8-abi.c
110 mswindows > Clang.CodeGen::sparcv8-abi.c
Script: -- : 'RUN: at line 1'; c:\ws\w64\llvm-project\premerge-checks\build\bin\clang.exe -cc1 -internal-isystem c:\ws\w64\llvm-project\premerge-checks\build\lib\clang\12.0.0\include -nostdsysteminc -triple sparc-unknown-unknown -emit-llvm C:\ws\w64\llvm-project\premerge-checks\clang\test\CodeGen\sparcv8-abi.c -o - | c:\ws\w64\llvm-project\premerge-checks\build\bin\filecheck.exe C:\ws\w64\llvm-project\premerge-checks\clang\test\CodeGen\sparcv8-abi.c
200 mswindows > lld.ELF/invalid::symtab-sh-info.s
Script: -- : 'RUN: at line 4'; c:\ws\w64\llvm-project\premerge-checks\build\bin\yaml2obj.exe --docnum=1 C:\ws\w64\llvm-project\premerge-checks\lld\test\ELF\invalid\symtab-sh-info.s -o C:\ws\w64\llvm-project\premerge-checks\build\tools\lld\test\ELF\invalid\Output\symtab-sh-info.s.tmp.o

Event Timeline

ro created this revision.Oct 9 2020, 7:03 AM
Herald added projects: Restricted Project, Restricted Project, Restricted Project. · View Herald TranscriptOct 9 2020, 7:03 AM
Herald added subscribers: Restricted Project, s.egerton, dexonsmith and 6 others. · View Herald Transcript
ro requested review of this revision.Oct 9 2020, 7:03 AM

SparcTargetLowering::LowerCall_32 is Sparc-specific code. Maybe you can take a look at where it's crashing, and ask some more specific question?

The compiler-rt requirement for __uint128_t is a bit inconvenient, I guess; maybe it could be changed, but that's probably an invasive patch.

Please split the compiler-rt changes into a separate patch; whether compiler-rt provides long double routines is separate from whether the compiler can generate calls to them. (For example, you might use clang and link against libgcc.)


Maybe worth adding code to use CCPassIndirect for f128? Might allow you to simplify the clang handling.


CCAssignToStack is used to pass values directly on the stack; I have no idea what it would mean on a return value. Are you sure you don't want to just fall back to the default handling, which returns the value indirectly?