1/**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <random>
17#include <gtest/gtest.h>
18
19const uint64_t SEED = 0x1234;
20#ifndef PANDA_NIGHTLY_TEST_ON
21const uint64_t ITERATION = 20;
22#else
23const uint64_t ITERATION = 4000;
24#endif
25static inline auto random_gen = std::mt19937_64(SEED);
26
27// Encoder header
28#include "optimizer/code_generator/operands.h"
29
30namespace panda::compiler {
31TEST(Operands, TypeInfo)
32{
33    uint8_t u8;
34    int8_t i8;
35    uint16_t u16;
36    int16_t i16;
37    uint32_t u32;
38    int32_t i32;
39    uint64_t u64;
40    int64_t i64;
41
42    float f32;
43    double f64;
44
45    TypeInfo arr[] = {
46        TypeInfo(u8),  // 0
47        TypeInfo(u16),
48        TypeInfo(u32),
49        TypeInfo(u64),
50        TypeInfo(i8),  // 4
51        TypeInfo(i16),
52        TypeInfo(i32),
53        TypeInfo(i64),
54        TypeInfo(INT8_TYPE),  // 8
55        TypeInfo(INT16_TYPE),
56        TypeInfo(INT32_TYPE),
57        TypeInfo(INT64_TYPE),
58        TypeInfo(f32),  // 12
59        TypeInfo(f64),
60        TypeInfo(FLOAT32_TYPE),  // 14
61        TypeInfo(FLOAT64_TYPE),
62        TypeInfo(),  // 16
63        INVALID_TYPE,
64    };
65
66    for (uint8_t i = 0; i < sizeof(arr) / sizeof(TypeInfo); ++i) {
67        if (i >= 16) {
68            ASSERT_FALSE(arr[i].IsValid());
69        } else {
70            ASSERT_TRUE(arr[i].IsValid());
71        }
72    }
73
74    for (int i = 0; i < 4; ++i) {
75        ASSERT_EQ(arr[i], arr[4 + i]);
76        ASSERT_EQ(arr[i], arr[8 + i]);
77        ASSERT_EQ(arr[4 + i], arr[8 + i]);
78
79        ASSERT_EQ(arr[i].GetSize(), arr[4 + i].GetSize());
80        ASSERT_EQ(arr[i].GetSize(), arr[8 + i].GetSize());
81        ASSERT_EQ(arr[4 + i].GetSize(), arr[8 + i].GetSize());
82
83        ASSERT_TRUE(arr[i].IsScalar());
84        ASSERT_TRUE(arr[4 + i].IsScalar());
85        ASSERT_TRUE(arr[8 + i].IsScalar());
86
87        ASSERT_FALSE(arr[i].IsFloat());
88        ASSERT_FALSE(arr[4 + i].IsFloat());
89        ASSERT_FALSE(arr[8 + i].IsFloat());
90
91        ASSERT_NE(arr[i], arr[12]);
92        ASSERT_NE(arr[i], arr[13]);
93        ASSERT_NE(arr[4 + i], arr[12]);
94        ASSERT_NE(arr[4 + i], arr[13]);
95        ASSERT_NE(arr[8 + i], arr[12]);
96        ASSERT_NE(arr[8 + i], arr[13]);
97
98        ASSERT_NE(arr[i], arr[14]);
99        ASSERT_NE(arr[i], arr[15]);
100        ASSERT_NE(arr[4 + i], arr[14]);
101        ASSERT_NE(arr[4 + i], arr[15]);
102        ASSERT_NE(arr[8 + i], arr[14]);
103        ASSERT_NE(arr[8 + i], arr[15]);
104        ASSERT_NE(arr[i], arr[16]);
105        ASSERT_NE(arr[i], arr[17]);
106        ASSERT_NE(arr[4 + i], arr[16]);
107        ASSERT_NE(arr[4 + i], arr[17]);
108        ASSERT_NE(arr[8 + i], arr[16]);
109        ASSERT_NE(arr[8 + i], arr[17]);
110    }
111    // Float
112    ASSERT_EQ(arr[2].GetSize(), arr[12].GetSize());
113    ASSERT_EQ(arr[2].GetSize(), arr[14].GetSize());
114
115    ASSERT_TRUE(arr[12].IsValid());
116    ASSERT_TRUE(arr[14].IsValid());
117    ASSERT_TRUE(arr[12].IsFloat());
118    ASSERT_TRUE(arr[14].IsFloat());
119    // Double
120    ASSERT_EQ(arr[3].GetSize(), arr[13].GetSize());
121    ASSERT_EQ(arr[3].GetSize(), arr[15].GetSize());
122
123    // Check sizes:
124    ASSERT_EQ(BYTE_SIZE, HALF_SIZE / 2);
125    ASSERT_EQ(HALF_SIZE, WORD_SIZE / 2);
126    ASSERT_EQ(WORD_SIZE, DOUBLE_WORD_SIZE / 2);
127
128    ASSERT_EQ(arr[0].GetSize(), BYTE_SIZE);
129    ASSERT_EQ(arr[1].GetSize(), HALF_SIZE);
130    ASSERT_EQ(arr[2].GetSize(), WORD_SIZE);
131    ASSERT_EQ(arr[3].GetSize(), DOUBLE_WORD_SIZE);
132
133    ASSERT_EQ(sizeof(TypeInfo), sizeof(uint8_t));
134
135    ASSERT_EQ(TypeInfo(u8), INT8_TYPE);
136    ASSERT_EQ(TypeInfo(u16), INT16_TYPE);
137    ASSERT_EQ(TypeInfo(u32), INT32_TYPE);
138    ASSERT_EQ(TypeInfo(u64), INT64_TYPE);
139
140    ASSERT_EQ(TypeInfo(f32), FLOAT32_TYPE);
141    ASSERT_EQ(TypeInfo(f64), FLOAT64_TYPE);
142}
143
144TEST(Operands, Reg)
145{
146    //  Size of structure
147    ASSERT_LE(sizeof(Reg), sizeof(size_t));
148
149    ASSERT_EQ(INVALID_REGISTER.GetId(), INVALID_REG_ID);
150
151    // Check, what it is possible to create all 32 registers
152    // for each type
153
154    // Check what special registers are possible to compare with others
155
156    // Check equality between registers
157
158    // Check invalid registers
159}
160
161TEST(Operands, Imm)
162{
163    // Check all possible types:
164    //  Imm holds same data (static cast for un-signed)
165    // GetType
166    // Getsize
167    // Is scalar
168    //  Is Valid
169    //  Bounary checks
170    //  Check IsZero
171    // Inc/dec checks
172    // INVALID_IMM check
173
174    for (uint64_t i = 0; i < ITERATION; ++i) {
175        uint8_t u8 = random_gen(), u8_z = 0, u8_min = std::numeric_limits<uint8_t>::min(),
176                u8_max = std::numeric_limits<uint8_t>::max();
177        uint16_t u16 = random_gen(), u16_z = 0, u16_min = std::numeric_limits<uint16_t>::min(),
178                 u16_max = std::numeric_limits<uint16_t>::max();
179        uint32_t u32 = random_gen(), u32_z = 0, u32_min = std::numeric_limits<uint32_t>::min(),
180                 u32_max = std::numeric_limits<uint32_t>::max();
181        uint64_t u64 = random_gen(), u64_z = 0, u64_min = std::numeric_limits<uint64_t>::min(),
182                 u64_max = std::numeric_limits<uint64_t>::max();
183
184        int8_t i8 = random_gen(), i8_z = 0, i8_min = std::numeric_limits<int8_t>::min(),
185               i8_max = std::numeric_limits<int8_t>::max();
186        int16_t i16 = random_gen(), i16_z = 0, i16_min = std::numeric_limits<int16_t>::min(),
187                i16_max = std::numeric_limits<int16_t>::max();
188        int32_t i32 = random_gen(), i32_z = 0, i32_min = std::numeric_limits<int32_t>::min(),
189                i32_max = std::numeric_limits<int32_t>::max();
190        int64_t i64 = random_gen(), i64_z = 0, i64_min = std::numeric_limits<int64_t>::min(),
191                i64_max = std::numeric_limits<int64_t>::max();
192
193        float f32 = random_gen(), f32_z = 0, f32_min = std::numeric_limits<float>::min(),
194              f32_max = std::numeric_limits<float>::max();
195        double f64 = random_gen(), f64_z = 0, f64_min = std::numeric_limits<double>::min(),
196               f64_max = std::numeric_limits<double>::max();
197
198        // Unsigned part - check across static_cast
199
200        Imm imm_u8(u8), imm_u8_z(u8_z), imm_u8_min(u8_min), imm_u8_max(u8_max);
201        ASSERT_EQ(imm_u8.GetValue<int8_t>(), static_cast<int8_t>(u8));
202        ASSERT_EQ(imm_u8_min.GetValue<int8_t>(), static_cast<int8_t>(u8_min));
203        ASSERT_EQ(imm_u8_max.GetValue<int8_t>(), static_cast<int8_t>(u8_max));
204        ASSERT_EQ(imm_u8_z.GetValue<int8_t>(), static_cast<int8_t>(u8_z));
205
206        ASSERT_TRUE(imm_u8_min.IsZero());
207        ASSERT_TRUE(imm_u8_z.IsZero());
208        ASSERT_FALSE(imm_u8_max.IsZero());
209
210        ASSERT_TRUE(imm_u8.IsValid());
211        ASSERT_TRUE(imm_u8_z.IsValid());
212        ASSERT_TRUE(imm_u8_min.IsValid());
213        ASSERT_TRUE(imm_u8_max.IsValid());
214
215        Imm imm_u16(u16), imm_u16_z(u16_z), imm_u16_min(u16_min), imm_u16_max(u16_max);
216        ASSERT_EQ(imm_u16.GetValue<int16_t>(), static_cast<int16_t>(u16));
217        ASSERT_EQ(imm_u16_min.GetValue<int16_t>(), static_cast<int16_t>(u16_min));
218        ASSERT_EQ(imm_u16_max.GetValue<int16_t>(), static_cast<int16_t>(u16_max));
219        ASSERT_EQ(imm_u16_z.GetValue<int16_t>(), static_cast<int16_t>(u16_z));
220
221        ASSERT_TRUE(imm_u16_min.IsZero());
222        ASSERT_TRUE(imm_u16_z.IsZero());
223        ASSERT_FALSE(imm_u16_max.IsZero());
224
225        ASSERT_TRUE(imm_u16.IsValid());
226        ASSERT_TRUE(imm_u16_z.IsValid());
227        ASSERT_TRUE(imm_u16_min.IsValid());
228        ASSERT_TRUE(imm_u16_max.IsValid());
229
230        Imm imm_u32(u32), imm_u32_z(u32_z), imm_u32_min(u32_min), imm_u32_max(u32_max);
231        ASSERT_EQ(imm_u32.GetValue<int32_t>(), static_cast<int32_t>(u32));
232        ASSERT_EQ(imm_u32_min.GetValue<int32_t>(), static_cast<int32_t>(u32_min));
233        ASSERT_EQ(imm_u32_max.GetValue<int32_t>(), static_cast<int32_t>(u32_max));
234        ASSERT_EQ(imm_u32_z.GetValue<int32_t>(), static_cast<int32_t>(u32_z));
235
236        ASSERT_TRUE(imm_u32_min.IsZero());
237        ASSERT_TRUE(imm_u32_z.IsZero());
238        ASSERT_FALSE(imm_u32_max.IsZero());
239
240        ASSERT_TRUE(imm_u32.IsValid());
241        ASSERT_TRUE(imm_u32_z.IsValid());
242        ASSERT_TRUE(imm_u32_min.IsValid());
243        ASSERT_TRUE(imm_u32_max.IsValid());
244
245        Imm imm_u64(u64), imm_u64_z(u64_z), imm_u64_min(u64_min), imm_u64_max(u64_max);
246        ASSERT_EQ(imm_u64.GetValue<int64_t>(), static_cast<int64_t>(u64));
247        ASSERT_EQ(imm_u64_min.GetValue<int64_t>(), static_cast<int64_t>(u64_min));
248        ASSERT_EQ(imm_u64_max.GetValue<int64_t>(), static_cast<int64_t>(u64_max));
249        ASSERT_EQ(imm_u64_z.GetValue<int64_t>(), static_cast<int64_t>(u64_z));
250
251        ASSERT_TRUE(imm_u64_min.IsZero());
252        ASSERT_TRUE(imm_u64_z.IsZero());
253        ASSERT_FALSE(imm_u64_max.IsZero());
254
255        ASSERT_TRUE(imm_u64.IsValid());
256        ASSERT_TRUE(imm_u64_z.IsValid());
257        ASSERT_TRUE(imm_u64_min.IsValid());
258        ASSERT_TRUE(imm_u64_max.IsValid());
259
260        // Signed part
261
262        Imm imm_i8(i8), imm_i8_z(i8_z), imm_i8_min(i8_min), imm_i8_max(i8_max);
263        ASSERT_EQ(imm_i8.GetValue<int8_t>(), i8);
264        ASSERT_EQ(imm_i8_min.GetValue<int8_t>(), i8_min);
265        ASSERT_EQ(imm_i8_max.GetValue<int8_t>(), i8_max);
266        ASSERT_EQ(imm_i8_z.GetValue<int8_t>(), i8_z);
267
268        ASSERT_FALSE(imm_i8_min.IsZero());
269        ASSERT_TRUE(imm_i8_z.IsZero());
270        ASSERT_FALSE(imm_i8_max.IsZero());
271
272        ASSERT_TRUE(imm_i8.IsValid());
273        ASSERT_TRUE(imm_i8_z.IsValid());
274        ASSERT_TRUE(imm_i8_min.IsValid());
275        ASSERT_TRUE(imm_i8_max.IsValid());
276
277        Imm imm_i16(i16), imm_i16_z(i16_z), imm_i16_min(i16_min), imm_i16_max(i16_max);
278        ASSERT_EQ(imm_i16.GetValue<int16_t>(), i16);
279        ASSERT_EQ(imm_i16_min.GetValue<int16_t>(), i16_min);
280        ASSERT_EQ(imm_i16_max.GetValue<int16_t>(), i16_max);
281        ASSERT_EQ(imm_i16_z.GetValue<int16_t>(), i16_z);
282
283        ASSERT_FALSE(imm_i16_min.IsZero());
284        ASSERT_TRUE(imm_i16_z.IsZero());
285        ASSERT_FALSE(imm_i16_max.IsZero());
286
287        ASSERT_TRUE(imm_i16.IsValid());
288        ASSERT_TRUE(imm_i16_z.IsValid());
289        ASSERT_TRUE(imm_i16_min.IsValid());
290        ASSERT_TRUE(imm_i16_max.IsValid());
291
292        Imm imm_i32(i32), imm_i32_z(i32_z), imm_i32_min(i32_min), imm_i32_max(i32_max);
293        ASSERT_EQ(imm_i32.GetValue<int32_t>(), i32);
294        ASSERT_EQ(imm_i32_min.GetValue<int32_t>(), i32_min);
295        ASSERT_EQ(imm_i32_max.GetValue<int32_t>(), i32_max);
296        ASSERT_EQ(imm_i32_z.GetValue<int32_t>(), i32_z);
297
298        ASSERT_FALSE(imm_i32_min.IsZero());
299        ASSERT_TRUE(imm_i32_z.IsZero());
300        ASSERT_FALSE(imm_i32_max.IsZero());
301
302        ASSERT_TRUE(imm_i32.IsValid());
303        ASSERT_TRUE(imm_i32_z.IsValid());
304        ASSERT_TRUE(imm_i32_min.IsValid());
305        ASSERT_TRUE(imm_i32_max.IsValid());
306
307        Imm imm_i64(i64), imm_i64_z(i64_z), imm_i64_min(i64_min), imm_i64_max(i64_max);
308        ASSERT_EQ(imm_i64.GetValue<int64_t>(), i64);
309        ASSERT_EQ(imm_i64_min.GetValue<int64_t>(), i64_min);
310        ASSERT_EQ(imm_i64_max.GetValue<int64_t>(), i64_max);
311        ASSERT_EQ(imm_i64_z.GetValue<int64_t>(), i64_z);
312
313        ASSERT_FALSE(imm_i64_min.IsZero());
314        ASSERT_TRUE(imm_i64_z.IsZero());
315        ASSERT_FALSE(imm_i64_max.IsZero());
316
317        ASSERT_TRUE(imm_i64.IsValid());
318        ASSERT_TRUE(imm_i64_z.IsValid());
319        ASSERT_TRUE(imm_i64_min.IsValid());
320        ASSERT_TRUE(imm_i64_max.IsValid());
321    }
322    // Sizeof imm:
323    // Imm holds 2 uint64_t values (std::variant)
324    ASSERT_LE(sizeof(Imm), sizeof(uint64_t) * 2);
325}
326}  // namespace panda::compiler
327