• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdint>
17 #include "libpandabase/utils/utils.h"
18 #include "compiler_logger.h"
19 #include "optimizer/ir/datatype.h"
20 #include "optimizer/ir/runtime_interface.h"
21 #include "optimizer/ir_builder/inst_builder.h"
22 #include "optimizer/ir_builder/ir_builder.h"
23 #include "optimizer/ir/inst.h"
24 #include "bytecode_instruction.h"
25 #include "bytecode_instruction-inl.h"
26 
27 namespace ark::compiler {
28 
29 template <Opcode OPCODE, bool IS_RANGE, bool ACC_READ>
BuildLaunch(const BytecodeInstruction * bcInst)30 void InstBuilder::BuildLaunch(const BytecodeInstruction *bcInst)
31 {
32     if (graph_->GetArch() == Arch::AARCH32) {
33         failed_ = true;
34         return;
35     }
36     auto pc = GetPc(bcInst->GetAddress());
37     auto inst = graph_->CreateInstLoadRuntimeClass(
38         DataType::REFERENCE, pc, TypeIdMixin {TypeIdMixin::MEM_PROMISE_CLASS_ID, GetGraph()->GetMethod()}, nullptr);
39     auto saveState = CreateSaveState(Opcode::SaveState, pc);
40     auto newObj = CreateNewObjectInst(pc, TypeIdMixin::MEM_PROMISE_CLASS_ID, saveState, inst);
41     AddInstruction(saveState, inst, newObj);
42     BuildCallHelper<OPCODE, IS_RANGE, ACC_READ>(bcInst, this, newObj);
43     UpdateDefinitionAcc(newObj);
44 }
45 
46 template void InstBuilder::BuildLaunch<Opcode::CallLaunchStatic, false, true>(const BytecodeInstruction *bc_inst);
47 template void InstBuilder::BuildLaunch<Opcode::CallLaunchStatic, true, false>(const BytecodeInstruction *bcInst);
48 template void InstBuilder::BuildLaunch<Opcode::CallLaunchStatic, false, false>(const BytecodeInstruction *bcInst);
49 
50 template void InstBuilder::BuildLaunch<Opcode::CallLaunchVirtual, false, true>(const BytecodeInstruction *bc_inst);
51 template void InstBuilder::BuildLaunch<Opcode::CallLaunchVirtual, true, false>(const BytecodeInstruction *bcInst);
52 template void InstBuilder::BuildLaunch<Opcode::CallLaunchVirtual, false, false>(const BytecodeInstruction *bcInst);
53 
BuildLdObjByName(const BytecodeInstruction * bcInst,DataType::Type type)54 void InstBuilder::BuildLdObjByName(const BytecodeInstruction *bcInst, DataType::Type type)
55 {
56     auto pc = GetPc(bcInst->GetAddress());
57     // Create SaveState instruction
58     auto saveState = CreateSaveState(Opcode::SaveState, pc);
59 
60     // Create NullCheck instruction
61     auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState);
62 
63     auto runtime = GetRuntime();
64     auto fieldIndex = bcInst->GetId(0).AsIndex();
65     auto fieldId = runtime->ResolveFieldIndex(GetMethod(), fieldIndex);
66     if (type != DataType::REFERENCE) {
67         type = runtime->GetFieldTypeById(GetMethod(), fieldId);
68     }
69 
70     RuntimeInterface::IntrinsicId id;
71     switch (type) {
72         case DataType::REFERENCE:
73             id = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_OBJ;
74             break;
75         case DataType::FLOAT64:
76             id = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_F64;
77             break;
78         case DataType::FLOAT32:
79             id = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_F32;
80             break;
81         case DataType::UINT64:
82         case DataType::INT64:
83             id = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_I64;
84             break;
85         case DataType::UINT8:
86         case DataType::INT8:
87         case DataType::UINT16:
88         case DataType::INT16:
89         case DataType::UINT32:
90         case DataType::INT32:
91             id = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_I32;
92             break;
93         default:
94             UNREACHABLE();
95             break;
96     }
97     auto intrinsic = GetGraph()->CreateInstIntrinsic(type, pc, id);
98     intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 2_I);
99 
100     intrinsic->AppendInput(nullCheck);
101     intrinsic->AddInputType(DataType::REFERENCE);
102 
103     intrinsic->AppendInput(saveState);
104     intrinsic->AddInputType(DataType::NO_TYPE);
105 
106     intrinsic->AddImm(GetGraph()->GetAllocator(), fieldId);
107     intrinsic->AddImm(GetGraph()->GetAllocator(), pc);
108 
109     intrinsic->SetMethodFirstInput();
110     intrinsic->SetMethod(GetMethod());
111 
112     AddInstruction(saveState);
113     AddInstruction(nullCheck);
114     AddInstruction(intrinsic);
115 
116     UpdateDefinitionAcc(intrinsic);
117 }
118 
ExtractIntrinsicIdByType(DataType::Type type)119 std::pair<RuntimeInterface::IntrinsicId, DataType::Type> ExtractIntrinsicIdByType(DataType::Type type)
120 {
121     switch (type) {
122         case DataType::REFERENCE:
123             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_OBJ, type};
124         case DataType::FLOAT64:
125             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_F64, type};
126         case DataType::FLOAT32:
127             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_F32, type};
128         case DataType::UINT64:
129         case DataType::INT64:
130             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I64, DataType::INT64};
131         case DataType::UINT8:
132         case DataType::INT8:
133             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I8, DataType::INT8};
134         case DataType::UINT16:
135         case DataType::INT16:
136             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I16, DataType::INT16};
137         case DataType::UINT32:
138         case DataType::INT32:
139             return {RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I32, DataType::INT32};
140         default:
141             UNREACHABLE();
142             break;
143     }
144     UNREACHABLE();
145 }
146 
CreateStObjByNameIntrinsic(size_t pc,DataType::Type type)147 IntrinsicInst *InstBuilder::CreateStObjByNameIntrinsic(size_t pc, DataType::Type type)
148 {
149     auto [id, extractedType] = ExtractIntrinsicIdByType(type);
150     type = extractedType;
151     auto *intrinsic = GetGraph()->CreateInstIntrinsic(DataType::VOID, pc, id);
152     intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 3_I);
153     intrinsic->AddInputType(DataType::REFERENCE);
154     intrinsic->AddInputType(type);
155     intrinsic->AddInputType(DataType::NO_TYPE);
156     return intrinsic;
157 }
158 
BuildStObjByName(const BytecodeInstruction * bcInst,DataType::Type type)159 void InstBuilder::BuildStObjByName(const BytecodeInstruction *bcInst, DataType::Type type)
160 {
161     auto pc = GetPc(bcInst->GetAddress());
162     // Create SaveState instruction
163     auto saveState = CreateSaveState(Opcode::SaveState, pc);
164     // Create NullCheck instruction
165     auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState);
166 
167     auto runtime = GetRuntime();
168     auto fieldIndex = bcInst->GetId(0).AsIndex();
169     auto fieldId = runtime->ResolveFieldIndex(GetMethod(), fieldIndex);
170     if (type != DataType::REFERENCE) {
171         type = runtime->GetFieldTypeById(GetMethod(), fieldId);
172     }
173 
174     // Get a value to store
175     Inst *storeVal = nullptr;
176     storeVal = GetDefinitionAcc();
177 
178     auto *intrinsic = CreateStObjByNameIntrinsic(pc, type);
179     intrinsic->AppendInput(nullCheck);
180     intrinsic->AppendInput(storeVal);
181     intrinsic->AppendInput(saveState);
182     intrinsic->AddImm(GetGraph()->GetAllocator(), fieldId);
183     intrinsic->AddImm(GetGraph()->GetAllocator(), pc);
184 
185     intrinsic->SetMethodFirstInput();
186     intrinsic->SetMethod(GetMethod());
187 
188     AddInstruction(saveState);
189     AddInstruction(nullCheck);
190     AddInstruction(intrinsic);
191 }
192 
BuildEquals(const BytecodeInstruction * bcInst)193 void InstBuilder::BuildEquals(const BytecodeInstruction *bcInst)
194 {
195     auto pc = GetPc(bcInst->GetAddress());
196 
197     Inst *obj1 = GetDefinition(bcInst->GetVReg(0));
198     Inst *obj2 = GetDefinition(bcInst->GetVReg(1));
199 
200     auto intrinsic = GetGraph()->CreateInstIntrinsic(DataType::BOOL, pc,
201                                                      RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_EQUALS);
202     intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 2_I);
203 
204     intrinsic->AppendInput(obj1);
205     intrinsic->AddInputType(DataType::REFERENCE);
206     intrinsic->AppendInput(obj2);
207     intrinsic->AddInputType(DataType::REFERENCE);
208 
209     AddInstruction(intrinsic);
210     UpdateDefinitionAcc(intrinsic);
211 }
212 
213 }  // namespace ark::compiler
214