[clang][Sparc] Fix __builtin_extract_return_addr etc.

While investigating the failures of `symbolize_pc.cpp` and
`symbolize_pc_inline.cpp` on SPARC (both Solaris and Linux), I noticed that
`__builtin_extract_return_addr` is a no-op in `clang` on all targets, while
`gcc` has non-default implementations for arm, mips, s390, and sparc.

This patch provides the SPARC implementation.  For background see
`SparcISelLowering.cpp` (`SparcTargetLowering::LowerReturn_32`), the SPARC
psABI p.3-12, `%i7` and p.3-16/17, and SCD 2.4.1, p.3P-10, `%i7` and
p.3P-15.

Tested (after enabling the `sanitizer_common` tests on SPARC) on
`sparcv9-sun-solaris2.11`.

Differential Revision: https://reviews.llvm.org/D91607
This commit is contained in:
Rainer Orth 2022-02-02 19:20:02 +01:00
parent b73d151a11
commit efdd0a29b7
2 changed files with 56 additions and 3 deletions

View File

@ -9474,6 +9474,28 @@ class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
public:
SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override {
int Offset;
if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))
Offset = 12;
else
Offset = 8;
return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
llvm::ConstantInt::get(CGF.Int32Ty, Offset));
}
llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override {
int Offset;
if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))
Offset = -12;
else
Offset = -8;
return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
llvm::ConstantInt::get(CGF.Int32Ty, Offset));
}
};
} // end anonymous namespace
@ -9748,6 +9770,18 @@ public:
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override;
llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override {
return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
llvm::ConstantInt::get(CGF.Int32Ty, 8));
}
llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const override {
return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
llvm::ConstantInt::get(CGF.Int32Ty, -8));
}
};
} // end anonymous namespace

View File

@ -1,10 +1,29 @@
// REQUIRES: sparc-registered-target
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple sparc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple sparc64-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix CHECK-V9 %s
void test_eh_return_data_regno(void)
{
volatile int res;
res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 24
res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 25
res = __builtin_eh_return_data_regno(0); // CHECK,CHECKV9: store volatile i32 24
res = __builtin_eh_return_data_regno(1); // CHECK,CHECKV9: store volatile i32 25
}
void *test_extract_return_address(void)
{
// CHECK,CHECKV9: getelementptr i8, i8* %0, i32 8
return __builtin_extract_return_addr(__builtin_return_address(0));
}
struct s {
void *p;
};
struct s test_extract_struct_return_address(void)
{
struct s s;
// CHECK: getelementptr i8, i8* %0, i32 12
// CHECK-V9: getelementptr i8, i8* %0, i32 8
s.p = __builtin_extract_return_addr(__builtin_return_address(0));
return s;
}