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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits