[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
This revision was automatically updated to reflect the committed changes. Closed by commit rG51585aa240de: [clang][AVR] Implement standard calling convention for AVR and AVRTiny (authored by benshi001). Changed prior to commit: https://reviews.llvm.org/D120720?vs=415734=417811#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120720/new/ https://reviews.llvm.org/D120720 Files: clang/lib/Basic/Targets/AVR.cpp clang/lib/Basic/Targets/AVR.h clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/avr/argument.c clang/test/CodeGen/avr/struct.c Index: clang/test/CodeGen/avr/struct.c === --- clang/test/CodeGen/avr/struct.c +++ clang/test/CodeGen/avr/struct.c @@ -1,15 +1,23 @@ -// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=TINY // Structure that is more than 8 bytes. struct s10 { int a, b, c, d, e; }; -// Structure that is less than 8 bytes. +// Structure that is less than 8 bytes but more than 4 bytes. struct s06 { int a, b, c; }; +// Structure that is less than 4 bytes. +struct s04 { + int a, b; +}; + struct s10 foo10(int a, int b, int c) { struct s10 a0; return a0; @@ -20,7 +28,21 @@ 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 noundef %a, i16 noundef %b, i16 noundef %c) -// CHECK: define{{.*}} %struct.s06 @foo06(i16 noundef %a, i16 noundef %b, i16 noundef %c) +struct s04 foo04(int a, int b) { + struct s04 a0; + return a0; +} + +// AVR: %struct.s10 = type { i16, i16, i16, i16, i16 } +// AVR: %struct.s06 = type { i16, i16, i16 } +// AVR: %struct.s04 = type { i16, i16 } +// AVR: define{{.*}} void @foo10(%struct.s10* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// AVR: define{{.*}} %struct.s06 @foo06(i16 noundef %a, i16 noundef %b, i16 noundef %c) +// AVR: define{{.*}} %struct.s04 @foo04(i16 noundef %a, i16 noundef %b) + +// TINY: %struct.s10 = type { i16, i16, i16, i16, i16 } +// TINY: %struct.s06 = type { i16, i16, i16 } +// TINY: %struct.s04 = type { i16, i16 } +// TINY: define{{.*}} void @foo10(%struct.s10* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// TINY: define{{.*}} void @foo06(%struct.s06* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// TINY: define{{.*}} %struct.s04 @foo04(i16 noundef %a, i16 noundef %b) Index: clang/test/CodeGen/avr/argument.c === --- /dev/null +++ clang/test/CodeGen/avr/argument.c @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix TINY + +// NOTE: All arguments are passed via the stack for functions with variable arguments. +// AVR: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// TINY: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// AVR-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +// TINY-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +char foo0(char a, char b, ...) { + return a + b; +} + +// NOTE: All arguments are passed via registers on both avr and avrtiny. +// AVR: define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}}) +char foo1(long a, char b) { + return a + b; +} + +// NOTE: The argument `char c` is passed via registers on avr, while via the stack on avrtiny. +// The argument `char b` costs 2 registers, so there is no vacant register left for +// `char c` on avrtiny. +// AVR: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}}) +// TINY-NOT: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +char foo2(long a, char b, char c) { + return a + b + c; +} + +// NOTE: On avr, the argument `a` costs 16 registers and `b` costs 2 registers, so +// `c` has to be passed via the stack. +// AVR: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}}, i8 {{.*}}) +// TINY-NOT: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +struct s15 { + char arr[15]; +}; +char foo3(struct s15 a, char b,
[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
benshi001 updated this revision to Diff 415734. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120720/new/ https://reviews.llvm.org/D120720 Files: clang/lib/Basic/Targets/AVR.cpp clang/lib/Basic/Targets/AVR.h clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/avr/argument.c clang/test/CodeGen/avr/struct.c Index: clang/test/CodeGen/avr/struct.c === --- clang/test/CodeGen/avr/struct.c +++ clang/test/CodeGen/avr/struct.c @@ -1,15 +1,23 @@ -// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=TINY // Structure that is more than 8 bytes. struct s10 { int a, b, c, d, e; }; -// Structure that is less than 8 bytes. +// Structure that is less than 8 bytes but more than 4 bytes. struct s06 { int a, b, c; }; +// Structure that is less than 4 bytes. +struct s04 { + int a, b; +}; + struct s10 foo10(int a, int b, int c) { struct s10 a0; return a0; @@ -20,7 +28,21 @@ 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 noundef %a, i16 noundef %b, i16 noundef %c) -// CHECK: define{{.*}} %struct.s06 @foo06(i16 noundef %a, i16 noundef %b, i16 noundef %c) +struct s04 foo04(int a, int b) { + struct s04 a0; + return a0; +} + +// AVR: %struct.s10 = type { i16, i16, i16, i16, i16 } +// AVR: %struct.s06 = type { i16, i16, i16 } +// AVR: %struct.s04 = type { i16, i16 } +// AVR: define{{.*}} void @foo10(%struct.s10* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// AVR: define{{.*}} %struct.s06 @foo06(i16 noundef %a, i16 noundef %b, i16 noundef %c) +// AVR: define{{.*}} %struct.s04 @foo04(i16 noundef %a, i16 noundef %b) + +// TINY: %struct.s10 = type { i16, i16, i16, i16, i16 } +// TINY: %struct.s06 = type { i16, i16, i16 } +// TINY: %struct.s04 = type { i16, i16 } +// TINY: define{{.*}} void @foo10(%struct.s10* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// TINY: define{{.*}} void @foo06(%struct.s06* {{.*}}, i16 noundef %a, i16 noundef %b, i16 noundef %c) +// TINY: define{{.*}} %struct.s04 @foo04(i16 noundef %a, i16 noundef %b) Index: clang/test/CodeGen/avr/argument.c === --- /dev/null +++ clang/test/CodeGen/avr/argument.c @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix TINY + +// NOTE: All arguments are passed via the stack for functions with variable arguments. +// AVR: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// TINY: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// AVR-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +// TINY-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +char foo0(char a, char b, ...) { + return a + b; +} + +// NOTE: All arguments are passed via registers on both avr and avrtiny. +// AVR: define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}}) +char foo1(long a, char b) { + return a + b; +} + +// NOTE: The argument `char c` is passed via registers on avr, while via the stack on avrtiny. +// The argument `char b` costs 2 registers, so there is no vacant register left for +// `char c` on avrtiny. +// AVR: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}}) +// TINY-NOT: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +char foo2(long a, char b, char c) { + return a + b + c; +} + +// NOTE: On avr, the argument `a` costs 16 registers and `b` costs 2 registers, so +// `c` has to be passed via the stack. +// AVR: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}}, i8 {{.*}}) +// TINY-NOT: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +struct s15 { + char arr[15]; +}; +char foo3(struct s15 a, char b, char c) { + return a.arr[b] + a.arr[c]; +} + +// NOTE: On avr, `a` only costs 16 registers, though there are 2 vacant registers, +// both `b` and `c` have to be passed via the stack. +// AVR: define {{.*}} i8 @foo4({{.*}}, i32 {{.*}}, i8 {{.*}}) +// AVR-NOT: define
[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
benshi001 added a comment. This patch fixes the issue https://github.com/llvm/llvm-project/issues/45485 . CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120720/new/ https://reviews.llvm.org/D120720 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
benshi001 updated this revision to Diff 412357. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120720/new/ https://reviews.llvm.org/D120720 Files: clang/lib/Basic/Targets/AVR.cpp clang/lib/Basic/Targets/AVR.h clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/avr/argument.c Index: clang/test/CodeGen/avr/argument.c === --- /dev/null +++ clang/test/CodeGen/avr/argument.c @@ -0,0 +1,167 @@ +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix TINY + +// NOTE: All arguments are passed in memory for functions with variable arguments. +// AVR: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// TINY: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// AVR-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +// TINY-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +char foo0(char a, char b, ...) { + return a + b; +} + +// NOTE: The char type argument is passed via registers on both avr and avrtiny. +// AVR: define {{.*}} @foo1({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} @foo1({{.*}}, i8 {{.*}} signext {{.*}}) +struct s08 { + char arr[8]; +}; +struct s06 { + char arr[6]; +}; +struct s08 foo1(struct s06 s6, char a) { + struct s08 s8; + s8.arr[a] = s6.arr[a]; + return s8; +} + +// NOTE: The char type argument is passed via registers on both avr and avrtiny. +// AVR: define {{.*}} void @foo2({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} void @foo2({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}}) +struct s09 { + char arr[9]; +}; +struct s04 { + char arr[4]; +}; +struct s09 foo2(struct s04 s4, char a) { + struct s09 s9; + s9.arr[a] = s4.arr[a]; + return s9; +} + +// NOTE: The char type argument is passed via registers on avr but via stack on avrtiny. +// AVR: define {{.*}} void @foo3({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} void @foo3({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} void @foo3({{.*}}, {{.*}}, i8 {{.*}}) +struct s09 foo3(struct s06 s6, char a) { + struct s09 s9; + s9.arr[a] = s6.arr[a]; + return s9; +} + +// NOTE: The char type argument is passed via stack on both avr and avrtiny. +// AVR: define {{.*}} void @foo4({{.*}}, i8 {{.*}}, ...) +// TINY: define {{.*}} void @foo4({{.*}}, i8 {{.*}}, ...) +// AVR-NOT: define {{.*}} i8 @foo4({{.*}}, i8 {{.*}} signext {{.*}}, ...) +// TINY-NOT: define {{.*}} i8 @foo4({{.*}}, i8 {{.*}} signext {{.*}}, ...) +struct s09 foo4(char b, ...) { + struct s09 s9; + s9.arr[b] = b; + return s9; +} + +// NOTE: The char type argument is passed via stack on both avr and avrtiny. +// AVR: define {{.*}} void @foo5({{.*}}, {{.*}}, i8 {{.*}}) +// TINY: define {{.*}} void @foo5({{.*}}, {{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} void @foo5({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} void @foo5({{{.*}}, {.*}}, i8 {{.*}} signext {{.*}}) +struct s15 { + char arr[15]; +}; +struct s09 foo5(struct s15 sx, char a) { + struct s09 s9; + s9.arr[a] = sx.arr[a]; + return s9; +} + +// NOTE: The char type argument is passed via registers on both avr and avrtiny. +// AVR: define {{.*}} i8 @foo6({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo6({{.*}}, i8 {{.*}} signext {{.*}}) +char foo6(struct s06 s, char b) { + return s.arr[b]; +} + +// NOTE: The char type argument is passed via stack on both avr and avrtiny. +// AVR: define {{.*}} @foo7({{.*}}, i8 {{.*}}) +// TINY: define {{.*}} @foo7({{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} @foo7({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} @foo7({{.*}}, i8 {{.*}} signext {{.*}}) +struct s17 { + char arr[17]; +}; +char foo7(struct s17 s, char c) { + return s.arr[c]; +} + +// NOTE: The char type argument is passed via registers on avr but via stack on avrtiny. +// AVR: define {{.*}} @foo8({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} @foo8({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} @foo8({{.*}}, i8 {{.*}}) +struct s07 { + char arr[7]; +}; +char foo8(struct s07 s, char a) { + return s.arr[a]; +} + +// NOTE: All arguments are passed via registers on both avr and avrtiny. +// AVR: define {{.*}} i8 @foo9(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo9(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +char foo9(char a, char b) { + return a + b; +} + +// NOTE: All arguments are passed via stack on both avr and avrtiny. +// AVR: define {{.*}} i8 @foo10({{.*}}, i8 {{.*}}) +// TINY: define {{.*}} i8 @foo10({{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} i8 @foo10({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} i8 @foo10({{.*}}, i8
[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
benshi001 added a comment. Herald added a project: All. This patch is a correct implementation against to the abundoned https://reviews.llvm.org/D120475 Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120720/new/ https://reviews.llvm.org/D120720 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D120720: [clang][AVR] Implement standard calling convention for AVR and AVRTiny
benshi001 created this revision. benshi001 added reviewers: aykevl, dylanmckay. Herald added a subscriber: Jim. benshi001 requested review of this revision. Herald added subscribers: cfe-commits, jacquesguan. Herald added a project: clang. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D120720 Files: clang/lib/Basic/Targets/AVR.cpp clang/lib/Basic/Targets/AVR.h clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/avr/argument.c Index: clang/test/CodeGen/avr/argument.c === --- /dev/null +++ clang/test/CodeGen/avr/argument.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix AVR +// RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix TINY + +// NOTE: All arguments are passed in memory for functions with variable arguments. +// AVR: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// TINY: define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...) +// AVR-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +// TINY-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...) +char foo0(char a, char b, ...) { + return a + b; +} + +// NOTE: All arguments are passed via registers. +// AVR: define {{.*}} i8 @foo1(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} i8 @foo1(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}) +char foo1(char a, char b) { + return a + b; +} + +// NOTE: The char type argument is passed via registers on both avr and avrtiny. +// AVR: define {{.*}} @foo2({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} @foo2({{.*}}, i8 {{.*}} signext {{.*}}) +struct s07 { + char arr[7]; +}; +struct s06 { + char arr[6]; +}; +struct s07 foo2(struct s06 s6, char a) { + struct s07 s7; + s7.arr[a] = s6.arr[a]; + return s7; +} + +// NOTE: The char type argument is passed via registers on avr but via stack on avrtiny. +// AVR: define {{.*}} @foo3({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} @foo3({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY: define {{.*}} @foo3({{.*}}, i8 {{.*}}) +struct s09 { + char arr[9]; +}; +struct s09 foo3(struct s06 s6, char a) { + struct s09 s9; + s9.arr[a] = s6.arr[a]; + return s9; +} + +// NOTE: The char type argument is passed via stack on both avr and avrtiny. +// AVR: define {{.*}} @foo4({{.*}}, i8 {{.*}}) +// TINY: define {{.*}} @foo4({{.*}}, i8 {{.*}}) +// AVR-NOT: define {{.*}} @foo4({{.*}}, i8 {{.*}} signext {{.*}}) +// TINY-NOT: define {{.*}} @foo4({{.*}}, i8 {{.*}} signext {{.*}}) +struct s17 { + char arr[17]; +}; +char foo4(struct s17 s, char c) { + return s.arr[c]; +} Index: clang/lib/CodeGen/TargetInfo.cpp === --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -19,9 +19,9 @@ #include "CodeGenFunction.h" #include "clang/AST/Attr.h" #include "clang/AST/RecordLayout.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Basic/Builtins.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/SwiftCallingConv.h" #include "llvm/ADT/SmallBitVector.h" @@ -33,6 +33,7 @@ #include "llvm/IR/IntrinsicsNVPTX.h" #include "llvm/IR/IntrinsicsS390.h" #include "llvm/IR/Type.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include // std::sort @@ -8272,32 +8273,83 @@ namespace { class AVRABIInfo : public DefaultABIInfo { +private: + // The total amount of registers can be used to pass parameters. It is 18 on + // AVR, or 8 on AVRTiny. + mutable unsigned ParamRegs; + public: - AVRABIInfo(CodeGenTypes ) : DefaultABIInfo(CGT) {} + AVRABIInfo(CodeGenTypes , unsigned N) + : DefaultABIInfo(CGT), ParamRegs(N) {} 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) +if (isAggregateTypeForABI(Ty)) { + // A return struct with size less than or equal to 8 bytes is returned + // directly via registers R18-R25. + if (getContext().getTypeSize(Ty) <= 64) +return ABIArgInfo::getDirect(); + // A return struct with size larger than 8 bytes is returned via a stack + // slot, along with a pointer to it as the function's implicit argument. + ParamRegs -= 2; + return getNaturalAlignIndirect(Ty); +} +// Otherwise we follow the default way which is compatible. +return DefaultABIInfo::classifyReturnType(Ty); + } + + ABIArgInfo classifyArgumentType(QualType Ty, unsigned ) const { +unsigned TySize = getContext().getTypeSize(Ty); + +// An int8 type