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