[clang] c94c8d8 - [AVR][clang] Fix wrong calling convention in functions return struct type

Ben Shi via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 28 21:29:42 PDT 2021


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)


        


More information about the cfe-commits mailing list