Page MenuHomePhabricator

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

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

Details

Reviewers
efriedma
brad
Summary

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 libc.so.1 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

TimeTest
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.)

llvm/lib/Target/Sparc/SparcCallingConv.td
30

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

38

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?