1 /** 2 * Copyright (c) 2023 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 <gtest/gtest.h> 17 18 #include "assembly-ins.h" 19 #include "assembly-parser.h" 20 #include "ide_helpers.h" 21 #include "ins_to_string.cpp" 22 #include "operand_types_print.h" 23 #include "extensions/ecmascript_meta.h" 24 #include "meta.h" 25 26 using namespace testing::ext; 27 28 namespace panda::pandasm { 29 class AssemblerInsTest : public testing::Test { 30 }; 31 32 /** 33 * @tc.name: assembler_ins_test_001 34 * @tc.desc: Verify the Parse function. 35 * @tc.type: FUNC 36 * @tc.require: issueNumber 37 */ 38 HWTEST_F(AssemblerInsTest, assembler_ins_test_001, TestSize.Level1) 39 { 40 Parser p; 41 const auto source = R"( 42 .function any foo(){} 43 .function any func(any a0, any a1, any a2) <static> { 44 mov v0, a0 45 mov v1, a1 46 mov v2, a2 47 ldglobalvar 0x0, "foo" 48 sta v4 49 lda v4 50 callarg0 0x1 51 return 52 } 53 )"; 54 auto item = p.Parse(source); 55 const std::string func_name = "func:(any,any,any)"; 56 auto it = item.Value().function_table.find(func_name); 57 EXPECT_NE(it, item.Value().function_table.end()); 58 const auto &func_value = item.Value().function_table.at(func_name).ins; 59 size_t user_size = 6; 60 size_t json_size = 280; 61 EXPECT_EQ(func_value[3].OperandListLength(), 2ULL); 62 EXPECT_EQ(func_value[3].HasFlag(InstFlags::TYPE_ID), false); 63 EXPECT_EQ(func_value[3].CanThrow(), true); 64 EXPECT_EQ(func_value[3].IsJump(), false); 65 EXPECT_EQ(func_value[3].IsConditionalJump(), false); 66 EXPECT_EQ(func_value[3].IsCall(), false); 67 EXPECT_EQ(func_value[3].IsCallRange(), false); 68 EXPECT_EQ(func_value[3].IsPseudoCall(), false); 69 EXPECT_EQ(func_value[7].IsReturn(), true); 70 EXPECT_EQ(func_value[7].MaxRegEncodingWidth(), 0); 71 EXPECT_EQ(func_value[7].HasDebugInfo(), true); 72 EXPECT_EQ(func_value[7].Uses().size(), user_size); 73 EXPECT_EQ(func_value[7].Def(), std::nullopt); 74 EXPECT_EQ(func_value[7].IsValidToEmit(), true); 75 EXPECT_EQ(item.Value().JsonDump().size(), json_size); 76 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE) << "ERR_NONE expected"; 77 } 78 79 /** 80 * @tc.name: assembler_ins_test_002 81 * @tc.desc: Verify the Parse function. 82 * @tc.type: FUNC 83 * @tc.require: issueNumber 84 */ 85 HWTEST_F(AssemblerInsTest, assembler_ins_test_002, TestSize.Level1) 86 { 87 Parser p; 88 const auto source = R"( 89 .function any func() { 90 sta v4 91 lda.str "xxx" 92 ldglobalvar 0x7, "oDiv" 93 callarg1 0x1, v0 94 return 95 } 96 )"; 97 auto item = p.Parse(source); 98 const std::string func_name = "func:()"; 99 auto it = item.Value().function_table.find(func_name); 100 EXPECT_NE(it, item.Value().function_table.end()); 101 const auto &function_value = item.Value().function_table.at(func_name).ins; 102 std::string ret = function_value[0].ToString("test", true, 0); 103 EXPECT_EQ(ret, "sta a4test"); 104 ret = function_value[0].ToString("test", false, 0); 105 EXPECT_EQ(ret, "sta v4test"); 106 107 ret = function_value[1].ToString("test", true, 0); 108 EXPECT_EQ(ret, "lda.str xxxtest"); 109 ret = function_value[1].ToString("test", false, 0); 110 EXPECT_EQ(ret, "lda.str xxxtest"); 111 112 ret = function_value[2].ToString("test", true, 0); 113 EXPECT_EQ(ret, "ldglobalvar 0x7, oDivtest"); 114 ret = function_value[2].ToString("test", false, 0); 115 EXPECT_EQ(ret, "ldglobalvar 0x7, oDivtest"); 116 } 117 118 /** 119 * @tc.name: assembler_ins_test_003 120 * @tc.desc: Verify the ToString function. 121 * @tc.type: FUNC 122 * @tc.require: issueNumber 123 */ 124 HWTEST_F(AssemblerInsTest, assembler_ins_test_003, TestSize.Level1) 125 { 126 panda::pandasm::Ins ins; 127 uint16_t reg1 = 2U; 128 uint16_t reg2 = 3U; 129 ins.opcode = Opcode::DEPRECATED_LDMODULEVAR; 130 ins.regs.push_back(reg1); 131 ins.regs.push_back(reg2); 132 ins.imms.push_back(Ins::IType(int64_t(0x1))); 133 ins.ids.push_back("a1"); 134 ins.set_label = false; 135 ins.label = "label"; 136 137 std::string ret = ins.ToString("test", true, 0); 138 EXPECT_EQ(ret, "deprecated.ldmodulevar a1, 0x1test"); 139 ret = ins.ToString("test", false, 0); 140 EXPECT_EQ(ret, "deprecated.ldmodulevar a1, 0x1test"); 141 142 ins.opcode = Opcode::MOVX; 143 ret = ins.ToString("test", true, 0); 144 EXPECT_EQ(ret, "MOVX a2, a3, 0x1, a1test"); 145 ret = ins.ToString("test", false, 0); 146 EXPECT_EQ(ret, "MOVX v2, v3, 0x1, a1test"); 147 148 ins.opcode = Opcode::DEFINEFUNC; 149 ret = ins.ToString("test", true, 0); 150 EXPECT_EQ(ret, "definefunc 0x1, a1test"); 151 ret = ins.ToString("test", false, 0); 152 EXPECT_EQ(ret, "definefunc 0x1, a1test"); 153 EXPECT_TRUE(ins.CanThrow()); 154 155 ins.opcode = Opcode::JEQZ; 156 EXPECT_TRUE(ins.IsConditionalJump()); 157 158 ins.opcode = Opcode::SUPERCALLARROWRANGE; 159 ret = ins.ToString("test", true, 0); 160 EXPECT_EQ(ret, "supercallarrowrange 0x1, a2test"); 161 ret = ins.ToString("test", false, 0); 162 EXPECT_EQ(ret, "supercallarrowrange 0x1, v2test"); 163 164 ins.opcode = Opcode::NEWOBJRANGE; 165 ret = ins.ToString("test", true, 0); 166 EXPECT_EQ(ret, "newobjrange 0x1, a2test"); 167 ret = ins.ToString("test", false, 0); 168 EXPECT_EQ(ret, "newobjrange 0x1, v2test"); 169 170 ins.imms.clear(); 171 ins.opcode = Opcode::DEFINECLASSWITHBUFFER; 172 ret = ins.ToString("test", true, 0); 173 EXPECT_EQ(ret, "defineclasswithbuffer, a1, a2test"); 174 ret = ins.ToString("test", false, 0); 175 EXPECT_EQ(ret, "defineclasswithbuffer, a1, v2test"); 176 177 ins.opcode = Opcode::CALLX; 178 auto unit = ins.Uses(); 179 EXPECT_GT(unit.size(), 0); 180 181 ins.regs.clear(); 182 ins.opcode = Opcode::STOBJBYVALUE; 183 ret = ins.ToString("test", true, 0); 184 EXPECT_EQ(ret, "stobjbyvaluetest"); 185 ret = ins.ToString("test", false, 0); 186 EXPECT_EQ(ret, "stobjbyvaluetest"); 187 188 EXPECT_EQ(ins.Def(), std::nullopt); 189 190 ins.opcode = Opcode::INVALID; 191 ret = ins.MaxRegEncodingWidth(); 192 auto unit1 = ins.Uses(); 193 EXPECT_EQ(unit1.size(), 0); 194 195 EXPECT_EQ(ins.Def(), std::nullopt); 196 197 ins.regs.push_back(1); 198 EXPECT_FALSE(ins.IsValidToEmit()); 199 } 200 201 /** 202 * @tc.name: assembler_ins_test_004 203 * @tc.desc: Verify the JsonDump function. 204 * @tc.type: FUNC 205 * @tc.require: issueNumber 206 */ 207 HWTEST_F(AssemblerInsTest, assembler_ins_test_004, TestSize.Level1) 208 { 209 panda::pandasm::Ins ins; 210 uint16_t reg1 = 2U; 211 uint16_t reg2 = 3U; 212 ins.opcode = Opcode::DEPRECATED_LDMODULEVAR; 213 ins.regs.push_back(reg1); 214 ins.regs.push_back(reg2); 215 ins.imms.push_back(Ins::IType(int64_t(0x1))); 216 ins.ids.push_back("a1"); 217 ins.set_label = false; 218 ins.label = "label"; 219 panda::pandasm::Program pro; 220 std::string ret = pro.JsonDump(); 221 EXPECT_EQ(ret, "{ \"functions\": [ ], \"records\": [ ] }"); 222 223 std::string_view component_name = "u8"; 224 size_t rank = 0; 225 panda::pandasm::Type type(component_name, rank); 226 bool bo = type.IsArrayContainsPrimTypes(); 227 EXPECT_TRUE(bo); 228 229 ret = type.GetDescriptor(false); 230 EXPECT_EQ(ret, "H"); 231 232 EXPECT_EQ(panda::pandasm::Type::GetId(component_name, true), panda_file::Type::TypeId::REFERENCE); 233 component_name = "[]"; 234 EXPECT_EQ(panda::pandasm::Type::FromDescriptor(component_name).GetName(), component_name); 235 EXPECT_EQ(panda::pandasm::Type::FromName(component_name, false).GetName(), component_name); 236 panda::panda_file::SourceLang language {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; 237 238 std::string name = "test"; 239 EXPECT_FALSE(panda::pandasm::Type::IsStringType(name, language)); 240 ins.opcode = Opcode::CALLRANGE; 241 size_t ins_def = 65535; 242 EXPECT_EQ(ins.Def(), ins_def); 243 auto unit2 = ins.Uses(); 244 EXPECT_GT(unit2.size(), 0); 245 246 component_name = "test"; 247 rank = 0; 248 panda::pandasm::Type type1(component_name, rank); 249 bo = type1.IsArrayContainsPrimTypes(); 250 EXPECT_FALSE(bo); 251 } 252 253 /** 254 * @tc.name: assembler_ins_test_005 255 * @tc.desc: Verify the JsonSerializeProgramItems function. 256 * @tc.type: FUNC 257 * @tc.require: issueNumber 258 */ 259 HWTEST_F(AssemblerInsTest, assembler_ins_test_005, TestSize.Level1) 260 { 261 Parser p; 262 const auto source = R"( 263 .function any func() { 264 sta v4 265 lda.str "xxx" 266 ldglobalvar 0x7, "oDiv" 267 callarg1 0x1, v0 268 return 269 } 270 )"; 271 auto item = p.Parse(source); 272 const std::string func_name = "func:()"; 273 panda::panda_file::SourceLang language1 {panda::panda_file::SourceLang::PANDA_ASSEMBLY}; 274 panda::pandasm::Function function("fun", language1); 275 function.file_location->is_defined = false; 276 panda::pandasm::Function function1("fun", language1, 0, 10, "func", false, 10); 277 278 std::string ret = JsonSerializeItemBody(function); 279 EXPECT_EQ(ret, "{ \"name\": \"fun\" }"); 280 281 std::map<std::string, panda::pandasm::Function> function_table; 282 ret = JsonSerializeProgramItems(function_table); 283 EXPECT_EQ(ret, "[ ]"); 284 285 std::string test = "test"; 286 function_table.emplace(test, std::move(function1)); 287 288 ret = JsonSerializeProgramItems(function_table); 289 EXPECT_EQ(ret, "[ { \"name\": \"fun\" } ]"); 290 291 ret = item.Value().function_table.at(func_name).ins[3].ToString("test", true, 0); 292 EXPECT_EQ(ret, "callarg1 0x1, a0test"); 293 ret = item.Value().function_table.at(func_name).ins[3].ToString("test", false, 0); 294 EXPECT_EQ(ret, "callarg1 0x1, v0test"); 295 } 296 297 /** 298 * @tc.name: assembler_ins_test_006 299 * @tc.desc: Verify the NextMask function. 300 * @tc.type: FUNC 301 * @tc.require: issueNumber 302 */ 303 HWTEST_F(AssemblerInsTest, assembler_ins_test_006, TestSize.Level1) 304 { 305 Context con; 306 con.token = "test"; 307 308 EXPECT_GT(con.Len(), 0); 309 size_t number_of_params_already_is = 65535; 310 EXPECT_FALSE(con.ValidateParameterName(number_of_params_already_is)); 311 number_of_params_already_is = 4; 312 EXPECT_FALSE(con.ValidateParameterName(number_of_params_already_is)); 313 314 panda::pandasm::Token token1; 315 con.tokens.push_back(token1); 316 panda::pandasm::Token token2; 317 con.tokens.push_back(token2); 318 EXPECT_EQ(con.Next(), Token::Type::ID_BAD); 319 size_t line_size = 3; 320 con.number = line_size; 321 con.end = false; 322 EXPECT_TRUE(con.NextMask()); 323 con.end = true; 324 EXPECT_TRUE(con.NextMask()); 325 } 326 }