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