-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[WIP][SPARC] Properly handle CC for long double on sparc32 #162226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Pass and return `long double`s indirectly, as specified in the psABI. This continues the patch at https://reviews.llvm.org/D89130. This should fix the issue at llvm#41838.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-backend-sparc Author: Koakuma (koachan) ChangesPass and return This should fix the issue at #41838. Full diff: https://github.com/llvm/llvm-project/pull/162226.diff 6 Files Affected:
diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h
index 3215e648ba6c3..acc27194c38ea 100644
--- a/clang/lib/Basic/Targets/Sparc.h
+++ b/clang/lib/Basic/Targets/Sparc.h
@@ -166,6 +166,13 @@ class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
PtrDiffType = SignedLong;
break;
}
+
+ // 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;
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index 38dbebdec2429..4259c8bbfdcae 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -26,6 +26,7 @@ class SparcV8ABIInfo : public DefaultABIInfo {
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
} // end anonymous namespace
@@ -33,12 +34,33 @@ class SparcV8ABIInfo : public DefaultABIInfo {
ABIArgInfo
SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+
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 {
+ const BuiltinType *BT = Ty->getAs<BuiltinType>();
+ bool IsF128 = false;
+
+ if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
+ IsF128 = true;
+
+ // FIXME not sure if redundant
+ if (BT && BT->getKind() == BuiltinType::LongDouble)
+ IsF128 = true;
+
+ if (IsF128)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+
+ return DefaultABIInfo::classifyArgumentType(Ty);
}
void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 6c226aa7d2d48..790bf5758f4a2 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -960,9 +960,9 @@ else ()
list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET)
endif()
- # For RISCV32, we must force enable int128 for compiling long
+ # For RISCV32 and 32-bit SPARC, we must force enable int128 for compiling long
# double routines.
- if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" STREQUAL "riscv32")
+ if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC)
list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128)
endif()
diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt
index 63f4c94605c90..5643bfc51ea81 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -44,7 +44,7 @@ foreach(arch ${BUILTIN_TEST_ARCH})
string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
endif()
- if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR ${arch} STREQUAL "riscv32")
+ if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${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()
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index 8afd0a7fc09ad..55be696c14a78 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -24,8 +24,8 @@ def CC_Sparc32 : CallingConv<[
// As are v2i32 arguments (this would be the default behavior for
// v2i32 if it wasn't allocated to the IntPair register-class)
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Split_64">>,
-
-
+ // f128 arguments are passed indirectly.
+ CCIfType<[f128], CCPassIndirect<i32>>,
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index a1607097af1ef..6ce636f470896 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -554,20 +554,19 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue Load ;
+ int FI;
if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
- Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
+ FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
} else if (VA.getValVT() == MVT::f128) {
- report_fatal_error("SPARCv8 does not handle f128 in calls; "
- "pass indirectly");
+ FI = MF.getFrameInfo().CreateFixedObject(16, Offset, false);
} else {
// We shouldn't see any other value types here.
llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
}
+
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load =
+ DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
InVals.push_back(Load);
}
@@ -913,7 +912,9 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
// Promote the value if needed.
switch (VA.getLocInfo()) {
default: llvm_unreachable("Unknown loc info!");
- case CCValAssign::Full: break;
+ case CCValAssign::Full:
+ case CCValAssign::Indirect:
+ break;
case CCValAssign::SExt:
Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
break;
|
Tagging this as WIP since there's some parts that's incomplete, I just want to solicit some advice for now. The status is that for C code (e.g
I'm still seeing miscompilations:
|
|
||
|
||
// f128 arguments are passed indirectly. | ||
CCIfType<[f128], CCPassIndirect<i32>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, am I doing this right @efriedma-quic? The argument to CCPassIndirect is the type of the pointer right?
I think the main issue here is that the fp128s need to be passed around as if it's a sret struct but I dunno how to declare it in (Ret)CC_Sparc32... |
Pass and return
long double
s indirectly, as specified in the psABI.This continues the patch at https://reviews.llvm.org/D89130.
This should fix the issue at #41838.