1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include "berberis/calling_conventions/calling_conventions_arm.h"
20 
21 namespace berberis::arm {
22 
23 namespace {
24 
TEST(CallingConventions_arm,Smoke)25 TEST(CallingConventions_arm, Smoke) {
26   CallingConventions conv;
27   ArgLocation loc;
28 
29   loc = conv.GetNextIntArgLoc(4, 4);
30   EXPECT_EQ(loc.kind, kArgLocationInt);
31   EXPECT_EQ(loc.offset, 0u);
32 
33   loc = conv.GetNextIntArgLoc(8, 8);
34   EXPECT_EQ(loc.kind, kArgLocationInt);
35   EXPECT_EQ(loc.offset, 2u);
36 
37   loc = conv.GetNextIntArgLoc(8, 8);
38   EXPECT_EQ(loc.kind, kArgLocationStack);
39   EXPECT_EQ(loc.offset, 0u);
40 
41   loc = conv.GetIntResLoc(1);
42   EXPECT_EQ(loc.kind, kArgLocationInt);
43   EXPECT_EQ(loc.offset, 0u);
44 }
45 
TEST(CallingConventions_arm,RegAndStack)46 TEST(CallingConventions_arm, RegAndStack) {
47   CallingConventions conv;
48   ArgLocation loc;
49 
50   loc = conv.GetNextIntArgLoc(4, 4);
51   EXPECT_EQ(loc.kind, kArgLocationInt);
52   EXPECT_EQ(loc.offset, 0u);
53 
54   loc = conv.GetNextIntArgLoc(16, 8);
55   EXPECT_EQ(loc.kind, kArgLocationIntAndStack);
56   EXPECT_EQ(loc.offset, 2u);
57 
58   loc = conv.GetNextIntArgLoc(4, 4);
59   EXPECT_EQ(loc.kind, kArgLocationStack);
60   EXPECT_EQ(loc.offset, 8u);
61 }
62 
TEST(CallingConventions_arm,UnalignedStack)63 TEST(CallingConventions_arm, UnalignedStack) {
64   CallingConventions conv(CallingConventions::kStackOnly, 4);
65   ArgLocation loc;
66 
67   loc = conv.GetNextIntArgLoc(16, 16);
68   EXPECT_EQ(loc.kind, kArgLocationStack);
69   // Note: we request alignment 16 here, but arm only supports alignment of 8.
70   EXPECT_EQ(loc.offset, 8u);
71 }
72 
TEST(CallingConventions_arm,Simd)73 TEST(CallingConventions_arm, Simd) {
74   CallingConventions conv;
75   ArgLocation loc;
76 
77   loc = conv.GetNextFpArgLoc(4, 4);
78   EXPECT_EQ(loc.kind, kArgLocationSimd);
79   EXPECT_EQ(loc.offset, 0u);
80 
81   loc = conv.GetNextFpArgLoc(8, 8);
82   EXPECT_EQ(loc.kind, kArgLocationSimd);
83   EXPECT_EQ(loc.offset, 2u);
84 
85   loc = conv.GetNextFpArgLoc(8, 8);
86   EXPECT_EQ(loc.kind, kArgLocationSimd);
87   EXPECT_EQ(loc.offset, 4u);
88 
89   loc = conv.GetNextFpArgLoc(4, 4);
90   EXPECT_EQ(loc.kind, kArgLocationSimd);
91   EXPECT_EQ(loc.offset, 1u);
92 
93   loc = conv.GetNextFpArgLoc(16, 16);
94   EXPECT_EQ(loc.kind, kArgLocationSimd);
95   EXPECT_EQ(loc.offset, 8u);
96 
97   loc = conv.GetNextFpArgLoc(16, 16);
98   EXPECT_EQ(loc.kind, kArgLocationSimd);
99   EXPECT_EQ(loc.offset, 12u);
100 
101   loc = conv.GetNextFpArgLoc(16, 16);
102   EXPECT_EQ(loc.kind, kArgLocationStack);
103   EXPECT_EQ(loc.offset, 0u);
104 
105   loc = conv.GetNextFpArgLoc(4, 4);
106   EXPECT_EQ(loc.kind, kArgLocationStack);
107   EXPECT_EQ(loc.offset, 16u);
108 }
109 
TEST(CallingConventions_arm,SimdRegAndStack)110 TEST(CallingConventions_arm, SimdRegAndStack) {
111   CallingConventions conv;
112   ArgLocation loc;
113 
114   loc = conv.GetNextFpArgLoc(16, 16);
115   EXPECT_EQ(loc.kind, kArgLocationSimd);
116   EXPECT_EQ(loc.offset, 0u);
117 
118   loc = conv.GetNextFpArgLoc(16, 16);
119   EXPECT_EQ(loc.kind, kArgLocationSimd);
120   EXPECT_EQ(loc.offset, 4u);
121 
122   loc = conv.GetNextFpArgLoc(16, 16);
123   EXPECT_EQ(loc.kind, kArgLocationSimd);
124   EXPECT_EQ(loc.offset, 8u);
125 
126   loc = conv.GetNextFpArgLoc(16, 16);
127   EXPECT_EQ(loc.kind, kArgLocationSimd);
128   EXPECT_EQ(loc.offset, 12u);
129 
130   loc = conv.GetNextFpArgLoc(16, 16);
131   EXPECT_EQ(loc.kind, kArgLocationStack);
132   EXPECT_EQ(loc.offset, 0u);
133 
134   loc = conv.GetNextIntArgLoc(4, 4);
135   EXPECT_EQ(loc.kind, kArgLocationInt);
136   EXPECT_EQ(loc.offset, 0u);
137 
138   loc = conv.GetNextIntArgLoc(16, 8);
139   EXPECT_EQ(loc.kind, kArgLocationStack);
140   EXPECT_EQ(loc.offset, 16u);
141 
142   loc = conv.GetNextIntArgLoc(4, 4);
143   EXPECT_EQ(loc.kind, kArgLocationStack);
144   EXPECT_EQ(loc.offset, 32u);
145 }
146 
147 }  // namespace
148 
149 }  // namespace berberis::arm
150