ro created this revision. ro added reviewers: efriedma, brad. Herald added subscribers: Sanitizers, s.egerton, dexonsmith, jrtc27, simoncook, fedor.sergeev, hiraditya, mgorny, jyknight. Herald added projects: clang, Sanitizers, LLVM. ro requested review of this revision.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D89130 Files: clang/lib/Basic/Targets/Sparc.h clang/lib/CodeGen/TargetInfo.cpp compiler-rt/lib/builtins/CMakeLists.txt compiler-rt/lib/builtins/int_types.h compiler-rt/test/builtins/CMakeLists.txt compiler-rt/test/builtins/Unit/divtc3_test.c llvm/lib/Target/Sparc/SparcCallingConv.td llvm/lib/Target/Sparc/SparcISelLowering.cpp
Index: llvm/lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -507,9 +507,6 @@ SDValue Load ; if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - } else if (VA.getValVT() == MVT::f128) { - report_fatal_error("SPARCv8 does not handle f128 in calls; " - "pass indirectly"); } else { // We shouldn't see any other value types here. llvm_unreachable("Unexpected ValVT encountered in frame lowering."); Index: llvm/lib/Target/Sparc/SparcCallingConv.td =================================================================== --- llvm/lib/Target/Sparc/SparcCallingConv.td +++ llvm/lib/Target/Sparc/SparcCallingConv.td @@ -34,6 +34,8 @@ CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>, CCIfType<[f64], CCAssignToReg<[D0, D1]>>, + CCIfInReg<CCIfType<[f128] , CCAssignToReg<[Q0, Q1]>>>, + CCIfType<[f128], CCAssignToStack<16, 8>>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; Index: compiler-rt/test/builtins/Unit/divtc3_test.c =================================================================== --- compiler-rt/test/builtins/Unit/divtc3_test.c +++ compiler-rt/test/builtins/Unit/divtc3_test.c @@ -2,10 +2,6 @@ // REQUIRES: librt_has_divtc3 // REQUIRES: c99-complex -// -// Bug 42493 -// XFAIL: sparc-target-arch -// #include <stdio.h> #include "int_lib.h" Index: compiler-rt/test/builtins/CMakeLists.txt =================================================================== --- compiler-rt/test/builtins/CMakeLists.txt +++ compiler-rt/test/builtins/CMakeLists.txt @@ -39,7 +39,7 @@ string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}") endif() - if (${arch} STREQUAL "riscv32") + if("${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC) list(APPEND BUILTINS_TEST_TARGET_CFLAGS -fforce-enable-int128) string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}") endif() Index: compiler-rt/lib/builtins/int_types.h =================================================================== --- compiler-rt/lib/builtins/int_types.h +++ compiler-rt/lib/builtins/int_types.h @@ -64,7 +64,7 @@ } udwords; #if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \ - defined(__riscv) || defined(_WIN64) + defined(__riscv) || defined(__sparc) || defined(_WIN64) #define CRT_HAS_128BIT #endif Index: compiler-rt/lib/builtins/CMakeLists.txt =================================================================== --- compiler-rt/lib/builtins/CMakeLists.txt +++ compiler-rt/lib/builtins/CMakeLists.txt @@ -668,9 +668,9 @@ list(APPEND BUILTIN_CFLAGS -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) endif() - # For RISCV32, we must force enable int128 for compiling long - # double routines. - if("${arch}" STREQUAL "riscv32") + # For RISCV32 and 32-bit SPARC, we must force enable int128 for compiling + # long double routines. + if("${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC) list(APPEND BUILTIN_CFLAGS -fforce-enable-int128) endif() Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -9198,6 +9198,7 @@ private: ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty) const; void computeInfo(CGFunctionInfo &FI) const override; }; } // end anonymous namespace @@ -9205,12 +9206,25 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { + if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128) + return getNaturalAlignIndirect(Ty); + if (Ty->isAnyComplexType()) { - return ABIArgInfo::getDirect(); - } - else { - return DefaultABIInfo::classifyReturnType(Ty); - } + auto AI = ABIArgInfo::getDirect(); + AI.setInReg(true); + return AI; + } + + return DefaultABIInfo::classifyReturnType(Ty); +} + +ABIArgInfo +SparcV8ABIInfo::classifyArgumentType(QualType Ty) const { + // FIXME: Need to check for BuiltinType::LongDouble, too? + if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128) + return getNaturalAlignIndirect(Ty); + + return DefaultABIInfo::classifyArgumentType(Ty); } void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { Index: clang/lib/Basic/Targets/Sparc.h =================================================================== --- clang/lib/Basic/Targets/Sparc.h +++ clang/lib/Basic/Targets/Sparc.h @@ -166,6 +166,15 @@ PtrDiffType = SignedLong; break; } + + if (getTriple().isOSSolaris()) { + // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit + // aligned. + LongDoubleWidth = 128; + LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } + // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're // willing to do atomic ops on up to 64 bits. MaxAtomicPromoteWidth = 64;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits