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 EXPECT 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 #include <iostream>
18
19 #include "assembly-emitter.h"
20 #include "assembly-parser.h"
21 #include "class_data_accessor-inl.h"
22 #include "code_data_accessor-inl.h"
23 #include "debug_data_accessor-inl.h"
24 #include "field_data_accessor-inl.h"
25 #include "file_items.h"
26 #include "lexer.h"
27 #include "method_data_accessor-inl.h"
28 #include "param_annotations_data_accessor.h"
29 #include "proto_data_accessor-inl.h"
30 #include "utils/span.h"
31 #include "utils/leb128.h"
32 #include "utils/utf.h"
33 #include "bytecode_instruction-inl.h"
34
35 using namespace testing::ext;
36
37 namespace panda::pandasm {
38 class AssemblyEmitterTest : public testing::Test {
39 };
40
GetTypeDescriptor(const std::string & name,std::string * storage)41 static const uint8_t *GetTypeDescriptor(const std::string &name, std::string *storage)
42 {
43 *storage = "L" + name + ";";
44 std::replace(storage->begin(), storage->end(), '.', '/');
45 return utf::CStringAsMutf8(storage->c_str());
46 }
47
GetSpecialOpcode(uint32_t pc_inc,int32_t line_inc)48 uint8_t GetSpecialOpcode(uint32_t pc_inc, int32_t line_inc)
49 {
50 return static_cast<uint8_t>(line_inc - panda_file::LineNumberProgramItem::LINE_BASE) +
51 static_cast<uint8_t>(pc_inc * panda_file::LineNumberProgramItem::LINE_RANGE) +
52 panda_file::LineNumberProgramItem::OPCODE_BASE;
53 }
54
55 /**
56 * @tc.name: assembly_emitter_test_001
57 * @tc.desc: Verify the EnumerateMethods function.
58 * @tc.type: FUNC
59 * @tc.require: issueNumber
60 */
61 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_001, TestSize.Level1)
62 {
63 Parser p;
64 auto source = R"(
65 .record R {}
66 .function void R.foo(R a0) <ctor> {}
67 )";
68
69 auto res = p.Parse(source);
70 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
71
72 auto pf = AsmEmitter::Emit(res.Value());
73 EXPECT_NE(pf, nullptr);
74
75 std::string descriptor;
76
77 auto class_id = pf->GetClassId(GetTypeDescriptor("R", &descriptor));
78 EXPECT_TRUE(class_id.IsValid());
79
80 panda_file::ClassDataAccessor cda(*pf, class_id);
81
__anon4b9ec5e20102(panda_file::MethodDataAccessor &mda) 82 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
83 auto *name = utf::Mutf8AsCString(pf->GetStringData(mda.GetNameId()).data);
84 EXPECT_STREQ(name, ".ctor");
85 });
86 }
87
88 /**
89 * @tc.name: assembly_emitter_test_002
90 * @tc.desc: Verify the EnumerateMethods function.
91 * @tc.type: FUNC
92 * @tc.require: issueNumber
93 */
94 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_002, TestSize.Level1)
95 {
96 Parser p;
97
98 auto source = R"( # 1
99 .record R { # 2
100 i32 sf <static> # 3
101 i8 if # 4
102 } # 5
103 # 6
104 .function void main() { # 7
105 return # 8
106 } # 9
107 )";
108
109 std::string source_filename = "source.pa";
110 auto res = p.Parse(source, source_filename);
111 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
112
113 auto pf = AsmEmitter::Emit(res.Value());
114 EXPECT_NE(pf, nullptr);
115
116 {
117 std::string descriptor;
118 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
119 EXPECT_TRUE(class_id.IsValid());
120 EXPECT_FALSE(pf->IsExternal(class_id));
121
122 panda_file::ClassDataAccessor cda(*pf, class_id);
123 EXPECT_EQ(cda.GetSuperClassId().GetOffset(), 0U);
124 EXPECT_EQ(cda.GetAccessFlags(), ACC_PUBLIC);
125 EXPECT_EQ(cda.GetFieldsNumber(), 0U);
126 EXPECT_EQ(cda.GetMethodsNumber(), 1U);
127 EXPECT_EQ(cda.GetIfacesNumber(), 0U);
128
129 EXPECT_FALSE(cda.GetSourceFileId().has_value());
130
__anon4b9ec5e20202(panda_file::File::EntityId) 131 cda.EnumerateAnnotations([](panda_file::File::EntityId) { EXPECT_TRUE(false); });
132
__anon4b9ec5e20302(panda_file::FieldDataAccessor &) 133 cda.EnumerateFields([](panda_file::FieldDataAccessor &) { EXPECT_TRUE(false); });
134
__anon4b9ec5e20402(panda_file::MethodDataAccessor &mda) 135 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
136 EXPECT_FALSE(mda.IsExternal());
137 EXPECT_EQ(mda.GetClassId(), class_id);
138 EXPECT_EQ(utf::CompareMUtf8ToMUtf8(pf->GetStringData(mda.GetNameId()).data, utf::CStringAsMutf8("main")),
139 0);
140
141 EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
142
143 EXPECT_EQ(mda.GetAccessFlags(), ACC_STATIC);
144 EXPECT_TRUE(mda.GetCodeId().has_value());
145
146 panda_file::CodeDataAccessor cdacc(*pf, mda.GetCodeId().value());
147 EXPECT_EQ(cdacc.GetNumVregs(), 0U);
148 EXPECT_EQ(cdacc.GetNumArgs(), 0U);
149 EXPECT_EQ(cdacc.GetCodeSize(), 1U);
150 EXPECT_EQ(cdacc.GetTriesSize(), 0U);
151
152 EXPECT_FALSE(mda.GetRuntimeParamAnnotationId().has_value());
153 EXPECT_FALSE(mda.GetParamAnnotationId().has_value());
154 EXPECT_TRUE(mda.GetDebugInfoId().has_value());
155
156 panda_file::DebugInfoDataAccessor dda(*pf, mda.GetDebugInfoId().value());
157 EXPECT_EQ(dda.GetLineStart(), 8U);
158 EXPECT_EQ(dda.GetNumParams(), 0U);
159
160 mda.EnumerateAnnotations([](panda_file::File::EntityId) {});
161 });
162 }
163 {
164 std::string descriptor;
165 auto class_id = pf->GetClassId(GetTypeDescriptor("R", &descriptor));
166 EXPECT_TRUE(class_id.IsValid());
167 EXPECT_FALSE(pf->IsExternal(class_id));
168
169 panda_file::ClassDataAccessor cda(*pf, class_id);
170 EXPECT_EQ(cda.GetSuperClassId().GetOffset(), 0U);
171 EXPECT_EQ(cda.GetAccessFlags(), ACC_PUBLIC);
172 EXPECT_EQ(cda.GetFieldsNumber(), 2U);
173 EXPECT_EQ(cda.GetMethodsNumber(), 0U);
174 EXPECT_EQ(cda.GetIfacesNumber(), 0U);
175
176 // We emit SET_FILE in debuginfo
177 EXPECT_TRUE(cda.GetSourceFileId().has_value());
178
179 EXPECT_EQ(std::string(reinterpret_cast<const char *>(pf->GetStringData(cda.GetSourceFileId().value()).data)),
180 source_filename);
181
182 struct FieldData {
183 std::string name;
184 panda_file::Type::TypeId type_id;
185 uint32_t access_flags;
186 };
187
188 std::vector<FieldData> fields {{"sf", panda_file::Type::TypeId::I32, ACC_STATIC},
189 {"if", panda_file::Type::TypeId::I8, 0}};
190
191 size_t i = 0;
__anon4b9ec5e20602(panda_file::FieldDataAccessor &fda) 192 cda.EnumerateFields([&](panda_file::FieldDataAccessor &fda) {
193 EXPECT_FALSE(fda.IsExternal());
194 EXPECT_EQ(fda.GetClassId(), class_id);
195 EXPECT_EQ(utf::CompareMUtf8ToMUtf8(pf->GetStringData(fda.GetNameId()).data,
196 utf::CStringAsMutf8(fields[i].name.c_str())),
197 0);
198
199 EXPECT_EQ(fda.GetType(), panda_file::Type(fields[i].type_id).GetFieldEncoding());
200 EXPECT_EQ(fda.GetAccessFlags(), fields[i].access_flags);
201
202 fda.EnumerateAnnotations([](panda_file::File::EntityId) { EXPECT_TRUE(false); });
203
204 ++i;
205 });
206
__anon4b9ec5e20802(panda_file::MethodDataAccessor &) 207 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &) { EXPECT_TRUE(false); });
208 }
209 }
210
211 /**
212 * @tc.name: assembly_emitter_test_003
213 * @tc.desc: Verify the EnumerateMethods function.
214 * @tc.type: FUNC
215 * @tc.require: issueNumber
216 */
217 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_003, TestSize.Level1)
218 {
219 Parser p;
220
221 auto source = R"(
222 .function void main() {
223 ldai 0 # line 3, pc 0
224 # line 4
225 # line 5
226 # line 6
227 # line 7
228 # line 8
229 # line 9
230 # line 10
231 # line 11
232 # line 12
233 # line 13
234 # line 14
235 ldai 1 # line 15, pc 9
236 return # line 16, pc 18
237 }
238 )";
239
240 std::string source_filename = "source.pa";
241 auto res = p.Parse(source, source_filename);
242 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
243
244 auto pf = AsmEmitter::Emit(res.Value());
245 EXPECT_NE(pf, nullptr);
246
247 std::string descriptor;
248 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
249 EXPECT_TRUE(class_id.IsValid());
250
251 panda_file::ClassDataAccessor cda(*pf, class_id);
252
__anon4b9ec5e20902(panda_file::MethodDataAccessor &mda) 253 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
254 panda_file::CodeDataAccessor cdacc(*pf, mda.GetCodeId().value());
255 EXPECT_TRUE(mda.GetDebugInfoId().has_value());
256
257 panda_file::DebugInfoDataAccessor dda(*pf, mda.GetDebugInfoId().value());
258 EXPECT_EQ(dda.GetLineStart(), 3U);
259 EXPECT_EQ(dda.GetNumParams(), 0U);
260
261 dda.GetLineNumberProgram();
262 Span<const uint8_t> constant_pool = dda.GetConstantPool();
263
264 std::vector<uint8_t> opcodes {static_cast<uint8_t>(panda_file::LineNumberProgramItem::Opcode::SET_FILE),
265 static_cast<uint8_t>(panda_file::LineNumberProgramItem::Opcode::ADVANCE_PC),
266 static_cast<uint8_t>(panda_file::LineNumberProgramItem::Opcode::ADVANCE_LINE),
267 GetSpecialOpcode(0, 0),
268 GetSpecialOpcode(9, 1),
269 static_cast<uint8_t>(panda_file::LineNumberProgramItem::Opcode::END_SEQUENCE)};
270
271 size_t size {};
272 bool is_full {};
273 size_t constant_pool_offset = 0;
274
275 uint32_t offset {};
276
277 std::tie(offset, size, is_full) = leb128::DecodeUnsigned<uint32_t>(&constant_pool[constant_pool_offset]);
278 constant_pool_offset += size;
279 EXPECT_TRUE(is_full);
280 EXPECT_EQ(
281 std::string(reinterpret_cast<const char *>(pf->GetStringData(panda_file::File::EntityId(offset)).data)),
282 source_filename);
283
284 uint32_t pc_inc;
285 std::tie(pc_inc, size, is_full) = leb128::DecodeUnsigned<uint32_t>(&constant_pool[constant_pool_offset]);
286 constant_pool_offset += size;
287 EXPECT_TRUE(is_full);
288 EXPECT_EQ(pc_inc, 0U);
289
290 int32_t line_inc;
291 std::tie(line_inc, size, is_full) = leb128::DecodeSigned<int32_t>(&constant_pool[constant_pool_offset]);
292 constant_pool_offset += size;
293 EXPECT_TRUE(is_full);
294 EXPECT_EQ(line_inc, 5);
295
296 EXPECT_EQ(constant_pool_offset + 1, constant_pool.size());
297 });
298 }
299
300 /**
301 * @tc.name: assembly_emitter_test_004
302 * @tc.desc: Verify the EnumerateMethods function.
303 * @tc.type: FUNC
304 * @tc.require: issueNumber
305 */
306 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_004, TestSize.Level1)
307 {
308 Parser p;
309
310 auto source = R"(
311 .record Exception1 {}
312 .record Exception2 {}
313
314 .function any myFunction(any a0, any a1, any a2) <static> {
315 mov v0, a0
316 mov v1, a1
317 mov v2, a2
318 ldundefined
319 sta v4
320 try_begin:
321 jmp handler_begin1
322 handler_begin1:
323 ldhole
324 sta v5
325 jmp handler_end2
326 handler_begin2:
327 sta v5
328 handler_end2:
329 lda v4
330 sta v6
331 ldundefined
332 eq 0x0, v6
333 jeqz jump_label_4
334 sta v4
335 jump_label_4:
336 lda v5
337 sta v6
338 ldhole
339 sta v7
340 lda v6
341 noteq 0x1, v7
342 jeqz jump_label_5
343 lda v6
344 throw
345 jump_label_5:
346 ldundefined
347 returnundefined
348
349 .catchall try_begin, try_begin, handler_begin1
350 .catchall try_begin, handler_begin1, handler_begin2, handler_end2
351 }
352 )";
353
354 auto res = p.Parse(source);
355 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
356 auto pf = AsmEmitter::Emit(res.Value());
357 EXPECT_NE(pf, nullptr);
358
359 std::string descriptor;
360
361 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
362 EXPECT_TRUE(class_id.IsValid());
363
364 panda_file::ClassDataAccessor cda(*pf, class_id);
365
366 size_t i = 0;
__anon4b9ec5e20a02(panda_file::MethodDataAccessor &mda) 367 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
368 panda_file::CodeDataAccessor cdacc(*pf, mda.GetCodeId().value());
369 // The NumVregs of arguments is 8U
370 // The NumArgs of arguments is 3U
371 // The tries size is 2U
372 EXPECT_EQ(cdacc.GetNumVregs(), 8U);
373 EXPECT_EQ(cdacc.GetNumArgs(), 3U);
374 EXPECT_EQ(cdacc.GetTriesSize(), 2U);
375
376 cdacc.EnumerateTryBlocks([&](panda_file::CodeDataAccessor::TryBlock &try_block) {
377 // Try start Pc is 9U
378 // Catches number is 1U
379 EXPECT_EQ(try_block.GetStartPc(), 9U);
380 EXPECT_EQ(try_block.GetNumCatches(), 1U);
381
382 struct CatchInfo {
383 panda_file::File::EntityId type_id;
384 uint32_t handler_pc;
385 };
386 // Exception1 class ID is 11.
387 // Exception2 class ID is 16.
388 // The file entity ID is 6 * 9.
389 std::vector<CatchInfo> catch_infos {{pf->GetClassId(GetTypeDescriptor("Exception1", &descriptor)), 11},
390 {pf->GetClassId(GetTypeDescriptor("Exception2", &descriptor)), 16},
391 {panda_file::File::EntityId(), 6 * 9}};
392
393 try_block.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catch_block) {
394 EXPECT_EQ(catch_block.GetHandlerPc(), catch_infos[i].handler_pc);
395 ++i;
396
397 return true;
398 });
399
400 return true;
401 });
402 });
403 }
404
405 /**
406 * @tc.name: assembly_emitter_test_005
407 * @tc.desc: Verify the AsmEmitter::GetLastError() function.
408 * @tc.type: FUNC
409 * @tc.require: issueNumber
410 */
411 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_005, TestSize.Level1)
412 {
413 {
414 Parser p;
415 auto source = R"(
416 .record A {
417 B b
418 }
419 )";
420
421 auto res = p.Parse(source);
422 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
423
424 auto pf = AsmEmitter::Emit(res.Value());
425 EXPECT_EQ(pf, nullptr);
426 EXPECT_EQ(AsmEmitter::GetLastError(), "Field A.b has undefined type");
427 }
428
429 {
430 Parser p;
431 auto source = R"(
432 .function void A.b() {}
433 )";
434
435 auto res = p.Parse(source);
436 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
437
438 auto pf = AsmEmitter::Emit(res.Value());
439 EXPECT_EQ(pf, nullptr);
440 EXPECT_EQ(AsmEmitter::GetLastError(), "Function A.b is bound to undefined record A");
441 }
442
443 {
444 Parser p;
445 auto source = R"(
446 .function A b() {}
447 )";
448
449 auto res = p.Parse(source);
450 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
451
452 auto pf = AsmEmitter::Emit(res.Value());
453 EXPECT_EQ(pf, nullptr);
454 EXPECT_EQ(AsmEmitter::GetLastError(), "Function b has undefined return type");
455 }
456
457 {
458 Parser p;
459 auto source = R"(
460 .function void a(b a0) {}
461 )";
462
463 auto res = p.Parse(source);
464 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
465
466 auto pf = AsmEmitter::Emit(res.Value());
467 EXPECT_EQ(pf, nullptr);
468 EXPECT_EQ(AsmEmitter::GetLastError(), "Argument 0 of function a has undefined type");
469 }
470
471 {
472 Parser p;
473 auto source = R"(
474 .record A <external>
475 .function void A.x() {}
476 )";
477
478 auto res = p.Parse(source);
479 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
480
481 auto pf = AsmEmitter::Emit(res.Value());
482 EXPECT_EQ(pf, nullptr);
483 EXPECT_EQ(AsmEmitter::GetLastError(), "Non-external function A.x is bound to external record");
484 }
485 }
486
487 /**
488 * @tc.name: assembly_emitter_test_006
489 * @tc.desc: Verify the EnumerateMethods function.
490 * @tc.type: FUNC
491 * @tc.require: issueNumber
492 */
493 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_006, TestSize.Level1)
494 {
495 Parser p;
496 auto source = R"(
497 .function void foo() {}
498 )";
499
500 auto res = p.Parse(source);
501 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
502
503 auto pf = AsmEmitter::Emit(res.Value());
504 EXPECT_NE(pf, nullptr);
505
506 std::string descriptor;
507
508 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
509 EXPECT_TRUE(class_id.IsValid());
510
511 panda_file::ClassDataAccessor cda(*pf, class_id);
512
513 EXPECT_FALSE(cda.GetSourceLang());
514
__anon4b9ec5e20d02(panda_file::MethodDataAccessor &mda) 515 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) { EXPECT_FALSE(mda.GetSourceLang()); });
516 }
517
518 /**
519 * @tc.name: assembly_emitter_test_007
520 * @tc.desc: Verify the EnumerateMethods function.
521 * @tc.type: FUNC
522 * @tc.require: issueNumber
523 */
524 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_007, TestSize.Level1)
525 {
526 {
527 Parser p;
528 auto source = R"(
529 .record R {}
530 .function void R.foo(R a0) <ctor> {}
531 )";
532
533 auto res = p.Parse(source);
534 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
535
536 auto pf = AsmEmitter::Emit(res.Value());
537 EXPECT_NE(pf, nullptr);
538
539 std::string descriptor;
540
541 auto class_id = pf->GetClassId(GetTypeDescriptor("R", &descriptor));
542 EXPECT_TRUE(class_id.IsValid());
543
544 panda_file::ClassDataAccessor cda(*pf, class_id);
545
__anon4b9ec5e20e02(panda_file::MethodDataAccessor &mda) 546 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
547 auto *name = utf::Mutf8AsCString(pf->GetStringData(mda.GetNameId()).data);
548 EXPECT_STREQ(name, ".ctor");
549 });
550 }
551
552 {
553 Parser p;
554 auto source = R"(
555 .record R {}
556 .function void R.foo(R a0) <cctor> {}
557 )";
558
559 auto res = p.Parse(source);
560 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
561
562 auto pf = AsmEmitter::Emit(res.Value());
563 EXPECT_NE(pf, nullptr);
564
565 std::string descriptor;
566
567 auto class_id = pf->GetClassId(GetTypeDescriptor("R", &descriptor));
568 EXPECT_TRUE(class_id.IsValid());
569
570 panda_file::ClassDataAccessor cda(*pf, class_id);
571
__anon4b9ec5e20f02(panda_file::MethodDataAccessor &mda) 572 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
573 auto *name = utf::Mutf8AsCString(pf->GetStringData(mda.GetNameId()).data);
574 EXPECT_STREQ(name, ".cctor");
575 });
576 }
577 }
578
579 /**
580 * @tc.name: assembly_emitter_test_008
581 * @tc.desc: Verify the EnumerateFields function.
582 * @tc.type: FUNC
583 * @tc.require: issueNumber
584 */
585 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_008, TestSize.Level1)
586 {
587 Parser p;
588
589 auto source = R"(
590 .record panda.String <external>
591
592 .record R {
593 u1 f_u1 <value=1>
594 i8 f_i8 <value=2>
595 u8 f_u8 <value=128>
596 i16 f_i16 <value=256>
597 u16 f_u16 <value=32768>
598 i32 f_i32 <value=65536>
599 u32 f_u32 <value=2147483648>
600 i64 f_i64 <value=4294967296>
601 u64 f_u64 <value=9223372036854775808>
602 f32 f_f32 <value=1.0>
603 f64 f_f64 <value=2.0>
604 panda.String f_str <value="str">
605 }
606 )";
607
608 struct FieldData {
609 std::string name;
610 panda_file::Type::TypeId type_id;
611 std::variant<int32_t, uint32_t, int64_t, uint64_t, float, double, std::string> value;
612 };
613
614 uint32_t f_u1 = 1;
615 int32_t f_i8 = 2;
616 uint32_t f_u8 = 128;
617 int32_t f_i16 = 256;
618 uint32_t f_u16 = 32768;
619 int32_t f_i32 = 65536;
620 uint32_t f_u32 = 2147483648;
621 int64_t f_i64 = 4294967296;
622 uint64_t f_u64 = 9223372036854775808ULL;
623 float f_f32 = 1.0;
624 double f_f64 = 2.0;
625
626 std::vector<FieldData> data {
627 {"f_u1", panda_file::Type::TypeId::U1, f_u1}, {"f_i8", panda_file::Type::TypeId::I8, f_i8},
628 {"f_u8", panda_file::Type::TypeId::U8, f_u8}, {"f_i16", panda_file::Type::TypeId::I16, f_i16},
629 {"f_u16", panda_file::Type::TypeId::U16, f_u16}, {"f_i32", panda_file::Type::TypeId::I32, f_i32},
630 {"f_u32", panda_file::Type::TypeId::U32, f_u32}, {"f_i64", panda_file::Type::TypeId::I64, f_i64},
631 {"f_u64", panda_file::Type::TypeId::U64, f_u64}, {"f_f32", panda_file::Type::TypeId::F32, f_f32},
632 {"f_f64", panda_file::Type::TypeId::F64, f_f64}, {"f_str", panda_file::Type::TypeId::REFERENCE, "str"}};
633
634 auto res = p.Parse(source);
635 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
636
637 auto pf = AsmEmitter::Emit(res.Value());
638 EXPECT_NE(pf, nullptr);
639
640 std::string descriptor;
641 auto class_id = pf->GetClassId(GetTypeDescriptor("R", &descriptor));
642 EXPECT_TRUE(class_id.IsValid());
643 EXPECT_FALSE(pf->IsExternal(class_id));
644
645 panda_file::ClassDataAccessor cda(*pf, class_id);
646 EXPECT_EQ(cda.GetFieldsNumber(), data.size());
647
648 auto panda_string_id = pf->GetClassId(GetTypeDescriptor("panda.String", &descriptor));
649
650 size_t idx = 0;
__anon4b9ec5e21002(panda_file::FieldDataAccessor &fda) 651 cda.EnumerateFields([&](panda_file::FieldDataAccessor &fda) {
652 const FieldData &field_data = data[idx];
653
654 EXPECT_EQ(utf::CompareMUtf8ToMUtf8(pf->GetStringData(fda.GetNameId()).data,
655 utf::CStringAsMutf8(field_data.name.c_str())),
656 0);
657
658 panda_file::Type type(field_data.type_id);
659 uint32_t type_value;
660 if (type.IsReference()) {
661 type_value = panda_string_id.GetOffset();
662 } else {
663 type_value = type.GetFieldEncoding();
664 }
665
666 switch (field_data.type_id) {
667 case panda_file::Type::TypeId::U1: {
668 auto result = fda.GetValue<uint8_t>();
669 EXPECT_TRUE(result);
670 EXPECT_EQ(result.value(), std::get<uint32_t>(field_data.value));
671 break;
672 }
673 case panda_file::Type::TypeId::I8: {
674 auto result = fda.GetValue<int8_t>();
675 EXPECT_TRUE(result);
676 EXPECT_EQ(result.value(), std::get<int32_t>(field_data.value));
677 break;
678 }
679 case panda_file::Type::TypeId::U8: {
680 auto result = fda.GetValue<uint8_t>();
681 EXPECT_TRUE(result);
682 EXPECT_EQ(result.value(), std::get<uint32_t>(field_data.value));
683 break;
684 }
685 case panda_file::Type::TypeId::I16: {
686 auto result = fda.GetValue<int16_t>();
687 EXPECT_TRUE(result);
688 EXPECT_EQ(result.value(), std::get<int32_t>(field_data.value));
689 break;
690 }
691 case panda_file::Type::TypeId::U16: {
692 auto result = fda.GetValue<uint16_t>();
693 EXPECT_TRUE(result);
694 EXPECT_EQ(result.value(), std::get<uint32_t>(field_data.value));
695 break;
696 }
697 case panda_file::Type::TypeId::I32: {
698 auto result = fda.GetValue<int32_t>();
699 EXPECT_TRUE(result);
700 EXPECT_EQ(result.value(), std::get<int32_t>(field_data.value));
701 break;
702 }
703 case panda_file::Type::TypeId::U32: {
704 auto result = fda.GetValue<uint32_t>();
705 EXPECT_TRUE(result);
706 EXPECT_EQ(result.value(), std::get<uint32_t>(field_data.value));
707 break;
708 }
709 case panda_file::Type::TypeId::I64: {
710 auto result = fda.GetValue<int64_t>();
711 EXPECT_TRUE(result);
712 EXPECT_EQ(result.value(), std::get<int64_t>(field_data.value));
713 break;
714 }
715 case panda_file::Type::TypeId::U64: {
716 auto result = fda.GetValue<uint64_t>();
717 EXPECT_TRUE(result);
718 EXPECT_EQ(result.value(), std::get<uint64_t>(field_data.value));
719 break;
720 }
721 case panda_file::Type::TypeId::F32: {
722 auto result = fda.GetValue<float>();
723 EXPECT_TRUE(result);
724 EXPECT_EQ(result.value(), std::get<float>(field_data.value));
725 break;
726 }
727 case panda_file::Type::TypeId::F64: {
728 auto result = fda.GetValue<double>();
729 EXPECT_TRUE(result);
730 EXPECT_EQ(result.value(), std::get<double>(field_data.value));
731 break;
732 }
733 case panda_file::Type::TypeId::REFERENCE: {
734 auto result = fda.GetValue<uint32_t>();
735 EXPECT_TRUE(result);
736
737 panda_file::File::EntityId string_id(result.value());
738 auto val = std::get<std::string>(field_data.value);
739
740 EXPECT_EQ(utf::CompareMUtf8ToMUtf8(pf->GetStringData(string_id).data, utf::CStringAsMutf8(val.c_str())),
741 0);
742 break;
743 }
744 default: {
745 UNREACHABLE();
746 break;
747 }
748 }
749
750 ++idx;
751 });
752 }
753
754 /**
755 * @tc.name: assembly_emitter_test_009
756 * @tc.desc: Verify the EnumerateMethods function.
757 * @tc.type: FUNC
758 * @tc.require: issueNumber
759 */
760 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_009, TestSize.Level1)
761 {
762 Parser p;
763 auto source = R"(
764 .function any foo(any a0) <noimpl>
765 )";
766
767 auto res = p.Parse(source);
768 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
769
770 auto pf = AsmEmitter::Emit(res.Value());
771 EXPECT_NE(pf, nullptr);
772
773 std::string descriptor;
774
775 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
776 EXPECT_TRUE(class_id.IsValid());
777
778 panda_file::ClassDataAccessor cda(*pf, class_id);
779
780 int32_t num_methods = 0;
__anon4b9ec5e21102(panda_file::MethodDataAccessor &mda) 781 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
782 EXPECT_FALSE(mda.IsExternal());
783 EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
784 EXPECT_TRUE(mda.GetCodeId().has_value());
785 panda_file::CodeDataAccessor cdacc(*pf, mda.GetCodeId().value());
786 EXPECT_EQ(1u, cdacc.GetNumArgs());
787
788 ++num_methods;
789 });
790 EXPECT_EQ(1, num_methods);
791 }
792
793 /**
794 * @tc.name: assembly_emitter_test_010
795 * @tc.desc: Verify the AsmEmitter::Emit function.
796 * @tc.type: FUNC
797 * @tc.require: issueNumber
798 */
799 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_010, TestSize.Level1)
800 {
801 Parser p;
802 auto source = R"(
803 .record Test {
804 any foo
805 }
806 )";
807
808 auto res = p.Parse(source);
809 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
810
811 auto pf = AsmEmitter::Emit(res.Value());
812 EXPECT_NE(pf, nullptr);
813
814 std::string descriptor;
815
816 auto class_id = pf->GetClassId(GetTypeDescriptor("Test", &descriptor));
817 EXPECT_TRUE(class_id.IsValid());
818
819 panda_file::ClassDataAccessor cda(*pf, class_id);
820
821 size_t num_fields = 0;
822 const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon4b9ec5e21202(panda_file::FieldDataAccessor &fda) 823 cda.EnumerateFields([&](panda_file::FieldDataAccessor &fda) {
824 uint32_t type = fda.GetType();
825 EXPECT_EQ(tagged.GetFieldEncoding(), type);
826
827 ++num_fields;
828 });
829 EXPECT_EQ(1, num_fields);
830 }
831
832 /**
833 * @tc.name: assembly_emitter_test_011
834 * @tc.desc: Verify the AsmEmitter::Emit function.
835 * @tc.type: FUNC
836 * @tc.require: issueNumber
837 */
838 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_011, TestSize.Level1)
839 {
840 Parser p1;
841 auto source1 = R"(
842 .record Test {
843 any foo
844 }
845 )";
846 Parser p2;
847 auto source2 = R"(
848 .function void main() {
849 ldai 0
850 ldai 1
851 return
852 }
853 )";
854 auto res1 = p1.Parse(source1);
855 EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
856
857 auto res2 = p2.Parse(source2);
858 EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
859
860 std::vector<Program *> progs;
861 progs.push_back(&res1.Value());
862 progs.push_back(&res2.Value());
863 const std::string filename = "source.pa";;
864 auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
865 EXPECT_TRUE(pf);
866 }
867
868 /**
869 * @tc.name: assembly_emitter_test_012
870 * @tc.desc: Verify the AsmEmitter::Emit function.
871 * @tc.type: FUNC
872 * @tc.require: issueNumber
873 */
874 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_012, TestSize.Level1)
875 {
876 Parser par;
877 auto source = R"(
878 .record Math <external>
879 .function i64 Math.minI64(i64 a0) <external>
880 .function i64 main(i64 a0, i64 a1) {
881 ldglobalvar 0x9, "Math.minI64"
882 callarg1 0x4, a0
883 return
884 }
885 )";
886 auto ret = par.Parse(source);
887 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
888 auto pf = AsmEmitter::Emit(ret.Value());
889 EXPECT_NE(pf, nullptr);
890
891 std::string descriptors;
892
893 auto class_id = pf->GetClassId(GetTypeDescriptor("Math", &descriptors));
894 EXPECT_TRUE(class_id.IsValid());
895 }
896
897 /**
898 * @tc.name: assembly_emitter_test_013
899 * @tc.desc: Verify the AsmEmitter::Emit function.
900 * @tc.type: FUNC
901 * @tc.require: issueNumber
902 */
903 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_013, TestSize.Level1)
904 {
905 Parser par;
906 auto source = R"(
907 .array array {
908 u1 1
909 u8 2
910 i8 -30
911 u16 400
912 i16 -5000
913 u32 60000
914 i32 -700000
915 u64 8000000
916 i64 -90000000
917 f32 12
918 f64 12
919 }
920 )";
921 std::string source_filename = "source.pa";
922 auto program = par.Parse(source, source_filename);
923 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
924 auto pf = AsmEmitter::Emit(program.Value());
925 EXPECT_NE(pf, nullptr);
926 }
927
928 /**
929 * @tc.name: assembly_emitter_test_014
930 * @tc.desc: Verify the AsmEmitter::Emit function.
931 * @tc.type: FUNC
932 * @tc.require: issueNumber
933 */
934 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_014, TestSize.Level1)
935 {
936 std::vector<std::vector<panda::pandasm::Token>> v;
937 Lexer l;
938 Parser par;
939 v.push_back(l.TokenizeString(".array array {").first);
940 v.push_back(l.TokenizeString("panda.String \"a\"").first);
941 v.push_back(l.TokenizeString("panda.String \"ab\"").first);
942 v.push_back(l.TokenizeString("panda.String \"abc\"").first);
943 v.push_back(l.TokenizeString("}").first);
944 v.push_back(l.TokenizeString(".array array_static panda.String 3 { \"a\" \"ab\" \"abc\" }").first);
945 auto program = par.Parse(v);
946 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
947 auto pf = AsmEmitter::Emit(program.Value());
948 EXPECT_NE(pf, nullptr);
949 }
950
951 /**
952 * @tc.name: assembly_emitter_test_015
953 * @tc.desc: Verify the AsmEmitter::Emit function.
954 * @tc.type: FUNC
955 * @tc.require: issueNumber
956 */
957 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_015, TestSize.Level1)
958 {
959 Parser par;
960 auto source = R"(
961 .record R {
962 R[][] f
963 }
964 .function any f(i8 a0) {
965 sta a0
966 }
967 .array array {
968 u1 1
969 }
970 )";
971 std::string source_filename = "source.pa";
972 auto program = par.Parse(source, source_filename);
973 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
974
975 panda::pandasm::Type type;
976 ScalarValue insn_order(ScalarValue::Create<panda::pandasm::Value::Type::RECORD>(type));
977 program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order);
978
979 auto pf = AsmEmitter::Emit(program.Value());
980 EXPECT_NE(pf, nullptr);
981
982 program.Value().literalarray_table.at("array").literals_[0].tag_ = panda_file::LiteralTag::LITERALARRAY;
983 program.Value().literalarray_table.at("array").literals_[0].value_.emplace<std::string>("array");
984 ScalarValue insn_order_lite(ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>("array"));
985 program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order_lite);
986 auto pf1 = AsmEmitter::Emit(program.Value());
987 EXPECT_NE(pf1, nullptr);
988
989 ScalarValue insn_order_enum(ScalarValue::Create<panda::pandasm::Value::Type::ENUM>("R.f"));
990 program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order_enum);
991 program.Value().record_table.at("R").field_list[0].metadata->SetAttributeValue("external", "enum");
992 auto pf2 = AsmEmitter::Emit(program.Value());
993 EXPECT_NE(pf2, nullptr);
994
995 ScalarValue insn_order_method(ScalarValue::Create<panda::pandasm::Value::Type::METHOD>("f:(i8)"));
996 program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order_method);
997 auto pf3 = AsmEmitter::Emit(program.Value());
998 EXPECT_NE(pf3, nullptr);
999
1000 ScalarValue insn_orders(ScalarValue::Create<panda::pandasm::Value::Type::I32>(1));
1001 std::vector<panda::pandasm::ScalarValue> elements;
1002 elements.emplace_back(std::move(insn_orders));
1003
1004 ArrayValue array_value(panda::pandasm::Value::Type::I32, elements);
1005 AnnotationElement anno_element("_TypeOfInstruction", std::make_unique<ArrayValue>(array_value));
1006 AnnotationData annotation("_ESSlotNumberAnnotation");
1007 annotation.AddElement(std::move(anno_element));
1008
1009
1010 ScalarValue insn_order_anno(ScalarValue::Create<panda::pandasm::Value::Type::ANNOTATION>(annotation));
1011
1012 static const std::string SLOT_NUMBER = "_ESSlotNumberAnnotation";
1013 pandasm::Record record(SLOT_NUMBER, pandasm::extensions::Language::ECMASCRIPT);
1014 record.metadata->AddAccessFlags(panda::ACC_ANNOTATION);
1015 program.Value().record_table.emplace(SLOT_NUMBER, std::move(record));
1016 program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order_anno);
1017 auto pf4 = AsmEmitter::Emit(program.Value());
1018 EXPECT_NE(pf4, nullptr);
1019 }
1020
1021 /**
1022 * @tc.name: assembly_emitter_test_016
1023 * @tc.desc: Verify the AsmEmitter::Emit function.
1024 * @tc.type: FUNC
1025 * @tc.require: issueNumber
1026 */
1027 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_016, TestSize.Level1)
1028 {
1029 Parser par;
1030 std::vector<std::vector<panda::pandasm::Token>> v;
1031 Lexer l;
1032 v.push_back(l.TokenizeString(".array array {").first);
1033 v.push_back(l.TokenizeString("u1 1").first);
1034 v.push_back(l.TokenizeString("u8 2").first);
1035 v.push_back(l.TokenizeString("i8 -30").first);
1036 v.push_back(l.TokenizeString("u16 400").first);
1037 v.push_back(l.TokenizeString("i16 -5000").first);
1038 v.push_back(l.TokenizeString("u32 60000").first);
1039 v.push_back(l.TokenizeString("i32 -700000").first);
1040 v.push_back(l.TokenizeString("u64 8000000").first);
1041 v.push_back(l.TokenizeString("i64 -90000000").first);
1042 v.push_back(l.TokenizeString("}").first);
1043 v.push_back(l.TokenizeString(".function any f(i8 a0) { sta a0 }").first);
1044 std::string source_filename = "source.pa";
1045 auto item = par.Parse(v, source_filename);
1046 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1047
1048 item.Value().literalarray_table.at("array").literals_[0].tag_ = panda_file::LiteralTag::BOOL;
1049 item.Value().literalarray_table.at("array").literals_[0].value_.emplace<0>(true);
1050
1051 item.Value().literalarray_table.at("array").literals_[1].tag_ = panda_file::LiteralTag::METHODAFFILIATE;
1052 item.Value().literalarray_table.at("array").literals_[1].value_.emplace<uint16_t>(1);
1053
1054 item.Value().literalarray_table.at("array").literals_[2].tag_ = panda_file::LiteralTag::FLOAT;
1055 item.Value().literalarray_table.at("array").literals_[2].value_.emplace<float>(1.0);
1056
1057 item.Value().literalarray_table.at("array").literals_[3].tag_ = panda_file::LiteralTag::DOUBLE;
1058 item.Value().literalarray_table.at("array").literals_[3].value_.emplace<double>(1.0);
1059
1060 item.Value().literalarray_table.at("array").literals_[4].tag_ = panda_file::LiteralTag::STRING;
1061 item.Value().literalarray_table.at("array").literals_[4].value_.emplace<std::string>("1.0");
1062
1063 item.Value().literalarray_table.at("array").literals_[5].tag_ = panda_file::LiteralTag::ASYNCGENERATORMETHOD;
1064 item.Value().literalarray_table.at("array").literals_[5].value_.emplace<std::string>("f:(i8)");
1065
1066 item.Value().literalarray_table.at("array").literals_[6].tag_ = panda_file::LiteralTag::LITERALARRAY;
1067 item.Value().literalarray_table.at("array").literals_[6].value_.emplace<std::string>("array");
1068
1069 auto pf = AsmEmitter::Emit(item.Value());
1070 EXPECT_NE(pf, nullptr);
1071 }
1072
1073 /**
1074 * @tc.name: assembly_emitter_test_017
1075 * @tc.desc: Verify the AsmEmitter::Emit function.
1076 * @tc.type: FUNC
1077 * @tc.require: issueNumber
1078 */
1079 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_017, TestSize.Level1)
1080 {
1081 Parser par;
1082 auto source = R"(
1083 .record Asm1 {
1084 i64 asm1
1085 void asm2
1086 i32 asm3
1087 }
1088 )";
1089 std::string source_filename = "source.pa";
1090 auto item = par.Parse(source, source_filename);
1091 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1092
1093 EXPECT_EQ(item.Value().record_table.at("Asm1").name, "Asm1");
1094 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[0].name, "asm1");
1095 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64);
1096 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[1].name, "asm2");
1097 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID);
1098 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[2].name, "asm3");
1099 EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32);
1100
1101 auto pf = AsmEmitter::Emit(item.Value());
1102 EXPECT_NE(pf, nullptr);
1103 }
1104
1105 /**
1106 * @tc.name: assembly_emitter_test_018
1107 * @tc.desc: Verify the AsmEmitter::Emit function.
1108 * @tc.type: FUNC
1109 * @tc.require: issueNumber
1110 */
1111 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_018, TestSize.Level1)
1112 {
1113 Parser par;
1114 auto source = R"(
1115 .function any f(i8 a0) {
1116 sta a0
1117 }
1118 )";
1119 std::string source_filename = "source.pa";
1120 AsmEmitter::PandaFileToPandaAsmMaps *maps = nullptr;
1121 auto items = panda::panda_file::ItemContainer {};
1122 auto program = par.Parse(source, source_filename);
1123 program.Value().function_table.at("f:(i8)").metadata->SetAttribute("external");
1124 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1125 auto pf = AsmEmitter::Emit(&items, program.Value(), maps, false);
1126 EXPECT_EQ(pf, true);
1127 }
1128
1129 /**
1130 * @tc.name: assembly_emitter_test_019
1131 * @tc.desc: Verify the AsmEmitter::Emit function.
1132 * @tc.type: FUNC
1133 * @tc.require: issueNumber
1134 */
1135 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_019, TestSize.Level1)
1136 {
1137 Parser par;
1138 auto source = R"(
1139 .function any f(i8 a0) {
1140 sta a0
1141 }
1142 )";
1143 std::string source_filename = "source.pa";
1144
1145 auto program = par.Parse(source, source_filename);
1146 program.Value().function_table.at("f:(i8)").metadata->SetAttribute("external");
1147 panda::pandasm::debuginfo::LocalVariable local;
1148 local.name = "test";
1149 local.signature = "test";
1150 local.signature_type = "test";
1151 program.Value().function_table.at("f:(i8)").local_variable_debug.push_back(local);
1152 EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1153 auto success = AsmEmitter::Emit(program.Value());
1154 EXPECT_NE(success, nullptr);
1155 }
1156
1157 /**
1158 * @tc.name: assembly_emitter_test_020
1159 * @tc.desc: Verify the EmitPrograms function.
1160 * @tc.type: FUNC
1161 * @tc.require: issueNumber
1162 */
1163 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_020, TestSize.Level1)
1164 {
1165 Parser p1;
1166 auto source1 = R"(
1167 .record Test {
1168 any foo
1169 }
1170 )";
1171 Parser p2;
1172 auto source2 = R"(
1173 .function void main() {
1174 ldai 0
1175 ldai 1
1176 return
1177 }
1178 )";
1179 auto res1 = p1.Parse(source1);
1180 EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1181
1182 auto res2 = p2.Parse(source2);
1183 EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1184
1185 std::vector<Program *> progs;
1186 progs.push_back(&res1.Value());
1187 progs.push_back(&res2.Value());
1188 const std::string filename = "source.pa";;
1189 auto success = AsmEmitter::EmitPrograms(filename, progs, true);
1190 EXPECT_TRUE(success);
1191 }
1192
1193 /**
1194 * @tc.name: assembly_emitter_test_021
1195 * @tc.desc: Verify the AsmEmitter::EmitPrograms function with different API version.
1196 * @tc.type: FUNC
1197 * @tc.require: issueNumber
1198 */
1199 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_021, TestSize.Level1)
1200 {
1201 Parser p;
1202 auto source = R"(
1203 .function any foo(any a0) <noimpl>
1204 )";
1205
1206 // api 11
1207 {
1208 auto res = p.Parse(source);
1209 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1210
1211 std::vector<Program *> progs;
1212 progs.push_back(&res.Value());
1213
1214 std::string descriptor;
1215 const std::string filename_api11 = "source_021_api11.abc";
1216 auto is_emitted = AsmEmitter::EmitPrograms(filename_api11, progs, false, 11);
1217 EXPECT_TRUE(is_emitted);
1218 auto pf = panda_file::OpenPandaFile(filename_api11);
1219 EXPECT_NE(pf, nullptr);
1220
1221 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1222 EXPECT_TRUE(class_id.IsValid());
1223
1224 panda_file::ClassDataAccessor cda(*pf, class_id);
1225
1226 EXPECT_FALSE(cda.GetSourceLang());
1227
1228 const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon4b9ec5e21302(panda_file::MethodDataAccessor &mda) 1229 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1230 EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1231 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1232 EXPECT_EQ(tagged, pda.GetReturnType());
1233 EXPECT_EQ(1u, pda.GetNumArgs());
1234 EXPECT_EQ(tagged, pda.GetArgType(0));
1235 });
1236 }
1237
1238 // api 12
1239 {
1240 auto res = p.Parse(source);
1241 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1242
1243 std::vector<Program *> progs;
1244 progs.push_back(&res.Value());
1245
1246 std::string descriptor;
1247 const std::string filename_api12 = "source_021_api12.abc";
1248 auto is_emitted = AsmEmitter::EmitPrograms(filename_api12, progs, false, 12);
1249 EXPECT_TRUE(is_emitted);
1250 auto pf = panda_file::OpenPandaFile(filename_api12);
1251 EXPECT_NE(pf, nullptr);
1252
1253 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1254 EXPECT_TRUE(class_id.IsValid());
1255
1256 panda_file::ClassDataAccessor cda(*pf, class_id);
1257
1258 EXPECT_FALSE(cda.GetSourceLang());
1259
__anon4b9ec5e21402(panda_file::MethodDataAccessor &mda) 1260 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1261 EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1262 });
1263 }
1264 }
1265
1266 /**
1267 * @tc.name: assembly_emitter_test_022
1268 * @tc.desc: Verify the AsmEmitter::Emit function with different API version.
1269 * @tc.type: FUNC
1270 * @tc.require: issueNumber
1271 */
1272 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_022, TestSize.Level1)
1273 {
1274 Parser p;
1275 auto source = R"(
1276 .function any foo(any a0) <noimpl>
1277 )";
1278 auto res = p.Parse(source);
1279 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1280
1281 // api 11
1282 {
1283 std::string descriptor;
1284 const std::string filename_api11 = "source_022_api11.abc";
1285 auto writer = panda_file::FileWriter(filename_api11);
1286 auto is_emitted = AsmEmitter::Emit(&writer, res.Value(), nullptr, nullptr, false, nullptr, 11);
1287 EXPECT_TRUE(is_emitted);
1288 auto pf = panda_file::OpenPandaFile(filename_api11);
1289 EXPECT_NE(pf, nullptr);
1290
1291 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1292 EXPECT_TRUE(class_id.IsValid());
1293
1294 panda_file::ClassDataAccessor cda(*pf, class_id);
1295
1296 EXPECT_FALSE(cda.GetSourceLang());
1297
1298 const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon4b9ec5e21502(panda_file::MethodDataAccessor &mda) 1299 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1300 EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1301 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1302 EXPECT_EQ(tagged, pda.GetReturnType());
1303 EXPECT_EQ(1u, pda.GetNumArgs());
1304 EXPECT_EQ(tagged, pda.GetArgType(0));
1305 });
1306 }
1307
1308 // api 12
1309 {
1310 std::string descriptor;
1311 const std::string filename_api12 = "source_022_api12.abc";
1312 auto writer = panda_file::FileWriter(filename_api12);
1313 auto is_emitted = AsmEmitter::Emit(&writer, res.Value(), nullptr, nullptr, false, nullptr, 12);
1314 EXPECT_TRUE(is_emitted);
1315 auto pf = panda_file::OpenPandaFile(filename_api12);
1316 EXPECT_NE(pf, nullptr);
1317
1318 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1319 EXPECT_TRUE(class_id.IsValid());
1320
1321 panda_file::ClassDataAccessor cda(*pf, class_id);
1322
1323 EXPECT_FALSE(cda.GetSourceLang());
1324
__anon4b9ec5e21602(panda_file::MethodDataAccessor &mda) 1325 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1326 EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1327 });
1328 }
1329 }
1330
1331 /**
1332 * @tc.name: assembly_emitter_test_023
1333 * @tc.desc: Verify the AsmEmitter::Emit function with different API version.
1334 * @tc.type: FUNC
1335 * @tc.require: issueNumber
1336 */
1337 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_023, TestSize.Level1)
1338 {
1339 Parser p;
1340 auto source = R"(
1341 .function any foo(any a0) <noimpl>
1342 )";
1343
1344 auto res = p.Parse(source);
1345 EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1346
1347 // api 11
1348 {
1349 std::string descriptor;
1350 auto pf = AsmEmitter::Emit(res.Value(), nullptr, 11);
1351 EXPECT_NE(pf, nullptr);
1352
1353 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1354 EXPECT_TRUE(class_id.IsValid());
1355
1356 panda_file::ClassDataAccessor cda(*pf, class_id);
1357
1358 EXPECT_FALSE(cda.GetSourceLang());
1359
1360 const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon4b9ec5e21702(panda_file::MethodDataAccessor &mda) 1361 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1362 EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1363 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1364 EXPECT_EQ(tagged, pda.GetReturnType());
1365 EXPECT_EQ(1u, pda.GetNumArgs());
1366 EXPECT_EQ(tagged, pda.GetArgType(0));
1367 });
1368 }
1369
1370 // api 12
1371 {
1372 std::string descriptor;
1373 auto pf = AsmEmitter::Emit(res.Value(), nullptr, 12);
1374 EXPECT_NE(pf, nullptr);
1375
1376 auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1377 EXPECT_TRUE(class_id.IsValid());
1378
1379 panda_file::ClassDataAccessor cda(*pf, class_id);
1380
1381 EXPECT_FALSE(cda.GetSourceLang());
1382
__anon4b9ec5e21802(panda_file::MethodDataAccessor &mda) 1383 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1384 EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1385 });
1386 }
1387 }
1388
1389 /**
1390 * @tc.name: assembly_emitter_test_024
1391 * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1392 * @tc.type: FUNC
1393 * @tc.require: I9OWSZ
1394 */
1395 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_024, TestSize.Level1)
1396 {
1397 Parser p1;
1398 auto source1 = R"(
1399 .record Rec {
1400 u8 rec <value=0>
1401 }
1402 )";
1403 Parser p2;
1404 auto source2 = R"(
1405 .record Rec {
1406 u8 rec <value=0>
1407 }
1408 )";
1409 auto res1 = p1.Parse(source1);
1410 EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1411
1412 auto res2 = p2.Parse(source2);
1413 EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1414
1415 std::vector<Program *> progs;
1416 progs.push_back(&res1.Value());
1417 progs.push_back(&res2.Value());
1418 const std::string filename = "source.pa";;
1419 auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1420 EXPECT_TRUE(pf);
1421 }
1422
1423 /**
1424 * @tc.name: assembly_emitter_test_025
1425 * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1426 * @tc.type: FUNC
1427 * @tc.require: I9OWSZ
1428 */
1429 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_025, TestSize.Level1)
1430 {
1431 Parser p1;
1432 auto source1 = R"(
1433 .record Rec {
1434 u8 rec <value=0>
1435 }
1436 )";
1437 Parser p2;
1438 auto source2 = R"(
1439 .record Rec {
1440 u8 rec <value=1>
1441 }
1442 )";
1443 auto res1 = p1.Parse(source1);
1444 EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1445
1446 auto res2 = p2.Parse(source2);
1447 EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1448
1449 std::vector<Program *> progs;
1450 progs.push_back(&res1.Value());
1451 progs.push_back(&res2.Value());
1452 const std::string filename = "source.pa";;
1453 auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1454 EXPECT_FALSE(pf);
1455 EXPECT_EQ(AsmEmitter::GetLastError(), "Field {Rec.rec} has different value.");
1456 }
1457
1458 /**
1459 * @tc.name: assembly_emitter_test_026
1460 * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1461 * @tc.type: FUNC
1462 * @tc.require: I9OWSZ
1463 */
1464 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_026, TestSize.Level1)
1465 {
1466 Parser p1;
1467 auto source1 = R"(
1468 .record Rec {
1469 u8 rec1 <value=0>
1470 }
1471 )";
1472 Parser p2;
1473 auto source2 = R"(
1474 .record Rec {
1475 u8 rec2 <value=0>
1476 }
1477 )";
1478 auto res1 = p1.Parse(source1);
1479 EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1480
1481 auto res2 = p2.Parse(source2);
1482 EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1483
1484 std::vector<Program *> progs;
1485 progs.push_back(&res1.Value());
1486 progs.push_back(&res2.Value());
1487 const std::string filename = "source.pa";;
1488 auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1489 EXPECT_TRUE(pf);
1490 }
1491 }