-
Notifications
You must be signed in to change notification settings - Fork 15.4k
release/21.x: [SPARC] Remove CCIfConsecutiveRegs for f128 returns (#170133) #170580
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: release/21.x
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. (cherry picked from commit 3e16aef)
It appears that using it will result in callers mistakenly thinking that complex f128 returns is done the sret-way, when it should be returned in registers. (cherry picked from commit 3d598c3)
|
@koachan @efriedma-quic What do you think about merging this PR to the release branch? |
|
@llvm/pr-subscribers-backend-sparc @llvm/pr-subscribers-clang Author: None (llvmbot) ChangesRequested by: @brad0 Patch is 43.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170580.diff 17 Files Affected:
diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp
index d1a891092b0f5..2dcf31fc5591d 100644
--- a/clang/lib/Basic/Targets/Sparc.cpp
+++ b/clang/lib/Basic/Targets/Sparc.cpp
@@ -160,6 +160,7 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
+ Builder.defineMacro("__LONG_DOUBLE_128__");
}
void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
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 0461f121d76c9..7f20c10338c52 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -26,23 +26,39 @@ class SparcV8ABIInfo : public DefaultABIInfo {
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
} // end anonymous namespace
+ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ const auto *CT = Ty->getAs<ComplexType>();
+ const auto *BT = Ty->getAs<BuiltinType>();
+ if (CT)
+ BT = CT->getElementType()->getAs<BuiltinType>();
+ bool IsLongDouble = BT && BT->getKind() == BuiltinType::LongDouble;
-ABIArgInfo
-SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
- if (Ty->isAnyComplexType()) {
- return ABIArgInfo::getDirect();
- }
- else {
- return DefaultABIInfo::classifyReturnType(Ty);
- }
+ // long double _Complex is special in that it should be marked as inreg.
+ if (CT)
+ return IsLongDouble ? ABIArgInfo::getDirectInReg()
+ : ABIArgInfo::getDirect();
+
+ if (IsLongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
+ /*ByVal=*/false);
+
+ return DefaultABIInfo::classifyReturnType(Ty);
}
-void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {
+ if (const auto *BT = Ty->getAs<BuiltinType>();
+ BT && BT->getKind() == BuiltinType::LongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+ return DefaultABIInfo::classifyArgumentType(Ty);
+}
+
+void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &Arg : FI.arguments())
Arg.info = classifyArgumentType(Arg.type);
diff --git a/clang/test/CodeGen/sparcv8-abi.c b/clang/test/CodeGen/sparcv8-abi.c
index c5faf130890f8..7beddd20e5e4d 100644
--- a/clang/test/CodeGen/sparcv8-abi.c
+++ b/clang/test/CodeGen/sparcv8-abi.c
@@ -1,22 +1,52 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 6
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// CHECK-LABEL: define{{.*}} { float, float } @p(ptr noundef byval({ float, float }) align 4 %a, ptr noundef byval({ float, float }) align 4 %b) #0 {
float __complex__
+// CHECK-LABEL: define dso_local { float, float } @p(
+// CHECK-SAME: ptr noundef byval({ float, float }) align 4 [[A:%.*]], ptr noundef byval({ float, float }) align 4 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK: [[ENTRY:.*:]]
+//
p (float __complex__ a, float __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { double, double } @q(ptr noundef byval({ double, double }) align 8 %a, ptr noundef byval({ double, double }) align 8 %b) #0 {
double __complex__
+// CHECK-LABEL: define dso_local { double, double } @q(
+// CHECK-SAME: ptr noundef byval({ double, double }) align 8 [[A:%.*]], ptr noundef byval({ double, double }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
q (double __complex__ a, double __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { i64, i64 } @r(ptr noundef byval({ i64, i64 }) align 8 %a, ptr noundef byval({ i64, i64 }) align 8 %b) #0 {
long long __complex__
+// CHECK-LABEL: define dso_local { i64, i64 } @r(
+// CHECK-SAME: ptr noundef byval({ i64, i64 }) align 8 [[A:%.*]], ptr noundef byval({ i64, i64 }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
r (long long __complex__ a, long long __complex__ b)
{
return 0;
}
+
+long double
+// CHECK-LABEL: define dso_local void @s(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(fp128) align 8 [[AGG_RESULT:%.*]], ptr noundef byval(fp128) align 8 [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+s(long double a)
+{
+ return 0;
+}
+
+long double _Complex
+// CHECK-LABEL: define dso_local inreg { fp128, fp128 } @t(
+// CHECK-SAME: ptr noundef byval({ fp128, fp128 }) align 8 [[A:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+t(long double _Complex a)
+{
+ return 0;
+}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7e0df96141364..3ef33de35f9ec 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -1106,19 +1106,19 @@
// SPARC:#define __INT_LEAST8_MAX__ 127
// SPARC:#define __INT_LEAST8_TYPE__ signed char
// SPARC:#define __INT_MAX__ 2147483647
-// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
-// SPARC:#define __LDBL_DIG__ 15
-// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+// SPARC:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// SPARC:#define __LDBL_DIG__ 33
+// SPARC:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// SPARC:#define __LDBL_HAS_DENORM__ 1
// SPARC:#define __LDBL_HAS_INFINITY__ 1
// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
-// SPARC:#define __LDBL_MANT_DIG__ 53
-// SPARC:#define __LDBL_MAX_10_EXP__ 308
-// SPARC:#define __LDBL_MAX_EXP__ 1024
-// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308L
-// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
-// SPARC:#define __LDBL_MIN_EXP__ (-1021)
-// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308L
+// SPARC:#define __LDBL_MANT_DIG__ 113
+// SPARC:#define __LDBL_MAX_10_EXP__ 4932
+// SPARC:#define __LDBL_MAX_EXP__ 16384
+// SPARC:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// SPARC:#define __LDBL_MIN_10_EXP__ (-4931)
+// SPARC:#define __LDBL_MIN_EXP__ (-16381)
+// SPARC:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// SPARC:#define __LONG_MAX__ 2147483647L
// SPARC-NOT:#define __LP64__
@@ -1134,7 +1134,7 @@
// SPARC:#define __SIZEOF_DOUBLE__ 8
// SPARC:#define __SIZEOF_FLOAT__ 4
// SPARC:#define __SIZEOF_INT__ 4
-// SPARC:#define __SIZEOF_LONG_DOUBLE__ 8
+// SPARC:#define __SIZEOF_LONG_DOUBLE__ 16
// SPARC:#define __SIZEOF_LONG_LONG__ 8
// SPARC:#define __SIZEOF_LONG__ 4
// SPARC:#define __SIZEOF_POINTER__ 4
diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c
index e82d825704439..0fd927a02fcb7 100644
--- a/clang/test/Preprocessor/predefined-arch-macros.c
+++ b/clang/test/Preprocessor/predefined-arch-macros.c
@@ -4206,6 +4206,11 @@
// CHECK_SPARC-NOT: #define __sparcv9 1
// CHECK_SPARC-NOT: #define __sparcv9__ 1
+// RUN: %clang -E -dM %s -o - 2>&1 \
+// RUN: -target sparc-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL
+// CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1
+
// RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \
// RUN: -target sparc-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 3ab92403d4168..b43d9aff45c48 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -948,9 +948,10 @@ 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..270624fdf6ecd 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -44,7 +44,8 @@ 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/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
index cfe8d800d3834..f6629ab81c3b3 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
index a38f34a245fae..9ca30f4a65688 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
index 8638bf69f749e..80063b7a0f9f9 100644
--- a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
@@ -9,9 +9,6 @@
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// RUN: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
// This test assumes float and double are IEEE-754 single- and double-precision.
#if defined(__APPLE__)
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
index ffd95a5f9c0bb..3edb296d90556 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
@@ -25,9 +25,6 @@
// FIXME: log_path is not supported on Windows yet.
// XFAIL: target={{.*windows-msvc.*}}
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index 8afd0a7fc09ad..6214000ddce5b 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -17,6 +17,9 @@
def CC_Sparc32 : CallingConv<[
// Custom assign SRet to [sp+64].
CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>,
+ // f128 arguments are passed indirectly, using i32 pointers.
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCPassIndirect<i32>>,
// i32 f32 arguments get passed in integer registers if there is space.
CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
// f64 arguments are split and passed through registers or through stack.
@@ -24,20 +27,20 @@ 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">>,
-
-
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
+
def RetCC_Sparc32 : CallingConv<[
CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
CCIfType<[f64], CCAssignToReg<[D0, D1]>>,
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCIfInReg<CCAssignToReg<[Q0, Q1]>>>,
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">>
]>;
-
//===----------------------------------------------------------------------===//
// SPARC v9 64-bit.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 57e7ff3a52cec..0ce29010f688e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -439,6 +439,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -452,6 +453,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
unsigned InIdx = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
CCValAssign &VA = ArgLocs[i];
+ EVT LocVT = VA.getLocVT();
if (Ins[InIdx].Flags.isSRet()) {
if (InIdx != 0)
@@ -465,6 +467,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
+ SDValue Arg;
if (VA.isRegLoc()) {
if (VA.needsCustom()) {
assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
@@ -499,76 +502,85 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
}
Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
- SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
- if (VA.getLocVT() == MVT::f32)
- Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
- else if (VA.getLocVT() != MVT::i32) {
- Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
- DAG.getValueType(VA.getLocVT()));
- Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ if (VA.getLocVT() == MVT::f32)
+ Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
+ else if (VA.getLocVT() != MVT::i32) {
+ Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
+ DAG.getValueType(VA.getLocVT()));
+ Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ }
+ InVals.push_back(Arg);
+ continue;
}
- InVals.push_back(Arg);
- continue;
- }
+ } else {
+ assert(VA.isMemLoc());
- assert(VA.isMemLoc());
+ unsigned Offset = VA.getLocMemOffset() + StackOffset;
- unsigned Offset = VA.getLocMemOffset()+StackOffset;
- auto PtrVT = getPointerTy(DAG.getDataLayout());
+ if (VA.needsCustom()) {
+ assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
+ // If it is double-word aligned, just load.
+ if (Offset % 8 == 0) {
+ int FI = MF.getFrameInfo().CreateFixedObject(8, Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
+ MachinePointerInfo());
+ InVals.push_back(Load);
+ continue;
+ }
- if (VA.needsCustom()) {
- assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
- // If it is double-word aligned, just load.
- if (Offset % 8 == 0) {
- int FI = MF.getFrameInfo().CreateFixedObject(8,
- Offset,
- true);
+ int FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue Load =
- DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
- InVals.push_back(Load);
- continue;
- }
+ SDValue HiVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
+ int FI2 = MF.getFrameInfo().CreateFixedObject(4, Offset + 4, true);
+ SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue HiVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
- int FI2 = MF.getFrameInfo().CreateFixedObject(4,
- Offset+4,
- true);
- SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
+ SDValue LoVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
- SDValue LoVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
+ if (IsLittleEndian)
+ std::swap(LoVal, HiVal);
- if (IsLittleEndian)
- std::swap(LoVal, HiVal);
+ SDValue WholeValue =
+ DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
+ WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
+ InVals.push_back(WholeValue);
+ continue;
+ }
- SDValue WholeValue =
- DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
- WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
- InVals.push_back(WholeValue);
- continue;
+ int FI = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8,
+ Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(LocVT, dl, Chain, FIPtr,
+ MachinePointerInfo::getFixedStack(MF, FI));
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ InVals.push_back(Load);
+ continue;
+ }
+ Arg = Load;
}
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- 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.");
+ assert(VA.getLocInfo() == CCValAssign::Indirect);
+
+ SDValue ArgValue =
+ ...
[truncated]
|
|
@llvm/pr-subscribers-clang-codegen Author: None (llvmbot) ChangesRequested by: @brad0 Patch is 43.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170580.diff 17 Files Affected:
diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp
index d1a891092b0f5..2dcf31fc5591d 100644
--- a/clang/lib/Basic/Targets/Sparc.cpp
+++ b/clang/lib/Basic/Targets/Sparc.cpp
@@ -160,6 +160,7 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
+ Builder.defineMacro("__LONG_DOUBLE_128__");
}
void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
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 0461f121d76c9..7f20c10338c52 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -26,23 +26,39 @@ class SparcV8ABIInfo : public DefaultABIInfo {
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
} // end anonymous namespace
+ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ const auto *CT = Ty->getAs<ComplexType>();
+ const auto *BT = Ty->getAs<BuiltinType>();
+ if (CT)
+ BT = CT->getElementType()->getAs<BuiltinType>();
+ bool IsLongDouble = BT && BT->getKind() == BuiltinType::LongDouble;
-ABIArgInfo
-SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
- if (Ty->isAnyComplexType()) {
- return ABIArgInfo::getDirect();
- }
- else {
- return DefaultABIInfo::classifyReturnType(Ty);
- }
+ // long double _Complex is special in that it should be marked as inreg.
+ if (CT)
+ return IsLongDouble ? ABIArgInfo::getDirectInReg()
+ : ABIArgInfo::getDirect();
+
+ if (IsLongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
+ /*ByVal=*/false);
+
+ return DefaultABIInfo::classifyReturnType(Ty);
}
-void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {
+ if (const auto *BT = Ty->getAs<BuiltinType>();
+ BT && BT->getKind() == BuiltinType::LongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+ return DefaultABIInfo::classifyArgumentType(Ty);
+}
+
+void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &Arg : FI.arguments())
Arg.info = classifyArgumentType(Arg.type);
diff --git a/clang/test/CodeGen/sparcv8-abi.c b/clang/test/CodeGen/sparcv8-abi.c
index c5faf130890f8..7beddd20e5e4d 100644
--- a/clang/test/CodeGen/sparcv8-abi.c
+++ b/clang/test/CodeGen/sparcv8-abi.c
@@ -1,22 +1,52 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 6
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// CHECK-LABEL: define{{.*}} { float, float } @p(ptr noundef byval({ float, float }) align 4 %a, ptr noundef byval({ float, float }) align 4 %b) #0 {
float __complex__
+// CHECK-LABEL: define dso_local { float, float } @p(
+// CHECK-SAME: ptr noundef byval({ float, float }) align 4 [[A:%.*]], ptr noundef byval({ float, float }) align 4 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK: [[ENTRY:.*:]]
+//
p (float __complex__ a, float __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { double, double } @q(ptr noundef byval({ double, double }) align 8 %a, ptr noundef byval({ double, double }) align 8 %b) #0 {
double __complex__
+// CHECK-LABEL: define dso_local { double, double } @q(
+// CHECK-SAME: ptr noundef byval({ double, double }) align 8 [[A:%.*]], ptr noundef byval({ double, double }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
q (double __complex__ a, double __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { i64, i64 } @r(ptr noundef byval({ i64, i64 }) align 8 %a, ptr noundef byval({ i64, i64 }) align 8 %b) #0 {
long long __complex__
+// CHECK-LABEL: define dso_local { i64, i64 } @r(
+// CHECK-SAME: ptr noundef byval({ i64, i64 }) align 8 [[A:%.*]], ptr noundef byval({ i64, i64 }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
r (long long __complex__ a, long long __complex__ b)
{
return 0;
}
+
+long double
+// CHECK-LABEL: define dso_local void @s(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(fp128) align 8 [[AGG_RESULT:%.*]], ptr noundef byval(fp128) align 8 [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+s(long double a)
+{
+ return 0;
+}
+
+long double _Complex
+// CHECK-LABEL: define dso_local inreg { fp128, fp128 } @t(
+// CHECK-SAME: ptr noundef byval({ fp128, fp128 }) align 8 [[A:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+t(long double _Complex a)
+{
+ return 0;
+}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7e0df96141364..3ef33de35f9ec 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -1106,19 +1106,19 @@
// SPARC:#define __INT_LEAST8_MAX__ 127
// SPARC:#define __INT_LEAST8_TYPE__ signed char
// SPARC:#define __INT_MAX__ 2147483647
-// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
-// SPARC:#define __LDBL_DIG__ 15
-// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+// SPARC:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// SPARC:#define __LDBL_DIG__ 33
+// SPARC:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// SPARC:#define __LDBL_HAS_DENORM__ 1
// SPARC:#define __LDBL_HAS_INFINITY__ 1
// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
-// SPARC:#define __LDBL_MANT_DIG__ 53
-// SPARC:#define __LDBL_MAX_10_EXP__ 308
-// SPARC:#define __LDBL_MAX_EXP__ 1024
-// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308L
-// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
-// SPARC:#define __LDBL_MIN_EXP__ (-1021)
-// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308L
+// SPARC:#define __LDBL_MANT_DIG__ 113
+// SPARC:#define __LDBL_MAX_10_EXP__ 4932
+// SPARC:#define __LDBL_MAX_EXP__ 16384
+// SPARC:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// SPARC:#define __LDBL_MIN_10_EXP__ (-4931)
+// SPARC:#define __LDBL_MIN_EXP__ (-16381)
+// SPARC:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// SPARC:#define __LONG_MAX__ 2147483647L
// SPARC-NOT:#define __LP64__
@@ -1134,7 +1134,7 @@
// SPARC:#define __SIZEOF_DOUBLE__ 8
// SPARC:#define __SIZEOF_FLOAT__ 4
// SPARC:#define __SIZEOF_INT__ 4
-// SPARC:#define __SIZEOF_LONG_DOUBLE__ 8
+// SPARC:#define __SIZEOF_LONG_DOUBLE__ 16
// SPARC:#define __SIZEOF_LONG_LONG__ 8
// SPARC:#define __SIZEOF_LONG__ 4
// SPARC:#define __SIZEOF_POINTER__ 4
diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c
index e82d825704439..0fd927a02fcb7 100644
--- a/clang/test/Preprocessor/predefined-arch-macros.c
+++ b/clang/test/Preprocessor/predefined-arch-macros.c
@@ -4206,6 +4206,11 @@
// CHECK_SPARC-NOT: #define __sparcv9 1
// CHECK_SPARC-NOT: #define __sparcv9__ 1
+// RUN: %clang -E -dM %s -o - 2>&1 \
+// RUN: -target sparc-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL
+// CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1
+
// RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \
// RUN: -target sparc-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 3ab92403d4168..b43d9aff45c48 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -948,9 +948,10 @@ 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..270624fdf6ecd 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -44,7 +44,8 @@ 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/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
index cfe8d800d3834..f6629ab81c3b3 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
index a38f34a245fae..9ca30f4a65688 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
index 8638bf69f749e..80063b7a0f9f9 100644
--- a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
@@ -9,9 +9,6 @@
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// RUN: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
// This test assumes float and double are IEEE-754 single- and double-precision.
#if defined(__APPLE__)
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
index ffd95a5f9c0bb..3edb296d90556 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
@@ -25,9 +25,6 @@
// FIXME: log_path is not supported on Windows yet.
// XFAIL: target={{.*windows-msvc.*}}
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index 8afd0a7fc09ad..6214000ddce5b 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -17,6 +17,9 @@
def CC_Sparc32 : CallingConv<[
// Custom assign SRet to [sp+64].
CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>,
+ // f128 arguments are passed indirectly, using i32 pointers.
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCPassIndirect<i32>>,
// i32 f32 arguments get passed in integer registers if there is space.
CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
// f64 arguments are split and passed through registers or through stack.
@@ -24,20 +27,20 @@ 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">>,
-
-
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
+
def RetCC_Sparc32 : CallingConv<[
CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
CCIfType<[f64], CCAssignToReg<[D0, D1]>>,
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCIfInReg<CCAssignToReg<[Q0, Q1]>>>,
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">>
]>;
-
//===----------------------------------------------------------------------===//
// SPARC v9 64-bit.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 57e7ff3a52cec..0ce29010f688e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -439,6 +439,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -452,6 +453,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
unsigned InIdx = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
CCValAssign &VA = ArgLocs[i];
+ EVT LocVT = VA.getLocVT();
if (Ins[InIdx].Flags.isSRet()) {
if (InIdx != 0)
@@ -465,6 +467,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
+ SDValue Arg;
if (VA.isRegLoc()) {
if (VA.needsCustom()) {
assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
@@ -499,76 +502,85 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
}
Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
- SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
- if (VA.getLocVT() == MVT::f32)
- Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
- else if (VA.getLocVT() != MVT::i32) {
- Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
- DAG.getValueType(VA.getLocVT()));
- Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ if (VA.getLocVT() == MVT::f32)
+ Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
+ else if (VA.getLocVT() != MVT::i32) {
+ Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
+ DAG.getValueType(VA.getLocVT()));
+ Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ }
+ InVals.push_back(Arg);
+ continue;
}
- InVals.push_back(Arg);
- continue;
- }
+ } else {
+ assert(VA.isMemLoc());
- assert(VA.isMemLoc());
+ unsigned Offset = VA.getLocMemOffset() + StackOffset;
- unsigned Offset = VA.getLocMemOffset()+StackOffset;
- auto PtrVT = getPointerTy(DAG.getDataLayout());
+ if (VA.needsCustom()) {
+ assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
+ // If it is double-word aligned, just load.
+ if (Offset % 8 == 0) {
+ int FI = MF.getFrameInfo().CreateFixedObject(8, Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
+ MachinePointerInfo());
+ InVals.push_back(Load);
+ continue;
+ }
- if (VA.needsCustom()) {
- assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
- // If it is double-word aligned, just load.
- if (Offset % 8 == 0) {
- int FI = MF.getFrameInfo().CreateFixedObject(8,
- Offset,
- true);
+ int FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue Load =
- DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
- InVals.push_back(Load);
- continue;
- }
+ SDValue HiVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
+ int FI2 = MF.getFrameInfo().CreateFixedObject(4, Offset + 4, true);
+ SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue HiVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
- int FI2 = MF.getFrameInfo().CreateFixedObject(4,
- Offset+4,
- true);
- SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
+ SDValue LoVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
- SDValue LoVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
+ if (IsLittleEndian)
+ std::swap(LoVal, HiVal);
- if (IsLittleEndian)
- std::swap(LoVal, HiVal);
+ SDValue WholeValue =
+ DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
+ WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
+ InVals.push_back(WholeValue);
+ continue;
+ }
- SDValue WholeValue =
- DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
- WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
- InVals.push_back(WholeValue);
- continue;
+ int FI = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8,
+ Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(LocVT, dl, Chain, FIPtr,
+ MachinePointerInfo::getFixedStack(MF, FI));
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ InVals.push_back(Load);
+ continue;
+ }
+ Arg = Load;
}
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- 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.");
+ assert(VA.getLocInfo() == CCValAssign::Indirect);
+
+ SDValue ArgValue =
+ ...
[truncated]
|
|
@llvm/pr-subscribers-compiler-rt-sanitizer Author: None (llvmbot) ChangesRequested by: @brad0 Patch is 43.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170580.diff 17 Files Affected:
diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp
index d1a891092b0f5..2dcf31fc5591d 100644
--- a/clang/lib/Basic/Targets/Sparc.cpp
+++ b/clang/lib/Basic/Targets/Sparc.cpp
@@ -160,6 +160,7 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
+ Builder.defineMacro("__LONG_DOUBLE_128__");
}
void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
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 0461f121d76c9..7f20c10338c52 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -26,23 +26,39 @@ class SparcV8ABIInfo : public DefaultABIInfo {
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
} // end anonymous namespace
+ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ const auto *CT = Ty->getAs<ComplexType>();
+ const auto *BT = Ty->getAs<BuiltinType>();
+ if (CT)
+ BT = CT->getElementType()->getAs<BuiltinType>();
+ bool IsLongDouble = BT && BT->getKind() == BuiltinType::LongDouble;
-ABIArgInfo
-SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
- if (Ty->isAnyComplexType()) {
- return ABIArgInfo::getDirect();
- }
- else {
- return DefaultABIInfo::classifyReturnType(Ty);
- }
+ // long double _Complex is special in that it should be marked as inreg.
+ if (CT)
+ return IsLongDouble ? ABIArgInfo::getDirectInReg()
+ : ABIArgInfo::getDirect();
+
+ if (IsLongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
+ /*ByVal=*/false);
+
+ return DefaultABIInfo::classifyReturnType(Ty);
}
-void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {
+ if (const auto *BT = Ty->getAs<BuiltinType>();
+ BT && BT->getKind() == BuiltinType::LongDouble)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+ return DefaultABIInfo::classifyArgumentType(Ty);
+}
+
+void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (auto &Arg : FI.arguments())
Arg.info = classifyArgumentType(Arg.type);
diff --git a/clang/test/CodeGen/sparcv8-abi.c b/clang/test/CodeGen/sparcv8-abi.c
index c5faf130890f8..7beddd20e5e4d 100644
--- a/clang/test/CodeGen/sparcv8-abi.c
+++ b/clang/test/CodeGen/sparcv8-abi.c
@@ -1,22 +1,52 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 6
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// CHECK-LABEL: define{{.*}} { float, float } @p(ptr noundef byval({ float, float }) align 4 %a, ptr noundef byval({ float, float }) align 4 %b) #0 {
float __complex__
+// CHECK-LABEL: define dso_local { float, float } @p(
+// CHECK-SAME: ptr noundef byval({ float, float }) align 4 [[A:%.*]], ptr noundef byval({ float, float }) align 4 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK: [[ENTRY:.*:]]
+//
p (float __complex__ a, float __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { double, double } @q(ptr noundef byval({ double, double }) align 8 %a, ptr noundef byval({ double, double }) align 8 %b) #0 {
double __complex__
+// CHECK-LABEL: define dso_local { double, double } @q(
+// CHECK-SAME: ptr noundef byval({ double, double }) align 8 [[A:%.*]], ptr noundef byval({ double, double }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
q (double __complex__ a, double __complex__ b)
{
return 0;
}
-// CHECK-LABEL: define{{.*}} { i64, i64 } @r(ptr noundef byval({ i64, i64 }) align 8 %a, ptr noundef byval({ i64, i64 }) align 8 %b) #0 {
long long __complex__
+// CHECK-LABEL: define dso_local { i64, i64 } @r(
+// CHECK-SAME: ptr noundef byval({ i64, i64 }) align 8 [[A:%.*]], ptr noundef byval({ i64, i64 }) align 8 [[B:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
r (long long __complex__ a, long long __complex__ b)
{
return 0;
}
+
+long double
+// CHECK-LABEL: define dso_local void @s(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret(fp128) align 8 [[AGG_RESULT:%.*]], ptr noundef byval(fp128) align 8 [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+s(long double a)
+{
+ return 0;
+}
+
+long double _Complex
+// CHECK-LABEL: define dso_local inreg { fp128, fp128 } @t(
+// CHECK-SAME: ptr noundef byval({ fp128, fp128 }) align 8 [[A:%.*]]) #[[ATTR0]] {
+// CHECK: [[ENTRY:.*:]]
+//
+t(long double _Complex a)
+{
+ return 0;
+}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7e0df96141364..3ef33de35f9ec 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -1106,19 +1106,19 @@
// SPARC:#define __INT_LEAST8_MAX__ 127
// SPARC:#define __INT_LEAST8_TYPE__ signed char
// SPARC:#define __INT_MAX__ 2147483647
-// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
-// SPARC:#define __LDBL_DIG__ 15
-// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+// SPARC:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// SPARC:#define __LDBL_DIG__ 33
+// SPARC:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// SPARC:#define __LDBL_HAS_DENORM__ 1
// SPARC:#define __LDBL_HAS_INFINITY__ 1
// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
-// SPARC:#define __LDBL_MANT_DIG__ 53
-// SPARC:#define __LDBL_MAX_10_EXP__ 308
-// SPARC:#define __LDBL_MAX_EXP__ 1024
-// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308L
-// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
-// SPARC:#define __LDBL_MIN_EXP__ (-1021)
-// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308L
+// SPARC:#define __LDBL_MANT_DIG__ 113
+// SPARC:#define __LDBL_MAX_10_EXP__ 4932
+// SPARC:#define __LDBL_MAX_EXP__ 16384
+// SPARC:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// SPARC:#define __LDBL_MIN_10_EXP__ (-4931)
+// SPARC:#define __LDBL_MIN_EXP__ (-16381)
+// SPARC:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// SPARC:#define __LONG_MAX__ 2147483647L
// SPARC-NOT:#define __LP64__
@@ -1134,7 +1134,7 @@
// SPARC:#define __SIZEOF_DOUBLE__ 8
// SPARC:#define __SIZEOF_FLOAT__ 4
// SPARC:#define __SIZEOF_INT__ 4
-// SPARC:#define __SIZEOF_LONG_DOUBLE__ 8
+// SPARC:#define __SIZEOF_LONG_DOUBLE__ 16
// SPARC:#define __SIZEOF_LONG_LONG__ 8
// SPARC:#define __SIZEOF_LONG__ 4
// SPARC:#define __SIZEOF_POINTER__ 4
diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c
index e82d825704439..0fd927a02fcb7 100644
--- a/clang/test/Preprocessor/predefined-arch-macros.c
+++ b/clang/test/Preprocessor/predefined-arch-macros.c
@@ -4206,6 +4206,11 @@
// CHECK_SPARC-NOT: #define __sparcv9 1
// CHECK_SPARC-NOT: #define __sparcv9__ 1
+// RUN: %clang -E -dM %s -o - 2>&1 \
+// RUN: -target sparc-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL
+// CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1
+
// RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \
// RUN: -target sparc-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 3ab92403d4168..b43d9aff45c48 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -948,9 +948,10 @@ 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..270624fdf6ecd 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -44,7 +44,8 @@ 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/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
index cfe8d800d3834..f6629ab81c3b3 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
index a38f34a245fae..9ca30f4a65688 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
@@ -1,8 +1,5 @@
// RUN: %clang %s -o %t && %run %t 2>&1
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
diff --git a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
index 8638bf69f749e..80063b7a0f9f9 100644
--- a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
@@ -9,9 +9,6 @@
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// RUN: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
// This test assumes float and double are IEEE-754 single- and double-precision.
#if defined(__APPLE__)
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
index ffd95a5f9c0bb..3edb296d90556 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
@@ -25,9 +25,6 @@
// FIXME: log_path is not supported on Windows yet.
// XFAIL: target={{.*windows-msvc.*}}
-// Issue #41838
-// XFAIL: sparc-target-arch && target={{.*solaris.*}}
-
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index 8afd0a7fc09ad..6214000ddce5b 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -17,6 +17,9 @@
def CC_Sparc32 : CallingConv<[
// Custom assign SRet to [sp+64].
CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>,
+ // f128 arguments are passed indirectly, using i32 pointers.
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCPassIndirect<i32>>,
// i32 f32 arguments get passed in integer registers if there is space.
CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
// f64 arguments are split and passed through registers or through stack.
@@ -24,20 +27,20 @@ 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">>,
-
-
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
+
def RetCC_Sparc32 : CallingConv<[
CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
CCIfType<[f64], CCAssignToReg<[D0, D1]>>,
+ // FIXME GCC in soft-float mode passes f128 as if 2xi64 values.
+ CCIfType<[f128], CCIfInReg<CCAssignToReg<[Q0, Q1]>>>,
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">>
]>;
-
//===----------------------------------------------------------------------===//
// SPARC v9 64-bit.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 57e7ff3a52cec..0ce29010f688e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -439,6 +439,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -452,6 +453,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
unsigned InIdx = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
CCValAssign &VA = ArgLocs[i];
+ EVT LocVT = VA.getLocVT();
if (Ins[InIdx].Flags.isSRet()) {
if (InIdx != 0)
@@ -465,6 +467,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
+ SDValue Arg;
if (VA.isRegLoc()) {
if (VA.needsCustom()) {
assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
@@ -499,76 +502,85 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
}
Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
- SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
- if (VA.getLocVT() == MVT::f32)
- Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
- else if (VA.getLocVT() != MVT::i32) {
- Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
- DAG.getValueType(VA.getLocVT()));
- Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ if (VA.getLocVT() == MVT::f32)
+ Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
+ else if (VA.getLocVT() != MVT::i32) {
+ Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
+ DAG.getValueType(VA.getLocVT()));
+ Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ }
+ InVals.push_back(Arg);
+ continue;
}
- InVals.push_back(Arg);
- continue;
- }
+ } else {
+ assert(VA.isMemLoc());
- assert(VA.isMemLoc());
+ unsigned Offset = VA.getLocMemOffset() + StackOffset;
- unsigned Offset = VA.getLocMemOffset()+StackOffset;
- auto PtrVT = getPointerTy(DAG.getDataLayout());
+ if (VA.needsCustom()) {
+ assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
+ // If it is double-word aligned, just load.
+ if (Offset % 8 == 0) {
+ int FI = MF.getFrameInfo().CreateFixedObject(8, Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
+ MachinePointerInfo());
+ InVals.push_back(Load);
+ continue;
+ }
- if (VA.needsCustom()) {
- assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
- // If it is double-word aligned, just load.
- if (Offset % 8 == 0) {
- int FI = MF.getFrameInfo().CreateFixedObject(8,
- Offset,
- true);
+ int FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue Load =
- DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
- InVals.push_back(Load);
- continue;
- }
+ SDValue HiVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
+ int FI2 = MF.getFrameInfo().CreateFixedObject(4, Offset + 4, true);
+ SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue HiVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
- int FI2 = MF.getFrameInfo().CreateFixedObject(4,
- Offset+4,
- true);
- SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
+ SDValue LoVal =
+ DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
- SDValue LoVal =
- DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
+ if (IsLittleEndian)
+ std::swap(LoVal, HiVal);
- if (IsLittleEndian)
- std::swap(LoVal, HiVal);
+ SDValue WholeValue =
+ DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
+ WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
+ InVals.push_back(WholeValue);
+ continue;
+ }
- SDValue WholeValue =
- DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
- WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
- InVals.push_back(WholeValue);
- continue;
+ int FI = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8,
+ Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load = DAG.getLoad(LocVT, dl, Chain, FIPtr,
+ MachinePointerInfo::getFixedStack(MF, FI));
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ InVals.push_back(Load);
+ continue;
+ }
+ Arg = Load;
}
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- 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.");
+ assert(VA.getLocInfo() == CCValAssign::Indirect);
+
+ SDValue ArgValue =
+ ...
[truncated]
|
Backport 3e16aef 3d598c3
Requested by: @brad0