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