From c8f664d838164bfc6203a3a421ea2239171469b2 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 2 Feb 2022 19:20:02 +0100 Subject: [PATCH] [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 (cherry picked from commit efdd0a29b7eb6f3b6ca3fe9182a6c1085806c73a) --- clang/lib/CodeGen/TargetInfo.cpp | 34 +++++++++++++++++++++++++++++ clang/test/CodeGen/builtins-sparc.c | 25 ++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 8a0150218a7a9..9af3004ebcc5b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -9474,6 +9474,28 @@ class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo { public: SparcV8TargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(std::make_unique(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 @@ class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo { 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 diff --git a/clang/test/CodeGen/builtins-sparc.c b/clang/test/CodeGen/builtins-sparc.c index 92cc7677e21f7..343a1c521526c 100644 --- a/clang/test/CodeGen/builtins-sparc.c +++ b/clang/test/CodeGen/builtins-sparc.c @@ -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; }