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
19 #include "mem/code_allocator.h"
20 #include "mem/pool_manager.h"
21 #include "target/aarch64/target.h"
22 #include "mem/base_mem_stats.h"
23
24 const uint64_t SEED = 0x1234;
25 #ifndef PANDA_NIGHTLY_TEST_ON
26 const uint64_t ITERATION = 40;
27 #else
28 const uint64_t ITERATION = 0xffffff;
29 #endif
30 static inline auto random_gen = std::mt19937_64(SEED);
31
32 namespace panda::compiler {
33 class Callconv64Test : public ::testing::Test {
34 public:
Callconv64Test()35 Callconv64Test()
36 {
37 panda::mem::MemConfig::Initialize(64_MB, 64_MB, 64_MB, 32_MB);
38 PoolManager::Initialize();
39 allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER);
40 encoder_ = Encoder::Create(allocator_, Arch::AARCH64, false);
41 encoder_->InitMasm();
42 regfile_ = RegistersDescription::Create(allocator_, Arch::AARCH64);
43 callconv_ = CallingConvention::Create(allocator_, encoder_, regfile_, Arch::AARCH64);
44 mem_stats_ = new BaseMemStats();
45 code_alloc_ = new (std::nothrow) CodeAllocator(mem_stats_);
46 }
~Callconv64Test()47 ~Callconv64Test()
48 {
49 Logger::Destroy();
50 encoder_->~Encoder();
51 delete allocator_;
52 delete code_alloc_;
53 delete mem_stats_;
54 PoolManager::Finalize();
55 panda::mem::MemConfig::Finalize();
56 }
57
GetAllocator()58 ArenaAllocator *GetAllocator()
59 {
60 return allocator_;
61 }
62
GetEncoder()63 Encoder *GetEncoder()
64 {
65 return encoder_;
66 }
67
GetRegfile()68 RegistersDescription *GetRegfile()
69 {
70 return regfile_;
71 }
72
GetCallconv()73 CallingConvention *GetCallconv()
74 {
75 return callconv_;
76 }
77
78 private:
79 ArenaAllocator *allocator_ {nullptr};
80 Encoder *encoder_ {nullptr};
81 RegistersDescription *regfile_ {nullptr};
82 CallingConvention *callconv_ {nullptr};
83 CodeAllocator *code_alloc_ {nullptr};
84 BaseMemStats *mem_stats_ {nullptr};
85 };
86
TEST_F(Callconv64Test,NativeParams)87 TEST_F(Callconv64Test, NativeParams)
88 {
89 // Test for
90 // std::variant<Reg, uint8_t> GetNativeParam(const ArenaVector<TypeInfo>& reg_list,
91 // const TypeInfo& type)
92
93 // 8 uint8_t params - in registers
94 {
95 auto param_info = GetCallconv()->GetParameterInfo(0);
96 auto ret = param_info->GetNativeParam(INT8_TYPE);
97 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
98 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
99 EXPECT_EQ(std::get<Reg>(ret), Reg(0, INT8_TYPE));
100
101 for (uint32_t i = 1; i <= 7; ++i) {
102 ret = param_info->GetNativeParam(INT8_TYPE);
103 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
104 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
105 EXPECT_EQ(std::get<Reg>(ret), Reg(i, INT8_TYPE));
106 }
107 }
108
109 // 8 uint32_t params - in registers
110 {
111 auto param_info = GetCallconv()->GetParameterInfo(0);
112 auto ret = param_info->GetNativeParam(INT32_TYPE);
113 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
114 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
115 EXPECT_EQ(std::get<Reg>(ret), Reg(0, INT32_TYPE));
116
117 for (uint32_t i = 1; i <= 7; ++i) {
118 ret = param_info->GetNativeParam(INT32_TYPE);
119 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
120 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
121 EXPECT_EQ(std::get<Reg>(ret), Reg(i, INT32_TYPE));
122 }
123 }
124
125 // 8 uint64_t params - in registers
126 {
127 auto param_info = GetCallconv()->GetParameterInfo(0);
128 auto ret = param_info->GetNativeParam(INT64_TYPE);
129 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
130 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
131 EXPECT_EQ(std::get<Reg>(ret), Reg(0, INT64_TYPE));
132
133 for (uint32_t i = 1; i <= 7; ++i) {
134 ret = param_info->GetNativeParam(INT64_TYPE);
135 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
136 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
137 EXPECT_EQ(std::get<Reg>(ret), Reg(i, INT64_TYPE));
138 }
139 }
140
141 // 8 float params - in registers
142 {
143 auto param_info = GetCallconv()->GetParameterInfo(0);
144 auto ret = param_info->GetNativeParam(FLOAT32_TYPE);
145 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
146 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
147 EXPECT_EQ(std::get<Reg>(ret), Reg(0, FLOAT32_TYPE));
148
149 for (uint32_t i = 1; i <= 7; ++i) {
150 ret = param_info->GetNativeParam(FLOAT32_TYPE);
151 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
152 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
153 EXPECT_EQ(std::get<Reg>(ret), Reg(i, FLOAT32_TYPE));
154 }
155 }
156
157 // 8 double params - in registers
158 {
159 auto param_info = GetCallconv()->GetParameterInfo(0);
160 auto ret = param_info->GetNativeParam(FLOAT64_TYPE);
161 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
162 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
163 EXPECT_EQ(std::get<Reg>(ret), Reg(0, FLOAT64_TYPE));
164
165 for (uint32_t i = 1; i <= 7; ++i) {
166 ret = param_info->GetNativeParam(FLOAT64_TYPE);
167 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
168 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
169 EXPECT_EQ(std::get<Reg>(ret), Reg(i, FLOAT64_TYPE));
170 }
171 }
172 }
173 } // namespace panda::compiler
174