• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
__anon3a1ef3230102(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 
__anon3a1ef3230202(panda_file::File::EntityId) 131         cda.EnumerateAnnotations([](panda_file::File::EntityId) { EXPECT_TRUE(false); });
132 
__anon3a1ef3230302(panda_file::FieldDataAccessor &) 133         cda.EnumerateFields([](panda_file::FieldDataAccessor &) { EXPECT_TRUE(false); });
134 
__anon3a1ef3230402(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;
__anon3a1ef3230602(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 
__anon3a1ef3230802(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 
__anon3a1ef3230902(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;
__anon3a1ef3230a02(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 
__anon3a1ef3230d02(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 
__anon3a1ef3230e02(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 
__anon3a1ef3230f02(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;
__anon3a1ef3231002(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;
__anon3a1ef3231102(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);
__anon3a1ef3231202(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     program.Value().record_table.at("R").field_list[0].metadata->SetValue(insn_order_anno);
1013     auto pf4 = AsmEmitter::Emit(program.Value());
1014     EXPECT_NE(pf4, nullptr);
1015 }
1016 
1017 /**
1018  * @tc.name: assembly_emitter_test_016
1019  * @tc.desc: Verify the AsmEmitter::Emit function.
1020  * @tc.type: FUNC
1021  * @tc.require: issueNumber
1022  */
1023 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_016, TestSize.Level1)
1024 {
1025     Parser par;
1026     std::vector<std::vector<panda::pandasm::Token>> v;
1027     Lexer l;
1028     v.push_back(l.TokenizeString(".array array {").first);
1029     v.push_back(l.TokenizeString("u1 1").first);
1030     v.push_back(l.TokenizeString("u8 2").first);
1031     v.push_back(l.TokenizeString("i8 -30").first);
1032     v.push_back(l.TokenizeString("u16 400").first);
1033     v.push_back(l.TokenizeString("i16 -5000").first);
1034     v.push_back(l.TokenizeString("u32 60000").first);
1035     v.push_back(l.TokenizeString("i32 -700000").first);
1036     v.push_back(l.TokenizeString("u64 8000000").first);
1037     v.push_back(l.TokenizeString("i64 -90000000").first);
1038     v.push_back(l.TokenizeString("}").first);
1039     v.push_back(l.TokenizeString(".function any f(i8 a0) { sta a0 }").first);
1040     std::string source_filename = "source.pa";
1041     auto item = par.Parse(v, source_filename);
1042     EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1043 
1044     item.Value().literalarray_table.at("array").literals_[0].tag_ = panda_file::LiteralTag::BOOL;
1045     item.Value().literalarray_table.at("array").literals_[0].value_.emplace<0>(true);
1046 
1047     item.Value().literalarray_table.at("array").literals_[1].tag_ = panda_file::LiteralTag::METHODAFFILIATE;
1048     item.Value().literalarray_table.at("array").literals_[1].value_.emplace<uint16_t>(1);
1049 
1050     item.Value().literalarray_table.at("array").literals_[2].tag_ = panda_file::LiteralTag::FLOAT;
1051     item.Value().literalarray_table.at("array").literals_[2].value_.emplace<float>(1.0);
1052 
1053     item.Value().literalarray_table.at("array").literals_[3].tag_ = panda_file::LiteralTag::DOUBLE;
1054     item.Value().literalarray_table.at("array").literals_[3].value_.emplace<double>(1.0);
1055 
1056     item.Value().literalarray_table.at("array").literals_[4].tag_ = panda_file::LiteralTag::STRING;
1057     item.Value().literalarray_table.at("array").literals_[4].value_.emplace<std::string>("1.0");
1058 
1059     item.Value().literalarray_table.at("array").literals_[5].tag_ = panda_file::LiteralTag::ASYNCGENERATORMETHOD;
1060     item.Value().literalarray_table.at("array").literals_[5].value_.emplace<std::string>("f:(i8)");
1061 
1062     item.Value().literalarray_table.at("array").literals_[6].tag_ = panda_file::LiteralTag::LITERALARRAY;
1063     item.Value().literalarray_table.at("array").literals_[6].value_.emplace<std::string>("array");
1064 
1065     auto pf = AsmEmitter::Emit(item.Value());
1066     EXPECT_NE(pf, nullptr);
1067 }
1068 
1069 /**
1070  * @tc.name: assembly_emitter_test_017
1071  * @tc.desc: Verify the AsmEmitter::Emit function.
1072  * @tc.type: FUNC
1073  * @tc.require: issueNumber
1074  */
1075 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_017, TestSize.Level1)
1076 {
1077     Parser par;
1078     auto source = R"(
1079         .record Asm1 {
1080             i64 asm1
1081             void asm2
1082             i32 asm3
1083         }
1084     )";
1085     std::string source_filename = "source.pa";
1086     auto item = par.Parse(source, source_filename);
1087     EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1088 
1089     EXPECT_EQ(item.Value().record_table.at("Asm1").name, "Asm1");
1090     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[0].name, "asm1");
1091     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[0].type.GetId(), panda::panda_file::Type::TypeId::I64);
1092     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[1].name, "asm2");
1093     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[1].type.GetId(), panda::panda_file::Type::TypeId::VOID);
1094     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[2].name, "asm3");
1095     EXPECT_EQ(item.Value().record_table.at("Asm1").field_list[2].type.GetId(), panda::panda_file::Type::TypeId::I32);
1096 
1097     auto pf = AsmEmitter::Emit(item.Value());
1098     EXPECT_NE(pf, nullptr);
1099 }
1100 
1101 /**
1102  * @tc.name: assembly_emitter_test_018
1103  * @tc.desc: Verify the AsmEmitter::Emit function.
1104  * @tc.type: FUNC
1105  * @tc.require: issueNumber
1106  */
1107 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_018, TestSize.Level1)
1108 {
1109     Parser par;
1110     auto source = R"(
1111         .function any f(i8 a0) {
1112             sta a0
1113         }
1114     )";
1115     std::string source_filename = "source.pa";
1116     AsmEmitter::PandaFileToPandaAsmMaps *maps = nullptr;
1117     auto items = panda::panda_file::ItemContainer {};
1118     auto program = par.Parse(source, source_filename);
1119     program.Value().function_table.at("f:(i8)").metadata->SetAttribute("external");
1120     EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1121     auto pf = AsmEmitter::Emit(&items, program.Value(), maps, false);
1122     EXPECT_EQ(pf, true);
1123 }
1124 
1125 /**
1126  * @tc.name: assembly_emitter_test_019
1127  * @tc.desc: Verify the AsmEmitter::Emit function.
1128  * @tc.type: FUNC
1129  * @tc.require: issueNumber
1130  */
1131 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_019, TestSize.Level1)
1132 {
1133     Parser par;
1134     auto source = R"(
1135         .function any f(i8 a0) {
1136             sta a0
1137         }
1138     )";
1139     std::string source_filename = "source.pa";
1140 
1141     auto program = par.Parse(source, source_filename);
1142     program.Value().function_table.at("f:(i8)").metadata->SetAttribute("external");
1143     panda::pandasm::debuginfo::LocalVariable local;
1144     local.name = "test";
1145     local.signature = "test";
1146     local.signature_type = "test";
1147     program.Value().function_table.at("f:(i8)").local_variable_debug.push_back(local);
1148     EXPECT_EQ(par.ShowError().err, Error::ErrorType::ERR_NONE);
1149     auto success = AsmEmitter::Emit(program.Value());
1150     EXPECT_NE(success, nullptr);
1151 }
1152 
1153 /**
1154  * @tc.name: assembly_emitter_test_020
1155  * @tc.desc: Verify the EmitPrograms function.
1156  * @tc.type: FUNC
1157  * @tc.require: issueNumber
1158  */
1159 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_020, TestSize.Level1)
1160 {
1161     Parser p1;
1162     auto source1 = R"(
1163         .record Test {
1164             any foo
1165         }
1166     )";
1167     Parser p2;
1168     auto source2 = R"(
1169         .function void main() {
1170             ldai 0
1171             ldai 1
1172             return
1173         }
1174     )";
1175     auto res1 = p1.Parse(source1);
1176     EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1177 
1178     auto res2 = p2.Parse(source2);
1179     EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1180 
1181     std::vector<Program *> progs;
1182     progs.push_back(&res1.Value());
1183     progs.push_back(&res2.Value());
1184     const std::string filename = "source.pa";;
1185     auto success = AsmEmitter::EmitPrograms(filename, progs, true);
1186     EXPECT_TRUE(success);
1187 }
1188 
1189 /**
1190  * @tc.name: assembly_emitter_test_021
1191  * @tc.desc: Verify the AsmEmitter::EmitPrograms function with different API version.
1192  * @tc.type: FUNC
1193  * @tc.require: issueNumber
1194  */
1195 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_021, TestSize.Level1)
1196 {
1197     Parser p;
1198     auto source = R"(
1199         .function any foo(any a0) <noimpl>
1200     )";
1201     auto res = p.Parse(source);
1202     EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1203 
1204     std::vector<Program *> progs;
1205     progs.push_back(&res.Value());
1206 
1207     // api 11
1208     {
1209         std::string descriptor;
1210         const std::string filename_api11 = "source_021_api11.abc";
1211         auto is_emitted = AsmEmitter::EmitPrograms(filename_api11, progs, false, 11);
1212         EXPECT_TRUE(is_emitted);
1213         auto pf = panda_file::OpenPandaFile(filename_api11);
1214         EXPECT_NE(pf, nullptr);
1215 
1216         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1217         EXPECT_TRUE(class_id.IsValid());
1218 
1219         panda_file::ClassDataAccessor cda(*pf, class_id);
1220 
1221         EXPECT_FALSE(cda.GetSourceLang());
1222 
1223         const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon3a1ef3231302(panda_file::MethodDataAccessor &mda) 1224         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1225             EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1226             panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1227             EXPECT_EQ(tagged, pda.GetReturnType());
1228             EXPECT_EQ(1u, pda.GetNumArgs());
1229             EXPECT_EQ(tagged, pda.GetArgType(0));
1230         });
1231     }
1232 
1233     // api 12
1234     {
1235         std::string descriptor;
1236         const std::string filename_api12 = "source_021_api12.abc";
1237         auto is_emitted = AsmEmitter::EmitPrograms(filename_api12, progs, false, 12);
1238         EXPECT_TRUE(is_emitted);
1239         auto pf = panda_file::OpenPandaFile(filename_api12);
1240         EXPECT_NE(pf, nullptr);
1241 
1242         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1243         EXPECT_TRUE(class_id.IsValid());
1244 
1245         panda_file::ClassDataAccessor cda(*pf, class_id);
1246 
1247         EXPECT_FALSE(cda.GetSourceLang());
1248 
__anon3a1ef3231402(panda_file::MethodDataAccessor &mda) 1249         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1250             EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1251         });
1252     }
1253 }
1254 
1255 /**
1256  * @tc.name: assembly_emitter_test_022
1257  * @tc.desc: Verify the AsmEmitter::Emit function with different API version.
1258  * @tc.type: FUNC
1259  * @tc.require: issueNumber
1260  */
1261 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_022, TestSize.Level1)
1262 {
1263     Parser p;
1264     auto source = R"(
1265         .function any foo(any a0) <noimpl>
1266     )";
1267     auto res = p.Parse(source);
1268     EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1269 
1270     // api 11
1271     {
1272         std::string descriptor;
1273         const std::string filename_api11 = "source_022_api11.abc";
1274         auto writer = panda_file::FileWriter(filename_api11);
1275         auto is_emitted = AsmEmitter::Emit(&writer, res.Value(), nullptr, nullptr, false, nullptr, 11);
1276         EXPECT_TRUE(is_emitted);
1277         auto pf = panda_file::OpenPandaFile(filename_api11);
1278         EXPECT_NE(pf, nullptr);
1279 
1280         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1281         EXPECT_TRUE(class_id.IsValid());
1282 
1283         panda_file::ClassDataAccessor cda(*pf, class_id);
1284 
1285         EXPECT_FALSE(cda.GetSourceLang());
1286 
1287         const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon3a1ef3231502(panda_file::MethodDataAccessor &mda) 1288         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1289             EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1290             panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1291             EXPECT_EQ(tagged, pda.GetReturnType());
1292             EXPECT_EQ(1u, pda.GetNumArgs());
1293             EXPECT_EQ(tagged, pda.GetArgType(0));
1294         });
1295     }
1296 
1297     // api 12
1298     {
1299         std::string descriptor;
1300         const std::string filename_api12 = "source_022_api12.abc";
1301         auto writer = panda_file::FileWriter(filename_api12);
1302         auto is_emitted = AsmEmitter::Emit(&writer, res.Value(), nullptr, nullptr, false, nullptr, 12);
1303         EXPECT_TRUE(is_emitted);
1304         auto pf = panda_file::OpenPandaFile(filename_api12);
1305         EXPECT_NE(pf, nullptr);
1306 
1307         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1308         EXPECT_TRUE(class_id.IsValid());
1309 
1310         panda_file::ClassDataAccessor cda(*pf, class_id);
1311 
1312         EXPECT_FALSE(cda.GetSourceLang());
1313 
__anon3a1ef3231602(panda_file::MethodDataAccessor &mda) 1314         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1315             EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1316         });
1317     }
1318 }
1319 
1320 /**
1321  * @tc.name: assembly_emitter_test_023
1322  * @tc.desc: Verify the AsmEmitter::Emit function with different API version.
1323  * @tc.type: FUNC
1324  * @tc.require: issueNumber
1325  */
1326 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_023, TestSize.Level1)
1327 {
1328     Parser p;
1329     auto source = R"(
1330         .function any foo(any a0) <noimpl>
1331     )";
1332 
1333     auto res = p.Parse(source);
1334     EXPECT_EQ(p.ShowError().err, Error::ErrorType::ERR_NONE);
1335 
1336     // api 11
1337     {
1338         std::string descriptor;
1339         auto pf = AsmEmitter::Emit(res.Value(), nullptr, 11);
1340         EXPECT_NE(pf, nullptr);
1341 
1342         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1343         EXPECT_TRUE(class_id.IsValid());
1344 
1345         panda_file::ClassDataAccessor cda(*pf, class_id);
1346 
1347         EXPECT_FALSE(cda.GetSourceLang());
1348 
1349         const auto tagged = panda_file::Type(panda_file::Type::TypeId::TAGGED);
__anon3a1ef3231702(panda_file::MethodDataAccessor &mda) 1350         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1351             EXPECT_NE(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1352             panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
1353             EXPECT_EQ(tagged, pda.GetReturnType());
1354             EXPECT_EQ(1u, pda.GetNumArgs());
1355             EXPECT_EQ(tagged, pda.GetArgType(0));
1356         });
1357     }
1358 
1359     // api 12
1360     {
1361         std::string descriptor;
1362         auto pf = AsmEmitter::Emit(res.Value(), nullptr, 12);
1363         EXPECT_NE(pf, nullptr);
1364 
1365         auto class_id = pf->GetClassId(GetTypeDescriptor("_GLOBAL", &descriptor));
1366         EXPECT_TRUE(class_id.IsValid());
1367 
1368         panda_file::ClassDataAccessor cda(*pf, class_id);
1369 
1370         EXPECT_FALSE(cda.GetSourceLang());
1371 
__anon3a1ef3231802(panda_file::MethodDataAccessor &mda) 1372         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
1373             EXPECT_EQ(mda.GetProtoIdx(), panda_file::INVALID_INDEX_16);
1374         });
1375     }
1376 }
1377 
1378 /**
1379  * @tc.name: assembly_emitter_test_024
1380  * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1381  * @tc.type: FUNC
1382  * @tc.require: I9OWSZ
1383  */
1384 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_024, TestSize.Level1)
1385 {
1386     Parser p1;
1387     auto source1 = R"(
1388         .record Rec {
1389             u8 rec <value=0>
1390         }
1391     )";
1392     Parser p2;
1393     auto source2 = R"(
1394         .record Rec {
1395             u8 rec <value=0>
1396         }
1397     )";
1398     auto res1 = p1.Parse(source1);
1399     EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1400 
1401     auto res2 = p2.Parse(source2);
1402     EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1403 
1404     std::vector<Program *> progs;
1405     progs.push_back(&res1.Value());
1406     progs.push_back(&res2.Value());
1407     const std::string filename = "source.pa";;
1408     auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1409     EXPECT_TRUE(pf);
1410 }
1411 
1412 /**
1413  * @tc.name: assembly_emitter_test_025
1414  * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1415  * @tc.type: FUNC
1416  * @tc.require: I9OWSZ
1417  */
1418 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_025, TestSize.Level1)
1419 {
1420     Parser p1;
1421     auto source1 = R"(
1422         .record Rec {
1423             u8 rec <value=0>
1424         }
1425     )";
1426     Parser p2;
1427     auto source2 = R"(
1428         .record Rec {
1429             u8 rec <value=1>
1430         }
1431     )";
1432     auto res1 = p1.Parse(source1);
1433     EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1434 
1435     auto res2 = p2.Parse(source2);
1436     EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1437 
1438     std::vector<Program *> progs;
1439     progs.push_back(&res1.Value());
1440     progs.push_back(&res2.Value());
1441     const std::string filename = "source.pa";;
1442     auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1443     EXPECT_FALSE(pf);
1444     EXPECT_EQ(AsmEmitter::GetLastError(), "Field {Rec.rec} has different value.");
1445 }
1446 
1447 /**
1448  * @tc.name: assembly_emitter_test_026
1449  * @tc.desc: Verify the AsmEmitter::Emit Handle Same Record.
1450  * @tc.type: FUNC
1451  * @tc.require: I9OWSZ
1452  */
1453 HWTEST_F(AssemblyEmitterTest, assembly_emitter_test_026, TestSize.Level1)
1454 {
1455     Parser p1;
1456     auto source1 = R"(
1457         .record Rec {
1458             u8 rec1 <value=0>
1459         }
1460     )";
1461     Parser p2;
1462     auto source2 = R"(
1463         .record Rec {
1464             u8 rec2 <value=0>
1465         }
1466     )";
1467     auto res1 = p1.Parse(source1);
1468     EXPECT_EQ(p1.ShowError().err, Error::ErrorType::ERR_NONE);
1469 
1470     auto res2 = p2.Parse(source2);
1471     EXPECT_EQ(p2.ShowError().err, Error::ErrorType::ERR_NONE);
1472 
1473     std::vector<Program *> progs;
1474     progs.push_back(&res1.Value());
1475     progs.push_back(&res2.Value());
1476     const std::string filename = "source.pa";;
1477     auto pf = AsmEmitter::EmitPrograms(filename, progs, false);
1478     EXPECT_TRUE(pf);
1479 }
1480 }