Author: Ben Shi Date: 2021-06-29T11:32:39+08:00 New Revision: c94c8d8b5d999c97ea424b35a1cb540d2a1d3bc6
URL: https://github.com/llvm/llvm-project/commit/c94c8d8b5d999c97ea424b35a1cb540d2a1d3bc6 DIFF: https://github.com/llvm/llvm-project/commit/c94c8d8b5d999c97ea424b35a1cb540d2a1d3bc6.diff LOG: [AVR][clang] Fix wrong calling convention in functions return struct type According to AVR ABI (https://gcc.gnu.org/wiki/avr-gcc), returned struct value within size 1-8 bytes should be returned directly (via register r18-r25), while larger ones should be returned via an implicit struct pointer argument. Reviewed By: dylanmckay Differential Revision: https://reviews.llvm.org/D99237 Added: clang/test/CodeGen/avr/struct.c Modified: clang/lib/CodeGen/TargetInfo.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index e9565a5aef63..035c131dacb7 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -8154,14 +8154,39 @@ void M68kTargetCodeGenInfo::setTargetAttributes( } //===----------------------------------------------------------------------===// -// AVR ABI Implementation. +// AVR ABI Implementation. Documented at +// https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention +// https://gcc.gnu.org/wiki/avr-gcc#Reduced_Tiny //===----------------------------------------------------------------------===// namespace { +class AVRABIInfo : public DefaultABIInfo { +public: + AVRABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + + ABIArgInfo classifyReturnType(QualType Ty) const { + // A return struct with size less than or equal to 8 bytes is returned + // directly via registers R18-R25. + if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) <= 64) + return ABIArgInfo::getDirect(); + else + return DefaultABIInfo::classifyReturnType(Ty); + } + + // Just copy the original implementation of DefaultABIInfo::computeInfo(), + // since DefaultABIInfo::classify{Return,Argument}Type() are not virtual. + void computeInfo(CGFunctionInfo &FI) const override { + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); + } +}; + class AVRTargetCodeGenInfo : public TargetCodeGenInfo { public: AVRTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {} + : TargetCodeGenInfo(std::make_unique<AVRABIInfo>(CGT)) {} LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, const VarDecl *D) const override { diff --git a/clang/test/CodeGen/avr/struct.c b/clang/test/CodeGen/avr/struct.c new file mode 100644 index 000000000000..cb4e84522df6 --- /dev/null +++ b/clang/test/CodeGen/avr/struct.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 bytes. +struct s10 { + int a, b, c, d, e; +}; + +// Structure that is less than 8 bytes. +struct s06 { + int a, b, c; +}; + +struct s10 foo10(int a, int b, int c) { + struct s10 a0; + return a0; +} + +struct s06 foo06(int a, int b, int c) { + struct s06 a0; + return a0; +} + +// CHECK: %struct.s10 = type { i16, i16, i16, i16, i16 } +// CHECK: %struct.s06 = type { i16, i16, i16 } +// CHECK: define{{.*}} void @foo10(%struct.s10* {{.*}}, i16 %a, i16 %b, i16 %c) +// CHECK: define{{.*}} %struct.s06 @foo06(i16 %a, i16 %b, i16 %c) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits