This is an archive of the discontinued LLVM Phabricator instance.

[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

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?