xref: /llvm-project/clang/test/CodeGen/avr/argument.c (revision 51585aa240de6ef07979345de5406483d7393b7b)
1 // RUN: %clang_cc1 -triple avr -target-cpu atmega328 -emit-llvm %s -o - \
2 // RUN:     | FileCheck %s --check-prefix AVR
3 // RUN: %clang_cc1 -triple avr -target-cpu attiny40 -emit-llvm %s -o - \
4 // RUN:     | FileCheck %s --check-prefix TINY
5 
6 // NOTE: All arguments are passed via the stack for functions with variable arguments.
7 // AVR:      define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...)
8 // TINY:     define {{.*}} i8 @foo0(i8 {{.*}}, i8 {{.*}}, ...)
9 // AVR-NOT:  define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...)
10 // TINY-NOT: define {{.*}} i8 @foo0(i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}}, ...)
foo0(char a,char b,...)11 char foo0(char a, char b, ...) {
12   return a + b;
13 }
14 
15 // NOTE: All arguments are passed via registers on both avr and avrtiny.
16 // AVR:  define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}})
17 // TINY: define {{.*}} i8 @foo1(i32 {{.*}}, i8 {{.*}} signext {{.*}})
foo1(long a,char b)18 char foo1(long a, char b) {
19   return a + b;
20 }
21 
22 // NOTE: The argument `char c` is passed via registers on avr, while via the stack on avrtiny.
23 //       The argument `char b` costs 2 registers, so there is no vacant register left for
24 //       `char c` on avrtiny.
25 // AVR:      define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
26 // TINY:     define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}})
27 // TINY-NOT: define {{.*}} i8 @foo2(i32 {{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
foo2(long a,char b,char c)28 char foo2(long a, char b, char c) {
29   return a + b + c;
30 }
31 
32 // NOTE: On avr, the argument `a` costs 16 registers and `b` costs 2 registers, so
33 //       `c` has to be passed via the stack.
34 // AVR:      define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}})
35 // AVR-NOT:  define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
36 // TINY:     define {{.*}} i8 @foo3({{.*}}, i8 {{.*}}, i8 {{.*}})
37 // TINY-NOT: define {{.*}} i8 @foo3({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
38 struct s15 {
39   char arr[15];
40 };
foo3(struct s15 a,char b,char c)41 char foo3(struct s15 a, char b, char c) {
42   return a.arr[b] + a.arr[c];
43 }
44 
45 // NOTE: On avr, `a` only costs 16 registers, though there are 2 vacant registers,
46 //       both `b` and `c` have to be passed via the stack.
47 // AVR:      define {{.*}} i8 @foo4({{.*}}, i32 {{.*}}, i8 {{.*}})
48 // AVR-NOT:  define {{.*}} i8 @foo4({{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
49 // TINY:     define {{.*}} i8 @foo4({{.*}}, i32 {{.*}}, i8 {{.*}})
50 // TINY-NOT: define {{.*}} i8 @foo4({{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
foo4(struct s15 a,long b,char c)51 char foo4(struct s15 a, long b, char c) {
52   return a.arr[c];
53 }
54 
55 // NOTE: On avrtiny, `a` only costs 4 registers, though there are 2 vacant
56 //       registers, both `b` and `c` are passed via the stack.
57 // AVR:      define {{.*}} i8 @foo5(i32 {{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
58 // TINY:     define {{.*}} i8 @foo5(i32 {{.*}}, i32 {{.*}}, i8 {{.*}})
59 // TINY-NOT: define {{.*}} i8 @foo5(i32 {{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
foo5(long a,long b,char c)60 char foo5(long a, long b, char c) {
61   return c + 1;
62 }
63 
64 // NOTE: All arguments are passed via the stack, though all registers are vacant.
65 // AVR:      define {{.*}} i8 @foo6({{.*}}, i8 {{.*}})
66 // AVR-NOT:  define {{.*}} i8 @foo6({{.*}}, i8 {{.*}} signext {{.*}})
67 // TINY:     define {{.*}} i8 @foo6({{.*}}, i8 {{.*}})
68 // TINY-NOT: define {{.*}} i8 @foo6({{.*}}, i8 {{.*}} signext {{.*}})
69 struct s32 {
70   char arr[32];
71 };
foo6(struct s32 a,char b)72 char foo6(struct s32 a, char b) {
73   return a.arr[b];
74 }
75 
76 // NOTE: All arguments are passed via registers on avr. While all arguments are passed
77 //       via the stack on avrtiny, though all registers are vacant.
78 // AVR:      define {{.*}} i8 @foo7({{.*}}, i8 {{.*}} signext {{.*}})
79 // TINY:     define {{.*}} i8 @foo7({{.*}}, i8 {{.*}})
80 // TINY-NOT: define {{.*}} i8 @foo7({{.*}}, i8 {{.*}} signext {{.*}})
foo7(struct s15 a,char b)81 char foo7(struct s15 a, char b) {
82   return a.arr[b];
83 }
84 
85 // NOTE: On avr, though `a` only cost 16 registers, `b` has to be passed via the
86 //       stack, since there is an implicit pointer argument costs 2 registers.
87 // AVR:      define {{.*}} @foo8({{.*}}, {{.*}}, i8 {{.*}})
88 // AVR-NOT:  define {{.*}} @foo8({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}})
89 // TINY:     define {{.*}} @foo8({{.*}}, {{.*}}, i8 {{.*}})
90 // TINY-NOT: define {{.*}} @foo8({{.*}}, {{.*}}, i8 {{.*}} signext {{.*}})
foo8(struct s15 a,char b)91 struct s15 foo8(struct s15 a, char b) {
92   a.arr[0] = b;
93   return a;
94 }
95 
96 // NOTE: On avrtiny, `b` has to be passed via the stack, since there is an
97 //       implicit pointer argument costs 2 registers.
98 // AVR:      define {{.*}} @foo9({{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
99 // TINY:     define {{.*}} @foo9({{.*}}, i32 {{.*}}, i8 {{.*}})
100 // TINY-NOT: define {{.*}} @foo9({{.*}}, i32 {{.*}}, i8 {{.*}} signext {{.*}})
foo9(long a,char b)101 struct s15 foo9(long a, char b) {
102   struct s15 x;
103   x.arr[0] = b;
104   return x;
105 }
106 
107 // NOTE: All arguments are passed via registers, though there is an implicit
108 //       pointer argument costs 2 registers.
109 // AVR:  define {{.*}} @fooa({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
110 // TINY: define {{.*}} @fooa({{.*}}, i8 {{.*}} signext {{.*}}, i8 {{.*}} signext {{.*}})
fooa(char a,char b)111 struct s15 fooa(char a, char b) {
112   struct s15 x;
113   x.arr[0] = a;
114   x.arr[1] = b;
115   return x;
116 }
117