• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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