• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "optimizer/ir/datatype.h"
17 #include "unit_test.h"
18 #include "optimizer/optimizations/cleanup.h"
19 #include "optimizer/optimizations/regalloc/reg_alloc_resolver.h"
20 
21 namespace panda::compiler {
22 class IrBuilderTest : public AsmTest {
23 public:
IrBuilderTest()24     IrBuilderTest()
25         : default_compiler_non_optimizing_(options.IsCompilerNonOptimizing()),
26           default_compiler_use_safe_point_(options.IsCompilerUseSafepoint())
27     {
28         options.SetCompilerNonOptimizing(false);
29         options.SetCompilerUseSafepoint(false);
30     }
31 
~IrBuilderTest()32     ~IrBuilderTest() override
33     {
34         options.SetCompilerNonOptimizing(default_compiler_non_optimizing_);
35         options.SetCompilerUseSafepoint(default_compiler_use_safe_point_);
36     }
37 
CheckSimple(std::string inst_name,DataType::Type data_type,std::string inst_type)38     void CheckSimple(std::string inst_name, DataType::Type data_type, std::string inst_type)
39     {
40         ASSERT(inst_name == "mov" || inst_name == "lda" || inst_name == "sta");
41         std::string curr_type;
42         if (data_type == DataType::Type::REFERENCE) {
43             curr_type = "i64[]";
44         } else {
45             curr_type = ToString(data_type);
46         }
47 
48         std::string source = ".function " + curr_type + " main(";
49         source += curr_type + " a0){\n";
50         if (inst_name == "mov") {
51             source += "mov" + inst_type + " v0, a0\n";
52             source += "lda" + inst_type + " v0\n";
53         } else if (inst_name == "lda") {
54             source += "lda" + inst_type + " a0\n";
55         } else if (inst_name == "sta") {
56             source += "lda" + inst_type + " a0\n";
57             source += "sta" + inst_type + " v0\n";
58             source += "lda" + inst_type + " v0\n";
59         } else {
60             UNREACHABLE();
61         }
62         source += "return" + inst_type + "\n";
63         source += "}";
64 
65         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
66 
67         auto graph = CreateGraphWithDefaultRuntime();
68         GRAPH(graph)
69         {
70             PARAMETER(0, 0);
71             INS(0).SetType(data_type);
72 
73             BASIC_BLOCK(2, -1)
74             {
75                 INST(1, Opcode::Return).Inputs(0);
76                 INS(1).SetType(data_type);
77             }
78         }
79         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
80     }
81 
CheckSimpleWithImm(std::string inst_name,DataType::Type data_type,std::string inst_type)82     void CheckSimpleWithImm(std::string inst_name, DataType::Type data_type, std::string inst_type)
83     {
84         ASSERT(inst_name == "mov" || inst_name == "fmov" || inst_name == "lda" || inst_name == "flda");
85         std::string curr_type = ToString(data_type);
86 
87         std::string source = ".function " + curr_type + " main(){\n";
88         if (inst_name == "mov") {
89             source += "movi" + inst_type + " v0, 0\n";
90             source += "lda" + inst_type + " v0\n";
91         } else if (inst_name == "fmov") {
92             source += "fmovi" + inst_type + " v0, 0.\n";
93             source += "lda" + inst_type + " v0\n";
94         } else if (inst_name == "lda") {
95             source += "ldai" + inst_type + " 0\n";
96         } else if (inst_name == "flda") {
97             source += "fldai" + inst_type + " 0.\n";
98         } else {
99             UNREACHABLE();
100         }
101         source += "return" + inst_type + "\n";
102         source += "}";
103 
104         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
105 
106         auto constant_type = GetCommonType(data_type);
107         auto graph = CreateGraphWithDefaultRuntime();
108 
109         GRAPH(graph)
110         {
111             CONSTANT(0, 0);
112             INS(0).SetType(constant_type);
113 
114             BASIC_BLOCK(2, -1)
115             {
116                 INST(1, Opcode::Return).Inputs(0);
117                 INS(1).SetType(data_type);
118             }
119         }
120         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
121     }
122 
CheckCmp(std::string inst_name,DataType::Type data_type,std::string inst_type)123     void CheckCmp(std::string inst_name, DataType::Type data_type, std::string inst_type)
124     {
125         ASSERT(inst_name == "cmp" || inst_name == "ucmp" || inst_name == "fcmpl" || inst_name == "fcmpg");
126         std::string curr_type;
127         if (data_type == DataType::Type::REFERENCE) {
128             curr_type = "i64[]";
129         } else {
130             curr_type = ToString(data_type);
131         }
132         std::string source = ".function i32 main(";
133         source += curr_type + " a0, ";
134         source += curr_type + " a1){\n";
135         source += "lda" + inst_type + " a0\n";
136         source += inst_name + inst_type + " a1\n";
137         source += "return\n";
138         source += "}";
139 
140         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
141 
142         auto graph = CreateGraphWithDefaultRuntime();
143         GRAPH(graph)
144         {
145             PARAMETER(0, 0);
146             INS(0).SetType(data_type);
147             PARAMETER(1, 1);
148             INS(1).SetType(data_type);
149 
150             BASIC_BLOCK(2, -1)
151             {
152                 INST(2, Opcode::Cmp).s32().Inputs(0, 1);
153                 INST(3, Opcode::Return).s32().Inputs(2);
154             }
155         }
156         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
157     }
158 
CheckFloatCmp(std::string inst_name,DataType::Type data_type,std::string inst_type,bool fcmpg)159     void CheckFloatCmp(std::string inst_name, DataType::Type data_type, std::string inst_type, bool fcmpg)
160     {
161         ASSERT(inst_name == "fcmpl" || inst_name == "fcmpg");
162         std::string curr_type = ToString(data_type);
163 
164         std::string source = ".function i32 main(";
165         source += curr_type + " a0, ";
166         source += curr_type + " a1){\n";
167         source += "lda" + inst_type + " a0\n";
168         source += inst_name + inst_type + " a1\n";
169         source += "return\n";
170         source += "}";
171 
172         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
173 
174         auto graph = CreateGraphWithDefaultRuntime();
175         GRAPH(graph)
176         {
177             PARAMETER(0, 0);
178             INS(0).SetType(data_type);
179             PARAMETER(1, 1);
180             INS(1).SetType(data_type);
181 
182             BASIC_BLOCK(2, -1)
183             {
184                 INST(2, Opcode::Cmp).s32().SrcType(data_type).Fcmpg(fcmpg).Inputs(0, 1);
185                 INST(3, Opcode::Return).s32().Inputs(2);
186             }
187         }
188         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
189     }
190 
191     template <bool is_obj>
CheckCondJump(ConditionCode CC)192     void CheckCondJump(ConditionCode CC)
193     {
194         std::string cmd;
195         switch (CC) {
196             case ConditionCode::CC_EQ:
197                 cmd = "jeq";
198                 break;
199             case ConditionCode::CC_NE:
200                 cmd = "jne";
201                 break;
202             case ConditionCode::CC_LT:
203                 cmd = "jlt";
204                 break;
205             case ConditionCode::CC_GT:
206                 cmd = "jgt";
207                 break;
208             case ConditionCode::CC_LE:
209                 cmd = "jle";
210                 break;
211             case ConditionCode::CC_GE:
212                 cmd = "jge";
213                 break;
214             default:
215                 UNREACHABLE();
216         }
217 
218         std::string inst_postfix = "";
219         std::string param_type = "i32";
220         auto type = DataType::INT32;
221         if constexpr (is_obj) {
222             inst_postfix = ".obj";
223             param_type = "i64[]";
224             type = DataType::REFERENCE;
225         }
226 
227         std::string source = ".function void main(";
228         source += param_type + " a0, " + param_type + " a1) {\n";
229         source += "lda" + inst_postfix + " a0\n";
230         source += cmd + inst_postfix + " a1, label\n";
231         source += "label:\n";
232         source += "return.void\n}";
233 
234         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
235 
236         auto graph = CreateGraphWithDefaultRuntime();
237         GRAPH(graph)
238         {
239             PARAMETER(0, 0);
240             INS(0).SetType(type);
241             PARAMETER(1, 1);
242             INS(1).SetType(type);
243 
244             BASIC_BLOCK(2, 3, 4)
245             {
246                 INST(2, Opcode::Compare).b().CC(CC).Inputs(0, 1);
247                 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
248             }
249             BASIC_BLOCK(3, 4) {}
250             BASIC_BLOCK(4, -1)
251             {
252                 INST(4, Opcode::ReturnVoid).v0id();
253             }
254         }
255         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
256     }
257 
258     template <bool is_obj>
CheckCondJumpWithZero(ConditionCode CC)259     void CheckCondJumpWithZero(ConditionCode CC)
260     {
261         std::string cmd;
262         switch (CC) {
263             case ConditionCode::CC_EQ:
264                 cmd = "jeqz";
265                 break;
266             case ConditionCode::CC_NE:
267                 cmd = "jnez";
268                 break;
269             case ConditionCode::CC_LT:
270                 cmd = "jltz";
271                 break;
272             case ConditionCode::CC_GT:
273                 cmd = "jgtz";
274                 break;
275             case ConditionCode::CC_LE:
276                 cmd = "jlez";
277                 break;
278             case ConditionCode::CC_GE:
279                 cmd = "jgez";
280                 break;
281             default:
282                 UNREACHABLE();
283         }
284 
285         std::string inst_postfix = "";
286         std::string param_type = "i32";
287         auto type = DataType::INT32;
288         if constexpr (is_obj) {
289             inst_postfix = ".obj";
290             param_type = "i64[]";
291             type = DataType::REFERENCE;
292         }
293 
294         std::string source = ".function void main(";
295         source += param_type + " a0) {\n";
296         source += "lda" + inst_postfix + " a0\n";
297         source += cmd + inst_postfix + " label\n";
298         source += "label:\n";
299         source += "return.void\n}";
300 
301         ASSERT_TRUE(ParseToGraph(source.c_str(), "main"));
302 
303         auto graph = CreateGraphWithDefaultRuntime();
304         GRAPH(graph)
305         {
306             PARAMETER(0, 0);
307             INS(0).SetType(type);
308             CONSTANT(2, 0).s64();
309 
310             BASIC_BLOCK(2, 3, 4)
311             {
312                 INST(1, Opcode::Compare).b().CC(CC).Inputs(0, 2);
313                 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(1);
314             }
315             BASIC_BLOCK(3, 4) {}
316             BASIC_BLOCK(4, -1)
317             {
318                 INST(4, Opcode::ReturnVoid).v0id();
319             }
320         }
321         ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
322     }
323 
324 private:
325     bool default_compiler_non_optimizing_;
326     bool default_compiler_use_safe_point_;
327 };
328 
TEST_F(IrBuilderTest,LoadArrayType64)329 TEST_F(IrBuilderTest, LoadArrayType64)
330 {
331     auto source = R"(
332     .function void main(i64[] a0, i32[] a1){
333         ldai 0
334         ldarr.64 a0
335         movi v0, 0
336         starr a1, v0
337         return.void
338     }
339     )";
340     ASSERT_TRUE(ParseToGraph(source, "main"));
341     auto graph = CreateGraphWithDefaultRuntime();
342     GRAPH(graph)
343     {
344         PARAMETER(0, 0).ref();
345         PARAMETER(1, 1).ref();
346         CONSTANT(2, 0).s64();
347 
348         BASIC_BLOCK(2, -1)
349         {
350             INST(3, Opcode::SaveState).Inputs(0, 1, 2).SrcVregs({1, 2, 3});
351             INST(4, Opcode::NullCheck).ref().Inputs(0, 3);
352             INST(5, Opcode::LenArray).s32().Inputs(4);
353             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 2, 3);
354             INST(7, Opcode::LoadArray).s64().Inputs(4, 6);
355             INST(8, Opcode::SaveState).Inputs(2, 0, 1, 7).SrcVregs({0, 1, 2, 3});
356             INST(9, Opcode::NullCheck).ref().Inputs(1, 8);
357             INST(10, Opcode::LenArray).s32().Inputs(9);
358             INST(11, Opcode::BoundsCheck).s32().Inputs(10, 2, 8);
359             INST(12, Opcode::StoreArray).s32().Inputs(9, 11, 7);
360             INST(13, Opcode::ReturnVoid).v0id();
361         }
362     }
363     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
364 }
365 
TEST_F(IrBuilderTest,IntrinsicPrintU64)366 TEST_F(IrBuilderTest, IntrinsicPrintU64)
367 {
368     auto source = R"(
369     .record IO <external>
370     .function void IO.printU64(u64 a0) <external>
371     .function void main(u64 a0){
372         ldai.64 23
373         sub2.64 a0
374         sta.64 a0
375         call.short IO.printU64, a0, a0
376         return.void
377     }
378     )";
379     ASSERT_TRUE(ParseToGraph(source, "main"));
380     auto graph = CreateGraphWithDefaultRuntime();
381     GRAPH(graph)
382     {
383         PARAMETER(1, 13).u64();
384         CONSTANT(0, 23).s64();
385 
386         BASIC_BLOCK(2, -1)
387         {
388             INST(2, Opcode::Sub).s64().Inputs(0, 1);
389             INST(4, Opcode::Intrinsic)
390                 .v0id()
391                 .Inputs({{DataType::UINT64, 2}})
392                 .SetFlag(compiler::inst_flags::NO_HOIST)
393                 .SetFlag(compiler::inst_flags::NO_DCE)
394                 .SetFlag(compiler::inst_flags::NO_CSE)
395                 .SetFlag(compiler::inst_flags::BARRIER)
396                 .ClearFlag(compiler::inst_flags::REQUIRE_STATE);
397             INST(5, Opcode::ReturnVoid).v0id();
398         }
399     }
400     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
401 }
402 
TEST_F(IrBuilderTest,BuiltinIsInf)403 TEST_F(IrBuilderTest, BuiltinIsInf)
404 {
405     auto source = R"(
406         .record Double <external>
407         .function u1 Double.isInfinite(f64 a0) <external>
408         .function u1 main(f64 a0){
409             call.short Double.isInfinite, a0
410             return
411         }
412         )";
413     ASSERT_TRUE(ParseToGraph(source, "main"));
414     auto graph = CreateGraphWithDefaultRuntime();
415     GRAPH(graph)
416     {
417         PARAMETER(0, 0).f64();
418 
419         BASIC_BLOCK(2, -1)
420         {
421             INST(1, Opcode::Intrinsic)
422                 .b()
423                 .Inputs({{DataType::FLOAT64, 0}})
424                 .ClearFlag(compiler::inst_flags::REQUIRE_STATE);
425             INST(2, Opcode::Return).b().Inputs(1);
426         }
427     }
428     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
429 }
430 
TEST_F(IrBuilderTest,IntrinsicAbs)431 TEST_F(IrBuilderTest, IntrinsicAbs)
432 {
433     auto source = R"(
434     .record Math <external>
435     .function f64 Math.absF64(f64 a0) <external>
436     .function f64 main(f64 a0){
437         fldai.64 1.23
438         fsub2.64 a0
439         sta.64 v5
440         call.short Math.absF64, v5, v5
441         return.64
442     }
443     )";
444     ASSERT_TRUE(ParseToGraph(source, "main"));
445     auto graph = CreateGraphWithDefaultRuntime();
446     GRAPH(graph)
447     {
448         PARAMETER(1, 13).f64();
449         CONSTANT(0, 1.23).f64();
450 
451         BASIC_BLOCK(2, -1)
452         {
453             INST(2, Opcode::Sub).f64().Inputs(0, 1);
454             INST(3, Opcode::Abs).f64().Inputs(2);
455             INST(4, Opcode::Return).f64().Inputs(3);
456         }
457     }
458     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
459 }
460 
TEST_F(IrBuilderTest,IntrinsicMathSqrt)461 TEST_F(IrBuilderTest, IntrinsicMathSqrt)
462 {
463     auto source = R"(
464     .record Math <external>
465     .function f64 Math.sqrt(f64 a0) <external>
466     .function f64 main(f64 a0){
467         fldai.64 3.14
468         fsub2.64 a0
469         sta.64 v1
470         call.short Math.sqrt, v1
471         return.64
472     }
473     )";
474     ASSERT_TRUE(ParseToGraph(source, "main"));
475     auto graph = CreateGraphWithDefaultRuntime();
476     GRAPH(graph)
477     {
478         PARAMETER(1, 0).f64();
479         CONSTANT(0, 3.14).f64();
480 
481         BASIC_BLOCK(2, -1)
482         {
483             INST(2, Opcode::Sub).f64().Inputs(0, 1);
484             INST(3, Opcode::Sqrt).f64().Inputs(2);
485             INST(4, Opcode::Return).f64().Inputs(3);
486         }
487     }
488     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
489 }
490 
TEST_F(IrBuilderTest,IntrinsicMathFsqrt)491 TEST_F(IrBuilderTest, IntrinsicMathFsqrt)
492 {
493     auto source = R"(
494     .record Math <external>
495     .function f32 Math.fsqrt(f32 a0) <external>
496     .function f32 main(f32 a0){
497         fldai 3.14
498         fsub2 a0
499         sta v1
500         call.short Math.fsqrt, v1
501         return
502     }
503     )";
504     ASSERT_TRUE(ParseToGraph(source, "main"));
505     auto graph = CreateGraphWithDefaultRuntime();
506     GRAPH(graph)
507     {
508         PARAMETER(1, 0).f32();
509         CONSTANT(0, 3.14f).f32();
510 
511         BASIC_BLOCK(2, -1)
512         {
513             INST(2, Opcode::Sub).f32().Inputs(0, 1);
514             INST(3, Opcode::Sqrt).f32().Inputs(2);
515             INST(4, Opcode::Return).f32().Inputs(3);
516         }
517     }
518     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
519 }
520 
TEST_F(IrBuilderTest,IntrinsicMathMinI32)521 TEST_F(IrBuilderTest, IntrinsicMathMinI32)
522 {
523     auto source = R"(
524     .record Math <external>
525     .function i32 Math.minI32(i32 a0, i32 a1) <external>
526     .function i32 main(i32 a0, i32 a1) {
527         call.short Math.minI32, a0, a1
528         return
529     }
530     )";
531     ASSERT_TRUE(ParseToGraph(source, "main"));
532     auto graph = CreateGraphWithDefaultRuntime();
533     GRAPH(graph)
534     {
535         PARAMETER(0, 0).s32();
536         PARAMETER(1, 1).s32();
537         BASIC_BLOCK(2, -1)
538         {
539             INST(2, Opcode::Min).s32().Inputs(0, 1);
540             INST(3, Opcode::Return).s32().Inputs(2);
541         }
542     }
543 
544     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
545 }
546 
TEST_F(IrBuilderTest,IntrinsicMathMinI64)547 TEST_F(IrBuilderTest, IntrinsicMathMinI64)
548 {
549     auto source = R"(
550     .record Math <external>
551     .function i64 Math.minI64(i64 a0, i64 a1) <external>
552     .function i64 main(i64 a0, i64 a1) {
553         call.short Math.minI64, a0, a1
554         return
555     }
556     )";
557     ASSERT_TRUE(ParseToGraph(source, "main"));
558     auto graph = CreateGraphWithDefaultRuntime();
559     GRAPH(graph)
560     {
561         PARAMETER(0, 0).s64();
562         PARAMETER(1, 1).s64();
563         BASIC_BLOCK(2, -1)
564         {
565             INST(2, Opcode::Min).s64().Inputs(0, 1);
566             INST(3, Opcode::Return).s64().Inputs(2);
567         }
568     }
569 
570     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
571 }
572 
TEST_F(IrBuilderTest,IntrinsicMathMinF64)573 TEST_F(IrBuilderTest, IntrinsicMathMinF64)
574 {
575     auto source = R"(
576     .record Math <external>
577     .function f64 Math.minF64(f64 a0, f64 a1) <external>
578     .function f64 main(f64 a0, f64 a1) {
579         call.short Math.minF64, a0, a1
580         return
581     }
582     )";
583     ASSERT_TRUE(ParseToGraph(source, "main"));
584     auto graph = CreateGraphWithDefaultRuntime();
585     GRAPH(graph)
586     {
587         PARAMETER(0, 0).f64();
588         PARAMETER(1, 1).f64();
589         BASIC_BLOCK(2, -1)
590         {
591             INST(2, Opcode::Min).f64().Inputs(0, 1);
592             INST(3, Opcode::Return).f64().Inputs(2);
593         }
594     }
595 
596     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
597 }
598 
TEST_F(IrBuilderTest,IntrinsicMathMinF32)599 TEST_F(IrBuilderTest, IntrinsicMathMinF32)
600 {
601     auto source = R"(
602     .record Math <external>
603     .function f32 Math.minF32(f32 a0, f32 a1) <external>
604     .function f32 main(f32 a0, f32 a1) {
605         call.short Math.minF32, a0, a1
606         return
607     }
608     )";
609     ASSERT_TRUE(ParseToGraph(source, "main"));
610     auto graph = CreateGraphWithDefaultRuntime();
611     GRAPH(graph)
612     {
613         PARAMETER(0, 0).f32();
614         PARAMETER(1, 1).f32();
615         BASIC_BLOCK(2, -1)
616         {
617             INST(4, Opcode::Min).f32().Inputs(0, 1);
618             INST(6, Opcode::Return).f32().Inputs(4);
619         }
620     }
621 
622     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
623 }
624 
TEST_F(IrBuilderTest,IntrinsicMathMaxI32)625 TEST_F(IrBuilderTest, IntrinsicMathMaxI32)
626 {
627     auto source = R"(
628     .record Math <external>
629     .function i32 Math.maxI32(i32 a0, i32 a1) <external>
630     .function i32 main(i32 a0, i32 a1) {
631         call.short Math.maxI32, a0, a1
632         return
633     }
634     )";
635     ASSERT_TRUE(ParseToGraph(source, "main"));
636     auto graph = CreateGraphWithDefaultRuntime();
637     GRAPH(graph)
638     {
639         PARAMETER(0, 0).s32();
640         PARAMETER(1, 1).s32();
641         BASIC_BLOCK(2, -1)
642         {
643             INST(2, Opcode::Max).s32().Inputs(0, 1);
644             INST(3, Opcode::Return).s32().Inputs(2);
645         }
646     }
647 
648     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
649 }
650 
TEST_F(IrBuilderTest,IntrinsicMathMaxI64)651 TEST_F(IrBuilderTest, IntrinsicMathMaxI64)
652 {
653     auto source = R"(
654     .record Math <external>
655     .function i64 Math.maxI64(i64 a0, i64 a1) <external>
656     .function i64 main(i64 a0, i64 a1) {
657         call.short Math.maxI64, a0, a1
658         return
659     }
660     )";
661     ASSERT_TRUE(ParseToGraph(source, "main"));
662     auto graph = CreateGraphWithDefaultRuntime();
663     GRAPH(graph)
664     {
665         PARAMETER(0, 0).s64();
666         PARAMETER(1, 1).s64();
667         BASIC_BLOCK(2, -1)
668         {
669             INST(2, Opcode::Max).s64().Inputs(0, 1);
670             INST(3, Opcode::Return).s64().Inputs(2);
671         }
672     }
673 
674     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
675 }
676 
TEST_F(IrBuilderTest,IntrinsicMathMaxF64)677 TEST_F(IrBuilderTest, IntrinsicMathMaxF64)
678 {
679     auto source = R"(
680     .record Math <external>
681     .function f64 Math.maxF64(f64 a0, f64 a1) <external>
682     .function f64 main(f64 a0, f64 a1) {
683         call.short Math.maxF64, a0, a1
684         return
685     }
686     )";
687     ASSERT_TRUE(ParseToGraph(source, "main"));
688     auto graph = CreateGraphWithDefaultRuntime();
689     GRAPH(graph)
690     {
691         PARAMETER(0, 0).f64();
692         PARAMETER(1, 1).f64();
693         BASIC_BLOCK(2, -1)
694         {
695             INST(2, Opcode::Max).f64().Inputs(0, 1);
696             INST(3, Opcode::Return).f64().Inputs(2);
697         }
698     }
699 
700     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
701 }
702 
TEST_F(IrBuilderTest,IntrinsicMathMaxF32)703 TEST_F(IrBuilderTest, IntrinsicMathMaxF32)
704 {
705     auto source = R"(
706     .record Math <external>
707     .function f32 Math.maxF32(f32 a0, f32 a1) <external>
708     .function f32 main(f32 a0, f32 a1) {
709         call.short Math.maxF32, a0, a1
710         return
711     }
712     )";
713     ASSERT_TRUE(ParseToGraph(source, "main"));
714     auto graph = CreateGraphWithDefaultRuntime();
715     GRAPH(graph)
716     {
717         PARAMETER(0, 0).f32();
718         PARAMETER(1, 1).f32();
719         BASIC_BLOCK(2, -1)
720         {
721             INST(4, Opcode::Max).f32().Inputs(0, 1);
722             INST(6, Opcode::Return).f32().Inputs(4);
723         }
724     }
725 
726     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
727 }
728 
TEST_F(IrBuilderTest,NoCheckForFloatDiv)729 TEST_F(IrBuilderTest, NoCheckForFloatDiv)
730 {
731     auto source = R"(
732     .function f64 main(f64 a0){
733         fldai.64 23.0
734         fdiv2.64 a0
735         return
736     }
737     )";
738     ASSERT_TRUE(ParseToGraph(source, "main"));
739     auto graph = CreateGraphWithDefaultRuntime();
740     GRAPH(graph)
741     {
742         PARAMETER(1, 0).f64();
743         CONSTANT(0, 23.0).f64();
744 
745         BASIC_BLOCK(2, -1)
746         {
747             INST(2, Opcode::Div).f64().Inputs(0, 1);
748             INST(3, Opcode::Return).f64().Inputs(2);
749         }
750     }
751     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
752 }
753 
TEST_F(IrBuilderTest,MultipleThrow)754 TEST_F(IrBuilderTest, MultipleThrow)
755 {
756     auto source = R"(
757     .record array <external>
758     .function void main(array a0){
759         throw a0
760         throw a0
761         throw a0
762         return.void
763     }
764     )";
765     ASSERT_TRUE(ParseToGraph(source, "main"));
766     auto graph = CreateGraphWithDefaultRuntime();
767     GRAPH(graph)
768     {
769         PARAMETER(0, 0).ref();
770 
771         BASIC_BLOCK(2, -1)
772         {
773             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
774             INST(2, Opcode::Throw).Inputs(0, 1);
775         }
776     }
777     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
778 }
779 
780 // Checks if not dominate inputs are removed from SaveStateInst
TEST_F(IrBuilderTest,RemoveNotDominateInputs)781 TEST_F(IrBuilderTest, RemoveNotDominateInputs)
782 {
783     auto source = R"(
784     .function void main(i32 a0, i32 a1) {
785         lda a0
786         jlt a1, label
787 
788         sub2 a1
789         sta v0
790         call foo1, v0
791     label:
792         call foo2
793         return.void
794     }
795 
796     .function i64 foo1(i32 a0) {
797         ldai.64 1
798         return.64
799     }
800 
801     .function i64 foo2() {
802         ldai.64 1
803         return.64
804     }
805     )";
806 
807     ASSERT_TRUE(ParseToGraph(source, "main"));
808 
809     auto graph = CreateGraphWithDefaultRuntime();
810     GRAPH(graph)
811     {
812         PARAMETER(0, 0).s32();
813         PARAMETER(1, 1).s32();
814         BASIC_BLOCK(2, 3, 4)
815         {
816             INST(2, Opcode::Compare).b().SrcType(DataType::INT32).CC(CC_LT).Inputs(0, 1);
817             INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
818         }
819         BASIC_BLOCK(3, 4)
820         {
821             INST(4, Opcode::Sub).s32().Inputs(0, 1);
822             INST(5, Opcode::SaveState).Inputs(4, 0, 1, 4).SrcVregs({0, 1, 2, 3});
823             INST(6, Opcode::CallStatic).s64().Inputs({{DataType::INT32, 4}, {DataType::NO_TYPE, 5}});
824         }
825         BASIC_BLOCK(4, -1)
826         {
827             INST(7, Opcode::SaveState).Inputs(1, 0).SrcVregs({2, 1});
828             INST(8, Opcode::CallStatic).s64().Inputs({{DataType::NO_TYPE, 7}});
829             INST(9, Opcode::ReturnVoid).v0id();
830         }
831     }
832     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
833 }
834 
835 // Checks the build of the mov instruction with integer parameters
TEST_F(IrBuilderTest,MovInt)836 TEST_F(IrBuilderTest, MovInt)
837 {
838     DataType::Type data_type = DataType::Type::INT32;
839     std::string inst_type = "";
840     CheckSimple("mov", data_type, inst_type);
841 }
842 
843 // Checks the build of the mov instruction with real parameters
TEST_F(IrBuilderTest,MovReal)844 TEST_F(IrBuilderTest, MovReal)
845 {
846     DataType::Type data_type = DataType::Type::FLOAT32;
847     std::string inst_type = "";
848     CheckSimple("mov", data_type, inst_type);
849 }
850 
851 // Checks the build of the mov.64 instruction with integer parameters
TEST_F(IrBuilderTest,Mov64Int)852 TEST_F(IrBuilderTest, Mov64Int)
853 {
854     DataType::Type data_type = DataType::Type::INT64;
855     std::string inst_type = ".64";
856     CheckSimple("mov", data_type, inst_type);
857 }
858 
859 // Checks the build of the mov.64 instruction with real parameters
TEST_F(IrBuilderTest,Mov64Real)860 TEST_F(IrBuilderTest, Mov64Real)
861 {
862     DataType::Type data_type = DataType::Type::FLOAT64;
863     std::string inst_type = ".64";
864     CheckSimple("mov", data_type, inst_type);
865 }
866 
867 // Checks the build of the mov.obj instruction
TEST_F(IrBuilderTest,MovObj)868 TEST_F(IrBuilderTest, MovObj)
869 {
870     DataType::Type data_type = DataType::Type::REFERENCE;
871     std::string inst_type = ".obj";
872     CheckSimple("mov", data_type, inst_type);
873 }
874 
875 // Checks the build of the mov.null instruction
TEST_F(IrBuilderTest,MovNull)876 TEST_F(IrBuilderTest, MovNull)
877 {
878     auto source = R"(
879         .record panda.String <external>
880         .function panda.String main(){
881             mov.null v0
882             lda v0
883             return
884         }
885         )";
886     ASSERT_TRUE(ParseToGraph(source, "main"));
887 
888     auto graph = CreateGraphWithDefaultRuntime();
889     GRAPH(graph)
890     {
891         CONSTANT(0, nullptr);
892         BASIC_BLOCK(2, -1)
893         {
894             INST(1, Opcode::Return).ref().Inputs(0);
895         }
896     }
897     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
898 }
899 
900 // Checks the build of the movi instruction with integer parameters
TEST_F(IrBuilderTest,MoviInt)901 TEST_F(IrBuilderTest, MoviInt)
902 {
903     DataType::Type data_type = DataType::Type::INT32;
904     std::string inst_type = "";
905     CheckSimpleWithImm("mov", data_type, inst_type);
906 }
907 
908 // Checks the build of the fmovi instruction with real parameters
TEST_F(IrBuilderTest,FmoviReal)909 TEST_F(IrBuilderTest, FmoviReal)
910 {
911     DataType::Type data_type = DataType::Type::FLOAT32;
912     std::string inst_type = "";
913     CheckSimpleWithImm("fmov", data_type, inst_type);
914 }
915 
916 // Checks the build of the movi.64 instruction with integer parameters
TEST_F(IrBuilderTest,Movi64Int)917 TEST_F(IrBuilderTest, Movi64Int)
918 {
919     DataType::Type data_type = DataType::Type::INT64;
920     std::string inst_type = ".64";
921     CheckSimpleWithImm("mov", data_type, inst_type);
922 }
923 
924 // Checks the build of the movi.64 instruction with real parameters
TEST_F(IrBuilderTest,Fmovi64Real)925 TEST_F(IrBuilderTest, Fmovi64Real)
926 {
927     DataType::Type data_type = DataType::Type::FLOAT64;
928     std::string inst_type = ".64";
929     CheckSimpleWithImm("fmov", data_type, inst_type);
930 }
931 
932 // Checks the build of the lda instruction with integer parameters
TEST_F(IrBuilderTest,LdaInt)933 TEST_F(IrBuilderTest, LdaInt)
934 {
935     DataType::Type data_type = DataType::Type::INT32;
936     std::string inst_type = "";
937     CheckSimple("lda", data_type, inst_type);
938 }
939 
940 // Checks the build of the lda instruction with real parameters
TEST_F(IrBuilderTest,LdaReal)941 TEST_F(IrBuilderTest, LdaReal)
942 {
943     DataType::Type data_type = DataType::Type::FLOAT32;
944     std::string inst_type = "";
945     CheckSimple("lda", data_type, inst_type);
946 }
947 
948 // Checks the build of the lda.64 instruction with integer parameters
TEST_F(IrBuilderTest,Lda64Int)949 TEST_F(IrBuilderTest, Lda64Int)
950 {
951     DataType::Type data_type = DataType::Type::INT64;
952     std::string inst_type = ".64";
953     CheckSimple("lda", data_type, inst_type);
954 }
955 
956 // Checks the build of the lda.64 instruction with real parameters
TEST_F(IrBuilderTest,Lda64Real)957 TEST_F(IrBuilderTest, Lda64Real)
958 {
959     DataType::Type data_type = DataType::Type::FLOAT64;
960     std::string inst_type = ".64";
961     CheckSimple("lda", data_type, inst_type);
962 }
963 
964 // Checks the build of the lda.obj instruction
TEST_F(IrBuilderTest,LdaObj)965 TEST_F(IrBuilderTest, LdaObj)
966 {
967     DataType::Type data_type = DataType::Type::REFERENCE;
968     std::string inst_type = ".obj";
969     CheckSimple("lda", data_type, inst_type);
970 }
971 
972 // Checks the build of the lda.obj instruction
TEST_F(IrBuilderTest,LdaNull)973 TEST_F(IrBuilderTest, LdaNull)
974 {
975     auto source = R"(
976         .record panda.String <external>
977         .function panda.String main(){
978             lda.null
979             return.obj
980         }
981         )";
982     ASSERT_TRUE(ParseToGraph(source, "main"));
983 
984     auto graph = CreateGraphWithDefaultRuntime();
985     GRAPH(graph)
986     {
987         CONSTANT(0, nullptr);
988         BASIC_BLOCK(2, -1)
989         {
990             INST(1, Opcode::Return).ref().Inputs(0);
991         }
992     }
993     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
994 }
995 
996 // Checks the build of the ldai instruction with integer parameters
TEST_F(IrBuilderTest,LdaiInt)997 TEST_F(IrBuilderTest, LdaiInt)
998 {
999     DataType::Type data_type = DataType::Type::INT32;
1000     std::string inst_type = "";
1001     CheckSimpleWithImm("lda", data_type, inst_type);
1002 }
1003 
1004 // Checks the build of the ldai instruction with real parameters
TEST_F(IrBuilderTest,FldaiReal)1005 TEST_F(IrBuilderTest, FldaiReal)
1006 {
1007     DataType::Type data_type = DataType::Type::FLOAT32;
1008     std::string inst_type = "";
1009     CheckSimpleWithImm("flda", data_type, inst_type);
1010 }
1011 
1012 // Checks the build of the ldai.64 instruction with integer parameters
TEST_F(IrBuilderTest,Ldai64Int)1013 TEST_F(IrBuilderTest, Ldai64Int)
1014 {
1015     DataType::Type data_type = DataType::Type::INT64;
1016     std::string inst_type = ".64";
1017     CheckSimpleWithImm("lda", data_type, inst_type);
1018 }
1019 
1020 // Checks the build of the ldai.64 instruction with real parameters
TEST_F(IrBuilderTest,Fldai64Real)1021 TEST_F(IrBuilderTest, Fldai64Real)
1022 {
1023     DataType::Type data_type = DataType::Type::FLOAT64;
1024     std::string inst_type = ".64";
1025     CheckSimpleWithImm("flda", data_type, inst_type);
1026 }
1027 
1028 // Checks the build of the lda.str instruction
TEST_F(IrBuilderTest,LdaStr)1029 TEST_F(IrBuilderTest, LdaStr)
1030 {
1031     auto source = R"(
1032     .record panda.String <external>
1033     .function panda.String main(){
1034         lda.str "lda_test"
1035         return.obj
1036     }
1037     )";
1038     ASSERT_TRUE(ParseToGraph(source, "main"));
1039 
1040     auto graph = CreateGraphWithDefaultRuntime();
1041     GRAPH(graph)
1042     {
1043         BASIC_BLOCK(2, -1)
1044         {
1045             INST(2, Opcode::SaveState).NoVregs();
1046             INST(0, Opcode::LoadString).ref().Inputs(2);
1047             INST(1, Opcode::Return).ref().Inputs(0);
1048         }
1049     }
1050     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1051 }
1052 
1053 // Checks the build of the lda.type instruction
TEST_F(IrBuilderTest,LdaType)1054 TEST_F(IrBuilderTest, LdaType)
1055 {
1056     auto source = R"(
1057     .record R {}
1058     .function R main(){
1059         lda.type R
1060         return.obj
1061     }
1062     )";
1063     ASSERT_TRUE(ParseToGraph(source, "main"));
1064 
1065     auto graph = CreateGraphWithDefaultRuntime();
1066     GRAPH(graph)
1067     {
1068         BASIC_BLOCK(2, -1)
1069         {
1070             INST(2, Opcode::SaveState).NoVregs();
1071             INST(0, Opcode::LoadType).ref().Inputs(2);
1072             INST(1, Opcode::Return).ref().Inputs(0);
1073         }
1074     }
1075     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1076 }
1077 
1078 // Checks the build of the sta instruction with integer parameters
TEST_F(IrBuilderTest,StaInt)1079 TEST_F(IrBuilderTest, StaInt)
1080 {
1081     DataType::Type data_type = DataType::Type::INT32;
1082     std::string inst_type = "";
1083     CheckSimple("sta", data_type, inst_type);
1084 }
1085 
1086 // Checks the build of the sta instruction with real parameters
TEST_F(IrBuilderTest,StaReal)1087 TEST_F(IrBuilderTest, StaReal)
1088 {
1089     DataType::Type data_type = DataType::Type::FLOAT32;
1090     std::string inst_type = "";
1091     CheckSimple("sta", data_type, inst_type);
1092 }
1093 
1094 // Checks the build of the sta.64 instruction with integer parameters
TEST_F(IrBuilderTest,Sta64Int)1095 TEST_F(IrBuilderTest, Sta64Int)
1096 {
1097     DataType::Type data_type = DataType::Type::INT64;
1098     std::string inst_type = ".64";
1099     CheckSimple("sta", data_type, inst_type);
1100 }
1101 
1102 // Checks the build of the sta.64 instruction with real parameters
TEST_F(IrBuilderTest,Sta64Real)1103 TEST_F(IrBuilderTest, Sta64Real)
1104 {
1105     DataType::Type data_type = DataType::Type::FLOAT64;
1106     std::string inst_type = ".64";
1107     CheckSimple("sta", data_type, inst_type);
1108 }
1109 
1110 // Checks the build of the sta.obj instruction
TEST_F(IrBuilderTest,StaObj)1111 TEST_F(IrBuilderTest, StaObj)
1112 {
1113     DataType::Type data_type = DataType::Type::REFERENCE;
1114     std::string inst_type = ".obj";
1115     CheckSimple("sta", data_type, inst_type);
1116 }
1117 
1118 // Checks the build of the jmp instruction
TEST_F(IrBuilderTest,Jmp)1119 TEST_F(IrBuilderTest, Jmp)
1120 {
1121     auto source = R"(
1122     .function void main(){
1123         jmp label
1124     label:
1125         return.void
1126     }
1127     )";
1128     ASSERT_TRUE(ParseToGraph(source, "main"));
1129 
1130     auto graph = CreateGraphWithDefaultRuntime();
1131     GRAPH(graph)
1132     {
1133         BASIC_BLOCK(2, 3) {}
1134         BASIC_BLOCK(3, -1)
1135         {
1136             INST(1, Opcode::ReturnVoid).v0id();
1137         }
1138     }
1139     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1140 }
1141 
1142 // Checks the build of the cmp.64 instruction
TEST_F(IrBuilderTest,Cmp64)1143 TEST_F(IrBuilderTest, Cmp64)
1144 {
1145     DataType::Type data_type = DataType::Type::INT64;
1146     std::string inst_type = ".64";
1147     CheckCmp("cmp", data_type, inst_type);
1148 }
1149 
1150 // Checks the build of the ucmp instruction
TEST_F(IrBuilderTest,Ucmp)1151 TEST_F(IrBuilderTest, Ucmp)
1152 {
1153     DataType::Type data_type = DataType::Type::UINT32;
1154     std::string inst_type = "";
1155     CheckCmp("ucmp", data_type, inst_type);
1156 }
1157 
1158 // Checks the build of the ucmp.64 instruction
TEST_F(IrBuilderTest,Ucmp64)1159 TEST_F(IrBuilderTest, Ucmp64)
1160 {
1161     DataType::Type data_type = DataType::Type::UINT64;
1162     std::string inst_type = ".64";
1163     CheckCmp("ucmp", data_type, inst_type);
1164 }
1165 
1166 // Checks the build of the fcmpl instruction
TEST_F(IrBuilderTest,Fcmpl)1167 TEST_F(IrBuilderTest, Fcmpl)
1168 {
1169     DataType::Type data_type = DataType::Type::FLOAT32;
1170     std::string inst_type = "";
1171     CheckFloatCmp("fcmpl", data_type, inst_type, false);
1172 }
1173 
1174 // Checks the build of the fcmpl.64 instruction
TEST_F(IrBuilderTest,Fcmpl64)1175 TEST_F(IrBuilderTest, Fcmpl64)
1176 {
1177     DataType::Type data_type = DataType::Type::FLOAT64;
1178     std::string inst_type = ".64";
1179     CheckFloatCmp("fcmpl", data_type, inst_type, false);
1180 }
1181 
1182 // Checks the build of the fcmpg instruction
TEST_F(IrBuilderTest,Fcmpg)1183 TEST_F(IrBuilderTest, Fcmpg)
1184 {
1185     DataType::Type data_type = DataType::Type::FLOAT32;
1186     std::string inst_type = "";
1187     CheckFloatCmp("fcmpg", data_type, inst_type, true);
1188 }
1189 
1190 // Checks the build of the fcmpg.64 instruction
TEST_F(IrBuilderTest,Fcmpg64)1191 TEST_F(IrBuilderTest, Fcmpg64)
1192 {
1193     DataType::Type data_type = DataType::Type::FLOAT64;
1194     std::string inst_type = ".64";
1195     CheckFloatCmp("fcmpg", data_type, inst_type, true);
1196 }
1197 
1198 // Checks the build of the jeqz.obj instruction
TEST_F(IrBuilderTest,JeqzObj)1199 TEST_F(IrBuilderTest, JeqzObj)
1200 {
1201     CheckCondJumpWithZero<true>(ConditionCode::CC_EQ);
1202 }
1203 
1204 // Checks the build of the jnez.obj instruction
TEST_F(IrBuilderTest,JnezObj)1205 TEST_F(IrBuilderTest, JnezObj)
1206 {
1207     CheckCondJumpWithZero<true>(ConditionCode::CC_NE);
1208 }
1209 
1210 // Checks the build of the jeqz instruction
TEST_F(IrBuilderTest,Jeqz)1211 TEST_F(IrBuilderTest, Jeqz)
1212 {
1213     CheckCondJumpWithZero<false>(ConditionCode::CC_EQ);
1214 }
1215 
1216 // Checks the build of the jnez instruction
TEST_F(IrBuilderTest,Jnez)1217 TEST_F(IrBuilderTest, Jnez)
1218 {
1219     CheckCondJumpWithZero<false>(ConditionCode::CC_NE);
1220 }
1221 
1222 // Checks the build of the jltz instruction
TEST_F(IrBuilderTest,Jltz)1223 TEST_F(IrBuilderTest, Jltz)
1224 {
1225     CheckCondJumpWithZero<false>(ConditionCode::CC_LT);
1226 }
1227 
1228 // Checks the build of the jgtz instruction
TEST_F(IrBuilderTest,Jgtz)1229 TEST_F(IrBuilderTest, Jgtz)
1230 {
1231     CheckCondJumpWithZero<false>(ConditionCode::CC_GT);
1232 }
1233 
1234 // Checks the build of the jlez instruction
TEST_F(IrBuilderTest,Jlez)1235 TEST_F(IrBuilderTest, Jlez)
1236 {
1237     CheckCondJumpWithZero<false>(ConditionCode::CC_LE);
1238 }
1239 
1240 // Checks the build of the jgez instruction
TEST_F(IrBuilderTest,Jgez)1241 TEST_F(IrBuilderTest, Jgez)
1242 {
1243     CheckCondJumpWithZero<false>(ConditionCode::CC_GE);
1244 }
1245 
1246 // Checks the build of the jeq.obj instruction
TEST_F(IrBuilderTest,JeqObj)1247 TEST_F(IrBuilderTest, JeqObj)
1248 {
1249     CheckCondJump<true>(ConditionCode::CC_EQ);
1250 }
1251 
1252 // Checks the build of the jne.obj instruction
TEST_F(IrBuilderTest,JneObj)1253 TEST_F(IrBuilderTest, JneObj)
1254 {
1255     CheckCondJump<true>(ConditionCode::CC_NE);
1256 }
1257 
1258 // Checks the build of the jeq instruction
TEST_F(IrBuilderTest,Jeq)1259 TEST_F(IrBuilderTest, Jeq)
1260 {
1261     CheckCondJump<false>(ConditionCode::CC_EQ);
1262 }
1263 
1264 // Checks the build of the jne instruction
TEST_F(IrBuilderTest,Jne)1265 TEST_F(IrBuilderTest, Jne)
1266 {
1267     CheckCondJump<false>(ConditionCode::CC_NE);
1268 }
1269 
1270 // Checks the build of the jlt instruction
TEST_F(IrBuilderTest,Jlt)1271 TEST_F(IrBuilderTest, Jlt)
1272 {
1273     CheckCondJump<false>(ConditionCode::CC_LT);
1274 }
1275 
1276 // Checks the build of the jgt instruction
TEST_F(IrBuilderTest,Jgt)1277 TEST_F(IrBuilderTest, Jgt)
1278 {
1279     CheckCondJump<false>(ConditionCode::CC_GT);
1280 }
1281 
1282 // Checks the build of the jle instruction
TEST_F(IrBuilderTest,Jle)1283 TEST_F(IrBuilderTest, Jle)
1284 {
1285     CheckCondJump<false>(ConditionCode::CC_LE);
1286 }
1287 
1288 // Checks the build of the jge instruction
TEST_F(IrBuilderTest,Jge)1289 TEST_F(IrBuilderTest, Jge)
1290 {
1291     CheckCondJump<false>(ConditionCode::CC_GE);
1292 }
1293 
1294 // Checks the build of the fadd2 instruction
TEST_F(IrBuilderTest,Fadd2)1295 TEST_F(IrBuilderTest, Fadd2)
1296 {
1297     auto source = R"(
1298     .function f32 main(f32 a0, f32 a1){
1299         lda a0
1300         fadd2 a1
1301         return
1302     }
1303     )";
1304     ASSERT_TRUE(ParseToGraph(source, "main"));
1305     auto graph = CreateGraphWithDefaultRuntime();
1306     GRAPH(graph)
1307     {
1308         PARAMETER(0, 0).f32();
1309         PARAMETER(1, 1).f32();
1310 
1311         BASIC_BLOCK(2, -1)
1312         {
1313             INST(2, Opcode::Add).f32().Inputs(0, 1);
1314             INST(3, Opcode::Return).f32().Inputs(2);
1315         }
1316     }
1317     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1318 }
1319 
1320 // Checks the build of the fadd2.64 instruction
TEST_F(IrBuilderTest,Fadd2_64)1321 TEST_F(IrBuilderTest, Fadd2_64)
1322 {
1323     auto source = R"(
1324     .function f64 main(f64 a0, f64 a1){
1325         lda.64 a0
1326         fadd2.64 a1
1327         return.64
1328     }
1329     )";
1330     ASSERT_TRUE(ParseToGraph(source, "main"));
1331     auto graph = CreateGraphWithDefaultRuntime();
1332     GRAPH(graph)
1333     {
1334         PARAMETER(0, 0).f64();
1335         PARAMETER(1, 1).f64();
1336 
1337         BASIC_BLOCK(2, -1)
1338         {
1339             INST(2, Opcode::Add).f64().Inputs(0, 1);
1340             INST(3, Opcode::Return).f64().Inputs(2);
1341         }
1342     }
1343     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1344 }
1345 
1346 // Checks the build of the fsub2 instruction
TEST_F(IrBuilderTest,Fsub2)1347 TEST_F(IrBuilderTest, Fsub2)
1348 {
1349     auto source = R"(
1350     .function f32 main(f32 a0, f32 a1){
1351         lda a0
1352         fsub2 a1
1353         return
1354     }
1355     )";
1356     ASSERT_TRUE(ParseToGraph(source, "main"));
1357     auto graph = CreateGraphWithDefaultRuntime();
1358     GRAPH(graph)
1359     {
1360         PARAMETER(0, 0).f32();
1361         PARAMETER(1, 1).f32();
1362 
1363         BASIC_BLOCK(2, -1)
1364         {
1365             INST(2, Opcode::Sub).f32().Inputs(0, 1);
1366             INST(3, Opcode::Return).f32().Inputs(2);
1367         }
1368     }
1369     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1370 }
1371 
1372 // Checks the build of the fsub2.64 instruction
TEST_F(IrBuilderTest,Fsub2_64)1373 TEST_F(IrBuilderTest, Fsub2_64)
1374 {
1375     auto source = R"(
1376     .function f64 main(f64 a0, f64 a1){
1377         lda.64 a0
1378         fsub2.64 a1
1379         return.64
1380     }
1381     )";
1382     ASSERT_TRUE(ParseToGraph(source, "main"));
1383     auto graph = CreateGraphWithDefaultRuntime();
1384     GRAPH(graph)
1385     {
1386         PARAMETER(0, 0).f64();
1387         PARAMETER(1, 1).f64();
1388 
1389         BASIC_BLOCK(2, -1)
1390         {
1391             INST(2, Opcode::Sub).f64().Inputs(0, 1);
1392             INST(3, Opcode::Return).f64().Inputs(2);
1393         }
1394     }
1395     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1396 }
1397 
1398 // Checks the build of the fmul2 instruction
TEST_F(IrBuilderTest,Fmul2)1399 TEST_F(IrBuilderTest, Fmul2)
1400 {
1401     auto source = R"(
1402     .function f32 main(f32 a0, f32 a1){
1403         lda a0
1404         fmul2 a1
1405         return
1406     }
1407     )";
1408     ASSERT_TRUE(ParseToGraph(source, "main"));
1409     auto graph = CreateGraphWithDefaultRuntime();
1410     GRAPH(graph)
1411     {
1412         PARAMETER(0, 0).f32();
1413         PARAMETER(1, 1).f32();
1414 
1415         BASIC_BLOCK(2, -1)
1416         {
1417             INST(2, Opcode::Mul).f32().Inputs(0, 1);
1418             INST(3, Opcode::Return).f32().Inputs(2);
1419         }
1420     }
1421     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1422 }
1423 
1424 // Checks the build of the fmul2.64 instruction
TEST_F(IrBuilderTest,Fmul2_64)1425 TEST_F(IrBuilderTest, Fmul2_64)
1426 {
1427     auto source = R"(
1428     .function f64 main(f64 a0, f64 a1){
1429         lda.64 a0
1430         fmul2.64 a1
1431         return.64
1432     }
1433     )";
1434     ASSERT_TRUE(ParseToGraph(source, "main"));
1435     auto graph = CreateGraphWithDefaultRuntime();
1436     GRAPH(graph)
1437     {
1438         PARAMETER(0, 0).f64();
1439         PARAMETER(1, 1).f64();
1440 
1441         BASIC_BLOCK(2, -1)
1442         {
1443             INST(2, Opcode::Mul).f64().Inputs(0, 1);
1444             INST(3, Opcode::Return).f64().Inputs(2);
1445         }
1446     }
1447     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1448 }
1449 
1450 // Checks the build of the fdiv2 instruction
TEST_F(IrBuilderTest,Fdiv2)1451 TEST_F(IrBuilderTest, Fdiv2)
1452 {
1453     auto source = R"(
1454     .function f32 main(f32 a0, f32 a1){
1455         lda a0
1456         fdiv2 a1
1457         return
1458     }
1459     )";
1460     ASSERT_TRUE(ParseToGraph(source, "main"));
1461     auto graph = CreateGraphWithDefaultRuntime();
1462     GRAPH(graph)
1463     {
1464         PARAMETER(0, 0).f32();
1465         PARAMETER(1, 1).f32();
1466 
1467         BASIC_BLOCK(2, -1)
1468         {
1469             INST(2, Opcode::Div).f32().Inputs(0, 1);
1470             INST(3, Opcode::Return).f32().Inputs(2);
1471         }
1472     }
1473     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1474 }
1475 
1476 // Checks the build of the fdiv2.64 instruction
TEST_F(IrBuilderTest,Fdiv2_64)1477 TEST_F(IrBuilderTest, Fdiv2_64)
1478 {
1479     auto source = R"(
1480     .function f64 main(f64 a0, f64 a1){
1481         lda.64 a0
1482         fdiv2.64 a1
1483         return.64
1484     }
1485     )";
1486     ASSERT_TRUE(ParseToGraph(source, "main"));
1487     auto graph = CreateGraphWithDefaultRuntime();
1488     GRAPH(graph)
1489     {
1490         PARAMETER(0, 0).f64();
1491         PARAMETER(1, 1).f64();
1492 
1493         BASIC_BLOCK(2, -1)
1494         {
1495             INST(2, Opcode::Div).f64().Inputs(0, 1);
1496             INST(3, Opcode::Return).f64().Inputs(2);
1497         }
1498     }
1499     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1500 }
1501 
1502 // Checks the build of the fmod2 instruction
TEST_F(IrBuilderTest,Fmod2)1503 TEST_F(IrBuilderTest, Fmod2)
1504 {
1505     auto source = R"(
1506     .function f32 main(f32 a0, f32 a1){
1507         lda a0
1508         fmod2 a1
1509         return
1510     }
1511     )";
1512     ASSERT_TRUE(ParseToGraph(source, "main"));
1513     auto graph = CreateGraphWithDefaultRuntime();
1514     GRAPH(graph)
1515     {
1516         PARAMETER(0, 0).f32();
1517         PARAMETER(1, 1).f32();
1518 
1519         BASIC_BLOCK(2, -1)
1520         {
1521             INST(2, Opcode::Mod).f32().Inputs(0, 1);
1522             INST(3, Opcode::Return).f32().Inputs(2);
1523         }
1524     }
1525     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1526 }
1527 
1528 // Checks the build of the fmod2.64 instruction
TEST_F(IrBuilderTest,Fmod2_64)1529 TEST_F(IrBuilderTest, Fmod2_64)
1530 {
1531     auto source = R"(
1532     .function f64 main(f64 a0, f64 a1){
1533         lda.64 a0
1534         fmod2.64 a1
1535         return.64
1536     }
1537     )";
1538     ASSERT_TRUE(ParseToGraph(source, "main"));
1539     auto graph = CreateGraphWithDefaultRuntime();
1540     GRAPH(graph)
1541     {
1542         PARAMETER(0, 0).f64();
1543         PARAMETER(1, 1).f64();
1544 
1545         BASIC_BLOCK(2, -1)
1546         {
1547             INST(2, Opcode::Mod).f64().Inputs(0, 1);
1548             INST(3, Opcode::Return).f64().Inputs(2);
1549         }
1550     }
1551     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1552 }
1553 
1554 // Checks the build of the add2 instruction
TEST_F(IrBuilderTest,Add2)1555 TEST_F(IrBuilderTest, Add2)
1556 {
1557     auto source = R"(
1558     .function i32 main(i32 a0, i32 a1){
1559         lda a0
1560         add2 a1
1561         return
1562     }
1563     )";
1564     ASSERT_TRUE(ParseToGraph(source, "main"));
1565     auto graph = CreateGraphWithDefaultRuntime();
1566     GRAPH(graph)
1567     {
1568         PARAMETER(0, 0).s32();
1569         PARAMETER(1, 1).s32();
1570 
1571         BASIC_BLOCK(2, -1)
1572         {
1573             INST(2, Opcode::Add).s32().Inputs(0, 1);
1574             INST(3, Opcode::Return).s32().Inputs(2);
1575         }
1576     }
1577     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1578 }
1579 
1580 // Checks the build of the add2.64 instruction
TEST_F(IrBuilderTest,Add2_64)1581 TEST_F(IrBuilderTest, Add2_64)
1582 {
1583     auto source = R"(
1584     .function i64 main(i64 a0, i64 a1){
1585         lda.64 a0
1586         add2.64 a1
1587         return.64
1588     }
1589     )";
1590     ASSERT_TRUE(ParseToGraph(source, "main"));
1591     auto graph = CreateGraphWithDefaultRuntime();
1592     GRAPH(graph)
1593     {
1594         PARAMETER(0, 0).s64();
1595         PARAMETER(1, 1).s64();
1596 
1597         BASIC_BLOCK(2, -1)
1598         {
1599             INST(2, Opcode::Add).s64().Inputs(0, 1);
1600             INST(3, Opcode::Return).s64().Inputs(2);
1601         }
1602     }
1603     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1604 }
1605 
1606 // Checks the build of the sub2 instruction
TEST_F(IrBuilderTest,Sub2)1607 TEST_F(IrBuilderTest, Sub2)
1608 {
1609     auto source = R"(
1610     .function i32 main(i32 a0, i32 a1){
1611         lda a0
1612         sub2 a1
1613         return
1614     }
1615     )";
1616     ASSERT_TRUE(ParseToGraph(source, "main"));
1617     auto graph = CreateGraphWithDefaultRuntime();
1618     GRAPH(graph)
1619     {
1620         PARAMETER(0, 0).s32();
1621         PARAMETER(1, 1).s32();
1622 
1623         BASIC_BLOCK(2, -1)
1624         {
1625             INST(2, Opcode::Sub).s32().Inputs(0, 1);
1626             INST(3, Opcode::Return).s32().Inputs(2);
1627         }
1628     }
1629     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1630 }
1631 
1632 // Checks the build of the sub2.64 instruction
TEST_F(IrBuilderTest,Sub2_64)1633 TEST_F(IrBuilderTest, Sub2_64)
1634 {
1635     auto source = R"(
1636     .function i64 main(i64 a0, i64 a1){
1637         lda.64 a0
1638         sub2.64 a1
1639         return.64
1640     }
1641     )";
1642     ASSERT_TRUE(ParseToGraph(source, "main"));
1643     auto graph = CreateGraphWithDefaultRuntime();
1644     GRAPH(graph)
1645     {
1646         PARAMETER(0, 0).s64();
1647         PARAMETER(1, 1).s64();
1648 
1649         BASIC_BLOCK(2, -1)
1650         {
1651             INST(2, Opcode::Sub).s64().Inputs(0, 1);
1652             INST(3, Opcode::Return).s64().Inputs(2);
1653         }
1654     }
1655     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1656 }
1657 
1658 // Checks the build of the mul2 instruction
TEST_F(IrBuilderTest,Mul2)1659 TEST_F(IrBuilderTest, Mul2)
1660 {
1661     auto source = R"(
1662     .function i32 main(i32 a0, i32 a1){
1663         lda a0
1664         mul2 a1
1665         return
1666     }
1667     )";
1668     ASSERT_TRUE(ParseToGraph(source, "main"));
1669     auto graph = CreateGraphWithDefaultRuntime();
1670     GRAPH(graph)
1671     {
1672         PARAMETER(0, 0).s32();
1673         PARAMETER(1, 1).s32();
1674 
1675         BASIC_BLOCK(2, -1)
1676         {
1677             INST(2, Opcode::Mul).s32().Inputs(0, 1);
1678             INST(3, Opcode::Return).s32().Inputs(2);
1679         }
1680     }
1681     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1682 }
1683 
1684 // Checks the build of the mul2.64 instruction
TEST_F(IrBuilderTest,Mul2_64)1685 TEST_F(IrBuilderTest, Mul2_64)
1686 {
1687     auto source = R"(
1688     .function i64 main(i64 a0, i64 a1){
1689         lda.64 a0
1690         mul2.64 a1
1691         return.64
1692     }
1693     )";
1694     ASSERT_TRUE(ParseToGraph(source, "main"));
1695     auto graph = CreateGraphWithDefaultRuntime();
1696     GRAPH(graph)
1697     {
1698         PARAMETER(0, 0).s64();
1699         PARAMETER(1, 1).s64();
1700 
1701         BASIC_BLOCK(2, -1)
1702         {
1703             INST(2, Opcode::Mul).s64().Inputs(0, 1);
1704             INST(3, Opcode::Return).s64().Inputs(2);
1705         }
1706     }
1707     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1708 }
1709 
1710 // Checks the build of the and2 instruction
TEST_F(IrBuilderTest,And2)1711 TEST_F(IrBuilderTest, And2)
1712 {
1713     auto source = R"(
1714     .function i32 main(i32 a0, i32 a1){
1715         lda a0
1716         and2 a1
1717         return
1718     }
1719     )";
1720     ASSERT_TRUE(ParseToGraph(source, "main"));
1721     auto graph = CreateGraphWithDefaultRuntime();
1722     GRAPH(graph)
1723     {
1724         PARAMETER(0, 0).s32();
1725         PARAMETER(1, 1).s32();
1726 
1727         BASIC_BLOCK(2, -1)
1728         {
1729             INST(2, Opcode::And).s32().Inputs(0, 1);
1730             INST(3, Opcode::Return).s32().Inputs(2);
1731         }
1732     }
1733     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1734 }
1735 
1736 // Checks the build of the and2.64 instruction
TEST_F(IrBuilderTest,And2_64)1737 TEST_F(IrBuilderTest, And2_64)
1738 {
1739     auto source = R"(
1740     .function i64 main(i64 a0, i64 a1){
1741         lda.64 a0
1742         and2.64 a1
1743         return.64
1744     }
1745     )";
1746     ASSERT_TRUE(ParseToGraph(source, "main"));
1747     auto graph = CreateGraphWithDefaultRuntime();
1748     GRAPH(graph)
1749     {
1750         PARAMETER(0, 0).s64();
1751         PARAMETER(1, 1).s64();
1752 
1753         BASIC_BLOCK(2, -1)
1754         {
1755             INST(2, Opcode::And).s64().Inputs(0, 1);
1756             INST(3, Opcode::Return).s64().Inputs(2);
1757         }
1758     }
1759     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1760 }
1761 
1762 // Checks the build of the or2 instruction
TEST_F(IrBuilderTest,Or2)1763 TEST_F(IrBuilderTest, Or2)
1764 {
1765     auto source = R"(
1766     .function i32 main(i32 a0, i32 a1){
1767         lda a0
1768         or2 a1
1769         return
1770     }
1771     )";
1772     ASSERT_TRUE(ParseToGraph(source, "main"));
1773     auto graph = CreateGraphWithDefaultRuntime();
1774     GRAPH(graph)
1775     {
1776         PARAMETER(0, 0).s32();
1777         PARAMETER(1, 1).s32();
1778 
1779         BASIC_BLOCK(2, -1)
1780         {
1781             INST(2, Opcode::Or).s32().Inputs(0, 1);
1782             INST(3, Opcode::Return).s32().Inputs(2);
1783         }
1784     }
1785     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1786 }
1787 
1788 // Checks the build of the or2.64 instruction
TEST_F(IrBuilderTest,Or2_64)1789 TEST_F(IrBuilderTest, Or2_64)
1790 {
1791     auto source = R"(
1792     .function i64 main(i64 a0, i64 a1){
1793         lda.64 a0
1794         or2.64 a1
1795         return.64
1796     }
1797     )";
1798     ASSERT_TRUE(ParseToGraph(source, "main"));
1799     auto graph = CreateGraphWithDefaultRuntime();
1800     GRAPH(graph)
1801     {
1802         PARAMETER(0, 0).s64();
1803         PARAMETER(1, 1).s64();
1804 
1805         BASIC_BLOCK(2, -1)
1806         {
1807             INST(2, Opcode::Or).s64().Inputs(0, 1);
1808             INST(3, Opcode::Return).s64().Inputs(2);
1809         }
1810     }
1811     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1812 }
1813 
1814 // Checks the build of the Xor2 instruction
TEST_F(IrBuilderTest,Xor2)1815 TEST_F(IrBuilderTest, Xor2)
1816 {
1817     auto source = R"(
1818     .function i32 main(i32 a0, i32 a1){
1819         lda a0
1820         xor2 a1
1821         return
1822     }
1823     )";
1824     ASSERT_TRUE(ParseToGraph(source, "main"));
1825     auto graph = CreateGraphWithDefaultRuntime();
1826     GRAPH(graph)
1827     {
1828         PARAMETER(0, 0).s32();
1829         PARAMETER(1, 1).s32();
1830 
1831         BASIC_BLOCK(2, -1)
1832         {
1833             INST(2, Opcode::Xor).s32().Inputs(0, 1);
1834             INST(3, Opcode::Return).s32().Inputs(2);
1835         }
1836     }
1837     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1838 }
1839 
1840 // Checks the build of the xor2.64 instruction
TEST_F(IrBuilderTest,Xor2_64)1841 TEST_F(IrBuilderTest, Xor2_64)
1842 {
1843     auto source = R"(
1844     .function i64 main(i64 a0, i64 a1){
1845         lda.64 a0
1846         xor2.64 a1
1847         return.64
1848     }
1849     )";
1850     ASSERT_TRUE(ParseToGraph(source, "main"));
1851     auto graph = CreateGraphWithDefaultRuntime();
1852     GRAPH(graph)
1853     {
1854         PARAMETER(0, 0).s64();
1855         PARAMETER(1, 1).s64();
1856 
1857         BASIC_BLOCK(2, -1)
1858         {
1859             INST(2, Opcode::Xor).s64().Inputs(0, 1);
1860             INST(3, Opcode::Return).s64().Inputs(2);
1861         }
1862     }
1863     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1864 }
1865 
1866 // Checks the build of the shl2 instruction
TEST_F(IrBuilderTest,Shl2)1867 TEST_F(IrBuilderTest, Shl2)
1868 {
1869     auto source = R"(
1870     .function i32 main(i32 a0, i32 a1){
1871         lda a0
1872         shl2 a1
1873         return
1874     }
1875     )";
1876     ASSERT_TRUE(ParseToGraph(source, "main"));
1877     auto graph = CreateGraphWithDefaultRuntime();
1878     GRAPH(graph)
1879     {
1880         PARAMETER(0, 0).s32();
1881         PARAMETER(1, 1).s32();
1882 
1883         BASIC_BLOCK(2, -1)
1884         {
1885             INST(2, Opcode::Shl).s32().Inputs(0, 1);
1886             INST(3, Opcode::Return).s32().Inputs(2);
1887         }
1888     }
1889     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1890 }
1891 
1892 // Checks the build of the shl2.64 instruction
TEST_F(IrBuilderTest,Shl2_64)1893 TEST_F(IrBuilderTest, Shl2_64)
1894 {
1895     auto source = R"(
1896     .function i64 main(i64 a0, i64 a1){
1897         lda.64 a0
1898         shl2.64 a1
1899         return.64
1900     }
1901     )";
1902     ASSERT_TRUE(ParseToGraph(source, "main"));
1903     auto graph = CreateGraphWithDefaultRuntime();
1904     GRAPH(graph)
1905     {
1906         PARAMETER(0, 0).s64();
1907         PARAMETER(1, 1).s64();
1908 
1909         BASIC_BLOCK(2, -1)
1910         {
1911             INST(2, Opcode::Shl).s64().Inputs(0, 1);
1912             INST(3, Opcode::Return).s64().Inputs(2);
1913         }
1914     }
1915     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1916 }
1917 
1918 // Checks the build of the shr2 instruction
TEST_F(IrBuilderTest,Shr2)1919 TEST_F(IrBuilderTest, Shr2)
1920 {
1921     auto source = R"(
1922     .function i32 main(i32 a0, i32 a1){
1923         lda a0
1924         shr2 a1
1925         return
1926     }
1927     )";
1928     ASSERT_TRUE(ParseToGraph(source, "main"));
1929     auto graph = CreateGraphWithDefaultRuntime();
1930     GRAPH(graph)
1931     {
1932         PARAMETER(0, 0).s32();
1933         PARAMETER(1, 1).s32();
1934 
1935         BASIC_BLOCK(2, -1)
1936         {
1937             INST(2, Opcode::Shr).s32().Inputs(0, 1);
1938             INST(3, Opcode::Return).s32().Inputs(2);
1939         }
1940     }
1941     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1942 }
1943 
1944 // Checks the build of the shr2.64 instruction
TEST_F(IrBuilderTest,Shr2_64)1945 TEST_F(IrBuilderTest, Shr2_64)
1946 {
1947     auto source = R"(
1948     .function i64 main(i64 a0, i64 a1){
1949         lda.64 a0
1950         shr2.64 a1
1951         return.64
1952     }
1953     )";
1954     ASSERT_TRUE(ParseToGraph(source, "main"));
1955     auto graph = CreateGraphWithDefaultRuntime();
1956     GRAPH(graph)
1957     {
1958         PARAMETER(0, 0).s64();
1959         PARAMETER(1, 1).s64();
1960 
1961         BASIC_BLOCK(2, -1)
1962         {
1963             INST(2, Opcode::Shr).s64().Inputs(0, 1);
1964             INST(3, Opcode::Return).s64().Inputs(2);
1965         }
1966     }
1967     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1968 }
1969 
1970 // Checks the build of the ashr2 instruction
TEST_F(IrBuilderTest,Ashr2)1971 TEST_F(IrBuilderTest, Ashr2)
1972 {
1973     auto source = R"(
1974     .function i32 main(i32 a0, i32 a1){
1975         lda a0
1976         ashr2 a1
1977         return
1978     }
1979     )";
1980     ASSERT_TRUE(ParseToGraph(source, "main"));
1981     auto graph = CreateGraphWithDefaultRuntime();
1982     GRAPH(graph)
1983     {
1984         PARAMETER(0, 0).s32();
1985         PARAMETER(1, 1).s32();
1986 
1987         BASIC_BLOCK(2, -1)
1988         {
1989             INST(2, Opcode::AShr).s32().Inputs(0, 1);
1990             INST(3, Opcode::Return).s32().Inputs(2);
1991         }
1992     }
1993     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1994 }
1995 
1996 // Checks the build of the ashr2.64 instruction
TEST_F(IrBuilderTest,Ashr2_64)1997 TEST_F(IrBuilderTest, Ashr2_64)
1998 {
1999     auto source = R"(
2000     .function i64 main(i64 a0, i64 a1){
2001         lda.64 a0
2002         ashr2.64 a1
2003         return.64
2004     }
2005     )";
2006     ASSERT_TRUE(ParseToGraph(source, "main"));
2007     auto graph = CreateGraphWithDefaultRuntime();
2008     GRAPH(graph)
2009     {
2010         PARAMETER(0, 0).s64();
2011         PARAMETER(1, 1).s64();
2012 
2013         BASIC_BLOCK(2, -1)
2014         {
2015             INST(2, Opcode::AShr).s64().Inputs(0, 1);
2016             INST(3, Opcode::Return).s64().Inputs(2);
2017         }
2018     }
2019     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2020 }
2021 
2022 // Checks the build of the div2 instruction
TEST_F(IrBuilderTest,Div2)2023 TEST_F(IrBuilderTest, Div2)
2024 {
2025     auto source = R"(
2026     .function i32 main(i32 a0, i32 a1){
2027         lda a0
2028         div2 a1
2029         return
2030     }
2031     )";
2032     ASSERT_TRUE(ParseToGraph(source, "main"));
2033     auto graph = CreateGraphWithDefaultRuntime();
2034     GRAPH(graph)
2035     {
2036         PARAMETER(0, 0).s32();
2037         PARAMETER(1, 1).s32();
2038 
2039         BASIC_BLOCK(2, -1)
2040         {
2041             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2042             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2043             INST(4, Opcode::Div).s32().Inputs(0, 3);
2044             INST(5, Opcode::Return).s32().Inputs(4);
2045         }
2046     }
2047     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2048 }
2049 
2050 // Checks the build of the div2.64 instruction
TEST_F(IrBuilderTest,Div2_64)2051 TEST_F(IrBuilderTest, Div2_64)
2052 {
2053     auto source = R"(
2054     .function i64 main(i64 a0, i64 a1){
2055         lda.64 a0
2056         div2.64 a1
2057         return.64
2058     }
2059     )";
2060     ASSERT_TRUE(ParseToGraph(source, "main"));
2061     auto graph = CreateGraphWithDefaultRuntime();
2062     GRAPH(graph)
2063     {
2064         PARAMETER(0, 0).s64();
2065         PARAMETER(1, 1).s64();
2066 
2067         BASIC_BLOCK(2, -1)
2068         {
2069             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2070             INST(3, Opcode::ZeroCheck).s64().Inputs(1, 2);
2071             INST(4, Opcode::Div).s64().Inputs(0, 3);
2072             INST(5, Opcode::Return).s64().Inputs(4);
2073         }
2074     }
2075     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2076 }
2077 
2078 // Checks the build of the mod2 instruction
TEST_F(IrBuilderTest,Mod2)2079 TEST_F(IrBuilderTest, Mod2)
2080 {
2081     auto source = R"(
2082     .function i32 main(i32 a0, i32 a1){
2083         lda a0
2084         mod2 a1
2085         return
2086     }
2087     )";
2088     ASSERT_TRUE(ParseToGraph(source, "main"));
2089     auto graph = CreateGraphWithDefaultRuntime();
2090     GRAPH(graph)
2091     {
2092         PARAMETER(0, 0).s32();
2093         PARAMETER(1, 1).s32();
2094 
2095         BASIC_BLOCK(2, -1)
2096         {
2097             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2098             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2099             INST(4, Opcode::Mod).s32().Inputs(0, 3);
2100             INST(5, Opcode::Return).s32().Inputs(4);
2101         }
2102     }
2103     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2104 }
2105 
2106 // Checks the build of the mod2.64 instruction
TEST_F(IrBuilderTest,Mod2_64)2107 TEST_F(IrBuilderTest, Mod2_64)
2108 {
2109     auto source = R"(
2110     .function i64 main(i64 a0, i64 a1){
2111         lda.64 a0
2112         mod2.64 a1
2113         return.64
2114     }
2115     )";
2116     ASSERT_TRUE(ParseToGraph(source, "main"));
2117     auto graph = CreateGraphWithDefaultRuntime();
2118     GRAPH(graph)
2119     {
2120         PARAMETER(0, 0).s64();
2121         PARAMETER(1, 1).s64();
2122 
2123         BASIC_BLOCK(2, -1)
2124         {
2125             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2126             INST(3, Opcode::ZeroCheck).s64().Inputs(1, 2);
2127             INST(4, Opcode::Mod).s64().Inputs(0, 3);
2128             INST(5, Opcode::Return).s64().Inputs(4);
2129         }
2130     }
2131     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2132 }
2133 
2134 // Checks the build of the divu2 instruction
TEST_F(IrBuilderTest,Divu2)2135 TEST_F(IrBuilderTest, Divu2)
2136 {
2137     auto source = R"(
2138     .function u32 main(u32 a0, u32 a1){
2139         lda a0
2140         divu2 a1
2141         return
2142     }
2143     )";
2144     ASSERT_TRUE(ParseToGraph(source, "main"));
2145     auto graph = CreateGraphWithDefaultRuntime();
2146     GRAPH(graph)
2147     {
2148         PARAMETER(0, 0).u32();
2149         PARAMETER(1, 1).u32();
2150 
2151         BASIC_BLOCK(2, -1)
2152         {
2153             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2154             INST(3, Opcode::ZeroCheck).u32().Inputs(1, 2);
2155             INST(4, Opcode::Div).u32().Inputs(0, 3);
2156             INST(5, Opcode::Return).u32().Inputs(4);
2157         }
2158     }
2159     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2160 }
2161 
2162 // Checks the build of the divu2.64 instruction
TEST_F(IrBuilderTest,Divu2_64)2163 TEST_F(IrBuilderTest, Divu2_64)
2164 {
2165     auto source = R"(
2166     .function u64 main(u64 a0, u64 a1){
2167         lda.64 a0
2168         divu2.64 a1
2169         return.64
2170     }
2171     )";
2172     ASSERT_TRUE(ParseToGraph(source, "main"));
2173     auto graph = CreateGraphWithDefaultRuntime();
2174     GRAPH(graph)
2175     {
2176         PARAMETER(0, 0).u64();
2177         PARAMETER(1, 1).u64();
2178 
2179         BASIC_BLOCK(2, -1)
2180         {
2181             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2182             INST(3, Opcode::ZeroCheck).u64().Inputs(1, 2);
2183             INST(4, Opcode::Div).u64().Inputs(0, 3);
2184             INST(5, Opcode::Return).u64().Inputs(4);
2185         }
2186     }
2187     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2188 }
2189 
2190 // Checks the build of the modu2 instruction
TEST_F(IrBuilderTest,Modu2)2191 TEST_F(IrBuilderTest, Modu2)
2192 {
2193     auto source = R"(
2194     .function u32 main(u32 a0, u32 a1){
2195         lda a0
2196         modu2 a1
2197         return
2198     }
2199     )";
2200     ASSERT_TRUE(ParseToGraph(source, "main"));
2201     auto graph = CreateGraphWithDefaultRuntime();
2202     GRAPH(graph)
2203     {
2204         PARAMETER(0, 0).u32();
2205         PARAMETER(1, 1).u32();
2206 
2207         BASIC_BLOCK(2, -1)
2208         {
2209             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2210             INST(3, Opcode::ZeroCheck).u32().Inputs(1, 2);
2211             INST(4, Opcode::Mod).u32().Inputs(0, 3);
2212             INST(5, Opcode::Return).u32().Inputs(4);
2213         }
2214     }
2215     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2216 }
2217 
2218 // Checks the build of the modu2.64 instruction
TEST_F(IrBuilderTest,Modu2_64)2219 TEST_F(IrBuilderTest, Modu2_64)
2220 {
2221     auto source = R"(
2222     .function u64 main(u64 a0, u64 a1){
2223         lda.64 a0
2224         modu2.64 a1
2225         return.64
2226     }
2227     )";
2228     ASSERT_TRUE(ParseToGraph(source, "main"));
2229     auto graph = CreateGraphWithDefaultRuntime();
2230     GRAPH(graph)
2231     {
2232         PARAMETER(0, 0).u64();
2233         PARAMETER(1, 1).u64();
2234 
2235         BASIC_BLOCK(2, -1)
2236         {
2237             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
2238             INST(3, Opcode::ZeroCheck).u64().Inputs(1, 2);
2239             INST(4, Opcode::Mod).u64().Inputs(0, 3);
2240             INST(5, Opcode::Return).u64().Inputs(4);
2241         }
2242     }
2243     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2244 }
2245 
2246 // Checks the build of the add instruction
TEST_F(IrBuilderTest,Add)2247 TEST_F(IrBuilderTest, Add)
2248 {
2249     auto source = R"(
2250     .function i32 main(i32 a0, i32 a1){
2251         add a0, a1
2252         return
2253     }
2254     )";
2255     ASSERT_TRUE(ParseToGraph(source, "main"));
2256     auto graph = CreateGraphWithDefaultRuntime();
2257     GRAPH(graph)
2258     {
2259         PARAMETER(0, 0).s32();
2260         PARAMETER(1, 1).s32();
2261 
2262         BASIC_BLOCK(2, -1)
2263         {
2264             INST(2, Opcode::Add).s32().Inputs(0, 1);
2265             INST(3, Opcode::Return).s32().Inputs(2);
2266         }
2267     }
2268     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2269 }
2270 
2271 // Checks the build of the sub instruction
TEST_F(IrBuilderTest,Sub)2272 TEST_F(IrBuilderTest, Sub)
2273 {
2274     auto source = R"(
2275     .function i32 main(i32 a0, i32 a1){
2276         sub a0, a1
2277         return
2278     }
2279     )";
2280     ASSERT_TRUE(ParseToGraph(source, "main"));
2281     auto graph = CreateGraphWithDefaultRuntime();
2282     GRAPH(graph)
2283     {
2284         PARAMETER(0, 0).s32();
2285         PARAMETER(1, 1).s32();
2286 
2287         BASIC_BLOCK(2, -1)
2288         {
2289             INST(2, Opcode::Sub).s32().Inputs(0, 1);
2290             INST(3, Opcode::Return).s32().Inputs(2);
2291         }
2292     }
2293     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2294 }
2295 
2296 // Checks the build of the mul instruction
TEST_F(IrBuilderTest,Mul)2297 TEST_F(IrBuilderTest, Mul)
2298 {
2299     auto source = R"(
2300     .function i32 main(i32 a0, i32 a1){
2301         mul a0, a1
2302         return
2303     }
2304     )";
2305     ASSERT_TRUE(ParseToGraph(source, "main"));
2306     auto graph = CreateGraphWithDefaultRuntime();
2307     GRAPH(graph)
2308     {
2309         PARAMETER(0, 0).s32();
2310         PARAMETER(1, 1).s32();
2311 
2312         BASIC_BLOCK(2, -1)
2313         {
2314             INST(2, Opcode::Mul).s32().Inputs(0, 1);
2315             INST(3, Opcode::Return).s32().Inputs(2);
2316         }
2317     }
2318     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2319 }
2320 
2321 // Checks the build of the and instruction
TEST_F(IrBuilderTest,And)2322 TEST_F(IrBuilderTest, And)
2323 {
2324     auto source = R"(
2325     .function i32 main(i32 a0, i32 a1){
2326         and a0, a1
2327         return
2328     }
2329     )";
2330     ASSERT_TRUE(ParseToGraph(source, "main"));
2331     auto graph = CreateGraphWithDefaultRuntime();
2332     GRAPH(graph)
2333     {
2334         PARAMETER(0, 0).s32();
2335         PARAMETER(1, 1).s32();
2336 
2337         BASIC_BLOCK(2, -1)
2338         {
2339             INST(2, Opcode::And).s32().Inputs(0, 1);
2340             INST(3, Opcode::Return).s32().Inputs(2);
2341         }
2342     }
2343     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2344 }
2345 
2346 // Checks the build of the or instruction
TEST_F(IrBuilderTest,Or)2347 TEST_F(IrBuilderTest, Or)
2348 {
2349     auto source = R"(
2350     .function i32 main(i32 a0, i32 a1){
2351         or a0, a1
2352         return
2353     }
2354     )";
2355     ASSERT_TRUE(ParseToGraph(source, "main"));
2356     auto graph = CreateGraphWithDefaultRuntime();
2357     GRAPH(graph)
2358     {
2359         PARAMETER(0, 0).s32();
2360         PARAMETER(1, 1).s32();
2361 
2362         BASIC_BLOCK(2, -1)
2363         {
2364             INST(2, Opcode::Or).s32().Inputs(0, 1);
2365             INST(3, Opcode::Return).s32().Inputs(2);
2366         }
2367     }
2368     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2369 }
2370 
2371 // Checks the build of the xor instruction
TEST_F(IrBuilderTest,Xor)2372 TEST_F(IrBuilderTest, Xor)
2373 {
2374     auto source = R"(
2375     .function i32 main(i32 a0, i32 a1){
2376         xor a0, a1
2377         return
2378     }
2379     )";
2380     ASSERT_TRUE(ParseToGraph(source, "main"));
2381     auto graph = CreateGraphWithDefaultRuntime();
2382     GRAPH(graph)
2383     {
2384         PARAMETER(0, 0).s32();
2385         PARAMETER(1, 1).s32();
2386 
2387         BASIC_BLOCK(2, -1)
2388         {
2389             INST(2, Opcode::Xor).s32().Inputs(0, 1);
2390             INST(3, Opcode::Return).s32().Inputs(2);
2391         }
2392     }
2393     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2394 }
2395 
2396 // Checks the build of the shl instruction
TEST_F(IrBuilderTest,Shl)2397 TEST_F(IrBuilderTest, Shl)
2398 {
2399     auto source = R"(
2400     .function i32 main(i32 a0, i32 a1){
2401         shl a0, a1
2402         return
2403     }
2404     )";
2405     ASSERT_TRUE(ParseToGraph(source, "main"));
2406     auto graph = CreateGraphWithDefaultRuntime();
2407     GRAPH(graph)
2408     {
2409         PARAMETER(0, 0).s32();
2410         PARAMETER(1, 1).s32();
2411 
2412         BASIC_BLOCK(2, -1)
2413         {
2414             INST(2, Opcode::Shl).s32().Inputs(0, 1);
2415             INST(3, Opcode::Return).s32().Inputs(2);
2416         }
2417     }
2418     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2419 }
2420 
2421 // Checks the build of the shr instruction
TEST_F(IrBuilderTest,Shr)2422 TEST_F(IrBuilderTest, Shr)
2423 {
2424     auto source = R"(
2425     .function i32 main(i32 a0, i32 a1){
2426         shr a0, a1
2427         return
2428     }
2429     )";
2430     ASSERT_TRUE(ParseToGraph(source, "main"));
2431     auto graph = CreateGraphWithDefaultRuntime();
2432     GRAPH(graph)
2433     {
2434         PARAMETER(0, 0).s32();
2435         PARAMETER(1, 1).s32();
2436 
2437         BASIC_BLOCK(2, -1)
2438         {
2439             INST(2, Opcode::Shr).s32().Inputs(0, 1);
2440             INST(3, Opcode::Return).s32().Inputs(2);
2441         }
2442     }
2443     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2444 }
2445 
2446 // Checks the build of the ashr instruction
TEST_F(IrBuilderTest,Ashr)2447 TEST_F(IrBuilderTest, Ashr)
2448 {
2449     auto source = R"(
2450     .function i32 main(i32 a0, i32 a1){
2451         ashr a0, a1
2452         return
2453     }
2454     )";
2455     ASSERT_TRUE(ParseToGraph(source, "main"));
2456     auto graph = CreateGraphWithDefaultRuntime();
2457     GRAPH(graph)
2458     {
2459         PARAMETER(0, 0).s32();
2460         PARAMETER(1, 1).s32();
2461 
2462         BASIC_BLOCK(2, -1)
2463         {
2464             INST(2, Opcode::AShr).s32().Inputs(0, 1);
2465             INST(3, Opcode::Return).s32().Inputs(2);
2466         }
2467     }
2468     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2469 }
2470 
2471 // Checks the build of the div instruction
TEST_F(IrBuilderTest,Div)2472 TEST_F(IrBuilderTest, Div)
2473 {
2474     auto source = R"(
2475     .function i32 main(i32 a0, i32 a1){
2476         div a0, a1
2477         return
2478     }
2479     )";
2480     ASSERT_TRUE(ParseToGraph(source, "main"));
2481     auto graph = CreateGraphWithDefaultRuntime();
2482     GRAPH(graph)
2483     {
2484         PARAMETER(0, 0).s32();
2485         PARAMETER(1, 1).s32();
2486 
2487         BASIC_BLOCK(2, -1)
2488         {
2489             INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
2490             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2491             INST(4, Opcode::Div).s32().Inputs(0, 3);
2492             INST(5, Opcode::Return).s32().Inputs(4);
2493         }
2494     }
2495     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2496 }
2497 
2498 // Checks the build of the mod instruction
TEST_F(IrBuilderTest,Mod)2499 TEST_F(IrBuilderTest, Mod)
2500 {
2501     auto source = R"(
2502     .function i32 main(i32 a0, i32 a1){
2503         mod a0, a1
2504         return
2505     }
2506     )";
2507     ASSERT_TRUE(ParseToGraph(source, "main"));
2508     auto graph = CreateGraphWithDefaultRuntime();
2509     GRAPH(graph)
2510     {
2511         PARAMETER(0, 0).s32();
2512         PARAMETER(1, 1).s32();
2513 
2514         BASIC_BLOCK(2, -1)
2515         {
2516             INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
2517             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2518             INST(4, Opcode::Mod).s32().Inputs(0, 3);
2519             INST(5, Opcode::Return).s32().Inputs(4);
2520         }
2521     }
2522     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2523 }
2524 
2525 // Checks the build of the addi instruction
TEST_F(IrBuilderTest,Addi)2526 TEST_F(IrBuilderTest, Addi)
2527 {
2528     auto source = R"(
2529     .function i32 main(i32 a0){
2530         lda a0
2531         addi 1
2532         return
2533     }
2534     )";
2535     ASSERT_TRUE(ParseToGraph(source, "main"));
2536     auto graph = CreateGraphWithDefaultRuntime();
2537     GRAPH(graph)
2538     {
2539         PARAMETER(0, 0).s32();
2540         CONSTANT(2, 1).s64();
2541 
2542         BASIC_BLOCK(2, -1)
2543         {
2544             INST(1, Opcode::Add).s32().Inputs(0, 2);
2545             INST(3, Opcode::Return).s32().Inputs(1);
2546         }
2547     }
2548     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2549 }
2550 
2551 // Checks the build of the subi instruction
TEST_F(IrBuilderTest,Subi)2552 TEST_F(IrBuilderTest, Subi)
2553 {
2554     auto source = R"(
2555     .function i32 main(i32 a0){
2556         lda a0
2557         subi 1
2558         return
2559     }
2560     )";
2561     ASSERT_TRUE(ParseToGraph(source, "main"));
2562     auto graph = CreateGraphWithDefaultRuntime();
2563     GRAPH(graph)
2564     {
2565         PARAMETER(0, 0).s32();
2566         CONSTANT(2, 1).s64();
2567 
2568         BASIC_BLOCK(2, -1)
2569         {
2570             INST(1, Opcode::Sub).s32().Inputs(0, 2);
2571             INST(3, Opcode::Return).s32().Inputs(1);
2572         }
2573     }
2574     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2575 }
2576 
2577 // Checks the build of the muli instruction
TEST_F(IrBuilderTest,Muli)2578 TEST_F(IrBuilderTest, Muli)
2579 {
2580     auto source = R"(
2581     .function i32 main(i32 a0){
2582         lda a0
2583         muli 1
2584         return
2585     }
2586     )";
2587     ASSERT_TRUE(ParseToGraph(source, "main"));
2588     auto graph = CreateGraphWithDefaultRuntime();
2589     GRAPH(graph)
2590     {
2591         PARAMETER(0, 0).s32();
2592         CONSTANT(2, 1).s64();
2593 
2594         BASIC_BLOCK(2, -1)
2595         {
2596             INST(1, Opcode::Mul).s32().Inputs(0, 2);
2597             INST(3, Opcode::Return).s32().Inputs(1);
2598         }
2599     }
2600     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2601 }
2602 
2603 // Checks the build of the andi instruction
TEST_F(IrBuilderTest,Andi)2604 TEST_F(IrBuilderTest, Andi)
2605 {
2606     auto source = R"(
2607     .function i32 main(i32 a0){
2608         lda a0
2609         andi 1
2610         return
2611     }
2612     )";
2613     ASSERT_TRUE(ParseToGraph(source, "main"));
2614     auto graph = CreateGraphWithDefaultRuntime();
2615     GRAPH(graph)
2616     {
2617         PARAMETER(0, 0).s32();
2618         CONSTANT(2, 1).s64();
2619 
2620         BASIC_BLOCK(2, -1)
2621         {
2622             INST(1, Opcode::And).s32().Inputs(0, 2);
2623             INST(3, Opcode::Return).s32().Inputs(1);
2624         }
2625     }
2626     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2627 }
2628 
2629 // Checks the build of the ori instruction
TEST_F(IrBuilderTest,Ori)2630 TEST_F(IrBuilderTest, Ori)
2631 {
2632     auto source = R"(
2633     .function i32 main(i32 a0){
2634         lda a0
2635         ori 1
2636         return
2637     }
2638     )";
2639     ASSERT_TRUE(ParseToGraph(source, "main"));
2640     auto graph = CreateGraphWithDefaultRuntime();
2641     GRAPH(graph)
2642     {
2643         PARAMETER(0, 0).s32();
2644         CONSTANT(2, 1).s64();
2645 
2646         BASIC_BLOCK(2, -1)
2647         {
2648             INST(1, Opcode::Or).s32().Inputs(0, 2);
2649             INST(3, Opcode::Return).s32().Inputs(1);
2650         }
2651     }
2652     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2653 }
2654 
2655 // Checks the build of the xori instruction
TEST_F(IrBuilderTest,Xori)2656 TEST_F(IrBuilderTest, Xori)
2657 {
2658     auto source = R"(
2659     .function i32 main(i32 a0){
2660         lda a0
2661         xori 1
2662         return
2663     }
2664     )";
2665     ASSERT_TRUE(ParseToGraph(source, "main"));
2666     auto graph = CreateGraphWithDefaultRuntime();
2667     GRAPH(graph)
2668     {
2669         PARAMETER(0, 0).s32();
2670         CONSTANT(2, 1).s64();
2671 
2672         BASIC_BLOCK(2, -1)
2673         {
2674             INST(1, Opcode::Xor).s32().Inputs(0, 2);
2675             INST(3, Opcode::Return).s32().Inputs(1);
2676         }
2677     }
2678     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2679 }
2680 
2681 // Checks the build of the shli instruction
TEST_F(IrBuilderTest,Shli)2682 TEST_F(IrBuilderTest, Shli)
2683 {
2684     auto source = R"(
2685     .function i32 main(i32 a0){
2686         lda a0
2687         shli 1
2688         return
2689     }
2690     )";
2691     ASSERT_TRUE(ParseToGraph(source, "main"));
2692     auto graph = CreateGraphWithDefaultRuntime();
2693     GRAPH(graph)
2694     {
2695         PARAMETER(0, 0).s32();
2696         CONSTANT(2, 1).s64();
2697 
2698         BASIC_BLOCK(2, -1)
2699         {
2700             INST(1, Opcode::Shl).s32().Inputs(0, 2);
2701             INST(3, Opcode::Return).s32().Inputs(1);
2702         }
2703     }
2704     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2705 }
2706 
2707 // Checks the build of the shri instruction
TEST_F(IrBuilderTest,Shri)2708 TEST_F(IrBuilderTest, Shri)
2709 {
2710     auto source = R"(
2711     .function i32 main(i32 a0){
2712         lda a0
2713         shri 1
2714         return
2715     }
2716     )";
2717     ASSERT_TRUE(ParseToGraph(source, "main"));
2718     auto graph = CreateGraphWithDefaultRuntime();
2719     GRAPH(graph)
2720     {
2721         PARAMETER(0, 0).s32();
2722         CONSTANT(2, 1).s64();
2723 
2724         BASIC_BLOCK(2, -1)
2725         {
2726             INST(1, Opcode::Shr).s32().Inputs(0, 2);
2727             INST(3, Opcode::Return).s32().Inputs(1);
2728         }
2729     }
2730     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2731 }
2732 
2733 // Checks the build of the ashri instruction
TEST_F(IrBuilderTest,Ashri)2734 TEST_F(IrBuilderTest, Ashri)
2735 {
2736     auto source = R"(
2737     .function i32 main(i32 a0){
2738         lda a0
2739         ashri 1
2740         return
2741     }
2742     )";
2743     ASSERT_TRUE(ParseToGraph(source, "main"));
2744     auto graph = CreateGraphWithDefaultRuntime();
2745     GRAPH(graph)
2746     {
2747         PARAMETER(0, 0).s32();
2748         CONSTANT(2, 1).s64();
2749 
2750         BASIC_BLOCK(2, -1)
2751         {
2752             INST(1, Opcode::AShr).s32().Inputs(0, 2);
2753             INST(3, Opcode::Return).s32().Inputs(1);
2754         }
2755     }
2756     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2757 }
2758 
2759 // Checks the build of the divi instruction
TEST_F(IrBuilderTest,Divi)2760 TEST_F(IrBuilderTest, Divi)
2761 {
2762     auto source = R"(
2763     .function i32 main(i32 a0){
2764         lda a0
2765         divi 1
2766         return
2767     }
2768     )";
2769     ASSERT_TRUE(ParseToGraph(source, "main"));
2770     auto graph = CreateGraphWithDefaultRuntime();
2771     GRAPH(graph)
2772     {
2773         PARAMETER(0, 0).s32();
2774         CONSTANT(1, 1).s64();
2775 
2776         BASIC_BLOCK(2, -1)
2777         {
2778             INST(2, Opcode::SaveState).Inputs(0, 0).SrcVregs({0, 1});
2779             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2780             INST(4, Opcode::Div).s32().Inputs(0, 3);
2781             INST(5, Opcode::Return).s32().Inputs(4);
2782         }
2783     }
2784     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2785 }
2786 
2787 // Checks the build of the modi instruction
TEST_F(IrBuilderTest,Modi)2788 TEST_F(IrBuilderTest, Modi)
2789 {
2790     auto source = R"(
2791     .function i32 main(i32 a0){
2792         lda a0
2793         modi 1
2794         return
2795     }
2796     )";
2797     ASSERT_TRUE(ParseToGraph(source, "main"));
2798     auto graph = CreateGraphWithDefaultRuntime();
2799     GRAPH(graph)
2800     {
2801         PARAMETER(0, 0).s32();
2802         CONSTANT(1, 1).s64();
2803 
2804         BASIC_BLOCK(2, -1)
2805         {
2806             INST(2, Opcode::SaveState).Inputs(0, 0).SrcVregs({0, 1});
2807             INST(3, Opcode::ZeroCheck).s32().Inputs(1, 2);
2808             INST(4, Opcode::Mod).s32().Inputs(0, 3);
2809             INST(5, Opcode::Return).s32().Inputs(4);
2810         }
2811     }
2812     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2813 }
2814 
2815 // Checks the build of the fneg instruction
TEST_F(IrBuilderTest,Fneg)2816 TEST_F(IrBuilderTest, Fneg)
2817 {
2818     auto source = R"(
2819     .function f32 main(f32 a0){
2820         lda a0
2821         fneg
2822         return
2823     }
2824     )";
2825     ASSERT_TRUE(ParseToGraph(source, "main"));
2826     auto graph = CreateGraphWithDefaultRuntime();
2827     GRAPH(graph)
2828     {
2829         PARAMETER(0, 0).f32();
2830 
2831         BASIC_BLOCK(2, -1)
2832         {
2833             INST(1, Opcode::Neg).f32().Inputs(0);
2834             INST(2, Opcode::Return).f32().Inputs(1);
2835         }
2836     }
2837     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2838 }
2839 
2840 // Checks the build of the fneg.64 instruction
TEST_F(IrBuilderTest,Fneg64)2841 TEST_F(IrBuilderTest, Fneg64)
2842 {
2843     auto source = R"(
2844     .function f64 main(f64 a0){
2845         lda a0
2846         fneg.64
2847         return.64
2848     }
2849     )";
2850     ASSERT_TRUE(ParseToGraph(source, "main"));
2851     auto graph = CreateGraphWithDefaultRuntime();
2852     GRAPH(graph)
2853     {
2854         PARAMETER(0, 0).f64();
2855 
2856         BASIC_BLOCK(2, -1)
2857         {
2858             INST(1, Opcode::Neg).f64().Inputs(0);
2859             INST(2, Opcode::Return).f64().Inputs(1);
2860         }
2861     }
2862     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2863 }
2864 
2865 // Checks the build of the neg instruction
TEST_F(IrBuilderTest,Neg)2866 TEST_F(IrBuilderTest, Neg)
2867 {
2868     auto source = R"(
2869     .function i32 main(i32 a0){
2870         lda a0
2871         neg
2872         return
2873     }
2874     )";
2875     ASSERT_TRUE(ParseToGraph(source, "main"));
2876     auto graph = CreateGraphWithDefaultRuntime();
2877     GRAPH(graph)
2878     {
2879         PARAMETER(0, 0).s32();
2880 
2881         BASIC_BLOCK(2, -1)
2882         {
2883             INST(1, Opcode::Neg).s32().Inputs(0);
2884             INST(2, Opcode::Return).s32().Inputs(1);
2885         }
2886     }
2887     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2888 }
2889 
2890 // Checks the build of the neg.64 instruction
TEST_F(IrBuilderTest,Neg64)2891 TEST_F(IrBuilderTest, Neg64)
2892 {
2893     auto source = R"(
2894     .function i64 main(i64 a0){
2895         lda a0
2896         neg.64
2897         return.64
2898     }
2899     )";
2900     ASSERT_TRUE(ParseToGraph(source, "main"));
2901     auto graph = CreateGraphWithDefaultRuntime();
2902     GRAPH(graph)
2903     {
2904         PARAMETER(0, 0).s64();
2905 
2906         BASIC_BLOCK(2, -1)
2907         {
2908             INST(1, Opcode::Neg).s64().Inputs(0);
2909             INST(2, Opcode::Return).s64().Inputs(1);
2910         }
2911     }
2912     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2913 }
2914 
2915 // Checks the build of the not instruction
TEST_F(IrBuilderTest,Not)2916 TEST_F(IrBuilderTest, Not)
2917 {
2918     auto source = R"(
2919     .function i32 main(i32 a0){
2920         lda a0
2921         not
2922         return
2923     }
2924     )";
2925     ASSERT_TRUE(ParseToGraph(source, "main"));
2926     auto graph = CreateGraphWithDefaultRuntime();
2927     GRAPH(graph)
2928     {
2929         PARAMETER(0, 0).s32();
2930 
2931         BASIC_BLOCK(2, -1)
2932         {
2933             INST(1, Opcode::Not).s32().Inputs(0);
2934             INST(2, Opcode::Return).s32().Inputs(1);
2935         }
2936     }
2937     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2938 }
2939 
2940 // Checks the build of the not.64 instruction
TEST_F(IrBuilderTest,Not64)2941 TEST_F(IrBuilderTest, Not64)
2942 {
2943     auto source = R"(
2944     .function i64 main(i64 a0){
2945         lda a0
2946         not.64
2947         return.64
2948     }
2949     )";
2950     ASSERT_TRUE(ParseToGraph(source, "main"));
2951     auto graph = CreateGraphWithDefaultRuntime();
2952     GRAPH(graph)
2953     {
2954         PARAMETER(0, 0).s64();
2955 
2956         BASIC_BLOCK(2, -1)
2957         {
2958             INST(1, Opcode::Not).s64().Inputs(0);
2959             INST(2, Opcode::Return).s64().Inputs(1);
2960         }
2961     }
2962     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2963 }
2964 
2965 // Checks the build of the inci instruction
TEST_F(IrBuilderTest,Inci)2966 TEST_F(IrBuilderTest, Inci)
2967 {
2968     auto source = R"(
2969     .function i32 main(i32 a0){
2970         inci a0, 1
2971         lda a0
2972         return
2973     }
2974     )";
2975     ASSERT_TRUE(ParseToGraph(source, "main"));
2976 
2977     auto graph = CreateGraphWithDefaultRuntime();
2978     GRAPH(graph)
2979     {
2980         PARAMETER(0, 0).s32();
2981         CONSTANT(2, 1).s64();
2982 
2983         BASIC_BLOCK(2, -1)
2984         {
2985             INST(1, Opcode::Add).s32().Inputs(0, 2);
2986             INST(3, Opcode::Return).s32().Inputs(1);
2987         }
2988     }
2989     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
2990 }
2991 
2992 // Checks the build of the i32tof32 instruction
TEST_F(IrBuilderTest,I32tof32)2993 TEST_F(IrBuilderTest, I32tof32)
2994 {
2995     auto source = R"(
2996     .function f32 main(i32 a0){
2997         lda a0
2998         i32tof32
2999         return
3000     }
3001     )";
3002     ASSERT_TRUE(ParseToGraph(source, "main"));
3003 
3004     auto graph = CreateGraphWithDefaultRuntime();
3005     GRAPH(graph)
3006     {
3007         PARAMETER(0, 0).s32();
3008 
3009         BASIC_BLOCK(2, -1)
3010         {
3011             INST(1, Opcode::Cast).f32().SrcType(DataType::INT32).Inputs(0);
3012             INST(2, Opcode::Return).f32().Inputs(1);
3013         }
3014     }
3015     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3016 }
3017 
3018 // Checks the build of the i32tof64 instruction
TEST_F(IrBuilderTest,I32tof64)3019 TEST_F(IrBuilderTest, I32tof64)
3020 {
3021     auto source = R"(
3022     .function f64 main(i32 a0){
3023         lda a0
3024         i32tof64
3025         return.64
3026     }
3027     )";
3028     ASSERT_TRUE(ParseToGraph(source, "main"));
3029 
3030     auto graph = CreateGraphWithDefaultRuntime();
3031     GRAPH(graph)
3032     {
3033         PARAMETER(0, 0).s32();
3034 
3035         BASIC_BLOCK(2, -1)
3036         {
3037             INST(1, Opcode::Cast).f64().SrcType(DataType::INT32).Inputs(0);
3038             INST(2, Opcode::Return).f64().Inputs(1);
3039         }
3040     }
3041     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3042 }
3043 
3044 // Checks the build of the u32tof32 instruction
TEST_F(IrBuilderTest,U32tof32)3045 TEST_F(IrBuilderTest, U32tof32)
3046 {
3047     auto source = R"(
3048     .function f32 main(u32 a0){
3049         lda a0
3050         u32tof32
3051         return
3052     }
3053     )";
3054     ASSERT_TRUE(ParseToGraph(source, "main"));
3055 
3056     auto graph = CreateGraphWithDefaultRuntime();
3057     GRAPH(graph)
3058     {
3059         PARAMETER(0, 0).u32();
3060 
3061         BASIC_BLOCK(2, -1)
3062         {
3063             INST(1, Opcode::Cast).f32().SrcType(DataType::UINT32).Inputs(0);
3064             INST(2, Opcode::Return).f32().Inputs(1);
3065         }
3066     }
3067     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3068 }
3069 
3070 // Checks the build of the u32tof64 instruction
TEST_F(IrBuilderTest,U32tof64)3071 TEST_F(IrBuilderTest, U32tof64)
3072 {
3073     auto source = R"(
3074     .function f64 main(u32 a0){
3075         lda a0
3076         u32tof64
3077         return.64
3078     }
3079     )";
3080     ASSERT_TRUE(ParseToGraph(source, "main"));
3081 
3082     auto graph = CreateGraphWithDefaultRuntime();
3083     GRAPH(graph)
3084     {
3085         PARAMETER(0, 0).u32();
3086 
3087         BASIC_BLOCK(2, -1)
3088         {
3089             INST(1, Opcode::Cast).f64().SrcType(DataType::UINT32).Inputs(0);
3090             INST(2, Opcode::Return).f64().Inputs(1);
3091         }
3092     }
3093     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3094 }
3095 
3096 // Checks the build of the i64tof32 instruction
TEST_F(IrBuilderTest,I64tof32)3097 TEST_F(IrBuilderTest, I64tof32)
3098 {
3099     auto source = R"(
3100     .function f32 main(i64 a0){
3101         lda.64 a0
3102         i64tof32
3103         return
3104     }
3105     )";
3106     ASSERT_TRUE(ParseToGraph(source, "main"));
3107 
3108     auto graph = CreateGraphWithDefaultRuntime();
3109     GRAPH(graph)
3110     {
3111         PARAMETER(0, 0).s64();
3112 
3113         BASIC_BLOCK(2, -1)
3114         {
3115             INST(1, Opcode::Cast).f32().SrcType(DataType::INT64).Inputs(0);
3116             INST(2, Opcode::Return).f32().Inputs(1);
3117         }
3118     }
3119     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3120 }
3121 
3122 // Checks the build of the i64tof64 instruction
TEST_F(IrBuilderTest,I64tof64)3123 TEST_F(IrBuilderTest, I64tof64)
3124 {
3125     auto source = R"(
3126     .function f64 main(i64 a0){
3127         lda.64 a0
3128         i64tof64
3129         return.64
3130     }
3131     )";
3132     ASSERT_TRUE(ParseToGraph(source, "main"));
3133 
3134     auto graph = CreateGraphWithDefaultRuntime();
3135     GRAPH(graph)
3136     {
3137         PARAMETER(0, 0).s64();
3138 
3139         BASIC_BLOCK(2, -1)
3140         {
3141             INST(1, Opcode::Cast).f64().SrcType(DataType::INT64).Inputs(0);
3142             INST(2, Opcode::Return).f64().Inputs(1);
3143         }
3144     }
3145     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3146 }
3147 
3148 // Checks the build of the u64tof32 instruction
TEST_F(IrBuilderTest,U64tof32)3149 TEST_F(IrBuilderTest, U64tof32)
3150 {
3151     auto source = R"(
3152     .function f32 main(u64 a0){
3153         lda.64 a0
3154         u64tof32
3155         return
3156     }
3157     )";
3158     ASSERT_TRUE(ParseToGraph(source, "main"));
3159 
3160     auto graph = CreateGraphWithDefaultRuntime();
3161     GRAPH(graph)
3162     {
3163         PARAMETER(0, 0).u64();
3164 
3165         BASIC_BLOCK(2, -1)
3166         {
3167             INST(1, Opcode::Cast).f32().SrcType(DataType::UINT64).Inputs(0);
3168             INST(2, Opcode::Return).f32().Inputs(1);
3169         }
3170     }
3171     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3172 }
3173 
3174 // Checks the build of the u64tof64 instruction
TEST_F(IrBuilderTest,U64tof64)3175 TEST_F(IrBuilderTest, U64tof64)
3176 {
3177     auto source = R"(
3178     .function f64 main(u64 a0){
3179         lda.64 a0
3180         u64tof64
3181         return.64
3182     }
3183     )";
3184     ASSERT_TRUE(ParseToGraph(source, "main"));
3185 
3186     auto graph = CreateGraphWithDefaultRuntime();
3187     GRAPH(graph)
3188     {
3189         PARAMETER(0, 0).u64();
3190 
3191         BASIC_BLOCK(2, -1)
3192         {
3193             INST(1, Opcode::Cast).f64().SrcType(DataType::UINT64).Inputs(0);
3194             INST(2, Opcode::Return).f64().Inputs(1);
3195         }
3196     }
3197     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3198 }
3199 
3200 // Checks the build of the f32toi32 instruction
TEST_F(IrBuilderTest,F32toi32)3201 TEST_F(IrBuilderTest, F32toi32)
3202 {
3203     auto source = R"(
3204     .function i32 main(f32 a0){
3205         lda a0
3206         f32toi32
3207         return
3208     }
3209     )";
3210     ASSERT_TRUE(ParseToGraph(source, "main"));
3211 
3212     auto graph = CreateGraphWithDefaultRuntime();
3213     GRAPH(graph)
3214     {
3215         PARAMETER(0, 0).f32();
3216 
3217         BASIC_BLOCK(2, -1)
3218         {
3219             INST(1, Opcode::Cast).s32().SrcType(DataType::FLOAT32).Inputs(0);
3220             INST(2, Opcode::Return).s32().Inputs(1);
3221         }
3222     }
3223     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3224 }
3225 
3226 // Checks the build of the f32toi64 instruction
TEST_F(IrBuilderTest,F32toi64)3227 TEST_F(IrBuilderTest, F32toi64)
3228 {
3229     auto source = R"(
3230     .function i64 main(f32 a0){
3231         lda a0
3232         f32toi64
3233         return.64
3234     }
3235     )";
3236     ASSERT_TRUE(ParseToGraph(source, "main"));
3237 
3238     auto graph = CreateGraphWithDefaultRuntime();
3239     GRAPH(graph)
3240     {
3241         PARAMETER(0, 0).f32();
3242 
3243         BASIC_BLOCK(2, -1)
3244         {
3245             INST(1, Opcode::Cast).s64().SrcType(DataType::FLOAT32).Inputs(0);
3246             INST(2, Opcode::Return).s64().Inputs(1);
3247         }
3248     }
3249     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3250 }
3251 
3252 // Checks the build of the f32tou32 instruction
TEST_F(IrBuilderTest,F32tou32)3253 TEST_F(IrBuilderTest, F32tou32)
3254 {
3255     auto source = R"(
3256     .function u32 main(f32 a0){
3257         lda a0
3258         f32tou32
3259         return
3260     }
3261     )";
3262     ASSERT_TRUE(ParseToGraph(source, "main"));
3263 
3264     auto graph = CreateGraphWithDefaultRuntime();
3265     GRAPH(graph)
3266     {
3267         PARAMETER(0, 0).f32();
3268 
3269         BASIC_BLOCK(2, -1)
3270         {
3271             INST(1, Opcode::Cast).u32().SrcType(DataType::FLOAT32).Inputs(0);
3272             INST(2, Opcode::Return).u32().Inputs(1);
3273         }
3274     }
3275     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3276 }
3277 
3278 // Checks the build of the f32tou64 instruction
TEST_F(IrBuilderTest,F32tou64)3279 TEST_F(IrBuilderTest, F32tou64)
3280 {
3281     auto source = R"(
3282     .function u64 main(f32 a0){
3283         lda a0
3284         f32tou64
3285         return.64
3286     }
3287     )";
3288     ASSERT_TRUE(ParseToGraph(source, "main"));
3289 
3290     auto graph = CreateGraphWithDefaultRuntime();
3291     GRAPH(graph)
3292     {
3293         PARAMETER(0, 0).f32();
3294 
3295         BASIC_BLOCK(2, -1)
3296         {
3297             INST(1, Opcode::Cast).u64().SrcType(DataType::FLOAT32).Inputs(0);
3298             INST(2, Opcode::Return).u64().Inputs(1);
3299         }
3300     }
3301     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3302 }
3303 
3304 // Checks the build of the f32tof64 instruction
TEST_F(IrBuilderTest,F32tof64)3305 TEST_F(IrBuilderTest, F32tof64)
3306 {
3307     auto source = R"(
3308     .function f64 main(f32 a0){
3309         lda a0
3310         f32tof64
3311         return.64
3312     }
3313     )";
3314     ASSERT_TRUE(ParseToGraph(source, "main"));
3315 
3316     auto graph = CreateGraphWithDefaultRuntime();
3317     GRAPH(graph)
3318     {
3319         PARAMETER(0, 0).f32();
3320 
3321         BASIC_BLOCK(2, -1)
3322         {
3323             INST(1, Opcode::Cast).f64().SrcType(DataType::FLOAT32).Inputs(0);
3324             INST(2, Opcode::Return).f64().Inputs(1);
3325         }
3326     }
3327     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3328 }
3329 
3330 // Checks the build of the f64toi32 instruction
TEST_F(IrBuilderTest,F64toi32)3331 TEST_F(IrBuilderTest, F64toi32)
3332 {
3333     auto source = R"(
3334     .function i32 main(f64 a0){
3335         lda.64 a0
3336         f64toi32
3337         return
3338     }
3339     )";
3340     ASSERT_TRUE(ParseToGraph(source, "main"));
3341 
3342     auto graph = CreateGraphWithDefaultRuntime();
3343     GRAPH(graph)
3344     {
3345         PARAMETER(0, 0).f64();
3346 
3347         BASIC_BLOCK(2, -1)
3348         {
3349             INST(1, Opcode::Cast).s32().SrcType(DataType::FLOAT64).Inputs(0);
3350             INST(2, Opcode::Return).s32().Inputs(1);
3351         }
3352     }
3353     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3354 }
3355 
3356 // Checks the build of the f64toi64 instruction
TEST_F(IrBuilderTest,F64toi64)3357 TEST_F(IrBuilderTest, F64toi64)
3358 {
3359     auto source = R"(
3360     .function i64 main(f64 a0){
3361         lda.64 a0
3362         f64toi64
3363         return.64
3364     }
3365     )";
3366     ASSERT_TRUE(ParseToGraph(source, "main"));
3367 
3368     auto graph = CreateGraphWithDefaultRuntime();
3369     GRAPH(graph)
3370     {
3371         PARAMETER(0, 0).f64();
3372 
3373         BASIC_BLOCK(2, -1)
3374         {
3375             INST(1, Opcode::Cast).s64().SrcType(DataType::FLOAT64).Inputs(0);
3376             INST(2, Opcode::Return).s64().Inputs(1);
3377         }
3378     }
3379     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3380 }
3381 
3382 // Checks the build of the f64tou32 instruction
TEST_F(IrBuilderTest,F64tou32)3383 TEST_F(IrBuilderTest, F64tou32)
3384 {
3385     auto source = R"(
3386     .function u32 main(f64 a0){
3387         lda.64 a0
3388         f64tou32
3389         return
3390     }
3391     )";
3392     ASSERT_TRUE(ParseToGraph(source, "main"));
3393 
3394     auto graph = CreateGraphWithDefaultRuntime();
3395     GRAPH(graph)
3396     {
3397         PARAMETER(0, 0).f64();
3398 
3399         BASIC_BLOCK(2, -1)
3400         {
3401             INST(1, Opcode::Cast).u32().SrcType(DataType::FLOAT64).Inputs(0);
3402             INST(2, Opcode::Return).u32().Inputs(1);
3403         }
3404     }
3405     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3406 }
3407 
3408 // Checks the build of the f64tou64 instruction
TEST_F(IrBuilderTest,F64tou64)3409 TEST_F(IrBuilderTest, F64tou64)
3410 {
3411     auto source = R"(
3412     .function u64 main(f64 a0){
3413         lda.64 a0
3414         f64tou64
3415         return.64
3416     }
3417     )";
3418     ASSERT_TRUE(ParseToGraph(source, "main"));
3419 
3420     auto graph = CreateGraphWithDefaultRuntime();
3421     GRAPH(graph)
3422     {
3423         PARAMETER(0, 0).f64();
3424 
3425         BASIC_BLOCK(2, -1)
3426         {
3427             INST(1, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(0);
3428             INST(2, Opcode::Return).u64().Inputs(1);
3429         }
3430     }
3431     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3432 }
3433 
3434 // Checks the build of the f64tof32 instruction
TEST_F(IrBuilderTest,F64tof32)3435 TEST_F(IrBuilderTest, F64tof32)
3436 {
3437     auto source = R"(
3438     .function f32 main(f64 a0){
3439         lda.64 a0
3440         f64tof32
3441         return
3442     }
3443     )";
3444     ASSERT_TRUE(ParseToGraph(source, "main"));
3445 
3446     auto graph = CreateGraphWithDefaultRuntime();
3447     GRAPH(graph)
3448     {
3449         PARAMETER(0, 0).f64();
3450 
3451         BASIC_BLOCK(2, -1)
3452         {
3453             INST(1, Opcode::Cast).f32().SrcType(DataType::FLOAT64).Inputs(0);
3454             INST(2, Opcode::Return).f32().Inputs(1);
3455         }
3456     }
3457     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3458 }
3459 
3460 // Checks the build of the i32toi64 instruction
TEST_F(IrBuilderTest,I32toi64)3461 TEST_F(IrBuilderTest, I32toi64)
3462 {
3463     auto source = R"(
3464     .function i64 main(i32 a0){
3465         lda a0
3466         i32toi64
3467         return
3468     }
3469     )";
3470     ASSERT_TRUE(ParseToGraph(source, "main"));
3471     auto graph = CreateGraphWithDefaultRuntime();
3472     GRAPH(graph)
3473     {
3474         PARAMETER(0, 0).s32();
3475 
3476         BASIC_BLOCK(2, -1)
3477         {
3478             INST(1, Opcode::Cast).s64().SrcType(DataType::INT32).Inputs(0);
3479             INST(2, Opcode::Return).s64().Inputs(1);
3480         }
3481     }
3482     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3483 }
3484 
3485 // Checks the build of the i64toi32 instruction
TEST_F(IrBuilderTest,I64toi32)3486 TEST_F(IrBuilderTest, I64toi32)
3487 {
3488     auto source = R"(
3489     .function i32 main(i64 a0){
3490         lda.64 a0
3491         i64toi32
3492         return
3493     }
3494     )";
3495     ASSERT_TRUE(ParseToGraph(source, "main"));
3496     auto graph = CreateGraphWithDefaultRuntime();
3497     GRAPH(graph)
3498     {
3499         PARAMETER(0, 0).s64();
3500 
3501         BASIC_BLOCK(2, -1)
3502         {
3503             INST(1, Opcode::Cast).s32().SrcType(DataType::INT64).Inputs(0);
3504             INST(2, Opcode::Return).s32().Inputs(1);
3505         }
3506     }
3507     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3508 }
3509 
3510 // Checks the build of the u32toi64 instruction
TEST_F(IrBuilderTest,U32toi64)3511 TEST_F(IrBuilderTest, U32toi64)
3512 {
3513     auto source = R"(
3514     .function i64 main(u32 a0){
3515         lda a0
3516         u32toi64
3517         return
3518     }
3519     )";
3520     ASSERT_TRUE(ParseToGraph(source, "main"));
3521     auto graph = CreateGraphWithDefaultRuntime();
3522     GRAPH(graph)
3523     {
3524         PARAMETER(0, 0).u32();
3525 
3526         BASIC_BLOCK(2, -1)
3527         {
3528             INST(1, Opcode::Cast).s64().SrcType(DataType::UINT32).Inputs(0);
3529             INST(2, Opcode::Return).s64().Inputs(1);
3530         }
3531     }
3532     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3533 }
3534 
3535 // Checks the build of the ldarr.8 instruction
TEST_F(IrBuilderTest,Ldarr8)3536 TEST_F(IrBuilderTest, Ldarr8)
3537 {
3538     auto source = R"(
3539     .function i8 main(i32 a0, i8[] a1){
3540         lda a0
3541         ldarr.8 a1
3542         return
3543     }
3544     )";
3545     ASSERT_TRUE(ParseToGraph(source, "main"));
3546     auto graph = CreateGraphWithDefaultRuntime();
3547     GRAPH(graph)
3548     {
3549         PARAMETER(0, 0).s32();
3550         PARAMETER(1, 1).ref();
3551 
3552         BASIC_BLOCK(2, -1)
3553         {
3554             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3555             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3556             INST(4, Opcode::LenArray).s32().Inputs(3);
3557             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3558             INST(6, Opcode::LoadArray).s8().Inputs(3, 5);
3559             INST(7, Opcode::Return).s8().Inputs(6);
3560         }
3561     }
3562     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3563 }
3564 
3565 // Checks the build of the ldarru.8 instruction
TEST_F(IrBuilderTest,Ldarru8)3566 TEST_F(IrBuilderTest, Ldarru8)
3567 {
3568     auto source = R"(
3569     .function u8 main(i32 a0, u8[] a1){
3570         lda a0
3571         ldarru.8 a1
3572         return
3573     }
3574     )";
3575     ASSERT_TRUE(ParseToGraph(source, "main"));
3576     auto graph = CreateGraphWithDefaultRuntime();
3577     GRAPH(graph)
3578     {
3579         PARAMETER(0, 0).s32();
3580         PARAMETER(1, 1).ref();
3581 
3582         BASIC_BLOCK(2, -1)
3583         {
3584             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3585             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3586             INST(4, Opcode::LenArray).s32().Inputs(3);
3587             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3588             INST(6, Opcode::LoadArray).u8().Inputs(3, 5);
3589             INST(7, Opcode::Return).u8().Inputs(6);
3590         }
3591     }
3592     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3593 }
3594 
3595 // Checks the build of the ldarr.16 instruction
TEST_F(IrBuilderTest,Ldarr16)3596 TEST_F(IrBuilderTest, Ldarr16)
3597 {
3598     auto source = R"(
3599     .function i16 main(i32 a0, i16[] a1){
3600         lda a0
3601         ldarr.16 a1
3602         return
3603     }
3604     )";
3605     ASSERT_TRUE(ParseToGraph(source, "main"));
3606     auto graph = CreateGraphWithDefaultRuntime();
3607     GRAPH(graph)
3608     {
3609         PARAMETER(0, 0).s32();
3610         PARAMETER(1, 1).ref();
3611 
3612         BASIC_BLOCK(2, -1)
3613         {
3614             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3615             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3616             INST(4, Opcode::LenArray).s32().Inputs(3);
3617             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3618             INST(6, Opcode::LoadArray).s16().Inputs(3, 5);
3619             INST(7, Opcode::Return).s16().Inputs(6);
3620         }
3621     }
3622     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3623 }
3624 
3625 // Checks the build of the ldarru.16 instruction
TEST_F(IrBuilderTest,Ldarru16)3626 TEST_F(IrBuilderTest, Ldarru16)
3627 {
3628     auto source = R"(
3629     .function u16 main(i32 a0, u16[] a1){
3630         lda a0
3631         ldarru.16 a1
3632         return
3633     }
3634     )";
3635     ASSERT_TRUE(ParseToGraph(source, "main"));
3636     auto graph = CreateGraphWithDefaultRuntime();
3637     GRAPH(graph)
3638     {
3639         PARAMETER(0, 0).s32();
3640         PARAMETER(1, 1).ref();
3641 
3642         BASIC_BLOCK(2, -1)
3643         {
3644             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3645             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3646             INST(4, Opcode::LenArray).s32().Inputs(3);
3647             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3648             INST(6, Opcode::LoadArray).u16().Inputs(3, 5);
3649             INST(7, Opcode::Return).u16().Inputs(6);
3650         }
3651     }
3652     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3653 }
3654 
3655 // Checks the build of the ldarr instruction
TEST_F(IrBuilderTest,Ldarr)3656 TEST_F(IrBuilderTest, Ldarr)
3657 {
3658     auto source = R"(
3659     .function i32 main(i32 a0, i32[] a1){
3660         lda a0
3661         ldarr a1
3662         return
3663     }
3664     )";
3665     ASSERT_TRUE(ParseToGraph(source, "main"));
3666     auto graph = CreateGraphWithDefaultRuntime();
3667     GRAPH(graph)
3668     {
3669         PARAMETER(0, 0).s32();
3670         PARAMETER(1, 1).ref();
3671 
3672         BASIC_BLOCK(2, -1)
3673         {
3674             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3675             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3676             INST(4, Opcode::LenArray).s32().Inputs(3);
3677             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3678             INST(6, Opcode::LoadArray).s32().Inputs(3, 5);
3679             INST(7, Opcode::Return).s32().Inputs(6);
3680         }
3681     }
3682     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3683 }
3684 
3685 // Checks the build of the fldarr.32 instruction
TEST_F(IrBuilderTest,Fldarr32)3686 TEST_F(IrBuilderTest, Fldarr32)
3687 {
3688     auto source = R"(
3689     .function f32 main(i32 a0, f32[] a1){
3690         lda a0
3691         fldarr.32 a1
3692         return
3693     }
3694     )";
3695     ASSERT_TRUE(ParseToGraph(source, "main"));
3696     auto graph = CreateGraphWithDefaultRuntime();
3697     GRAPH(graph)
3698     {
3699         PARAMETER(0, 0).s32();
3700         PARAMETER(1, 1).ref();
3701 
3702         BASIC_BLOCK(2, -1)
3703         {
3704             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3705             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3706             INST(4, Opcode::LenArray).s32().Inputs(3);
3707             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3708             INST(6, Opcode::LoadArray).f32().Inputs(3, 5);
3709             INST(8, Opcode::Return).f32().Inputs(6);
3710         }
3711     }
3712     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3713 }
3714 
3715 // Checks the build of the ldarr.64 instruction
TEST_F(IrBuilderTest,Ldarr64)3716 TEST_F(IrBuilderTest, Ldarr64)
3717 {
3718     auto source = R"(
3719     .function u64 main(i32 a0, u64[] a1){
3720         lda a0
3721         ldarr.64 a1
3722         return
3723     }
3724     )";
3725     ASSERT_TRUE(ParseToGraph(source, "main"));
3726     auto graph = CreateGraphWithDefaultRuntime();
3727     GRAPH(graph)
3728     {
3729         PARAMETER(0, 0).s32();
3730         PARAMETER(1, 1).ref();
3731 
3732         BASIC_BLOCK(2, -1)
3733         {
3734             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3735             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3736             INST(4, Opcode::LenArray).s32().Inputs(3);
3737             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3738             INST(6, Opcode::LoadArray).s64().Inputs(3, 5);
3739             INST(7, Opcode::Return).u64().Inputs(6);
3740         }
3741     }
3742     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3743 }
3744 
3745 // Checks the build of the fldarr.64 instruction
TEST_F(IrBuilderTest,Fldarr64)3746 TEST_F(IrBuilderTest, Fldarr64)
3747 {
3748     auto source = R"(
3749     .function f64 main(i32 a0, f64[] a1){
3750         lda a0
3751         fldarr.64 a1
3752         return
3753     }
3754     )";
3755     ASSERT_TRUE(ParseToGraph(source, "main"));
3756     auto graph = CreateGraphWithDefaultRuntime();
3757     GRAPH(graph)
3758     {
3759         PARAMETER(0, 0).s32();
3760         PARAMETER(1, 1).ref();
3761 
3762         BASIC_BLOCK(2, -1)
3763         {
3764             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3765             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3766             INST(4, Opcode::LenArray).s32().Inputs(3);
3767             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3768             INST(6, Opcode::LoadArray).f64().Inputs(3, 5);
3769             INST(7, Opcode::Return).f64().Inputs(6);
3770         }
3771     }
3772     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3773 }
3774 
3775 // Checks the build of the ldarr.obj instruction
TEST_F(IrBuilderTest,LdarrObj)3776 TEST_F(IrBuilderTest, LdarrObj)
3777 {
3778     auto source = R"(
3779     .record panda.String <external>
3780     .function panda.String main(i32 a0, panda.String[] a1){
3781         lda a0
3782         ldarr.obj a1
3783         return
3784     }
3785     )";
3786     ASSERT_TRUE(ParseToGraph(source, "main"));
3787     auto graph = CreateGraphWithDefaultRuntime();
3788     GRAPH(graph)
3789     {
3790         PARAMETER(0, 0).s32();
3791         PARAMETER(1, 1).ref();
3792 
3793         BASIC_BLOCK(2, -1)
3794         {
3795             INST(2, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
3796             INST(3, Opcode::NullCheck).ref().Inputs(1, 2);
3797             INST(4, Opcode::LenArray).s32().Inputs(3);
3798             INST(5, Opcode::BoundsCheck).s32().Inputs(4, 0, 2);
3799             INST(6, Opcode::LoadArray).ref().Inputs(3, 5);
3800             INST(7, Opcode::Return).ref().Inputs(6);
3801         }
3802     }
3803     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3804 }
3805 
3806 // Checks the build of the starr.8 instruction
TEST_F(IrBuilderTest,Starr8)3807 TEST_F(IrBuilderTest, Starr8)
3808 {
3809     auto source = R"(
3810     .function void main(i32 a0, u8[] a1, u8 a2){
3811         lda a2
3812         starr.8 a1, a0
3813         return.void
3814     }
3815     )";
3816     ASSERT_TRUE(ParseToGraph(source, "main"));
3817     auto graph = CreateGraphWithDefaultRuntime();
3818     GRAPH(graph)
3819     {
3820         PARAMETER(0, 0).s32();
3821         PARAMETER(1, 1).ref();
3822         PARAMETER(2, 2).u8();
3823 
3824         BASIC_BLOCK(2, -1)
3825         {
3826             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3827             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3828             INST(5, Opcode::LenArray).s32().Inputs(4);
3829             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3830             INST(7, Opcode::StoreArray).s8().Inputs(4, 6, 2);
3831             INST(8, Opcode::ReturnVoid).v0id();
3832         }
3833     }
3834     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3835 }
3836 
3837 // Checks the build of the starr.16 instruction
TEST_F(IrBuilderTest,Starr16)3838 TEST_F(IrBuilderTest, Starr16)
3839 {
3840     auto source = R"(
3841     .function void main(i32 a0, u16[] a1, u16 a2){
3842         lda a2
3843         starr.16 a1, a0
3844         return.void
3845     }
3846     )";
3847     ASSERT_TRUE(ParseToGraph(source, "main"));
3848     auto graph = CreateGraphWithDefaultRuntime();
3849     GRAPH(graph)
3850     {
3851         PARAMETER(0, 0).s32();
3852         PARAMETER(1, 1).ref();
3853         PARAMETER(2, 2).u16();
3854 
3855         BASIC_BLOCK(2, -1)
3856         {
3857             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3858             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3859             INST(5, Opcode::LenArray).s32().Inputs(4);
3860             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3861             INST(7, Opcode::StoreArray).s16().Inputs(4, 6, 2);
3862             INST(8, Opcode::ReturnVoid).v0id();
3863         }
3864     }
3865     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3866 }
3867 
3868 // Checks the build of the starr instruction
TEST_F(IrBuilderTest,Starr)3869 TEST_F(IrBuilderTest, Starr)
3870 {
3871     auto source = R"(
3872     .function void main(i32 a0, i32[] a1, i32 a2){
3873         lda a2
3874         starr a1, a0
3875         return.void
3876     }
3877     )";
3878     ASSERT_TRUE(ParseToGraph(source, "main"));
3879     auto graph = CreateGraphWithDefaultRuntime();
3880     GRAPH(graph)
3881     {
3882         PARAMETER(0, 0).s32();
3883         PARAMETER(1, 1).ref();
3884         PARAMETER(2, 2).s32();
3885 
3886         BASIC_BLOCK(2, -1)
3887         {
3888             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3889             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3890             INST(5, Opcode::LenArray).s32().Inputs(4);
3891             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3892             INST(7, Opcode::StoreArray).s32().Inputs(4, 6, 2);
3893             INST(8, Opcode::ReturnVoid).v0id();
3894         }
3895     }
3896     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3897 }
3898 
3899 // Checks the build of the fstarr.32 instruction
TEST_F(IrBuilderTest,Fstarr32)3900 TEST_F(IrBuilderTest, Fstarr32)
3901 {
3902     auto source = R"(
3903     .function void main(i32 a0, f32[] a1, f32 a2){
3904         lda a2
3905         fstarr.32 a1, a0
3906         return.void
3907     }
3908     )";
3909     ASSERT_TRUE(ParseToGraph(source, "main"));
3910     auto graph = CreateGraphWithDefaultRuntime();
3911     GRAPH(graph)
3912     {
3913         PARAMETER(0, 0).s32();
3914         PARAMETER(1, 1).ref();
3915         PARAMETER(2, 2).f32();
3916 
3917         BASIC_BLOCK(2, -1)
3918         {
3919             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3920             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3921             INST(5, Opcode::LenArray).s32().Inputs(4);
3922             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3923             INST(8, Opcode::StoreArray).f32().Inputs(4, 6, 2);
3924             INST(9, Opcode::ReturnVoid).v0id();
3925         }
3926     }
3927     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3928 }
3929 
3930 // Checks the build of the starr.64 instruction
TEST_F(IrBuilderTest,Starr64)3931 TEST_F(IrBuilderTest, Starr64)
3932 {
3933     auto source = R"(
3934     .function void main(i32 a0, i64[] a1, i64 a2){
3935         lda.64 a2
3936         starr.64 a1, a0
3937         return.void
3938     }
3939     )";
3940     ASSERT_TRUE(ParseToGraph(source, "main"));
3941     auto graph = CreateGraphWithDefaultRuntime();
3942     GRAPH(graph)
3943     {
3944         PARAMETER(0, 0).s32();
3945         PARAMETER(1, 1).ref();
3946         PARAMETER(2, 2).s64();
3947 
3948         BASIC_BLOCK(2, -1)
3949         {
3950             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3951             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3952             INST(5, Opcode::LenArray).s32().Inputs(4);
3953             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3954             INST(7, Opcode::StoreArray).s64().Inputs(4, 6, 2);
3955             INST(8, Opcode::ReturnVoid).v0id();
3956         }
3957     }
3958     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3959 }
3960 
3961 // Checks the build of the fstarr.64 instruction
TEST_F(IrBuilderTest,Fstarr64)3962 TEST_F(IrBuilderTest, Fstarr64)
3963 {
3964     auto source = R"(
3965     .function void main(i32 a0, f64[] a1, f64 a2){
3966         lda.64 a2
3967         fstarr.64 a1, a0
3968         return.void
3969     }
3970     )";
3971     ASSERT_TRUE(ParseToGraph(source, "main"));
3972     auto graph = CreateGraphWithDefaultRuntime();
3973     GRAPH(graph)
3974     {
3975         PARAMETER(0, 0).s32();
3976         PARAMETER(1, 1).ref();
3977         PARAMETER(2, 2).f64();
3978 
3979         BASIC_BLOCK(2, -1)
3980         {
3981             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
3982             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
3983             INST(5, Opcode::LenArray).s32().Inputs(4);
3984             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
3985             INST(7, Opcode::StoreArray).f64().Inputs(4, 6, 2);
3986             INST(8, Opcode::ReturnVoid).v0id();
3987         }
3988     }
3989     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
3990 }
3991 
3992 // Checks the build of the starr.obj instruction
TEST_F(IrBuilderTest,StarrObj)3993 TEST_F(IrBuilderTest, StarrObj)
3994 {
3995     auto source = R"(
3996     .record panda.String <external>
3997     .function void main(i32 a0, panda.String[] a1, panda.String a2){
3998         lda.obj a2
3999         starr.obj a1, a0
4000         return.void
4001     }
4002     )";
4003     ASSERT_TRUE(ParseToGraph(source, "main"));
4004     auto graph = CreateGraphWithDefaultRuntime();
4005     GRAPH(graph)
4006     {
4007         PARAMETER(0, 0).s32();
4008         PARAMETER(1, 1).ref();
4009         PARAMETER(2, 2).ref();
4010 
4011         BASIC_BLOCK(2, -1)
4012         {
4013             INST(3, Opcode::SaveState).Inputs(0, 1, 2, 2).SrcVregs({0, 1, 2, 3});
4014             INST(4, Opcode::NullCheck).ref().Inputs(1, 3);
4015             INST(5, Opcode::LenArray).s32().Inputs(4);
4016             INST(6, Opcode::BoundsCheck).s32().Inputs(5, 0, 3);
4017             INST(9, Opcode::RefTypeCheck).ref().Inputs(4, 2, 3);
4018             INST(7, Opcode::StoreArray).ref().Inputs(4, 6, 9);
4019             INST(8, Opcode::ReturnVoid).v0id();
4020         }
4021     }
4022     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4023 }
4024 
4025 // Checks the build of the lenarr instruction
TEST_F(IrBuilderTest,Lenarr)4026 TEST_F(IrBuilderTest, Lenarr)
4027 {
4028     auto source = R"(
4029     .function i32 main(i32[] a0){
4030         lenarr a0
4031         return
4032     }
4033     )";
4034     ASSERT_TRUE(ParseToGraph(source, "main"));
4035     auto graph = CreateGraphWithDefaultRuntime();
4036     GRAPH(graph)
4037     {
4038         PARAMETER(0, 0).ref();
4039 
4040         BASIC_BLOCK(2, -1)
4041         {
4042             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4043             INST(2, Opcode::NullCheck).ref().Inputs(0, 1);
4044             INST(3, Opcode::LenArray).s32().Inputs(2);
4045             INST(4, Opcode::Return).s32().Inputs(3);
4046         }
4047     }
4048     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4049 }
4050 
4051 // Checks the build of the newarr instruction
TEST_F(IrBuilderTest,Newarr)4052 TEST_F(IrBuilderTest, Newarr)
4053 {
4054     auto source = R"(
4055     .function i32[] main(i32 a0){
4056         newarr a0, a0, i32[]
4057         lda.obj a0
4058         return
4059     }
4060     )";
4061     ASSERT_TRUE(ParseToGraph(source, "main"));
4062     auto graph = CreateGraphWithDefaultRuntime();
4063     GRAPH(graph)
4064     {
4065         PARAMETER(0, 1).s32();
4066 
4067         BASIC_BLOCK(2, -1)
4068         {
4069             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4070             INST(44, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(68);
4071             INST(2, Opcode::NegativeCheck).s32().Inputs(0, 1);
4072             INST(3, Opcode::NewArray).ref().Inputs(44, 2, 1);
4073             INST(4, Opcode::Return).ref().Inputs(3);
4074         }
4075     }
4076     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4077 }
4078 
4079 // Checks the build of lda.const instruction
TEST_F(IrBuilderTest,LdaConst)4080 TEST_F(IrBuilderTest, LdaConst)
4081 {
4082     auto source = R"(
4083 .array array0 panda.String 3 { "a" "ab" "abc"}
4084 .array array1 u1 3 { 0 1 0}
4085 .array array2 i32 3 { 2 3 4}
4086 .array array3 f32 3 { 5.0 6.0 7.0 }
4087 
4088 .function void main() {
4089 lda.const v0, array0
4090 lda.const v1, array1
4091 lda.const v2, array2
4092 lda.const v3, array3
4093 return.void
4094 }
4095 )";
4096     auto default_option = options.GetCompilerUnfoldConstArrayMaxSize();
4097     options.SetCompilerUnfoldConstArrayMaxSize(2);
4098     ASSERT_TRUE(ParseToGraph(source, "main"));
4099     auto graph = CreateGraphWithDefaultRuntime();
4100     GRAPH(graph)
4101     {
4102         CONSTANT(40, 3).s64();
4103         BASIC_BLOCK(2, -1)
4104         {
4105             // string array
4106             INST(0, Opcode::SaveState).NoVregs();
4107             INST(1, Opcode::LoadConstArray).ref().Inputs(0);
4108 
4109             // bool array
4110             INST(12, Opcode::SaveState).Inputs(1).SrcVregs({0});
4111             INST(44, Opcode::LoadAndInitClass).ref().Inputs(12).TypeId(68);
4112             INST(13, Opcode::NegativeCheck).s32().Inputs(40, 12);
4113             INST(14, Opcode::NewArray).ref().Inputs(44, 13, 12);
4114 
4115             INST(15, Opcode::SaveState).Inputs(1, 14).SrcVregs({0, 1});
4116             INST(16, Opcode::FillConstArray).s8().Inputs(14, 15);
4117 
4118             // int array
4119             INST(22, Opcode::SaveState).Inputs(1, 14).SrcVregs({0, 1});
4120             INST(45, Opcode::LoadAndInitClass).ref().Inputs(22).TypeId(68);
4121             INST(23, Opcode::NegativeCheck).s32().Inputs(40, 22);
4122             INST(24, Opcode::NewArray).ref().Inputs(45, 23, 22);
4123 
4124             INST(25, Opcode::SaveState).Inputs(1, 14, 24).SrcVregs({0, 1, 2});
4125             INST(26, Opcode::FillConstArray).s32().Inputs(24, 25);
4126 
4127             // float array
4128             INST(32, Opcode::SaveState).Inputs(1, 14, 24).SrcVregs({0, 1, 2});
4129             INST(46, Opcode::LoadAndInitClass).ref().Inputs(32).TypeId(68);
4130             INST(33, Opcode::NegativeCheck).s32().Inputs(40, 32);
4131             INST(34, Opcode::NewArray).ref().Inputs(46, 33, 32);
4132 
4133             INST(35, Opcode::SaveState).Inputs(1, 14, 24, 34).SrcVregs({0, 1, 2, 3});
4134             INST(36, Opcode::FillConstArray).f32().Inputs(34, 35);
4135 
4136             INST(8, Opcode::ReturnVoid).v0id();
4137         }
4138     }
4139     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4140     options.SetCompilerUnfoldConstArrayMaxSize(default_option);
4141 }
4142 
4143 // Checks the build of unfolded lda.const instruction
TEST_F(IrBuilderTest,LdaConstUnfold)4144 TEST_F(IrBuilderTest, LdaConstUnfold)
4145 {
4146     auto source = R"(
4147 .array array0 panda.String 2 { "a" "ab" }
4148 .array array1 u1 2 { 0 1 }
4149 .array array2 i32 2 { 2 3 }
4150 .array array3 f32 2 { 4.0 5.0 }
4151 
4152 .function void main() {
4153 lda.const v0, array0
4154 lda.const v1, array1
4155 lda.const v2, array2
4156 lda.const v3, array3
4157 return.void
4158 }
4159 )";
4160     ASSERT_TRUE(ParseToGraph(source, "main"));
4161     auto graph = CreateGraphWithDefaultRuntime();
4162     GRAPH(graph)
4163     {
4164         CONSTANT(0, 2).s64();
4165         CONSTANT(4, 0).s64();
4166         CONSTANT(13, 1).s64();
4167         CONSTANT(43, 3).s64();
4168         CONSTANT(52, 4.0f).f32();
4169         CONSTANT(59, 5.0f).f32();
4170 
4171         BASIC_BLOCK(2, -1)
4172         {
4173             // string array
4174             INST(1, Opcode::SaveState).NoVregs();
4175             INST(444, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(68);
4176             INST(2, Opcode::NegativeCheck).s32().Inputs(0, 1);
4177             INST(3, Opcode::NewArray).ref().Inputs(444, 2, 1);
4178 
4179             INST(5, Opcode::SaveState).Inputs(3).SrcVregs({0});
4180             INST(6, Opcode::LoadString).ref().Inputs(5);
4181             INST(7, Opcode::SaveState).Inputs(3).SrcVregs({0});
4182             INST(8, Opcode::NullCheck).ref().Inputs(3, 7);
4183             INST(9, Opcode::LenArray).s32().Inputs(8);
4184             INST(10, Opcode::BoundsCheck).s32().Inputs(9, 4, 7);
4185             INST(11, Opcode::StoreArray).ref().Inputs(8, 10, 6);
4186 
4187             INST(14, Opcode::SaveState).Inputs(3).SrcVregs({0});
4188             INST(15, Opcode::LoadString).ref().Inputs(14);
4189             INST(16, Opcode::SaveState).Inputs(3).SrcVregs({0});
4190             INST(17, Opcode::NullCheck).ref().Inputs(3, 16);
4191             INST(18, Opcode::LenArray).s32().Inputs(17);
4192             INST(19, Opcode::BoundsCheck).s32().Inputs(18, 13, 16);
4193             INST(20, Opcode::StoreArray).ref().Inputs(17, 19, 15);
4194 
4195             // bool array
4196             INST(22, Opcode::SaveState).Inputs(3).SrcVregs({0});
4197             INST(445, Opcode::LoadAndInitClass).ref().Inputs(22).TypeId(68);
4198             INST(23, Opcode::NegativeCheck).s32().Inputs(0, 22);
4199             INST(24, Opcode::NewArray).ref().Inputs(445, 23, 22);
4200 
4201             INST(25, Opcode::SaveState).Inputs(3, 24).SrcVregs({0, 1});
4202             INST(26, Opcode::NullCheck).ref().Inputs(24, 25);
4203             INST(27, Opcode::LenArray).s32().Inputs(26);
4204             INST(28, Opcode::BoundsCheck).s32().Inputs(27, 4, 25);
4205             INST(29, Opcode::StoreArray).s8().Inputs(26, 28, 4);
4206 
4207             INST(30, Opcode::SaveState).Inputs(3, 24).SrcVregs({0, 1});
4208             INST(31, Opcode::NullCheck).ref().Inputs(24, 30);
4209             INST(32, Opcode::LenArray).s32().Inputs(31);
4210             INST(33, Opcode::BoundsCheck).s32().Inputs(32, 13, 30);
4211             INST(34, Opcode::StoreArray).s8().Inputs(31, 33, 13);
4212 
4213             // int array
4214             INST(35, Opcode::SaveState).Inputs(3, 24).SrcVregs({0, 1});
4215             INST(446, Opcode::LoadAndInitClass).ref().Inputs(35).TypeId(68);
4216             INST(36, Opcode::NegativeCheck).s32().Inputs(0, 35);
4217             INST(37, Opcode::NewArray).ref().Inputs(446, 36, 35);
4218 
4219             INST(38, Opcode::SaveState).Inputs(3, 24, 37).SrcVregs({0, 1, 2});
4220             INST(39, Opcode::NullCheck).ref().Inputs(37, 38);
4221             INST(40, Opcode::LenArray).s32().Inputs(39);
4222             INST(41, Opcode::BoundsCheck).s32().Inputs(40, 4, 38);
4223             INST(42, Opcode::StoreArray).s32().Inputs(39, 41, 0);
4224 
4225             INST(44, Opcode::SaveState).Inputs(3, 24, 37).SrcVregs({0, 1, 2});
4226             INST(45, Opcode::NullCheck).ref().Inputs(37, 44);
4227             INST(46, Opcode::LenArray).s32().Inputs(45);
4228             INST(47, Opcode::BoundsCheck).s32().Inputs(46, 13, 44);
4229             INST(48, Opcode::StoreArray).s32().Inputs(45, 47, 43);
4230 
4231             // float array
4232             INST(49, Opcode::SaveState).Inputs(3, 24, 37).SrcVregs({0, 1, 2});
4233             INST(447, Opcode::LoadAndInitClass).ref().Inputs(49).TypeId(68);
4234             INST(50, Opcode::NegativeCheck).s32().Inputs(0, 49);
4235             INST(51, Opcode::NewArray).ref().Inputs(447, 50, 49);
4236 
4237             INST(53, Opcode::SaveState).Inputs(3, 24, 37, 51).SrcVregs({0, 1, 2, 3});
4238             INST(54, Opcode::NullCheck).ref().Inputs(51, 53);
4239             INST(55, Opcode::LenArray).s32().Inputs(54);
4240             INST(56, Opcode::BoundsCheck).s32().Inputs(55, 4, 53);
4241             INST(57, Opcode::StoreArray).f32().Inputs(54, 56, 52);
4242 
4243             INST(60, Opcode::SaveState).Inputs(3, 24, 37, 51).SrcVregs({0, 1, 2, 3});
4244             INST(61, Opcode::NullCheck).ref().Inputs(51, 60);
4245             INST(62, Opcode::LenArray).s32().Inputs(61);
4246             INST(63, Opcode::BoundsCheck).s32().Inputs(62, 13, 60);
4247             INST(64, Opcode::StoreArray).f32().Inputs(61, 63, 59);
4248 
4249             INST(66, Opcode::ReturnVoid).v0id();
4250         }
4251     }
4252     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4253 }
4254 
4255 // Checks the build of the newobj instruction
TEST_F(IrBuilderTest,Newobj)4256 TEST_F(IrBuilderTest, Newobj)
4257 {
4258     auto source = R"(
4259     .record panda.String <external>
4260     .function panda.String main(){
4261         newobj v0, panda.String
4262         lda.obj v0
4263         return
4264     }
4265     )";
4266     ASSERT_TRUE(ParseToGraph(source, "main"));
4267     auto graph = CreateGraphWithDefaultRuntime();
4268     GRAPH(graph)
4269     {
4270         BASIC_BLOCK(2, -1)
4271         {
4272             INST(2, Opcode::SaveState).Inputs().SrcVregs({});
4273             INST(3, Opcode::LoadAndInitClass).ref().Inputs(2);
4274             INST(0, Opcode::NewObject).ref().Inputs(3, 2);
4275             INST(1, Opcode::Return).ref().Inputs(0);
4276         }
4277     }
4278     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4279 }
4280 
TEST_F(IrBuilderTest,Initobj)4281 TEST_F(IrBuilderTest, Initobj)
4282 {
4283     auto source = R"(
4284     .record R{
4285         i32 f
4286     }
4287     .function R main(){
4288         initobj R.ctor
4289         return
4290     }
4291     .function void R.ctor() <ctor> {
4292         return.void
4293     }
4294     )";
4295     ASSERT_TRUE(ParseToGraph(source, "main"));
4296     auto graph = CreateGraphWithDefaultRuntime();
4297     GRAPH(graph)
4298     {
4299         BASIC_BLOCK(2, -1)
4300         {
4301             INST(0, Opcode::SaveState).Inputs().SrcVregs({});
4302             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0);
4303             INST(2, Opcode::NewObject).ref().Inputs(1, 0);
4304             INST(4, Opcode::SaveState).Inputs(2).SrcVregs({0});
4305             INST(3, Opcode::CallStatic).v0id().Inputs({{DataType::REFERENCE, 2}, {DataType::NO_TYPE, 4}});
4306             INST(5, Opcode::Return).ref().Inputs(2);
4307         }
4308     }
4309     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4310 }
4311 
4312 // Enable after supporting MultiArray in panda assembly
TEST_F(IrBuilderTest,DISABLED_MultiArray)4313 TEST_F(IrBuilderTest, DISABLED_MultiArray)
4314 {
4315     // TODO(pishin): fix ctor before enabling
4316     auto source = R"(
4317     .record __I <external>
4318     .function ___I _init__i32_i32_(i32 a0, i32 a1) <ctor, external>
4319     .record panda.Array <external>
4320     .function panda.Array main(i32 a0){
4321         movi v0, 0x1
4322         initobj _init__i32_i32_ v0, a0
4323         return
4324     }
4325     )";
4326     ASSERT_TRUE(ParseToGraph(source, "main"));
4327     auto graph = CreateGraphWithDefaultRuntime();
4328     GRAPH(graph)
4329     {
4330         PARAMETER(0, 0).ref();
4331         CONSTANT(1, 1);
4332         BASIC_BLOCK(2, -1)
4333         {
4334             INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({1, 0});
4335             INST(3, Opcode::LoadAndInitClass).ref().Inputs(1);
4336             INST(4, Opcode::MultiArray)
4337                 .ref()
4338                 .Inputs({{DataType::REFERENCE, 3}, {DataType::INT32, 1}, {DataType::INT32, 0}, {DataType::NO_TYPE, 2}});
4339             INST(5, Opcode::Return).ref().Inputs(4);
4340         }
4341     }
4342     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4343 }
4344 
4345 // Checks the build of the ldobj instruction
TEST_F(IrBuilderTest,Ldobj)4346 TEST_F(IrBuilderTest, Ldobj)
4347 {
4348     auto source = R"(
4349     .record panda.String <external>
4350     .record R {
4351         i32 v_i32
4352         panda.String v_string
4353     }
4354     .function i32 main(R a0){
4355         ldobj a0, R.v_i32
4356         return
4357     }
4358     )";
4359     ASSERT_TRUE(ParseToGraph(source, "main"));
4360     auto graph = CreateGraphWithDefaultRuntime();
4361     GRAPH(graph)
4362     {
4363         PARAMETER(0, 0).ref();
4364 
4365         BASIC_BLOCK(2, -1)
4366         {
4367             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4368             INST(2, Opcode::NullCheck).ref().Inputs(0, 1);
4369             INST(3, Opcode::LoadObject).s32().Inputs(2);
4370             INST(4, Opcode::Return).s32().Inputs(3);
4371         }
4372     }
4373     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4374 }
4375 
4376 // Checks the build of the ldobj.64 instruction
TEST_F(IrBuilderTest,Ldobj64)4377 TEST_F(IrBuilderTest, Ldobj64)
4378 {
4379     auto source = R"(
4380     .record panda.String <external>
4381     .record R {
4382         i64 v_i64
4383         panda.String v_string
4384     }
4385     .function i64 main(R a0){
4386         ldobj.64 a0, R.v_i64
4387         return
4388     }
4389     )";
4390     ASSERT_TRUE(ParseToGraph(source, "main"));
4391     auto graph = CreateGraphWithDefaultRuntime();
4392     GRAPH(graph)
4393     {
4394         PARAMETER(0, 0).ref();
4395 
4396         BASIC_BLOCK(2, -1)
4397         {
4398             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4399             INST(2, Opcode::NullCheck).ref().Inputs(0, 1);
4400             INST(3, Opcode::LoadObject).s64().Inputs(2);
4401             INST(4, Opcode::Return).s64().Inputs(3);
4402         }
4403     }
4404 
4405     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4406 }
4407 
4408 // Checks the build of the ldobj.obj instruction
TEST_F(IrBuilderTest,LdobjObj)4409 TEST_F(IrBuilderTest, LdobjObj)
4410 {
4411     auto source = R"(
4412     .record panda.String <external>
4413     .record R {
4414         i32 v_i32
4415         panda.String v_string
4416     }
4417     .function panda.String main(R a0){
4418         ldobj.obj a0, R.v_string
4419         return.obj
4420     }
4421     )";
4422     ASSERT_TRUE(ParseToGraph(source, "main"));
4423     auto graph = CreateGraphWithDefaultRuntime();
4424     GRAPH(graph)
4425     {
4426         PARAMETER(0, 0).ref();
4427 
4428         BASIC_BLOCK(2, -1)
4429         {
4430             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4431             INST(2, Opcode::NullCheck).ref().Inputs(0, 1);
4432             INST(3, Opcode::LoadObject).ref().Inputs(2);
4433             INST(4, Opcode::Return).ref().Inputs(3);
4434         }
4435     }
4436     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4437 }
4438 
4439 // Checks the build of the stobj instruction
TEST_F(IrBuilderTest,Stobj)4440 TEST_F(IrBuilderTest, Stobj)
4441 {
4442     auto source = R"(
4443     .record panda.String <external>
4444     .record R {
4445         i32 v_i32
4446         panda.String v_string
4447     }
4448     .function void main(R a0, i32 a1){
4449         lda a1
4450         stobj a0, R.v_i32
4451         return.void
4452     }
4453     )";
4454     ASSERT_TRUE(ParseToGraph(source, "main"));
4455     auto graph = CreateGraphWithDefaultRuntime();
4456     GRAPH(graph)
4457     {
4458         PARAMETER(0, 0).ref();
4459         PARAMETER(1, 1).s32();
4460 
4461         BASIC_BLOCK(2, -1)
4462         {
4463             INST(2, Opcode::SaveState).Inputs(0, 1, 1).SrcVregs({0, 1, 2});
4464             INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
4465             INST(4, Opcode::StoreObject).s32().Inputs(3, 1);
4466             INST(5, Opcode::ReturnVoid).v0id();
4467         }
4468     }
4469     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4470 }
4471 
4472 // Checks the build of the stobj instruction
TEST_F(IrBuilderTest,Stobj64)4473 TEST_F(IrBuilderTest, Stobj64)
4474 {
4475     auto source = R"(
4476     .record panda.String <external>
4477     .record R {
4478         i64 v_i64
4479         panda.String v_string
4480     }
4481     .function void main(R a0, i64 a1){
4482         lda.64 a1
4483         stobj.64 a0, R.v_i64
4484         return.void
4485     }
4486     )";
4487     ASSERT_TRUE(ParseToGraph(source, "main"));
4488     auto graph = CreateGraphWithDefaultRuntime();
4489     GRAPH(graph)
4490     {
4491         PARAMETER(0, 0).ref();
4492         PARAMETER(1, 1).s64();
4493 
4494         BASIC_BLOCK(2, -1)
4495         {
4496             INST(2, Opcode::SaveState).Inputs(0, 1, 1).SrcVregs({0, 1, 2});
4497             INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
4498             INST(4, Opcode::StoreObject).s64().Inputs(3, 1);
4499             INST(5, Opcode::ReturnVoid).v0id();
4500         }
4501     }
4502     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4503 }
4504 
4505 // Checks the build of the stobj.obj instruction
TEST_F(IrBuilderTest,StobjObj)4506 TEST_F(IrBuilderTest, StobjObj)
4507 {
4508     auto source = R"(
4509     .record panda.String <external>
4510     .record R {
4511         i32 v_i32
4512         panda.String v_string
4513     }
4514     .function void main(R a0, panda.String a1){
4515         lda.obj a1
4516         stobj.obj a0, R.v_string
4517         return.void
4518     }
4519     )";
4520     ASSERT_TRUE(ParseToGraph(source, "main"));
4521     auto graph = CreateGraphWithDefaultRuntime();
4522     GRAPH(graph)
4523     {
4524         PARAMETER(0, 0).ref();
4525         PARAMETER(1, 1).ref();
4526 
4527         BASIC_BLOCK(2, -1)
4528         {
4529             INST(2, Opcode::SaveState).Inputs(0, 1, 1).SrcVregs({0, 1, 2});
4530             INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
4531             INST(4, Opcode::StoreObject).ref().Inputs(3, 1);
4532             INST(5, Opcode::ReturnVoid).v0id();
4533         }
4534     }
4535     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4536 }
4537 
4538 // Checks the build of the ldstatic instruction
TEST_F(IrBuilderTest,Ldstatic)4539 TEST_F(IrBuilderTest, Ldstatic)
4540 {
4541     auto source = R"(
4542     .record panda.String <external>
4543     .record R {
4544         i32 v_i32             <static>
4545         panda.String v_string <static>
4546     }
4547     .function i32 main(){
4548         ldstatic R.v_i32
4549         return
4550     }
4551     )";
4552     ASSERT_TRUE(ParseToGraph(source, "main"));
4553     auto graph = CreateGraphWithDefaultRuntime();
4554     GRAPH(graph)
4555     {
4556         BASIC_BLOCK(2, -1)
4557         {
4558             INST(3, Opcode::SaveState).SrcVregs({});
4559             INST(0, Opcode::LoadAndInitClass).ref().Inputs(3);
4560             INST(1, Opcode::LoadStatic).s32().Inputs(0);
4561             INST(2, Opcode::Return).s32().Inputs(1);
4562         }
4563     }
4564     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4565 }
4566 
4567 // Checks the build of the ldstatic.64 instruction
TEST_F(IrBuilderTest,Ldstatic64)4568 TEST_F(IrBuilderTest, Ldstatic64)
4569 {
4570     auto source = R"(
4571     .record panda.String <external>
4572     .record R {
4573         i64 v_i64             <static>
4574         panda.String v_string <static>
4575     }
4576     .function i64 main(){
4577         ldstatic.64 R.v_i64
4578         return
4579     }
4580     )";
4581     ASSERT_TRUE(ParseToGraph(source, "main"));
4582     auto graph = CreateGraphWithDefaultRuntime();
4583     GRAPH(graph)
4584     {
4585         BASIC_BLOCK(2, -1)
4586         {
4587             INST(3, Opcode::SaveState).SrcVregs({});
4588             INST(0, Opcode::LoadAndInitClass).ref().Inputs(3);
4589             INST(1, Opcode::LoadStatic).s64().Inputs(0);
4590             INST(2, Opcode::Return).s64().Inputs(1);
4591         }
4592     }
4593     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4594 }
4595 
4596 // Checks the build of the ldstatic.obj instruction
TEST_F(IrBuilderTest,LdstaticObj)4597 TEST_F(IrBuilderTest, LdstaticObj)
4598 {
4599     auto source = R"(
4600     .record panda.String <external>
4601     .record R {
4602         i32 v_i32             <static>
4603         panda.String v_string <static>
4604     }
4605     .function panda.String main(){
4606         ldstatic.obj R.v_string
4607         return
4608     }
4609     )";
4610     ASSERT_TRUE(ParseToGraph(source, "main"));
4611     auto graph = CreateGraphWithDefaultRuntime();
4612     GRAPH(graph)
4613     {
4614         BASIC_BLOCK(2, -1)
4615         {
4616             INST(3, Opcode::SaveState).SrcVregs({});
4617             INST(0, Opcode::LoadAndInitClass).ref().Inputs(3);
4618             INST(1, Opcode::LoadStatic).ref().Inputs(0);
4619             INST(2, Opcode::Return).ref().Inputs(1);
4620         }
4621     }
4622     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4623 }
4624 
4625 // Checks the build of the ststatic instruction
TEST_F(IrBuilderTest,Ststatic)4626 TEST_F(IrBuilderTest, Ststatic)
4627 {
4628     auto source = R"(
4629     .record panda.String <external>
4630     .record R {
4631         i32 v_i32             <static>
4632         panda.String v_string <static>
4633     }
4634     .function void main(i32 a0){
4635         lda a0
4636         ststatic R.v_i32
4637         return.void
4638     }
4639     )";
4640     ASSERT_TRUE(ParseToGraph(source, "main"));
4641     auto graph = CreateGraphWithDefaultRuntime();
4642     GRAPH(graph)
4643     {
4644         PARAMETER(0, 0).s32();
4645 
4646         BASIC_BLOCK(2, -1)
4647         {
4648             INST(4, Opcode::SaveState).Inputs(0, 0).SrcVregs({0, 1});
4649             INST(1, Opcode::LoadAndInitClass).ref().Inputs(4);
4650             INST(2, Opcode::StoreStatic).s32().Inputs(1, 0);
4651             INST(3, Opcode::ReturnVoid).v0id();
4652         }
4653     }
4654     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4655 }
4656 
4657 // Checks the build of the ststatic.64 instruction
TEST_F(IrBuilderTest,Ststatic64)4658 TEST_F(IrBuilderTest, Ststatic64)
4659 {
4660     auto source = R"(
4661     .record panda.String <external>
4662     .record R {
4663         i64 v_i64             <static>
4664         panda.String v_string <static>
4665     }
4666     .function void main(i64 a0){
4667         lda.64 a0
4668         ststatic.64 R.v_i64
4669         return.void
4670     }
4671     )";
4672     ASSERT_TRUE(ParseToGraph(source, "main"));
4673     auto graph = CreateGraphWithDefaultRuntime();
4674     GRAPH(graph)
4675     {
4676         PARAMETER(0, 0).s64();
4677 
4678         BASIC_BLOCK(2, -1)
4679         {
4680             INST(4, Opcode::SaveState).Inputs(0, 0).SrcVregs({0, 1});
4681             INST(1, Opcode::LoadAndInitClass).ref().Inputs(4);
4682             INST(2, Opcode::StoreStatic).s64().Inputs(1, 0);
4683             INST(3, Opcode::ReturnVoid).v0id();
4684         }
4685     }
4686     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4687 }
4688 
4689 // Checks the build of the ststatic.obj instruction
TEST_F(IrBuilderTest,StstaticObj)4690 TEST_F(IrBuilderTest, StstaticObj)
4691 {
4692     auto source = R"(
4693     .record panda.String <external>
4694     .record R {
4695         i32 v_i32             <static>
4696         panda.String v_string <static>
4697     }
4698     .function void main(panda.String a0){
4699         lda.obj a0
4700         ststatic.obj R.v_string
4701         return.void
4702     }
4703     )";
4704     ASSERT_TRUE(ParseToGraph(source, "main"));
4705     auto graph = CreateGraphWithDefaultRuntime();
4706     GRAPH(graph)
4707     {
4708         PARAMETER(0, 0).ref();
4709 
4710         BASIC_BLOCK(2, -1)
4711         {
4712             INST(4, Opcode::SaveState).Inputs(0, 0).SrcVregs({0, 1});
4713             INST(1, Opcode::LoadAndInitClass).ref().Inputs(4);
4714             INST(2, Opcode::StoreStatic).ref().Inputs(1, 0);
4715             INST(3, Opcode::ReturnVoid).v0id();
4716         }
4717     }
4718     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4719 }
4720 
4721 // Checks the build of the return instruction
TEST_F(IrBuilderTest,Return)4722 TEST_F(IrBuilderTest, Return)
4723 {
4724     auto source = R"(
4725     .function i32 main(i32 a0){
4726         lda a0
4727         return
4728     }
4729     )";
4730     ASSERT_TRUE(ParseToGraph(source, "main"));
4731     auto graph = CreateGraphWithDefaultRuntime();
4732     GRAPH(graph)
4733     {
4734         PARAMETER(0, 0).s32();
4735 
4736         BASIC_BLOCK(2, -1)
4737         {
4738             INST(1, Opcode::Return).s32().Inputs(0);
4739         }
4740     }
4741     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4742 }
4743 
4744 // Checks the build of the return.64 instruction
TEST_F(IrBuilderTest,Return64)4745 TEST_F(IrBuilderTest, Return64)
4746 {
4747     auto source = R"(
4748     .function i64 main(i64 a0){
4749         lda.64 a0
4750         return.64
4751     }
4752     )";
4753     ASSERT_TRUE(ParseToGraph(source, "main"));
4754     auto graph = CreateGraphWithDefaultRuntime();
4755     GRAPH(graph)
4756     {
4757         PARAMETER(0, 0).s64();
4758 
4759         BASIC_BLOCK(2, -1)
4760         {
4761             INST(1, Opcode::Return).s64().Inputs(0);
4762         }
4763     }
4764     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4765 }
4766 
4767 // Checks the build of the return.obj instruction
TEST_F(IrBuilderTest,ReturnObj)4768 TEST_F(IrBuilderTest, ReturnObj)
4769 {
4770     auto source = R"(
4771     .record panda.String <external>
4772     .function panda.String main(panda.String a0){
4773         lda.obj a0
4774         return.obj
4775     }
4776     )";
4777     ASSERT_TRUE(ParseToGraph(source, "main"));
4778     auto graph = CreateGraphWithDefaultRuntime();
4779     GRAPH(graph)
4780     {
4781         PARAMETER(0, 0).ref();
4782 
4783         BASIC_BLOCK(2, -1)
4784         {
4785             INST(1, Opcode::Return).ref().Inputs(0);
4786         }
4787     }
4788     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4789 }
4790 
4791 // Checks the build of the return.void instruction
TEST_F(IrBuilderTest,ReturnVoid)4792 TEST_F(IrBuilderTest, ReturnVoid)
4793 {
4794     auto source = R"(
4795     .function void main(){
4796         return.void
4797     }
4798     )";
4799     ASSERT_TRUE(ParseToGraph(source, "main"));
4800     auto graph = CreateGraphWithDefaultRuntime();
4801     GRAPH(graph)
4802     {
4803         BASIC_BLOCK(2, -1)
4804         {
4805             INST(0, Opcode::ReturnVoid).v0id();
4806         }
4807     }
4808     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4809 }
4810 
4811 // Checks the build of the throw instruction
TEST_F(IrBuilderTest,Throw)4812 TEST_F(IrBuilderTest, Throw)
4813 {
4814     auto source = R"(
4815     .record panda.String <external>
4816     .function void main(panda.String a0){
4817         throw a0
4818     }
4819     )";
4820     ASSERT_TRUE(ParseToGraph(source, "main"));
4821     auto graph = CreateGraphWithDefaultRuntime();
4822     GRAPH(graph)
4823     {
4824         PARAMETER(0, 0).ref();
4825 
4826         BASIC_BLOCK(2, -1)
4827         {
4828             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4829             INST(2, Opcode::Throw).Inputs(0, 1);
4830         }
4831     }
4832     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4833 }
4834 
4835 // Checks the build of the call.short instruction
TEST_F(IrBuilderTest,CallShort)4836 TEST_F(IrBuilderTest, CallShort)
4837 {
4838     auto source = R"(
4839     .function i32 main(){
4840         movi.64 v0, 1
4841         call.short foo1, v0, v0
4842         call.short foo2, v0, v0
4843         return
4844     }
4845     .function i32 foo1(i64 a0) {
4846         ldai 0
4847         return
4848     }
4849     .function i32 foo2(i64 a0, i64 a1) {
4850         ldai 1
4851         return
4852     }
4853     )";
4854     ASSERT_TRUE(ParseToGraph(source, "main"));
4855     auto graph = CreateGraphWithDefaultRuntime();
4856     GRAPH(graph)
4857     {
4858         CONSTANT(0, 1);
4859 
4860         BASIC_BLOCK(2, -1)
4861         {
4862             using namespace DataType;
4863             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4864             INST(2, Opcode::CallStatic).s32().Inputs({{INT64, 0}, {NO_TYPE, 1}});
4865             INST(3, Opcode::SaveState).Inputs(0, 2).SrcVregs({0, 1});
4866             INST(4, Opcode::CallStatic).s32().Inputs({{INT64, 0}, {INT64, 0}, {NO_TYPE, 3}});
4867             INST(5, Opcode::Return).s32().Inputs(4);
4868         }
4869     }
4870     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4871 }
4872 
4873 // Checks the build of the call instruction
TEST_F(IrBuilderTest,Call)4874 TEST_F(IrBuilderTest, Call)
4875 {
4876     auto source = R"(
4877     .function i64 main(){
4878         movi.64 v0, 1
4879         call foo1, v0, v0, v0, v0
4880         call foo2, v0, v0, v0, v0
4881         return
4882     }
4883     .function i64 foo1(i32 a0) {
4884         ldai.64 0
4885         return
4886     }
4887     .function i64 foo2(i32 a0, i32 a1) {
4888         ldai.64 1
4889         return
4890     }
4891     )";
4892     ASSERT_TRUE(ParseToGraph(source, "main"));
4893     auto graph = CreateGraphWithDefaultRuntime();
4894     GRAPH(graph)
4895     {
4896         CONSTANT(0, 1).s64();
4897 
4898         BASIC_BLOCK(2, -1)
4899         {
4900             using namespace DataType;
4901             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
4902             INST(2, Opcode::CallStatic).s64().Inputs({{INT32, 0}, {NO_TYPE, 1}});
4903             INST(3, Opcode::SaveState).Inputs(0, 2).SrcVregs({0, 1});
4904             INST(4, Opcode::CallStatic).s64().Inputs({{INT32, 0}, {INT32, 0}, {NO_TYPE, 3}});
4905             INST(5, Opcode::Return).s64().Inputs(4);
4906         }
4907     }
4908     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4909 }
4910 
4911 // Checks the build of the call.range instruction
TEST_F(IrBuilderTest,CallRange)4912 TEST_F(IrBuilderTest, CallRange)
4913 {
4914     auto source = R"(
4915     .function i64 main(){
4916         movi.64 v0, 1
4917         movi.64 v1, 2
4918         call.range foo, v0
4919         return
4920     }
4921     .function i64 foo(i32 a0) {
4922         ldai.64 0
4923         return
4924     }
4925     )";
4926     ASSERT_TRUE(ParseToGraph(source, "main"));
4927     auto graph = CreateGraphWithDefaultRuntime();
4928     GRAPH(graph)
4929     {
4930         CONSTANT(0, 1);
4931         CONSTANT(1, 2);
4932 
4933         BASIC_BLOCK(2, -1)
4934         {
4935             INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
4936             INST(3, Opcode::CallStatic).s64().Inputs({{DataType::INT32, 0}, {DataType::NO_TYPE, 2}});
4937             INST(4, Opcode::Return).s64().Inputs(3);
4938         }
4939     }
4940     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4941 }
4942 
TEST_F(IrBuilderTest,Checkcast)4943 TEST_F(IrBuilderTest, Checkcast)
4944 {
4945     auto source = R"(
4946     .record Asm{
4947         i32 asm1
4948         i64 asm2
4949     }
4950     .function void main(){
4951         newobj v0, Asm
4952         lda.obj v0
4953         checkcast Asm
4954         return.void
4955     }
4956     )";
4957     ASSERT_TRUE(ParseToGraph(source, "main"));
4958     auto graph = CreateGraphWithDefaultRuntime();
4959     GRAPH(graph)
4960     {
4961         BASIC_BLOCK(2, -1)
4962         {
4963             INST(5, Opcode::SaveState).Inputs().SrcVregs({});
4964             INST(6, Opcode::LoadAndInitClass).ref().Inputs(5);
4965             INST(1, Opcode::NewObject).ref().Inputs(6, 5);
4966             INST(2, Opcode::SaveState).Inputs(1, 1).SrcVregs({0, 1});
4967             INST(7, Opcode::LoadClass).ref().Inputs(2);
4968             INST(3, Opcode::CheckCast).Inputs(1, 7, 2);
4969             INST(4, Opcode::ReturnVoid).v0id();
4970         }
4971     }
4972     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
4973 }
4974 
TEST_F(IrBuilderTest,Isinstance)4975 TEST_F(IrBuilderTest, Isinstance)
4976 {
4977     auto source = R"(
4978     .record Asm{
4979         i32 asm1
4980         i64 asm2
4981     }
4982     .function u1 main(){
4983         newobj v0, Asm
4984         lda.obj v0
4985         isinstance Asm
4986         return
4987     }
4988     )";
4989     ASSERT_TRUE(ParseToGraph(source, "main"));
4990     auto graph = CreateGraphWithDefaultRuntime();
4991     GRAPH(graph)
4992     {
4993         BASIC_BLOCK(2, -1)
4994         {
4995             INST(4, Opcode::SaveState).Inputs().SrcVregs({});
4996             INST(5, Opcode::LoadAndInitClass).ref().Inputs(4);
4997             INST(1, Opcode::NewObject).ref().Inputs(5, 4);
4998             INST(6, Opcode::SaveState).Inputs(1, 1).SrcVregs({0, 1});
4999             INST(7, Opcode::LoadClass).ref().Inputs(6);
5000             INST(2, Opcode::IsInstance).b().Inputs(1, 7, 6);
5001             INST(3, Opcode::Return).b().Inputs(2);
5002         }
5003     }
5004     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
5005 }
5006 
TEST_F(IrBuilderTest,SimpleTryCatch)5007 TEST_F(IrBuilderTest, SimpleTryCatch)
5008 {
5009     auto source = R"(
5010     .record E1 {}
5011 
5012     .function void foo() {
5013     }
5014 
5015     .function u1 main() {
5016     try_begin:
5017         call foo
5018         ldai 2
5019     try_end:
5020         jmp exit
5021 
5022     catch_block1_begin:
5023         ldai 0
5024         return
5025 
5026     catch_block2_begin:
5027         ldai 1
5028         return
5029 
5030     exit:
5031         return
5032 
5033     .catchall try_begin, try_end, catch_block1_begin
5034     .catch E1, try_begin, try_end, catch_block2_begin
5035 
5036     }
5037     )";
5038 
5039     // build IR with try-catch
5040     auto graph = CreateGraph();
5041     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5042 
5043     auto expected_graph = CreateGraphWithDefaultRuntime();
5044     GRAPH(expected_graph)
5045     {
5046         CONSTANT(0, 2);
5047         CONSTANT(1, 1);
5048         CONSTANT(2, 0);
5049 
5050         BASIC_BLOCK(2, 3, 5, 6)
5051         {
5052             INST(5, Opcode::Try).CatchTypeIds({0x0, 0xE1});
5053         }
5054         BASIC_BLOCK(3, 4)
5055         {
5056             INST(14, Opcode::SaveState).Inputs().SrcVregs({});
5057             INST(15, Opcode::CallStatic).v0id().InputsAutoType(14);
5058         }
5059         BASIC_BLOCK(4, 7, 5, 6) {}  // Try-end
5060         BASIC_BLOCK(7, -1)
5061         {
5062             INST(12, Opcode::Return).b().Inputs(0);
5063         }
5064         BASIC_BLOCK(5, -1)
5065         {
5066             INST(11, Opcode::Return).b().Inputs(2);
5067         }
5068         BASIC_BLOCK(6, -1)
5069         {
5070             INST(13, Opcode::Return).b().Inputs(1);
5071         }
5072     }
5073     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5074 }
5075 
TEST_F(IrBuilderTest,TryCatchFinally)5076 TEST_F(IrBuilderTest, TryCatchFinally)
5077 {
5078     auto source = R"(
5079     .record E1 {}
5080 
5081     .function void foo() {
5082     }
5083 
5084     .function u1 main() {
5085     try_begin:
5086         call foo
5087         ldai 1
5088     try_end:
5089         jmp label
5090 
5091     catch_block1_begin:
5092         ldai 2
5093         jmp label
5094 
5095     catch_block2_begin:
5096         ldai 3
5097 
5098     label:
5099         subi 1
5100         return
5101 
5102     .catchall try_begin, try_end, catch_block1_begin
5103     .catch E1, try_begin, try_end, catch_block2_begin
5104     }
5105 
5106     )";
5107 
5108     // build IR with try-catch
5109     auto graph = CreateGraph();
5110     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5111 
5112     auto expected_graph = CreateGraphWithDefaultRuntime();
5113     GRAPH(expected_graph)
5114     {
5115         CONSTANT(0, 1);
5116         CONSTANT(1, 3);
5117         CONSTANT(2, 2);
5118 
5119         BASIC_BLOCK(2, 7, 4, 5)
5120         {
5121             INST(3, Opcode::Try).CatchTypeIds({0x0, 0xE1});
5122         }
5123         BASIC_BLOCK(7, 3)
5124         {
5125             INST(4, Opcode::SaveState).Inputs().SrcVregs({});
5126             INST(5, Opcode::CallStatic).v0id().InputsAutoType(4);
5127         }
5128         BASIC_BLOCK(3, 6, 4, 5) {}  // Try-end
5129         BASIC_BLOCK(4, 6) {}
5130         BASIC_BLOCK(5, 6) {}
5131         BASIC_BLOCK(6, -1)
5132         {
5133             INST(11, Opcode::Phi).s32().Inputs({{3, 0}, {4, 2}, {5, 1}});
5134             INST(12, Opcode::Sub).s32().Inputs(11, 0);
5135             INST(13, Opcode::Return).b().Inputs(12);
5136         }
5137     }
5138     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5139 }
5140 
TEST_F(IrBuilderTest,CatchPhis)5141 TEST_F(IrBuilderTest, CatchPhis)
5142 {
5143     auto source = R"(
5144     .record E1 {}
5145     .record A {}
5146 
5147     .function i64 main(i64 a0) {
5148     try_begin:
5149         movi.64 v0, 100
5150         lda.64 v0
5151         div2.64 a0
5152         sta.64 v0
5153         div2.64 a0
5154     try_end:
5155         jmp exit
5156 
5157     catch_block1_begin:
5158         lda.64 v0
5159         return
5160 
5161     catch_block2_begin:
5162         lda.64 v0
5163         return
5164 
5165     exit:
5166         return
5167 
5168     .catch E1, try_begin, try_end, catch_block1_begin
5169     .catchall try_begin, try_end, catch_block2_begin
5170 
5171     }
5172     )";
5173 
5174     // build IR with try-catch
5175     auto graph = CreateGraph();
5176     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5177 
5178     auto expected_graph = CreateGraphWithDefaultRuntime();
5179     GRAPH(expected_graph)
5180     {
5181         PARAMETER(0, 0).s64();
5182         CONSTANT(1, 100);
5183 
5184         BASIC_BLOCK(2, 3, 4, 5)
5185         {
5186             INST(2, Opcode::Try).CatchTypeIds({0xE1, 0x0});
5187         }
5188         BASIC_BLOCK(3, 6)
5189         {
5190             INST(3, Opcode::SaveState).Inputs(1, 0, 1).SrcVregs({0, 1, 2});
5191             INST(4, Opcode::ZeroCheck).s64().Inputs(0, 3);
5192             INST(5, Opcode::Div).s64().Inputs(1, 4);
5193             INST(6, Opcode::SaveState).Inputs(5, 0, 5).SrcVregs({0, 1, 2});
5194             INST(7, Opcode::ZeroCheck).s64().Inputs(0, 6);
5195             INST(8, Opcode::Div).s64().Inputs(5, 7);
5196         }
5197         BASIC_BLOCK(6, 7, 4, 5) {}  // Try-end
5198         BASIC_BLOCK(7, -1)
5199         {
5200             INST(9, Opcode::Return).s64().Inputs(8);
5201         }
5202         BASIC_BLOCK(4, -1)
5203         {
5204             INST(10, Opcode::CatchPhi).s64().Inputs(1, 5);
5205             INST(11, Opcode::Return).s64().Inputs(10);
5206         }
5207         BASIC_BLOCK(5, -1)
5208         {
5209             INST(12, Opcode::CatchPhi).s64().Inputs(1, 5);
5210             INST(13, Opcode::Return).s64().Inputs(12);
5211         }
5212     }
5213     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5214 }
5215 
TEST_F(IrBuilderTest,NestedTryCatch)5216 TEST_F(IrBuilderTest, NestedTryCatch)
5217 {
5218     auto source = R"(
5219     .record panda.ArithmeticException <external>
5220 
5221     .function i32 main(i32 a0, i32 a1, i32 a2) {
5222     try_begin:
5223         lda a0
5224         div2 a1
5225     try_end:
5226         jmp lbl
5227 
5228     catch_block:
5229     try_begin1:
5230         lda a0
5231         div2 a2
5232     try_end1:
5233         jmp lbl
5234 
5235     catch_block1:
5236         lda a0
5237         addi 1
5238 
5239     lbl:
5240         return
5241 
5242     .catch panda.ArithmeticException, try_begin, try_end, catch_block
5243     .catch panda.ArithmeticException, try_begin1, try_end1, catch_block1
5244 
5245     }
5246     )";
5247 
5248     // build IR with try-catch
5249     auto graph = CreateGraph();
5250     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5251     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5252 
5253     auto expected_graph = CreateGraphWithDefaultRuntime();
5254     GRAPH(expected_graph)
5255     {
5256         PARAMETER(0, 0).s32();
5257         PARAMETER(1, 1).s32();
5258         PARAMETER(2, 2).s32();
5259         CONSTANT(3, 1);
5260 
5261         BASIC_BLOCK(2, 3, 4)
5262         {
5263             INST(4, Opcode::Try).CatchTypeIds({0x0});
5264         }
5265         BASIC_BLOCK(3, 10)
5266         {
5267             INST(5, Opcode::SaveState).Inputs(0, 1, 2, 0).SrcVregs({0, 1, 2, 3});
5268             INST(6, Opcode::ZeroCheck).s32().Inputs(1, 5);
5269             INST(7, Opcode::Div).s32().Inputs(0, 6);
5270         }
5271         BASIC_BLOCK(10, 9, 4) {}  // Try-end
5272 
5273         BASIC_BLOCK(4, 5) {}  // Catch-begin
5274         BASIC_BLOCK(5, 6, 7)
5275         {
5276             INST(11, Opcode::Try).CatchTypeIds({0x0});
5277         }
5278         BASIC_BLOCK(6, 11)
5279         {
5280             INST(12, Opcode::SaveState).Inputs(0, 1, 2, 0).SrcVregs({0, 1, 2, 3});
5281             INST(13, Opcode::ZeroCheck).s32().Inputs(2, 12);
5282             INST(14, Opcode::Div).s32().Inputs(0, 13);
5283         }
5284         BASIC_BLOCK(11, 9, 7) {}  // Try-end
5285 
5286         BASIC_BLOCK(7, 9)  // Catch-begin
5287         {
5288             INST(16, Opcode::Add).s32().Inputs(0, 3);
5289         }
5290         BASIC_BLOCK(9, -1)
5291         {
5292             INST(17, Opcode::Phi).s32().Inputs(7, 14, 16);
5293             INST(18, Opcode::Return).s32().Inputs(17);
5294         }
5295     }
5296     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5297 }
5298 
TEST_F(IrBuilderTest,EmptyCatchBlock)5299 TEST_F(IrBuilderTest, EmptyCatchBlock)
5300 {
5301     auto source = R"(
5302     .record panda.ArithmeticException <external>
5303 
5304     .function i32 main(i32 a0, i32 a1) {
5305     try_begin:
5306         lda a0
5307         div2 a1
5308         sta a0
5309     try_end:
5310         jmp lbl
5311 
5312     catch_block:
5313     lbl:
5314         lda a0
5315         addi 1
5316         return
5317 
5318     .catch panda.ArithmeticException, try_begin, try_end, catch_block
5319     }
5320     )";
5321 
5322     // build IR with try-catch
5323     auto graph = CreateGraph();
5324     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5325     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5326 
5327     auto expected_graph = CreateGraphWithDefaultRuntime();
5328     GRAPH(expected_graph)
5329     {
5330         PARAMETER(0, 0).s32();
5331         PARAMETER(1, 1).s32();
5332         CONSTANT(2, 1);
5333 
5334         BASIC_BLOCK(2, 3, 4)
5335         {
5336             INST(3, Opcode::Try).CatchTypeIds({0x0});
5337         }
5338         BASIC_BLOCK(3, 6)
5339         {
5340             INST(5, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
5341             INST(6, Opcode::ZeroCheck).s32().Inputs(1, 5);
5342             INST(7, Opcode::Div).s32().Inputs(0, 6);
5343         }
5344         BASIC_BLOCK(6, 5, 4) {}  // Try-end
5345         BASIC_BLOCK(4, 5) {}     // Catch-begin
5346         BASIC_BLOCK(5, -1)
5347         {
5348             INST(9, Opcode::Phi).s32().Inputs(7, 0);
5349             INST(10, Opcode::Add).s32().Inputs(9, 2);
5350             INST(11, Opcode::Return).s32().Inputs(10);
5351         }
5352     }
5353     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5354 }
5355 
TEST_F(IrBuilderTest,EmptyTryBlock)5356 TEST_F(IrBuilderTest, EmptyTryBlock)
5357 {
5358     auto source = R"(
5359     .record panda.ArithmeticException <external>
5360 
5361     .function i32 main(i32 a0, i32 a1) {
5362     try_begin1:
5363     try_end1:
5364         jmp lbl1
5365 
5366     catch_block1:
5367         lda a0
5368         return
5369 
5370     try_begin2:
5371     try_end2:
5372     lbl1:
5373         jmp lbl2
5374 
5375     catch_block2:
5376         lda a1
5377         return
5378 
5379     lbl2:
5380         ldai 0
5381         return
5382 
5383     .catchall try_begin1, try_end1, catch_block1
5384     .catchall try_begin2, try_end2, catch_block2
5385 
5386     }
5387     )";
5388 
5389     // build IR with try-catch
5390     auto graph = CreateGraph();
5391     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5392 
5393     auto expected_graph = CreateGraphWithDefaultRuntime();
5394     GRAPH(expected_graph)
5395     {
5396         CONSTANT(2, 0);
5397 
5398         BASIC_BLOCK(2, -1)
5399         {
5400             INST(3, Opcode::Return).s32().Inputs(2);
5401         }
5402     }
5403     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5404 }
5405 
TEST_F(IrBuilderTest,CatchBlockWithCycle)5406 TEST_F(IrBuilderTest, CatchBlockWithCycle)
5407 {
5408     auto source = R"(
5409     .record panda.ArithmeticException <external>
5410 
5411     .function i32 main(i32 a0, i32 a1) {
5412     try_begin:
5413         lda a0
5414         div2 a1
5415         sta a0
5416     try_end:
5417         jmp exit
5418 
5419     catch_block:
5420         lda a0
5421     loop:
5422         jeqz exit
5423         subi 1
5424         jmp loop
5425 
5426     exit:
5427         return
5428 
5429     .catch panda.ArithmeticException, try_begin, try_end, catch_block
5430     }
5431     )";
5432 
5433     // build IR with try-catch
5434     auto graph = CreateGraph();
5435     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5436     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5437 
5438     auto expected_graph = CreateGraphWithDefaultRuntime();
5439     GRAPH(expected_graph)
5440     {
5441         PARAMETER(0, 0).s32();
5442         PARAMETER(1, 1).s32();
5443         CONSTANT(2, 0);
5444         CONSTANT(3, 1);
5445 
5446         BASIC_BLOCK(2, 3, 4)
5447         {
5448             INST(4, Opcode::Try).CatchTypeIds({0x0});
5449         }
5450         BASIC_BLOCK(3, 8)
5451         {
5452             INST(5, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
5453             INST(6, Opcode::ZeroCheck).s32().Inputs(1, 5);
5454             INST(7, Opcode::Div).s32().Inputs(0, 6);
5455         }
5456         BASIC_BLOCK(8, 5, 4) {}  // Try-end
5457         BASIC_BLOCK(4, 6)
5458         {
5459             INST(16, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
5460         }
5461         BASIC_BLOCK(6, 5, 7)
5462         {
5463             INST(9, Opcode::Phi).s32().Inputs(0, 12);
5464             INST(10, Opcode::Compare).b().CC(CC_EQ).Inputs(9, 2);
5465             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
5466         }
5467         BASIC_BLOCK(7, 6)
5468         {
5469             INST(12, Opcode::Sub).s32().Inputs(9, 3);
5470         }
5471 
5472         BASIC_BLOCK(5, -1)
5473         {
5474             INST(13, Opcode::Phi).s32().Inputs(7, 9);
5475             INST(14, Opcode::Return).s32().Inputs(13);
5476         }
5477     }
5478     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5479 }
5480 
TEST_F(IrBuilderTest,DeadBlocksAfterThrow)5481 TEST_F(IrBuilderTest, DeadBlocksAfterThrow)
5482 {
5483     auto source = R"(
5484 .record E1 {}
5485 
5486 .function i32 main() {
5487     newobj v1, E1
5488 begin1:
5489     throw v1
5490 end1:
5491     ldai 0
5492 loop:
5493     addi 1
5494     jnez loop
5495     return
5496 
5497 catch1:
5498     jeq.obj v1, ok
5499     ldai 1
5500     return
5501 ok:
5502     ldai 0
5503     return
5504 
5505 .catch E1, begin1, end1, catch1
5506 }
5507 )";
5508 
5509     // build IR with try-catch
5510     auto graph = CreateGraph();
5511     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5512     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5513 
5514     auto expected_graph = CreateGraphWithDefaultRuntime();
5515     GRAPH(expected_graph)
5516     {
5517         CONSTANT(11, 1);
5518         CONSTANT(13, 0);
5519 
5520         BASIC_BLOCK(5, 6)
5521         {
5522             INST(9, Opcode::SaveState).Inputs().SrcVregs({});
5523             INST(10, Opcode::LoadAndInitClass).ref().Inputs(9);
5524             INST(2, Opcode::NewObject).ref().Inputs(10, 9);
5525         }
5526         BASIC_BLOCK(6, 2, 11)
5527         {
5528             INST(1, Opcode::Try).CatchTypeIds({0xE1});
5529         }
5530         BASIC_BLOCK(2, 7)  // try block
5531         {
5532             INST(3, Opcode::SaveState).Inputs(2).SrcVregs({1});
5533             INST(4, Opcode::Throw).Inputs(2, 3);
5534         }
5535         BASIC_BLOCK(7, -1, 11) {}  // try_end block
5536 
5537         BASIC_BLOCK(11, 3, 4)
5538         {
5539             INST(6, Opcode::CatchPhi).ref().Inputs();  // catch-phi for acc, which holds exception-object
5540             INST(7, Opcode::Compare).b().CC(CC_EQ).Inputs(6, 2);
5541             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
5542         }
5543 
5544         BASIC_BLOCK(4, -1)
5545         {
5546             INST(14, Opcode::Return).s32().Inputs(11);
5547         }
5548 
5549         BASIC_BLOCK(3, -1)
5550         {
5551             INST(15, Opcode::Return).s32().Inputs(13);
5552         }
5553     }
5554     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5555 }
5556 
TEST_F(IrBuilderTest,FallthroughBeforeTryBlockEnd)5557 TEST_F(IrBuilderTest, FallthroughBeforeTryBlockEnd)
5558 {
5559     auto source = R"(
5560 .record panda.NullPointerException {}
5561 
5562 .function i32 main(i32 a0, i32 a1, i32 a2) {
5563 begin1:
5564     lda a0
5565     div2 a1
5566 end1:
5567     jeqz exit
5568     lda a0
5569 begin2:
5570     div2 a2
5571 end2:
5572     jeqz exit
5573     ldai 1
5574     jmp exit
5575 catch1:
5576     lda a0
5577     addi 1
5578     jmp exit
5579 exit:
5580     return
5581 
5582 .catch panda.NullPointerException, begin1, end1, catch1
5583 .catch panda.NullPointerException, begin2, end2, catch1
5584 }
5585 )";
5586 
5587     // build IR with try-catch
5588     auto graph = CreateGraph();
5589     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5590     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5591 
5592     auto expected_graph = CreateGraphWithDefaultRuntime();
5593     GRAPH(expected_graph)
5594     {
5595         PARAMETER(0, 0).s32();
5596         PARAMETER(1, 1).s32();
5597         PARAMETER(2, 3).s32();
5598         CONSTANT(3, 0);
5599         CONSTANT(4, 1);
5600 
5601         BASIC_BLOCK(2, 3, 10)
5602         {
5603             INST(5, Opcode::Try).CatchTypeIds({0x0});
5604         }
5605         BASIC_BLOCK(3, 4)
5606         {
5607             INST(6, Opcode::SaveState).Inputs(0, 1, 2, 0).SrcVregs({0, 1, 2, 3});
5608             INST(7, Opcode::ZeroCheck).s32().Inputs(1, 6);
5609             INST(8, Opcode::Div).s32().Inputs(0, 7);
5610         }
5611         BASIC_BLOCK(4, 5, 10) {}  // Try-end
5612         BASIC_BLOCK(5, 6, 12)
5613         {
5614             INST(9, Opcode::Compare).b().CC(CC_EQ).Inputs(8, 3);
5615             INST(10, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(9);
5616         }
5617         BASIC_BLOCK(6, 7, 10)
5618         {
5619             INST(11, Opcode::Try).CatchTypeIds({0x0});
5620         }
5621         BASIC_BLOCK(7, 8)
5622         {
5623             INST(12, Opcode::SaveState).Inputs(0, 1, 2, 0).SrcVregs({0, 1, 2, 3});
5624             INST(13, Opcode::ZeroCheck).s32().Inputs(2, 12);
5625             INST(14, Opcode::Div).s32().Inputs(0, 13);
5626         }
5627         BASIC_BLOCK(8, 9, 10) {}  // Try-end
5628         BASIC_BLOCK(9, 11, 12)
5629         {
5630             INST(15, Opcode::Compare).b().CC(CC_EQ).Inputs(14, 3);
5631             INST(16, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(15);
5632         }
5633         BASIC_BLOCK(11, 12) {}
5634         BASIC_BLOCK(10, 12)  // Catch-block
5635         {
5636             INST(18, Opcode::Add).s32().Inputs(0, 4);
5637         }
5638         BASIC_BLOCK(12, -1)
5639         {
5640             INST(19, Opcode::Phi).s32().Inputs(8, 14, 4, 18);
5641             INST(20, Opcode::Return).s32().Inputs(19);
5642         }
5643     }
5644     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5645 }
5646 
TEST_F(IrBuilderTest,CatchWithFallthrough)5647 TEST_F(IrBuilderTest, CatchWithFallthrough)
5648 {
5649     auto source = R"(
5650 .record E1 {}
5651 
5652 .function i32 main(i32 a0, i32 a1) {
5653 begin1:
5654     lda a0
5655     div2 a1
5656     sta a0
5657 end1:
5658     jmp exit
5659 
5660 catch1:
5661     lda a0
5662     jeqz label
5663     subi 1
5664     jmp exit
5665 label:
5666     ldai 0
5667     return
5668 
5669 exit:
5670     return
5671 
5672 .catch E1, begin1, end1, catch1
5673 }
5674 )";
5675 
5676     // build IR with try-catch
5677     auto graph = CreateGraph();
5678     ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
5679     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
5680 
5681     auto expected_graph = CreateGraphWithDefaultRuntime();
5682     GRAPH(expected_graph)
5683     {
5684         PARAMETER(0, 0).s32();
5685         PARAMETER(1, 1).s32();
5686         CONSTANT(2, 0);
5687         CONSTANT(3, 1);
5688 
5689         BASIC_BLOCK(2, 3, 4)
5690         {
5691             INST(4, Opcode::Try).CatchTypeIds({0xE1});
5692         }
5693         BASIC_BLOCK(3, 9)
5694         {
5695             INST(5, Opcode::SaveState).Inputs(0, 1, 0).SrcVregs({0, 1, 2});
5696             INST(6, Opcode::ZeroCheck).s32().Inputs(1, 5);
5697             INST(7, Opcode::Div).s32().Inputs(0, 6);
5698         }
5699         BASIC_BLOCK(9, 8, 4) {}  // Try-end
5700         BASIC_BLOCK(4, 6, 7)
5701         {
5702             INST(10, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 2);
5703             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
5704         }
5705         BASIC_BLOCK(6, -1)
5706         {
5707             INST(12, Opcode::Return).s32().Inputs(2);
5708         }
5709         BASIC_BLOCK(7, 8)
5710         {
5711             INST(13, Opcode::Sub).s32().Inputs(0, 3);
5712         }
5713         BASIC_BLOCK(8, -1)
5714         {
5715             INST(14, Opcode::Phi).s32().Inputs(7, 13);
5716             INST(15, Opcode::Return).s32().Inputs(14);
5717         }
5718     }
5719     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5720 }
5721 
TEST_F(IrBuilderTest,OsrMode)5722 TEST_F(IrBuilderTest, OsrMode)
5723 {
5724     auto source = R"(
5725     .function u32 foo(u32 a0){
5726         lda a0
5727     loop:
5728         jlez exit
5729         subi 1
5730         jmp loop
5731     exit:
5732         return
5733     }
5734     )";
5735 
5736     auto graph = CreateGraphOsr();
5737     ASSERT_TRUE(ParseToGraph(source, "foo", graph));
5738     EXPECT_TRUE(graph->RunPass<Cleanup>());
5739 
5740     auto expected_graph = CreateGraphOsrWithDefaultRuntime();
5741     GRAPH(expected_graph)
5742     {
5743         PARAMETER(0, 0).u32();
5744         CONSTANT(1, 0);
5745         CONSTANT(2, 1);
5746 
5747         BASIC_BLOCK(2, 3) {}
5748         BASIC_BLOCK(3, 5, 4)
5749         {
5750             INST(3, Opcode::Phi).s32().Inputs(0, 7);
5751             INST(4, Opcode::SaveStateOsr).Inputs(0, 3).SrcVregs({0, 1});
5752             INST(5, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LE).Inputs(3, 1);
5753             INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
5754         }
5755         BASIC_BLOCK(4, 3)
5756         {
5757             INST(7, Opcode::Sub).s32().Inputs(3, 2);
5758         }
5759         BASIC_BLOCK(5, -1)
5760         {
5761             INST(8, Opcode::Return).u32().Inputs(3);
5762         }
5763     }
5764     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5765 }
5766 
TEST_F(IrBuilderTest,TestSaveStateDeoptimize)5767 TEST_F(IrBuilderTest, TestSaveStateDeoptimize)
5768 {
5769     auto source = R"(
5770     .function u32 foo(u32 a0){
5771         lda a0
5772     loop:
5773         jlez exit
5774         subi 1
5775         jmp loop
5776     exit:
5777         return
5778     }
5779     )";
5780 
5781     auto graph = CreateGraph();
5782     ASSERT_TRUE(ParseToGraph(source, "foo", graph));
5783     EXPECT_TRUE(graph->RunPass<Cleanup>());
5784     auto expected_graph = CreateGraphWithDefaultRuntime();
5785     GRAPH(expected_graph)
5786     {
5787         PARAMETER(0, 0).u32();
5788         CONSTANT(1, 0);
5789         CONSTANT(2, 1);
5790 
5791         BASIC_BLOCK(2, 3)
5792         {
5793             INST(4, Opcode::SaveStateDeoptimize).Inputs(0).SrcVregs({0});
5794         }
5795         BASIC_BLOCK(3, 5, 4)
5796         {
5797             INST(3, Opcode::Phi).s32().Inputs(0, 7);
5798             INST(5, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LE).Inputs(3, 1);
5799             INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
5800         }
5801         BASIC_BLOCK(4, 3)
5802         {
5803             INST(7, Opcode::Sub).s32().Inputs(3, 2);
5804         }
5805         BASIC_BLOCK(5, -1)
5806         {
5807             INST(8, Opcode::Return).u32().Inputs(3);
5808         }
5809     }
5810     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5811 }
5812 
TEST_F(IrBuilderTest,InfiniteLoop)5813 TEST_F(IrBuilderTest, InfiniteLoop)
5814 {
5815     auto source = R"(
5816     .function u32 foo_inf(i32 a0){
5817     loop:
5818         inci a0, 1
5819         jmp loop
5820     }
5821     )";
5822     auto graph = CreateGraph();
5823     ASSERT_TRUE(ParseToGraph(source, "foo_inf", graph));
5824     ASSERT_FALSE(graph->HasEndBlock());
5825     auto expected_graph = CreateGraphWithDefaultRuntime();
5826     GRAPH(expected_graph)
5827     {
5828         PARAMETER(0, 0).s32();
5829         CONSTANT(1, 1);
5830         BASIC_BLOCK(3, 2)
5831         {
5832             INST(4, Opcode::SaveStateDeoptimize).Inputs(0).SrcVregs({0});
5833         }
5834         BASIC_BLOCK(2, 2)
5835         {
5836             INST(2, Opcode::Phi).s32().Inputs(0, 3);
5837             INST(3, Opcode::Add).s32().Inputs(2, 1);
5838         }
5839     }
5840     ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
5841 }
5842 
TEST_F(IrBuilderTest,TestSaveStateDeoptimizeAuxiliaryBlock)5843 TEST_F(IrBuilderTest, TestSaveStateDeoptimizeAuxiliaryBlock)
5844 {
5845     auto source = R"(
5846     .function u32 foo(i32 a0){
5847         ldai 0
5848         jne a0, test
5849         jmp end_test
5850     test:
5851         ldai 10
5852         jmp loop
5853     end_test:
5854         lda a0
5855     loop:
5856         jlez exit
5857         subi 1
5858         jmp loop
5859     exit:
5860         return
5861     }
5862     )";
5863 
5864     ASSERT_TRUE(ParseToGraph(source, "foo"));
5865     EXPECT_TRUE(GetGraph()->RunPass<Cleanup>());
5866     auto expected_graph = CreateGraphWithDefaultRuntime();
5867     GRAPH(expected_graph)
5868     {
5869         PARAMETER(0, 0).s32();
5870         CONSTANT(1, 0);
5871         CONSTANT(20, 10);
5872         CONSTANT(2, 1);
5873         BASIC_BLOCK(2, 10, 11)
5874         {
5875             INST(10, Opcode::Compare).b().CC(CC_NE).Inputs(1, 0);
5876             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
5877         }
5878         BASIC_BLOCK(11, 10) {}
5879         BASIC_BLOCK(10, 3)
5880         {
5881             INST(12, Opcode::Phi).s32().Inputs({{2, 20}, {11, 0}});
5882             INST(4, Opcode::SaveStateDeoptimize).Inputs(0, 12).SrcVregs({0, 1});
5883         }
5884         BASIC_BLOCK(3, 5, 4)
5885         {
5886             INST(3, Opcode::Phi).s32().Inputs(12, 7);
5887             INST(5, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LE).Inputs(3, 1);
5888             INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
5889         }
5890         BASIC_BLOCK(4, 3)
5891         {
5892             INST(7, Opcode::Sub).s32().Inputs(3, 2);
5893         }
5894         BASIC_BLOCK(5, -1)
5895         {
5896             INST(8, Opcode::Return).u32().Inputs(3);
5897         }
5898     }
5899     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected_graph));
5900 }
5901 
TEST_F(IrBuilderTest,TestEmptyLoop)5902 TEST_F(IrBuilderTest, TestEmptyLoop)
5903 {
5904     auto source = R"(
5905     .function i32 main() {
5906         ldai 1
5907     loop:
5908         jeqz loop
5909         ldai 0
5910         return
5911     }
5912     )";
5913 
5914     ASSERT_TRUE(ParseToGraph(source, "main"));
5915     // IrBuilder construct dead PHI:
5916     //   2p.i32  Phi                        v1(bb0), v2p(bb1) -> (v2p, v3)
5917     // GraphComparator failed on the instruction
5918     EXPECT_TRUE(GetGraph()->RunPass<Cleanup>());
5919 
5920     auto expected_graph = CreateGraphWithDefaultRuntime();
5921     GRAPH(expected_graph)
5922     {
5923         CONSTANT(0, 1);
5924         CONSTANT(1, 0);
5925         BASIC_BLOCK(2, 3)
5926         {
5927             INST(2, Opcode::SaveStateDeoptimize).NoVregs();
5928         }
5929         BASIC_BLOCK(3, 3, 4)
5930         {
5931             INST(3, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1).SrcType(DataType::Type::INT32);
5932             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
5933         }
5934         BASIC_BLOCK(4, -1)
5935         {
5936             INST(5, Opcode::Return).s32().Inputs(1);
5937         }
5938     }
5939     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected_graph));
5940 }
5941 
TEST_F(IrBuilderTest,MultiThrowTryBlock)5942 TEST_F(IrBuilderTest, MultiThrowTryBlock)
5943 {
5944     auto source = R"(
5945     .record E1 {}
5946     .record E2 {}
5947 
5948 
5949     .function i32 main(i32 a0) {
5950     try_begin:
5951         lda a0
5952         jeqz label
5953         newobj v0, E1
5954         throw v0
5955     label:
5956         newobj v0, E2
5957         throw v0
5958     try_end:
5959         ldai 0
5960         jmp exit
5961     catch1:
5962         ldai 1
5963         jmp exit
5964     catch2:
5965         ldai 2
5966         jmp exit
5967 
5968     exit:
5969         return
5970 
5971     .catch E1, try_begin, try_end, catch1
5972     .catch E2, try_begin, try_end, catch2
5973     }
5974     )";
5975 
5976     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
5977 
5978     auto expected_graph = CreateGraphWithDefaultRuntime();
5979     GRAPH(expected_graph)
5980     {
5981         PARAMETER(0, 0).s32();
5982         CONSTANT(1, 0);
5983         CONSTANT(2, 2);
5984         CONSTANT(3, 1);
5985 
5986         BASIC_BLOCK(6, 2, 13, 14)
5987         {
5988             INST(4, Opcode::Try).CatchTypeIds({0xE1, 0xE2});
5989         }
5990         BASIC_BLOCK(2, 3, 4)
5991         {
5992             INST(5, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1).SrcType(DataType::Type::INT32);
5993             INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
5994         }
5995         BASIC_BLOCK(4, -1)
5996         {
5997             INST(9, Opcode::SaveState).Inputs(0, 0).SrcVregs({1, 2});
5998             INST(10, Opcode::LoadAndInitClass).ref().Inputs(9);
5999             INST(11, Opcode::NewObject).ref().Inputs(10, 9);
6000             INST(12, Opcode::SaveState).Inputs(11, 0, 0).SrcVregs({0, 1, 2});
6001             INST(13, Opcode::Throw).Inputs(11, 12);
6002         }
6003         BASIC_BLOCK(3, 7)
6004         {
6005             INST(14, Opcode::SaveState).Inputs(0, 0).SrcVregs({1, 2});
6006             INST(15, Opcode::LoadAndInitClass).ref().Inputs(14);
6007             INST(16, Opcode::NewObject).ref().Inputs(15, 14);
6008             INST(17, Opcode::SaveState).Inputs(16, 0, 0).SrcVregs({0, 1, 2});
6009             INST(18, Opcode::Throw).Inputs(16, 17);
6010         }
6011         BASIC_BLOCK(7, -1, 13, 14) {}  // try end
6012         BASIC_BLOCK(14, 5) {}          // catch1
6013         BASIC_BLOCK(13, 5) {}          // catch2
6014         BASIC_BLOCK(5, -1)
6015         {
6016             INST(20, Opcode::Phi).s32().Inputs(2, 3);
6017             INST(21, Opcode::Return).s32().Inputs(20);
6018         }
6019     }
6020     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected_graph));
6021 }
6022 
TEST_F(IrBuilderTest,JumpToCatchHandler)6023 TEST_F(IrBuilderTest, JumpToCatchHandler)
6024 {
6025     auto source = R"(
6026     .record E0 {}
6027     .record E1 {}
6028 
6029     .function void foo() {
6030         return.void
6031     }
6032 
6033     .function i32 main(i32 a0) {
6034     try_begin1:
6035         lda a0
6036         jeqz try_end
6037         call.short foo
6038     try_begin2:
6039         newobj v1, E1
6040         throw v1
6041     try_end:
6042     catch_begin:
6043         ldai 0
6044         return
6045 
6046     .catch E0, try_begin1, try_end, catch_begin
6047     .catch E1, try_begin2, try_end, catch_begin
6048     }
6049     )";
6050 
6051     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
6052 
6053     auto expected_graph = CreateGraphWithDefaultRuntime();
6054     GRAPH(expected_graph)
6055     {
6056         PARAMETER(6, 0).s32();
6057         CONSTANT(8, 0x0).s64();
6058 
6059         BASIC_BLOCK(5, 2, 12)
6060         {
6061             INST(0, Opcode::Try).CatchTypeIds({0xE0});
6062         }
6063         BASIC_BLOCK(2, 3, 4)
6064         {
6065             INST(7, Opcode::Compare).b().CC(CC_EQ).Inputs(6, 8).SrcType(DataType::Type::INT32);
6066             INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0x0).Inputs(7);
6067         }
6068         BASIC_BLOCK(4, 7)
6069         {
6070             INST(10, Opcode::SaveState).Inputs(6, 6).SrcVregs({2, 3});
6071             INST(11, Opcode::CallStatic).v0id().InputsAutoType(10);
6072         }
6073         BASIC_BLOCK(7, 9, 12)
6074         {
6075             INST(1, Opcode::Try).CatchTypeIds({0xE1});
6076         }
6077         BASIC_BLOCK(9, 8)
6078         {
6079             INST(12, Opcode::SaveState).Inputs(6).SrcVregs({2});
6080             INST(13, Opcode::LoadAndInitClass).ref().Inputs(12);
6081             INST(14, Opcode::NewObject).ref().Inputs(13, 12);
6082             INST(15, Opcode::SaveState).Inputs(14, 6).SrcVregs({1, 2});
6083             INST(16, Opcode::Throw).Inputs(14, 15);
6084         }
6085         BASIC_BLOCK(8, 6, 12) {}   // try_end
6086         BASIC_BLOCK(6, -1, 12) {}  // try_end
6087         BASIC_BLOCK(12, 3) {}      // catch_begin, catch
6088         BASIC_BLOCK(3, -1)
6089         {
6090             INST(19, Opcode::Return).s32().Inputs(8);
6091         }
6092     }
6093     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected_graph));
6094 }
6095 
TEST_F(IrBuilderTest,GroupOfThrowableInstructions)6096 TEST_F(IrBuilderTest, GroupOfThrowableInstructions)
6097 {
6098     auto source = R"(
6099     .record E1 {}
6100     .record Obj {}
6101 
6102     .function void Obj.ctor(Obj a0) <ctor> {
6103         return.void
6104     }
6105 
6106     .function i32 Obj.foo(Obj a0) {
6107         ldai 42
6108         return
6109     }
6110 
6111     .function u1 main() {
6112         try_begin:
6113             initobj.short Obj.ctor
6114             sta.obj v0
6115             call.virt Obj.foo, v0
6116             jmp exit
6117         try_end:
6118             lda v1
6119         exit:
6120             return
6121 
6122         .catch E1, try_begin, try_end, try_end
6123     }
6124 
6125     )";
6126 
6127     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
6128     for (auto bb : GetGraph()->GetBlocksRPO()) {
6129         if (bb->IsTryBegin()) {
6130             auto try_bb = bb->GetSuccessor(0);
6131             EXPECT_TRUE(try_bb->IsTry());
6132 
6133             auto first_real_inst = try_bb->GetFirstInst();
6134             while (first_real_inst->IsSaveState()) {
6135                 first_real_inst = first_real_inst->GetNext();
6136             }
6137             EXPECT_TRUE(GetGraph()->IsInstThrowable(first_real_inst));
6138         }
6139     }
6140 }
6141 
TEST_F(IrBuilderTest,InfiniteLoopInsideTryBlock)6142 TEST_F(IrBuilderTest, InfiniteLoopInsideTryBlock)
6143 {
6144     auto source = R"(
6145     .record E {}
6146 
6147     .function void foo() {
6148         return.void
6149     }
6150 
6151     .function u1 main() {
6152         movi v0, 0x0
6153         mov v2, v0
6154     try_begin:
6155         movi v0, 0x2
6156         call.short foo
6157         mov.obj v3, v0
6158         inci v2, 0x1
6159         jmp try_begin
6160     try_end:
6161         lda v2
6162         return
6163 
6164     .catch E, try_begin, try_end, try_end
6165     }
6166     )";
6167     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
6168     auto expected = CreateGraphWithDefaultRuntime();
6169     GRAPH(expected)
6170     {
6171         CONSTANT(7, 0);
6172         CONSTANT(10, 2);
6173         CONSTANT(14, 1);
6174 
6175         BASIC_BLOCK(2, 4)
6176         {
6177             INST(6, Opcode::SaveStateDeoptimize).NoVregs();
6178         }
6179         BASIC_BLOCK(4, 3, 9)  // try_begin, loop
6180         {
6181             INST(9, Opcode::Phi).s32().Inputs(7, 13);
6182             INST(0, Opcode::Try).CatchTypeIds({0xE});
6183         }
6184         BASIC_BLOCK(3, 5)  // try, loop
6185         {
6186             INST(11, Opcode::SaveState).Inputs(10, 9).SrcVregs({0, 2});
6187             INST(12, Opcode::CallStatic).v0id().InputsAutoType(11);
6188             INST(13, Opcode::Add).s32().Inputs(9, 14);
6189         }
6190         BASIC_BLOCK(5, 4, 9) {}  // try_end, loop
6191         BASIC_BLOCK(9, -1)       // catch
6192         {
6193             INST(3, Opcode::CatchPhi).b().Inputs(9);
6194             INST(15, Opcode::Return).b().Inputs(3);
6195         }
6196     }
6197     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected));
6198 }
6199 
TEST_F(IrBuilderTest,ReturnInsideTryBlock)6200 TEST_F(IrBuilderTest, ReturnInsideTryBlock)
6201 {
6202     auto source = R"(
6203     .record E {}
6204 
6205     .function void foo() {
6206         return.void
6207     }
6208 
6209     .function void main() {
6210     try_begin:
6211         call.short foo
6212         return.void
6213     try_end:
6214         return.void
6215 
6216     .catch E, try_begin, try_end, try_end
6217     }
6218 
6219     )";
6220 
6221     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
6222 
6223     auto expected = CreateGraphWithDefaultRuntime();
6224     GRAPH(expected)
6225     {
6226         BASIC_BLOCK(3, 2, 8)  // try_begin
6227         {
6228             INST(0, Opcode::Try).CatchTypeIds({0xE});
6229         }
6230         BASIC_BLOCK(2, 4)  // try
6231         {
6232             INST(2, Opcode::SaveState).NoVregs();
6233             INST(3, Opcode::CallStatic).v0id().InputsAutoType(2);
6234             INST(4, Opcode::ReturnVoid).v0id();
6235         }
6236         BASIC_BLOCK(4, -1, 8) {}  // try_end
6237         BASIC_BLOCK(8, -1)
6238         {
6239             INST(5, Opcode::ReturnVoid).v0id();
6240         }
6241     }
6242 
6243     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected));
6244 }
6245 
TEST_F(IrBuilderTest,JumpInsideTryBlock)6246 TEST_F(IrBuilderTest, JumpInsideTryBlock)
6247 {
6248     auto source = R"(
6249     .record E {}
6250 
6251     .function void foo() {
6252         return.void
6253     }
6254 
6255     .function void main() {
6256     try_begin:
6257         call.short foo
6258         jmp label
6259     try_end:
6260         call.short foo
6261     label:
6262         ldai 0x0
6263         return.void
6264 
6265     .catch E, try_begin, try_end, try_end
6266     }
6267 
6268     )";
6269 
6270     ASSERT_TRUE(ParseToGraph<true>(source, "main"));
6271 
6272     auto expected = CreateGraphWithDefaultRuntime();
6273     GRAPH(expected)
6274     {
6275         BASIC_BLOCK(4, 2, 9)  // try_begin
6276         {
6277             INST(0, Opcode::Try).CatchTypeIds({0xE});
6278         }
6279         BASIC_BLOCK(2, 5)  // try
6280         {
6281             INST(2, Opcode::SaveState).NoVregs();
6282             INST(3, Opcode::CallStatic).v0id().InputsAutoType(2);
6283         }
6284         BASIC_BLOCK(5, 3, 9) {}  // try_end
6285         BASIC_BLOCK(9, 3)        // catch
6286         {
6287             INST(4, Opcode::SaveState).NoVregs();
6288             INST(5, Opcode::CallStatic).v0id().InputsAutoType(4);
6289         }
6290         BASIC_BLOCK(3, -1)
6291         {
6292             INST(7, Opcode::ReturnVoid).v0id();
6293         }
6294     }
6295 
6296     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), expected));
6297 }
6298 
TEST_F(IrBuilderTest,CompareAnyType)6299 TEST_F(IrBuilderTest, CompareAnyType)
6300 {
6301     // no crash.
6302     auto graph = CreateGraphWithDefaultRuntime();
6303     graph->SetDynamicMethod();
6304     GRAPH(graph)
6305     {
6306         PARAMETER(0, 0);
6307         INS(0).SetType(DataType::Type::ANY);
6308 
6309         BASIC_BLOCK(2, -1)
6310         {
6311             INST(2, Opcode::CompareAnyType).b().AnyType(AnyBaseType::UNDEFINED_TYPE).Inputs(0);
6312             INST(3, Opcode::Return).s32().Inputs(2);
6313         }
6314     }
6315 
6316     const CompareAnyTypeInst *cati = INS(2).CastToCompareAnyType();
6317 
6318     ASSERT_TRUE(cati != nullptr);
6319     EXPECT_TRUE(cati->GetInputType(0) == DataType::Type::ANY);
6320     EXPECT_TRUE(cati->GetType() == DataType::BOOL);
6321     EXPECT_TRUE(cati->GetAnyType() == AnyBaseType::UNDEFINED_TYPE);
6322 }
6323 
TEST_F(IrBuilderTest,CastAnyTypeValue)6324 TEST_F(IrBuilderTest, CastAnyTypeValue)
6325 {
6326     // no crash.
6327     auto graph = CreateGraphWithDefaultRuntime();
6328     graph->SetDynamicMethod();
6329     GRAPH(graph)
6330     {
6331         PARAMETER(0, 0);
6332         INS(0).SetType(DataType::Type::ANY);
6333 
6334         BASIC_BLOCK(2, -1)
6335         {
6336             INST(2, Opcode::CastAnyTypeValue).AnyType(AnyBaseType::UNDEFINED_TYPE).Inputs(0).u64();
6337             INST(3, Opcode::Return).u64().Inputs(2);
6338         }
6339     }
6340 
6341     const CastAnyTypeValueInst *catvi = INS(2).CastToCastAnyTypeValue();
6342 
6343     ASSERT_TRUE(catvi != nullptr);
6344     EXPECT_TRUE(catvi->GetInputType(0) == DataType::Type::ANY);
6345     EXPECT_TRUE(catvi->GetDeducedType() == DataType::Type::ANY);
6346     EXPECT_TRUE(catvi->GetAnyType() == AnyBaseType::UNDEFINED_TYPE);
6347 }
6348 
TEST_F(IrBuilderTest,PhiWithIdenticalInputs)6349 TEST_F(IrBuilderTest, PhiWithIdenticalInputs)
6350 {
6351     auto graph = CreateGraphWithDefaultRuntime();
6352     GRAPH(graph)
6353     {
6354         PARAMETER(0, 0).s32();
6355         PARAMETER(1, 1).s32();
6356         PARAMETER(2, 2).s32();
6357 
6358         BASIC_BLOCK(2, 3, 5)
6359         {
6360             INST(4, Opcode::Try).CatchTypeIds({0xE1});
6361         }
6362         BASIC_BLOCK(3, 4)
6363         {
6364             INST(20, Opcode::SaveState).NoVregs();
6365             INST(5, Opcode::CallStatic).v0id().InputsAutoType(20);
6366             INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
6367         }
6368         BASIC_BLOCK(4, 5) {}  // try-end
6369         BASIC_BLOCK(5, 6)
6370         {  // catch
6371             INST(7, Opcode::CatchPhi).s32().Inputs(0, 0);
6372         }
6373         BASIC_BLOCK(6, 7, 8)
6374         {
6375             INST(8, Opcode::If).SrcType(compiler::DataType::INT32).CC(compiler::CC_EQ).Inputs(1, 2);
6376         }
6377         BASIC_BLOCK(7, 8) {}
6378         BASIC_BLOCK(8, -1)
6379         {
6380             INST(10, Opcode::Phi).s32().Inputs(7, 7);
6381             INST(11, Opcode::Return).s32().Inputs(10);
6382         }
6383     }
6384     ASSERT_TRUE(graph->RunPass<Cleanup>());
6385     ASSERT_TRUE(RegAllocResolver(graph).ResolveCatchPhis());
6386 
6387     EXPECT_EQ(INS(11).GetInput(0).GetInst(), &INS(0));
6388 }
6389 
6390 }  // namespace panda::compiler
6391