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:
|
public:
|
||||||
SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
|
SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
|
||||||
: TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(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
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
@ -9748,6 +9770,18 @@ public:
|
||||||
|
|
||||||
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *Address) const override;
|
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
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,29 @@
|
||||||
// REQUIRES: sparc-registered-target
|
// REQUIRES: sparc-registered-target
|
||||||
// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
|
// 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)
|
void test_eh_return_data_regno(void)
|
||||||
{
|
{
|
||||||
volatile int res;
|
volatile int res;
|
||||||
res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 24
|
res = __builtin_eh_return_data_regno(0); // CHECK,CHECKV9: store volatile i32 24
|
||||||
res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 25
|
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