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/amd64/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::X86_64, false);
41 encoder_->InitMasm();
42 regfile_ = RegistersDescription::Create(allocator_, Arch::X86_64);
43 callconv_ = CallingConvention::Create(allocator_, encoder_, regfile_, Arch::X86_64);
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 Target target(Arch::X86_64);
94 // 6 uint8_t params - in registers
95 {
96 auto param_info = GetCallconv()->GetParameterInfo(0);
97 auto ret = param_info->GetNativeParam(INT8_TYPE);
98 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
99 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(0));
100 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(0), INT8_TYPE));
101
102 for (uint32_t i = 1; i <= 5; ++i) {
103 ret = param_info->GetNativeParam(INT8_TYPE);
104 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
105 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(i));
106 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(i), INT8_TYPE));
107 }
108 }
109
110 // 6 uint32_t params - in registers
111 {
112 auto param_info = GetCallconv()->GetParameterInfo(0);
113 auto ret = param_info->GetNativeParam(INT32_TYPE);
114 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
115 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(0));
116 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(0), INT32_TYPE));
117
118 for (uint32_t i = 1; i <= 5; ++i) {
119 ret = param_info->GetNativeParam(INT32_TYPE);
120 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
121 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(i));
122 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(i), INT32_TYPE));
123 }
124 }
125
126 // 6 uint64_t params - in registers
127 {
128 auto param_info = GetCallconv()->GetParameterInfo(0);
129 auto ret = param_info->GetNativeParam(INT64_TYPE);
130 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
131 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(0));
132 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(0), INT64_TYPE));
133
134 for (uint32_t i = 1; i <= 5; ++i) {
135 ret = param_info->GetNativeParam(INT64_TYPE);
136 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
137 EXPECT_EQ(std::get<Reg>(ret).GetId(), target.GetParamRegId(i));
138 EXPECT_EQ(std::get<Reg>(ret), Reg(target.GetParamRegId(i), INT64_TYPE));
139 }
140 }
141
142 // 8 float params - in registers
143 {
144 auto param_info = GetCallconv()->GetParameterInfo(0);
145 auto ret = param_info->GetNativeParam(FLOAT32_TYPE);
146 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
147 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
148 EXPECT_EQ(std::get<Reg>(ret), Reg(0, FLOAT32_TYPE));
149
150 for (uint32_t i = 1; i <= 7; ++i) {
151 ret = param_info->GetNativeParam(FLOAT32_TYPE);
152 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
153 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
154 EXPECT_EQ(std::get<Reg>(ret), Reg(i, FLOAT32_TYPE));
155 }
156 }
157
158 // 8 double params - in registers
159 {
160 auto param_info = GetCallconv()->GetParameterInfo(0);
161 auto ret = param_info->GetNativeParam(FLOAT64_TYPE);
162 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
163 EXPECT_EQ(std::get<Reg>(ret).GetId(), 0);
164 EXPECT_EQ(std::get<Reg>(ret), Reg(0, FLOAT64_TYPE));
165
166 for (uint32_t i = 1; i <= 7; ++i) {
167 ret = param_info->GetNativeParam(FLOAT64_TYPE);
168 EXPECT_TRUE(std::holds_alternative<Reg>(ret));
169 EXPECT_EQ(std::get<Reg>(ret).GetId(), i);
170 EXPECT_EQ(std::get<Reg>(ret), Reg(i, FLOAT64_TYPE));
171 }
172 }
173 }
174 } // namespace panda::compiler
175