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 "compiler/optimizer/code_generator/codegen.h"
17
18 namespace panda::compiler {
19
LaunchCallCodegen(CallInst * callInst)20 bool Codegen::LaunchCallCodegen(CallInst *callInst)
21 {
22 SCOPED_DISASM_STR(this, "Create Launch Call");
23
24 auto dstReg = ConvertRegister(callInst->GetDstReg(), callInst->GetType());
25
26 Reg param0 = GetTarget().GetParamReg(0);
27 ScopedTmpRegLazy tmp(GetEncoder());
28
29 RegMask liveRegs {GetLiveRegisters(callInst).first};
30 if (liveRegs.Test(param0.GetId())) {
31 tmp.Acquire();
32 param0 = tmp;
33 }
34
35 Reg objReg;
36 Reg thisReg;
37 if (callInst->GetOpcode() == Opcode::CallResolvedLaunchStatic ||
38 callInst->GetOpcode() == Opcode::CallResolvedLaunchVirtual) {
39 auto location = callInst->GetLocation(0);
40 ASSERT(location.IsFixedRegister() && location.IsRegisterValid());
41
42 param0 = ConvertRegister(location.GetValue(), DataType::POINTER);
43 auto location1 = callInst->GetLocation(1);
44 ASSERT(location1.IsFixedRegister() && location1.IsRegisterValid());
45
46 objReg = ConvertRegister(location1.GetValue(), DataType::REFERENCE);
47 if (callInst->GetOpcode() == Opcode::CallResolvedLaunchVirtual) {
48 thisReg = ConvertRegister(callInst->GetLocation(2U).GetValue(), DataType::REFERENCE);
49 }
50 } else {
51 auto location = callInst->GetLocation(0);
52 ASSERT(location.IsFixedRegister() && location.IsRegisterValid());
53
54 objReg = ConvertRegister(location.GetValue(), DataType::REFERENCE);
55
56 auto method = callInst->GetCallMethod();
57 if (callInst->GetOpcode() == Opcode::CallLaunchStatic) {
58 ASSERT(!GetGraph()->IsAotMode());
59 GetEncoder()->EncodeMov(param0, Imm(reinterpret_cast<size_t>(method)));
60 } else {
61 ASSERT(callInst->GetOpcode() == Opcode::CallLaunchVirtual);
62 thisReg = ConvertRegister(callInst->GetLocation(1).GetValue(), DataType::REFERENCE);
63 LoadClassFromObject(param0, thisReg);
64 // Get index
65 auto vtableIndex = GetRuntime()->GetVTableIndex(method);
66 // Load from VTable, address = klass + ((index << shift) + vtable_offset)
67 auto totalOffset = GetRuntime()->GetVTableOffset(GetArch()) + (vtableIndex << GetVtableShift());
68 // Class ref was loaded to method_reg
69 GetEncoder()->EncodeLdr(param0, false, MemRef(param0, totalOffset));
70 }
71 }
72
73 if (callInst->IsStaticLaunchCall()) {
74 CallRuntime(callInst, EntrypointId::CREATE_LAUNCH_STATIC_COROUTINE, dstReg, RegMask::GetZeroMask(), param0,
75 objReg, SpReg());
76 } else {
77 CallRuntime(callInst, EntrypointId::CREATE_LAUNCH_VIRTUAL_COROUTINE, dstReg, RegMask::GetZeroMask(), param0,
78 objReg, SpReg(), thisReg);
79 }
80 if (callInst->GetFlag(inst_flags::MEM_BARRIER)) {
81 GetEncoder()->EncodeMemoryBarrier(memory_order::RELEASE);
82 }
83 return true;
84 }
85 } // namespace panda::compiler
86