Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/lib/Basic/Targets/Sparc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably also need to fix the datalayout

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It already has the f128:64 part, so I think I'm good here?

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;
Expand Down
33 changes: 24 additions & 9 deletions clang/lib/CodeGen/Targets/Sparc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,38 @@ 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());

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);
Expand Down
36 changes: 33 additions & 3 deletions clang/test/CodeGen/Sparc/sparcv8-abi.c
Original file line number Diff line number Diff line change
@@ -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;
}
22 changes: 11 additions & 11 deletions clang/test/Preprocessor/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1009,9 +1009,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}" STREQUAL "riscv32" OR ("${arch}" STREQUAL "sparc" AND NOT CMAKE_COMPILER_IS_GNUCC))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for going back and forth, I suppose -fforce-enable-in128 isn't supported by riscv-gcc either, so it should be the same as in the file below.


When compiled with gcc, how is the library supposed to link if int128 routines are not compiled in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When compiled with gcc, how is the library supposed to link if int128 routines are not compiled in?

I suppose in that case the library will lack long double routines? @rorth probably know better about this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When compiled with gcc, how is the library supposed to link if int128 routines are not compiled in?

I suppose in that case the library will lack long double routines? @rorth probably know better about this.

I've no idea right now (have tried to forget all of this ;-). Besides, I'm so busy with the upcoming GCC 16 release that I've no time left for LLVM.

What I've done in the past is do build with both clang and gcc as build compiler, 2-stage builds with clang, 1-stage ones with gcc. And note that the compiler-rt tests still aren't run in runtime builds (which is the default these days), not even a target to do so manually, so I've always used

 -DLLVM_ENABLE_PROJECTS=compiler-rt

to avoid that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint! I tried running it and seems like I found some other long double related failures:

SanitizerCommon-asan-sparc-Linux :: printf-ldbl.c
SanitizerCommon-asan-sparc-Linux :: scanf-ldbl.c
SanitizerCommon-ubsan-sparc-Linux :: printf-ldbl.c                                                                                                                                                                                                                            
SanitizerCommon-ubsan-sparc-Linux :: scanf-ldbl.c

Because clang lowers the printf/scanf calls into something like __nldbl_snprintf and __nldbl___isoc99_sscanf...
Seems like I missed defining __LONG_DOUBLE_128__, lemme fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay seems like after __LONG_DOUBLE_128__ is added the issue is gone.

list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128)
endif()

Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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()
Expand Down
3 changes: 0 additions & 3 deletions compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c
Original file line number Diff line number Diff line change
@@ -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>
Expand Down
3 changes: 0 additions & 3 deletions compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c
Original file line number Diff line number Diff line change
@@ -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>
Expand Down
3 changes: 0 additions & 3 deletions compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
3 changes: 0 additions & 3 deletions compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,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[]) {
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Target/Sparc/SparcCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@
def CC_Sparc32 : CallingConv<[
// Custom assign SRet to [sp+64].
CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>,
// f128 arguments are passed indirectly, using i32 pointers.
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.
CCIfType<[f64], CCCustom<"CC_Sparc_Assign_Split_64">>,
// 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]>>,
CCIfType<[f128], CCIfInReg<CCIfConsecutiveRegs<CCAssignToReg<[Q0, Q1]>>>>,
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">>
]>;

Expand Down
Loading