# Copyright (c) 2021-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Checked tests for basic inlining. # #! CHECKER Instructions limit #! RUN force_jit: true, options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8", entry: "Test1::main" #! EVENT /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/ #! EVENT_NEXT /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/ #! CHECKER Instructions limit at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8" #! EVENT /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/ #! EVENT_NEXT /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/ #! RUN entry: "Test1::main" #! CHECKER Instructions max size #! RUN force_jit: true, options: "--compiler-regex=Test1::main --compiler-inlining-max-size=6", entry: "Test1::main" #! EVENT /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/ #! EVENT_NEXT /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/ #! CHECKER Instructions max size at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test1::main --compiler-inlining-max-size=6" #! EVENT /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/ #! EVENT_NEXT /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/ #! RUN entry: "Test1::main" .record Test1 {} .function i32 func(i32 a0) { newobj v0, Test1 newobj v0, Test1 newobj v0, Test1 newobj v0, Test1 ldai 1 add2 a0 return } .function i32 small_func(i32 a0) { ldai 1 add2 a0 return } .function i32 Test1.main() { movi v1, 10 call.short func, v1 call.short small_func, v1 add2 v1 ldai 0 return } #! CHECKER Inline depth limit #! RUN force_jit: true, options: "--compiler-regex=Test1::main_depth --compiler-inlining-max-depth=2", entry: "Test1::main_depth" #! EVENTS_COUNT /Inline,Test1::main_depth,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1 #! EVENTS_COUNT /Inline,_GLOBAL::func_rec,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1 #! CHECKER Inline depth limit at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test1::main_depth --compiler-inlining-max-depth=2" #! EVENTS_COUNT /Inline,Test1::main_depth,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1 #! EVENTS_COUNT /Inline,_GLOBAL::func_rec,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1 #! RUN entry: "Test1::main_depth" .function i32 func_rec(i32 a0) { lda a0 jeqz exit subi 1 sta a0 call.short func_rec, a0 exit: return } .function i32 Test1.main_depth() { movi v1, 10 call.short func_rec, v1 return } #! CHECKER Check inlined float array #! RUN force_jit: true, options: "--compiler-regex=_GLOBAL::main", entry: "_GLOBAL::main" #! EVENT /Inline,_GLOBAL::main,_GLOBAL::farray,.*STATIC,SUCCESS/ #! METHOD "_GLOBAL::main" #! PASS_AFTER "Inline" #! INST "CallStatic.Inlined" #! CHECKER Check inlined float array at Regular AOT #! RUN_PAOC options: "--compiler-regex=_GLOBAL::main" #! EVENT /Inline,_GLOBAL::main,_GLOBAL::farray,.*STATIC,SUCCESS/ #! METHOD "_GLOBAL::main" #! PASS_AFTER "Inline" #! INST "CallStatic.Inlined" #! RUN entry: "_GLOBAL::main" #! CHECKER Check inlined float array at LLVM AOT #! RUN_LLVM options: "--compiler-regex='(_GLOBAL::main|_GLOBAL::farray)' --llvm-dump-before --llvm-dump-after" #! READ_FILE "console.out" #! INST "LLVM IR module BEFORE LLVM optimizations" #! INST_NEXT /define protected.*_GLOBAL::main/ #! INST_NEXT /call.*_GLOBAL::farray/ #! INST "LLVM IR module AFTER LLVM optimizations" #! INST_NEXT /define protected.*_GLOBAL::main/ #! INST_NEXT /label %"void _GLOBAL::farray/ #! RUN entry: "_GLOBAL::main" .function void farray(f64[] a0) { ldai 2 movi v0, 1 fstarr.64 a0, v0 return.void } .function i32 main() { movi v0, 5 newarr v1, v0, f64[] call.short farray, v1 ldai 0 return } #! CHECKER Inline function with dead loop #! RUN force_jit: true, options: "--compiler-regex=_GLOBAL::main1", entry: "_GLOBAL::main1" #! EVENT /Inline,_GLOBAL::main1,_GLOBAL::foo1,.*STATIC,SUCCESS/ #! METHOD "_GLOBAL::main1" #! PASS_AFTER "Inline" #! INST_NOT "CallStatic.Inlined" #! INST_NOT "Return.Inlined" #! INST_NOT "SaveStateDeoptimize" #! CHECKER Inline function with dead loop at Regular AOT #! RUN_PAOC options: "--compiler-regex=_GLOBAL::main1" #! EVENT /Inline,_GLOBAL::main1,_GLOBAL::foo1,.*STATIC,SUCCESS/ #! METHOD "_GLOBAL::main1" #! PASS_AFTER "Inline" #! INST_NOT "CallStatic.Inlined" #! INST_NOT "Return.Inlined" #! INST_NOT "SaveStateDeoptimize" #! RUN entry: "_GLOBAL::main1" #! CHECKER Inline function with dead loop at LLVM AOT #! RUN_LLVM options: "--compiler-regex='(_GLOBAL::main1|_GLOBAL::foo1)' --llvm-dump-before --llvm-dump-after" #! READ_FILE "console.out" #! INST "LLVM IR module BEFORE LLVM optimizations" #! INST_NEXT /define protected.*_GLOBAL::main/ #! INST_NEXT /call.*_GLOBAL::foo1/ #! INST "LLVM IR module AFTER LLVM optimizations" #! INST_NEXT /define protected.*_GLOBAL::main/ #! INST_NEXT "ret i32 0" #! RUN entry: "_GLOBAL::main1" .function i32 foo1() { movi v1, 0 ldai 10 lbl: jle v1, lbl # jump to 0 offset, never happens ldai 0 return } .function i32 main1() { call foo1 return } #! CHECKER Change to CallStatic by instructions limit #! RUN force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=12", entry: "Test2::main" #! EVENT /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/ #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/ #! CHECKER Change to CallStatic by instructions limit at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=12" #! EVENT /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/ #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/ #! RUN entry: "Test2::main" #! CHECKER Change to CallStatic by instructions limit at LLVM AOT #! RUN_LLVM options: "--compiler-regex=Test2.* --compiler-inlining-max-insts=12" #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,DEVIRTUALIZED/ #! RUN entry: "Test2::main" #! CHECKER Change to CallStatic by instructions max size #! RUN force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-size=6", entry: "Test2::main" #! EVENT /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/ #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/ #! CHECKER Change to CallStatic by instructions size at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test2::main --compiler-inlining-max-size=6" #! EVENT /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/ #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/ #! RUN entry: "Test2::main" #! CHECKER Change to CallStatic by instructions size at LLVM AOT #! RUN_LLVM options: "--compiler-regex=Test2::main --compiler-inlining-max-size=6" #! EVENT_NEXT /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/ #! EVENT_NEXT /Inline,Test2::main,Test2::small_func,.*VIRTUAL,DEVIRTUALIZED/ #! RUN entry: "Test2::main" .record Test2 {} .function i32 Test2.func(Test2 a0, i32 a1) { newobj v0, Test1 newobj v0, Test1 newobj v0, Test1 newobj v0, Test1 ldai 1 add2 a1 return } .function i32 Test2.small_func(Test2 a0, i32 a1) { ldai 1 add2 a1 return } .function i32 Test2.main() { newobj v0, Test2 movi v1, 10 call.virt Test2.func, v0, v1 call.virt Test2.small_func, v0, v1 add2 v1 ldai 0 return } #! CHECKER Do not inline infinite loop #! RUN force_jit: true, entry: "Test3::main" #! EVENT /Inline,Test3::main,Test3::foo1,.*VIRTUAL,SUCCESS/ #! EVENT /Inline,Test3::main,_GLOBAL::foo_inf_loop,.*STATIC,INF_LOOP/ #! CHECKER Do not inline infinite loop at Regular AOT #! RUN_PAOC options: "--compiler-regex=Test3::main" #! EVENT /Inline,Test3::main,Test3::foo1,.*VIRTUAL,SUCCESS/ #! EVENT /Inline,Test3::main,_GLOBAL::foo_inf_loop,.*STATIC,INF_LOOP/ #! RUN entry: "Test3::main" #! CHECKER Do not inline infinite loop at LLVM AOT #! RUN_LLVM options: "--compiler-regex='(Test3::main|Test3::foo1|_GLOBAL::foo_inf_loop)' --llvm-dump-before --llvm-dump-after" #! READ_FILE "console.out" #! INST "LLVM IR module BEFORE LLVM optimizations" #! INST_NEXT /define protected.*Test3::main/ #! INST_NEXT /call.*_GLOBAL::foo_inf_loop/ #! INST "LLVM IR module AFTER LLVM optimizations" #! INST_NEXT /define protected.*Test3::main/ #! INST_NEXT_NOT "resolve_method" #! RUN entry: "Test3::main" .record Test3 {} .function i32 Test3.foo1(Test3 a0) { ldai 0 return } .function i32 foo_inf_loop(i32 a0) { lda a0 jeqz exit loop: addi 1 sta a0 jmp loop exit: return } .function i32 Test3.main() { newobj v0, Test3 call.virt Test3.foo1, v0 jeqz exit sta v1 call.short foo_inf_loop, v1 ldai 0 exit: return } #! CHECKER Inline external files in AOT mode #! RUN_PAOC options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true --compiler-regex=Test4.*" #! METHOD "Test4::func_A_getConst_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getConst/ #! INST_NOT "Constant" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getConst/ #! INST "Constant" #! METHOD "Test4::func_A_getConst_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getConst/ #! INST_NOT "Constant" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getConst/ #! INST "Constant" #! METHOD "Test4::func_A_getParam_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getParam/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getParam/ #! METHOD "Test4::func_A_getParam_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getParam/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getParam/ #! METHOD "Test4::func_A_getVoid_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getVoid/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getVoid/ #! METHOD "Test4::func_A_getVoid_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getVoid/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getVoid/ #! METHOD "Test4::func_A_getObj_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_getObj_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_setObj_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_setObj_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_getObj_wrong_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_setObj_wrong_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_setObj_multiple__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj_multiple/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::setObj_multiple/ #! METHOD "Test4::func_A_complexMethod__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::complexMethod/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::complexMethod/ #! METHOD "Test4::func_A_setObj_unknown_target__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj/ #! PASS_AFTER "Inline" #! INST /CallStatic.*A::setObj/ #! RUN options: "--panda-files=../../inline_external.checked/test.abc", entry: "Test4::main" #! CHECKER Inline external files in LLVM AOT mode #! RUN_LLVM options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true --compiler-regex=Test4.*" #! METHOD "Test4::func_A_getConst_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getConst/ #! INST_NOT "Constant" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getConst/ #! INST "Constant" #! METHOD "Test4::func_A_getConst_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getConst/ #! INST_NOT "Constant" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getConst/ #! INST "Constant" #! METHOD "Test4::func_A_getParam_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getParam/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getParam/ #! METHOD "Test4::func_A_getParam_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getParam/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getParam/ #! METHOD "Test4::func_A_getVoid_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getVoid/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getVoid/ #! METHOD "Test4::func_A_getVoid_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getVoid/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getVoid/ #! METHOD "Test4::func_A_getObj_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_getObj_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_setObj_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_setObj_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_getObj_wrong_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::getObj/ #! INST_NOT "LoadObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::getObj/ #! INST "LoadObject" #! METHOD "Test4::func_A_setObj_wrong_virtual__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::setObj/ #! INST_NOT "StoreObject" #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::setObj/ #! INST "StoreObject" #! METHOD "Test4::func_A_setObj_multiple__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj_multiple/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::setObj_multiple/ #! METHOD "Test4::func_A_complexMethod__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::complexMethod/ #! PASS_AFTER "Inline" #! INST_NOT /CallVirtual.*A::complexMethod/ #! METHOD "Test4::func_A_setObj_unknown_target__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::setObj/ #! PASS_AFTER "Inline" #! INST /CallStatic.*A::setObj/ #! RUN options: "--panda-files=../../inline_external.checked/test.abc", entry: "Test4::main" #! CHECKER CallVirtual for external method is replaced with CallStatic #! RUN_PAOC options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true \ #! --compiler-regex=Test4.* --compiler-inlining-max-size=0" #! METHOD "Test4::func_A_complexMethod__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::complexMethod/ #! PASS_AFTER "Inline" #! INST /CallStatic.*A::complexMethod/ #! CHECKER CallVirtual for external method is not replaced with CallStatic if external inlining is disabled #! RUN_PAOC options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true \ #! --compiler-regex=Test4.* --compiler-inlining-max-size=0 \ #! --compiler-inline-external-methods=false" #! METHOD "Test4::func_A_complexMethod__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallVirtual.*A::complexMethod/ #! PASS_AFTER "Inline" #! INST_NOT /CallStatic.*A::complexMethod/ #! INST /CallVirtual.*A::complexMethod/ #! CHECKER Don't inline external files in AOT mode without cha #! RUN_PAOC options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=false --compiler-regex=Test4.*" #! METHOD "Test4::func_A_getConst_static__noinline__" #! PASS_AFTER "IrBuilder" #! INST /CallStatic.*A::getConst/ #! INST_NOT "Constant" #! PASS_AFTER "Inline" #! INST /CallStatic.*A::getConst/ #! INST_NOT "Constant" .record A { i32 data } .record A.data .function i32 A.getConst() .function i32 A.getConst_virt(A a0) .function i32 A.getParam(i32 a0) .function i32 A.getParam_virt(A a0, i32 a1) .function void A.getVoid() .function void A.getVoid_virt(A a0) .function i32 A.getObj(A a0) .function i32 A.getObj_virt(A a0) .function void A.setObj(A a0, i32 a1) .function void A.setObjConst_virt(A a0) .function void A.setObj_virt(A a0, i32 a1) .function i32 A.getObj_wrong_virt(A a0, A a1) .function void A.setObj_wrong_virt(A a0, i32 a1, A a2) .function void A.setObj_multiple(A a0, i32 a1, i32 a2) .function i32 A.complexMethod(A a0) .record Test4 {} .function i32 Test4.func_A_getConst_static__noinline__() { call A.getConst return } .function i32 Test4.func_A_getConst_virtual__noinline__() { newobj v0, A call.virt A.getConst_virt, v0 return } .function i32 Test4.func_A_getParam_static__noinline__(i32 a0) { call A.getParam, a0 return } .function i32 Test4.func_A_getParam_virtual__noinline__(i32 a0) { newobj v0, A call.virt A.getParam_virt, v0, a0 return } .function void Test4.func_A_getVoid_static__noinline__() { call A.getVoid return.void } .function void Test4.func_A_getVoid_virtual__noinline__() { newobj v0, A call.virt A.getVoid_virt, v0 return.void } .function i32 Test4.func_A_getObj_static__noinline__() { newobj v0, A ldai 0x5 stobj v0, A.data call A.getObj, v0 return } .function i32 Test4.func_A_getObj_virtual__noinline__() { newobj v0, A ldai 0x6 stobj v0, A.data call.virt A.getObj_virt, v0 return } .function i32 Test4.func_A_setObj_static__noinline__() { newobj v0, A movi v1, 0x7 call A.setObj, v0, v1 ldobj v0, A.data return } .function i32 Test4.func_A_setObj_virtual__noinline__() { newobj v0, A movi v1, 0x8 call.virt A.setObj_virt, v0, v1 ldobj v0, A.data return } .function i32 Test4.func_A_getObj_wrong_virtual__noinline__() { newobj v0, A newobj v1, A ldai 0x9 stobj v0, A.data ldai 0x10 stobj v1, A.data call.virt A.getObj_wrong_virt, v0, v1 return } .function i32 Test4.func_A_setObj_wrong_virtual__noinline__() { newobj v0, A newobj v2, A movi v1, 0x11 call.virt A.setObj_wrong_virt, v0, v1, v2 ldobj v2, A.data return } .function i32 Test4.func_A_setObjConst_virtual__noinline__() { newobj v0, A call.virt A.setObjConst_virt, v0 ldobj v0, A.data return } .function i32 Test4.func_A_setObj_multiple__noinline__() { newobj v0, A movi v1, 42 movi v2, 0 call A.setObj_multiple, v0, v1, v2 ldobj v0, A.data return } .function i32 Test4.func_A_complexMethod__noinline__() { newobj v0, A call.virt A.complexMethod, v0 sta v0 ldai 42 jeq v0, success ldai 1 return success: ldai 0 return } .function i32 Test4.func_A_setObj_unknown_target__noinline__(A a0) { movi v0, 0 call A.setObj, a0, v0 ldobj a0, A.data return } .function i32 Test4.func_A_setObj_unknown_target_wrapper__noinline__() { newobj v0, A call Test4.func_A_setObj_unknown_target__noinline__, v0 return } .function i32 Test4.main() { movi v0, 0x1 call Test4.func_A_getConst_static__noinline__ jne v0, error_exit_1 movi v0, 0x2 call Test4.func_A_getConst_virtual__noinline__ jne v0, error_exit_2 movi v0, 0x3 call Test4.func_A_getParam_static__noinline__, v0 jne v0, error_exit_3 movi v0, 0x4 call Test4.func_A_getParam_virtual__noinline__, v0 jne v0, error_exit_4 call Test4.func_A_getVoid_static__noinline__, v0 call Test4.func_A_getVoid_virtual__noinline__, v0 movi v0, 0x5 call Test4.func_A_getObj_static__noinline__ jne v0, error_exit_5 movi v0, 0x6 call Test4.func_A_getObj_virtual__noinline__ jne v0, error_exit_6 movi v0, 0x7 call Test4.func_A_setObj_static__noinline__ jne v0, error_exit_7 movi v0, 0x8 call Test4.func_A_setObj_virtual__noinline__ jne v0, error_exit_8 movi v0, 0x9 call Test4.func_A_setObjConst_virtual__noinline__ jne v0, error_exit_9 movi v0, 0x10 call Test4.func_A_getObj_wrong_virtual__noinline__ jne v0, error_exit_10 movi v0, 0x11 call Test4.func_A_setObj_wrong_virtual__noinline__ jne v0, error_exit_11 call Test4.func_A_setObj_multiple__noinline__ jnez error_exit_12 call Test4.func_A_complexMethod__noinline__ jnez error_exit_13 call Test4.func_A_setObj_unknown_target_wrapper__noinline__ jnez error_exit_14 ldai 0x0 return error_exit_1: ldai 0x1 return error_exit_2: ldai 0x2 error_exit_3: ldai 0x3 return error_exit_4: ldai 0x4 return error_exit_5: ldai 0x5 return error_exit_6: ldai 0x6 return error_exit_7: ldai 0x7 return error_exit_8: ldai 0x8 return error_exit_9: ldai 0x9 return error_exit_10: ldai 0xa return error_exit_11: ldai 0xb return error_exit_12: ldai 0xc return error_exit_13: ldai 0xd return error_exit_14: ldai 0xe return } #! CHECKER Inline nested calls in AOT mode #! RUN_PAOC options: "--panda-files=../../inline.checked/test.abc --compiler-regex=NestedCalls::main" #! EVENT /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/ #! EVENT /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/ #! CHECKER Inline nested calls in JIT mode #! RUN force_jit: true, entry: "NestedCalls::main", options: "--compiler-regex=NestedCalls::main --compiler-no-cha-inlining" #! EVENT /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/ #! EVENT /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/ .record NestedCalls {} .function i32 NestedCalls.outer(NestedCalls a0) { call.virt NestedCalls.inner, a0 return } .function i32 NestedCalls.inner(NestedCalls a0) { ldai 0 return } .function i32 NestedCalls.main() { newobj v0, NestedCalls call.virt NestedCalls.outer, v0 return } #! CHECKER Inline final class #! RUN force_jit: true, options: "", entry: "Test5::main" #! EVENT /Inline,B1::func__noinline__,B1::func,.*VIRTUAL,SUCCESS/ #! EVENT_NEXT /Inline,B1::func__noinline__,C1::func,.*VIRTUAL,SUCCESS/ #! EVENT_NOT /Inline,B1::func__noinline__,A1::func,.*VIRTUAL,SUCCESS/ #! CHECKER Inline final class AOT #! RUN_PAOC options: "" #! EVENT /Inline,B1::func__noinline__,B1::func,.*VIRTUAL,SUCCESS/ #! EVENT_NEXT /Inline,B1::func__noinline__,C1::func,.*VIRTUAL,SUCCESS/ #! EVENT_NOT /Inline,B1::func__noinline__,A1::func,.*VIRTUAL,SUCCESS/ #! RUN options: "", entry: "Test5::main" .record Test5 {} .record A1 {} .record B1 {} .record C1 {} .function i32 A1.func(A1 a0) { ldai 1 return } .function i32 B1.func(B1 a0) { ldai 2 return } .function i32 C1.func(C1 a0) { ldai 3 return } .function i32 A1.func__noinline__(A1 a0, C1 a1, A1 a2) { ldai 5 return } .function i32 B1.func__noinline__(B1 a0, C1 a1, A1 a2) { call.virt A1.func, a0 movi v0, 0x2 jne v0, error_exit_1 call.virt C1.func, a1 movi v0, 0x3 jne v0, error_exit_2 call.virt A1.func, a2 movi v0, 0x1 jne v0, error_exit_3 ldai 0x0 return error_exit_1: ldai 0x1 return error_exit_2: ldai 0x2 return error_exit_3: ldai 0x3 return } .function i32 Test5.main() { newobj v0, A1 newobj v1, B1 newobj v2, C1 call.virt A1.func__noinline__, v1, v2, v0 return }