forked from OSchip/llvm-project
[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:
parent
b73d151a11
commit
efdd0a29b7
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue