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 }