1 /*
2 * Copyright (c) 2024-2025 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 "encode_visitor.h"
17
18 namespace ark::compiler {
19
20 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
21 #define UNARY_OPERATION(opc) \
22 void EncodeVisitor::Visit##opc(GraphVisitor *visitor, Inst *inst) \
23 { \
24 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
25 auto [dst, src0] = enc->GetCodegen()->ConvertRegisters<1U>(inst); \
26 enc->GetEncoder()->Encode##opc(dst, src0); \
27 }
28
29 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
30 #define BINARY_OPERATION(opc) \
31 void EncodeVisitor::Visit##opc(GraphVisitor *visitor, Inst *inst) \
32 { \
33 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
34 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst); \
35 enc->GetEncoder()->Encode##opc(dst, src0, src1); \
36 }
37
38 // CC-OFFNXT(G.PRE.06) solid logic
39 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
40 #define BINARY_SHIFTED_REGISTER_OPERATION(opc) \
41 void EncodeVisitor::Visit##opc##SR(GraphVisitor *visitor, Inst *inst) \
42 { \
43 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
44 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst); \
45 auto imm_shift_inst = static_cast<BinaryShiftedRegisterOperation *>(inst); \
46 auto dstSize = dst.GetSize() > 1 ? dst.GetSize() - 1 : 0; \
47 auto imm_value = static_cast<uint32_t>(imm_shift_inst->GetImm()) & (dstSize); \
48 auto shift = Shift(src1, imm_shift_inst->GetShiftType(), imm_value); \
49 enc->GetEncoder()->Encode##opc(dst, src0, shift); \
50 }
51
52 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
53 #define INST_DEF(OPCODE, MACRO) MACRO(OPCODE)
54
55 ENCODE_MATH_LIST(INST_DEF)
ENCODE_INST_WITH_SHIFTED_OPERAND(INST_DEF)56 ENCODE_INST_WITH_SHIFTED_OPERAND(INST_DEF)
57
58 #undef UNARY_OPERATION
59 #undef BINARY_OPERATION
60 #undef BINARY_SHIFTED_REGISTER_OPERATION
61 #undef INST_DEF
62
63 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
64 #define BINARY_IMM_OPERATION(opc) \
65 void EncodeVisitor::Visit##opc##I(GraphVisitor *visitor, Inst *inst) \
66 { \
67 auto binop = inst->CastTo##opc##I(); \
68 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
69 auto [dst, src0] = enc->GetCodegen()->ConvertRegisters<1U>(inst); \
70 enc->GetEncoder()->Encode##opc(dst, src0, Imm(binop->GetImm())); \
71 }
72
73 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
74 #define BINARRY_IMM_OPS(DEF) \
75 DEF(Add) \
76 DEF(Sub) \
77 DEF(Shl) \
78 DEF(AShr) \
79 DEF(And) \
80 DEF(Or) \
81 DEF(Xor)
82
83 BINARRY_IMM_OPS(BINARY_IMM_OPERATION)
84
85 #undef BINARRY_IMM_OPS
86 #undef BINARY_IMM_OPERATION
87
88 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
89 #define BINARY_IMM_SIGN_OPERATION(opc) \
90 void EncodeVisitor::Visit##opc##I(GraphVisitor *visitor, Inst *inst) \
91 { \
92 auto type = inst->GetType(); \
93 auto binop = inst->CastTo##opc##I(); \
94 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
95 auto [dst, src0] = enc->GetCodegen()->ConvertRegisters<1U>(inst); \
96 enc->GetEncoder()->Encode##opc(dst, src0, Imm(binop->GetImm()), IsTypeSigned(type)); \
97 }
98
99 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
100 #define BINARY_IMM_SIGN_OPS(DEF) \
101 DEF(Div) \
102 DEF(Mod)
103
104 BINARY_IMM_SIGN_OPS(BINARY_IMM_SIGN_OPERATION)
105
106 #undef BINARY_IMM_SIGN_OPS
107 #undef BINARY_IMM_SIGN_OPERATION
108
109 // CC-OFFNXT(G.PRE.06) solid logic
110 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
111 #define BINARY_SIGN_UNSIGN_OPERATION(opc) \
112 void EncodeVisitor::Visit##opc(GraphVisitor *visitor, Inst *inst) \
113 { \
114 auto type = inst->GetType(); \
115 EncodeVisitor *enc = static_cast<EncodeVisitor *>(visitor); \
116 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst); \
117 auto arch = enc->GetCodegen()->GetArch(); \
118 if (!Codegen::InstEncodedWithLibCall(inst, arch)) { \
119 enc->GetEncoder()->Encode##opc(dst, IsTypeSigned(type), src0, src1); \
120 return; /* CC-OFF(G.PRE.05) function gen */ \
121 } \
122 ASSERT(arch == Arch::AARCH32); \
123 if (enc->cg_->GetGraph()->IsAotMode()) { \
124 enc->GetEncoder()->SetFalseResult(); \
125 return; /* CC-OFF(G.PRE.05) function gen */ \
126 } \
127 auto [liveRegs, liveFpRegs] = enc->GetCodegen()->GetLiveRegisters(inst); \
128 enc->GetEncoder()->SetRegister(&liveRegs, &liveFpRegs, dst, false); \
129 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveFpRegs, true); \
130 enc->GetEncoder()->Encode##opc(dst, IsTypeSigned(type), src0, src1); \
131 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveFpRegs, true); \
132 }
133
134 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
135 #define SIGN_UNSIGN_OPS(DEF) \
136 DEF(Div) \
137 DEF(Min) \
138 DEF(Max)
139
140 SIGN_UNSIGN_OPS(BINARY_SIGN_UNSIGN_OPERATION)
141
142 #undef SIGN_UNSIGN_OPS
143 #undef BINARY_SIGN_UNSIGN_OPERATION
144
145 void EncodeVisitor::VisitMod(GraphVisitor *visitor, Inst *inst)
146 {
147 auto type = inst->GetType();
148 auto *enc = static_cast<EncodeVisitor *>(visitor);
149 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
150 auto arch = enc->GetCodegen()->GetArch();
151 if (!Codegen::InstEncodedWithLibCall(inst, arch)) {
152 enc->GetEncoder()->EncodeMod(dst, IsTypeSigned(type), src0, src1);
153 return;
154 }
155 if (DataType::IsFloatType(type)) {
156 RuntimeInterface::IntrinsicId entry =
157 ((type == DataType::FLOAT32) ? RuntimeInterface::IntrinsicId::LIB_CALL_FMODF
158 : RuntimeInterface::IntrinsicId::LIB_CALL_FMOD);
159 auto [liveRegs, liveFpRegs] = enc->GetCodegen()->GetLiveRegisters(inst);
160 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveFpRegs, true);
161
162 enc->GetCodegen()->FillCallParams(src0, src1);
163 enc->GetCodegen()->CallIntrinsic(inst, entry);
164
165 auto retVal = enc->GetCodegen()->GetTarget().GetReturnFpReg();
166 if (retVal.GetType().IsFloat()) {
167 // ret_val is FLOAT64 for Arm64, AMD64 and ARM32 HardFP, but dst can be FLOAT32
168 // so we convert ret_val to FLOAT32
169 enc->GetEncoder()->EncodeMov(dst, Reg(retVal.GetId(), dst.GetType()));
170 } else {
171 // case for ARM32 SoftFP
172 enc->GetEncoder()->EncodeMov(dst,
173 Reg(retVal.GetId(), dst.GetSize() == WORD_SIZE ? INT32_TYPE : INT64_TYPE));
174 }
175
176 enc->GetEncoder()->SetRegister(&liveRegs, &liveFpRegs, dst, false);
177 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveFpRegs, true);
178 return;
179 }
180 ASSERT(arch == Arch::AARCH32);
181 // Fix after supporting AOT mode for arm32
182 if (enc->cg_->GetGraph()->IsAotMode()) {
183 enc->GetEncoder()->SetFalseResult();
184 return;
185 }
186 auto [liveRegs, liveFpRegs] = enc->GetCodegen()->GetLiveRegisters(inst);
187 enc->GetEncoder()->SetRegister(&liveRegs, &liveFpRegs, dst, false);
188 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveFpRegs, true);
189 enc->GetEncoder()->EncodeMod(dst, IsTypeSigned(type), src0, src1);
190 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveFpRegs, true);
191 }
192
VisitShrI(GraphVisitor * visitor,Inst * inst)193 void EncodeVisitor::VisitShrI(GraphVisitor *visitor, Inst *inst)
194 {
195 auto binop = inst->CastToShrI();
196 auto enc = static_cast<EncodeVisitor *>(visitor);
197 auto [dst, src0] = enc->GetCodegen()->ConvertRegisters<1U>(inst);
198 enc->GetEncoder()->EncodeShr(dst, src0, Imm(binop->GetImm()));
199 }
200
VisitMAdd(GraphVisitor * visitor,Inst * inst)201 void EncodeVisitor::VisitMAdd(GraphVisitor *visitor, Inst *inst)
202 {
203 auto enc = static_cast<EncodeVisitor *>(visitor);
204 auto [dst, src0, src1, src2] = enc->GetCodegen()->ConvertRegisters<3U>(inst);
205 enc->GetEncoder()->EncodeMAdd(dst, src0, src1, src2);
206 }
207
VisitMSub(GraphVisitor * visitor,Inst * inst)208 void EncodeVisitor::VisitMSub(GraphVisitor *visitor, Inst *inst)
209 {
210 auto enc = static_cast<EncodeVisitor *>(visitor);
211 auto [dst, src0, src1, src2] = enc->GetCodegen()->ConvertRegisters<3U>(inst);
212 enc->GetEncoder()->EncodeMSub(dst, src0, src1, src2);
213 }
214
VisitMNeg(GraphVisitor * visitor,Inst * inst)215 void EncodeVisitor::VisitMNeg(GraphVisitor *visitor, Inst *inst)
216 {
217 auto enc = static_cast<EncodeVisitor *>(visitor);
218 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
219 enc->GetEncoder()->EncodeMNeg(dst, src0, src1);
220 }
221
VisitOrNot(GraphVisitor * visitor,Inst * inst)222 void EncodeVisitor::VisitOrNot(GraphVisitor *visitor, Inst *inst)
223 {
224 auto enc = static_cast<EncodeVisitor *>(visitor);
225 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
226 enc->GetEncoder()->EncodeOrNot(dst, src0, src1);
227 }
228
VisitAndNot(GraphVisitor * visitor,Inst * inst)229 void EncodeVisitor::VisitAndNot(GraphVisitor *visitor, Inst *inst)
230 {
231 auto enc = static_cast<EncodeVisitor *>(visitor);
232 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
233 enc->GetEncoder()->EncodeAndNot(dst, src0, src1);
234 }
235
VisitXorNot(GraphVisitor * visitor,Inst * inst)236 void EncodeVisitor::VisitXorNot(GraphVisitor *visitor, Inst *inst)
237 {
238 auto enc = static_cast<EncodeVisitor *>(visitor);
239 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
240 enc->GetEncoder()->EncodeXorNot(dst, src0, src1);
241 }
242
VisitNegSR(GraphVisitor * visitor,Inst * inst)243 void EncodeVisitor::VisitNegSR(GraphVisitor *visitor, Inst *inst)
244 {
245 auto enc = static_cast<EncodeVisitor *>(visitor);
246 auto [dst, src] = enc->GetCodegen()->ConvertRegisters<1U>(inst);
247 auto immShiftInst = static_cast<UnaryShiftedRegisterOperation *>(inst);
248 enc->GetEncoder()->EncodeNeg(dst, Shift(src, immShiftInst->GetShiftType(), immShiftInst->GetImm()));
249 }
250
VisitCast(GraphVisitor * visitor,Inst * inst)251 void EncodeVisitor::VisitCast(GraphVisitor *visitor, Inst *inst)
252 {
253 auto enc = static_cast<EncodeVisitor *>(visitor);
254 auto srcType = inst->GetInputType(0);
255 auto dstType = inst->GetType();
256 ASSERT(dstType != DataType::ANY);
257 bool srcSigned = IsTypeSigned(srcType);
258 bool dstSigned = IsTypeSigned(dstType);
259 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), srcType);
260 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), dstType);
261 if (dstType == DataType::BOOL) {
262 enc->GetEncoder()->EncodeCastToBool(dst, src);
263 return;
264 }
265 if (inst->CastToCast()->IsDynamicCast()) {
266 enc->GetCodegen()->EncodeDynamicCast(inst, dst, dstSigned, src);
267 return;
268 }
269 auto arch = enc->GetCodegen()->GetArch();
270 if (!Codegen::InstEncodedWithLibCall(inst, arch)) {
271 enc->GetEncoder()->EncodeCast(dst, dstSigned, src, srcSigned);
272 return;
273 }
274 ASSERT(arch == Arch::AARCH32);
275 // Fix after supporting AOT mode for arm32
276 if (enc->cg_->GetGraph()->IsAotMode()) {
277 enc->GetEncoder()->SetFalseResult();
278 return;
279 }
280 auto [liveRegs, liveVregs] = enc->GetCodegen()->GetLiveRegisters(inst);
281 enc->GetEncoder()->SetRegister(&liveRegs, &liveVregs, dst, false);
282 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveVregs, true);
283 enc->GetEncoder()->EncodeCast(dst, dstSigned, src, srcSigned);
284 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveVregs, true);
285 }
286
VisitBitcast(GraphVisitor * visitor,Inst * inst)287 void EncodeVisitor::VisitBitcast(GraphVisitor *visitor, Inst *inst)
288 {
289 auto enc = static_cast<EncodeVisitor *>(visitor);
290 auto codegen = enc->GetCodegen();
291 auto srcType = inst->GetInputType(0);
292 auto dstType = inst->GetType();
293 auto dst = codegen->ConvertRegister(inst->GetDstReg(), dstType);
294 auto src = codegen->ConvertRegister(inst->GetSrcReg(0), srcType);
295 enc->GetEncoder()->EncodeMov(dst, src);
296 }
297
VisitPhi(GraphVisitor * visitor,Inst * inst)298 void EncodeVisitor::VisitPhi([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst) {}
299
VisitConstant(GraphVisitor * visitor,Inst * inst)300 void EncodeVisitor::VisitConstant(GraphVisitor *visitor, Inst *inst)
301 {
302 auto *enc = static_cast<EncodeVisitor *>(visitor);
303 if (inst->GetDstReg() == INVALID_REG) {
304 return;
305 }
306 if (inst->GetDstReg() == enc->cg_->GetGraph()->GetZeroReg()) {
307 ASSERT(IsZeroConstant(inst));
308 ASSERT(enc->GetRegfile()->GetZeroReg() != INVALID_REGISTER);
309 return;
310 }
311 auto *constInst = inst->CastToConstant();
312 auto type = inst->GetType();
313 if (enc->cg_->GetGraph()->IsDynamicMethod() && type == DataType::INT64) {
314 type = DataType::INT32;
315 }
316 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
317 #ifndef NDEBUG
318 switch (type) {
319 case DataType::FLOAT32:
320 enc->GetEncoder()->EncodeMov(dst, Imm(constInst->GetFloatValue()));
321 break;
322 case DataType::FLOAT64:
323 enc->GetEncoder()->EncodeMov(dst, Imm(constInst->GetDoubleValue()));
324 break;
325 default:
326 enc->GetEncoder()->EncodeMov(dst, Imm(constInst->GetRawValue()));
327 }
328 #else
329 enc->GetEncoder()->EncodeMov(dst, Imm(constInst->GetRawValue()));
330 #endif
331 }
332
VisitNullPtr(GraphVisitor * visitor,Inst * inst)333 void EncodeVisitor::VisitNullPtr(GraphVisitor *visitor, Inst *inst)
334 {
335 auto *enc = static_cast<EncodeVisitor *>(visitor);
336 if (inst->GetDstReg() == enc->cg_->GetGraph()->GetZeroReg()) {
337 ASSERT_PRINT(enc->GetRegfile()->GetZeroReg() != INVALID_REGISTER,
338 "NullPtr doesn't have correct destination register");
339 return;
340 }
341 auto type = inst->GetType();
342 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
343 enc->GetEncoder()->EncodeMov(dst, Imm(0));
344 }
345
VisitLoadUniqueObject(GraphVisitor * visitor,Inst * inst)346 void EncodeVisitor::VisitLoadUniqueObject(GraphVisitor *visitor, Inst *inst)
347 {
348 auto *enc = static_cast<EncodeVisitor *>(visitor);
349 auto type = inst->GetType();
350 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
351 auto runtime = enc->GetCodegen()->GetGraph()->GetRuntime();
352 auto graph = enc->GetCodegen()->GetGraph();
353 if (graph->IsJitOrOsrMode()) {
354 enc->GetEncoder()->EncodeMov(dst, Imm(runtime->GetUniqueObject()));
355 } else {
356 auto ref = MemRef(enc->GetCodegen()->ThreadReg(), runtime->GetTlsUniqueObjectOffset(graph->GetArch()));
357 enc->GetEncoder()->EncodeLdr(dst, false, ref);
358 }
359 }
360
VisitCallIndirect(GraphVisitor * visitor,Inst * inst)361 void EncodeVisitor::VisitCallIndirect(GraphVisitor *visitor, Inst *inst)
362 {
363 static_cast<EncodeVisitor *>(visitor)->GetCodegen()->VisitCallIndirect(inst->CastToCallIndirect());
364 }
365
VisitCall(GraphVisitor * visitor,Inst * inst)366 void EncodeVisitor::VisitCall(GraphVisitor *visitor, Inst *inst)
367 {
368 static_cast<EncodeVisitor *>(visitor)->GetCodegen()->VisitCall(inst->CastToCall());
369 }
370
VisitCompare(GraphVisitor * visitor,Inst * inst)371 void EncodeVisitor::VisitCompare(GraphVisitor *visitor, Inst *inst)
372 {
373 auto *enc = static_cast<EncodeVisitor *>(visitor);
374
375 auto type = inst->CastToCompare()->GetOperandsType();
376 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
377 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
378 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
379 auto cc = enc->GetCodegen()->ConvertCc(inst->CastToCompare()->GetCc());
380 if (IsTestCc(cc)) {
381 enc->GetEncoder()->EncodeCompareTest(dst, src0, src1, cc);
382 } else {
383 enc->GetEncoder()->EncodeCompare(dst, src0, src1, cc);
384 }
385 }
386
VisitCmp(GraphVisitor * visitor,Inst * inst)387 void EncodeVisitor::VisitCmp(GraphVisitor *visitor, Inst *inst)
388 {
389 auto *enc = static_cast<EncodeVisitor *>(visitor);
390 auto cmpInst = inst->CastToCmp();
391 auto type = cmpInst->GetOperandsType();
392 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
393 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
394 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
395 Condition cc;
396 if (DataType::IsFloatType(type)) {
397 // check whether MI is fully correct here
398 cc = cmpInst->IsFcmpg() ? (Condition::MI) : (Condition::LT);
399 } else if (IsTypeSigned(type)) {
400 cc = Condition::LT;
401 } else {
402 cc = Condition::LO;
403 }
404 enc->GetEncoder()->EncodeCmp(dst, src0, src1, cc);
405 }
406
VisitReturnVoid(GraphVisitor * visitor,Inst * inst)407 void EncodeVisitor::VisitReturnVoid(GraphVisitor *visitor, Inst *inst)
408 {
409 auto *enc = static_cast<EncodeVisitor *>(visitor);
410 if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
411 enc->GetEncoder()->EncodeMemoryBarrier(memory_order::RELEASE);
412 }
413 enc->GetCodegen()->CreateReturn(inst);
414 }
415
VisitReturn(GraphVisitor * visitor,Inst * inst)416 void EncodeVisitor::VisitReturn(GraphVisitor *visitor, Inst *inst)
417 {
418 auto *enc = static_cast<EncodeVisitor *>(visitor);
419 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), inst->GetType());
420 enc->GetEncoder()->EncodeMov(enc->GetCodegen()->GetTarget().GetReturnReg(src.GetType()), src);
421 enc->GetCodegen()->CreateReturn(inst);
422 }
423
VisitReturnI(GraphVisitor * visitor,Inst * inst)424 void EncodeVisitor::VisitReturnI(GraphVisitor *visitor, Inst *inst)
425 {
426 auto *enc = static_cast<EncodeVisitor *>(visitor);
427 auto codegen = enc->GetCodegen();
428 auto rzero = enc->GetRegfile()->GetZeroReg();
429 auto immVal = inst->CastToReturnI()->GetImm();
430 Imm imm = codegen->ConvertImmWithExtend(immVal, inst->GetType());
431 auto returnReg = codegen->GetTarget().GetReturnReg(codegen->ConvertDataType(inst->GetType(), codegen->GetArch()));
432 if (immVal == 0 && codegen->GetTarget().SupportZeroReg() && !DataType::IsFloatType(inst->GetType())) {
433 enc->GetEncoder()->EncodeMov(returnReg, rzero);
434 } else {
435 enc->GetEncoder()->EncodeMov(returnReg, imm);
436 }
437 enc->GetCodegen()->CreateReturn(inst);
438 }
439
440 #if defined(EVENT_METHOD_EXIT_ENABLED) && EVENT_METHOD_EXIT_ENABLED != 0
GetCallInstFromReturnInlined(Inst * return_inlined)441 static CallInst *GetCallInstFromReturnInlined(Inst *return_inlined)
442 {
443 auto ss = return_inlined->GetSaveState();
444 for (auto &user : ss->GetUsers()) {
445 auto inst = user.GetInst();
446 if (inst->IsCall() && static_cast<CallInst *>(inst)->IsInlined()) {
447 return static_cast<CallInst *>(inst);
448 }
449 }
450 return nullptr;
451 }
452 #endif
453
VisitReturnInlined(GraphVisitor * visitor,Inst * inst)454 void EncodeVisitor::VisitReturnInlined(GraphVisitor *visitor, Inst *inst)
455 {
456 auto *enc = static_cast<EncodeVisitor *>(visitor);
457 if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
458 enc->GetEncoder()->EncodeMemoryBarrier(memory_order::RELEASE);
459 }
460 #if defined(EVENT_METHOD_EXIT_ENABLED) && EVENT_METHOD_EXIT_ENABLED != 0
461 if (!enc->cg_->GetGraph()->IsAotMode()) {
462 auto callInst = GetCallInstFromReturnInlined(inst->CastToReturnInlined());
463 ASSERT(callInst != nullptr);
464 static_cast<EncodeVisitor *>(visitor)->GetCodegen()->InsertTrace(
465 {Imm(static_cast<size_t>(TraceId::METHOD_EXIT)), Imm(reinterpret_cast<size_t>(callInst->GetCallMethod())),
466 Imm(static_cast<size_t>(events::MethodExitKind::INLINED))});
467 }
468 #endif
469 }
470
VisitLoadConstArray(GraphVisitor * visitor,Inst * inst)471 void EncodeVisitor::VisitLoadConstArray(GraphVisitor *visitor, Inst *inst)
472 {
473 auto *enc = static_cast<EncodeVisitor *>(visitor);
474 auto method = inst->CastToLoadConstArray()->GetMethod();
475 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
476 auto arrayType = inst->CastToLoadConstArray()->GetTypeId();
477 enc->GetCodegen()->CallRuntimeWithMethod(inst, method, EntrypointId::RESOLVE_LITERAL_ARRAY, dst,
478 TypedImm(arrayType));
479 }
480
VisitFillConstArray(GraphVisitor * visitor,Inst * inst)481 void EncodeVisitor::VisitFillConstArray(GraphVisitor *visitor, Inst *inst)
482 {
483 auto type = inst->GetType();
484 ASSERT(type != DataType::REFERENCE);
485 auto *enc = static_cast<EncodeVisitor *>(visitor);
486 auto encoder = enc->GetEncoder();
487 auto runtime = enc->cg_->GetGraph()->GetRuntime();
488 auto arrayType = inst->CastToFillConstArray()->GetTypeId();
489 auto arch = enc->cg_->GetGraph()->GetArch();
490 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE);
491 auto method = inst->CastToFillConstArray()->GetMethod();
492 auto offset = runtime->GetArrayDataOffset(enc->GetCodegen()->GetArch());
493 auto arraySize = inst->CastToFillConstArray()->GetImm() << DataType::ShiftByType(type, arch);
494 auto arrayReg = enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::GetIntTypeForReference(arch));
495 encoder->EncodeAdd(arrayReg, src, Imm(offset));
496 ASSERT(arraySize != 0);
497 if (enc->cg_->GetGraph()->IsAotMode()) {
498 auto arrOffset = runtime->GetOffsetToConstArrayData(method, arrayType);
499 auto pfOffset = runtime->GetPandaFileOffset(arch);
500 ScopedTmpReg methodReg(encoder);
501 enc->GetCodegen()->LoadMethod(methodReg);
502 // load pointer to panda file
503 encoder->EncodeLdr(methodReg, false, MemRef(methodReg, pfOffset));
504 // load pointer to binary file
505 encoder->EncodeLdr(methodReg, false, MemRef(methodReg, runtime->GetBinaryFileBaseOffset(enc->GetArch())));
506 // Get pointer to array data
507 encoder->EncodeAdd(methodReg, methodReg, Imm(arrOffset));
508 // call memcpy
509 RuntimeInterface::IntrinsicId entry = RuntimeInterface::IntrinsicId::LIB_CALL_MEM_COPY;
510 auto [liveRegs, liveFpRegs] = enc->GetCodegen()->GetLiveRegisters(inst);
511 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveFpRegs, true);
512
513 enc->GetCodegen()->FillCallParams(arrayReg, methodReg, TypedImm(arraySize));
514 enc->GetCodegen()->CallIntrinsic(inst, entry);
515 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveFpRegs, true);
516 } else {
517 auto data = runtime->GetPointerToConstArrayData(method, arrayType);
518 // call memcpy
519 RuntimeInterface::IntrinsicId entry = RuntimeInterface::IntrinsicId::LIB_CALL_MEM_COPY;
520 auto [liveRegs, liveFpRegs] = enc->GetCodegen()->GetLiveRegisters(inst);
521 enc->GetCodegen()->SaveCallerRegisters(liveRegs, liveFpRegs, true);
522
523 enc->GetCodegen()->FillCallParams(arrayReg, TypedImm(data), TypedImm(arraySize));
524 enc->GetCodegen()->CallIntrinsic(inst, entry);
525 enc->GetCodegen()->LoadCallerRegisters(liveRegs, liveFpRegs, true);
526 }
527 }
528
VisitNewArray(GraphVisitor * visitor,Inst * inst)529 void EncodeVisitor::VisitNewArray(GraphVisitor *visitor, Inst *inst)
530 {
531 auto *enc = static_cast<EncodeVisitor *>(visitor);
532 return enc->GetCodegen()->VisitNewArray(inst);
533 }
534
VisitParameter(GraphVisitor * visitor,Inst * inst)535 void EncodeVisitor::VisitParameter(GraphVisitor *visitor, Inst *inst)
536 {
537 // Default register parameters pushed in ir_builder
538 // In regalloc filled spill/fill parameters part.
539 auto *enc = static_cast<EncodeVisitor *>(visitor);
540 auto codegen = enc->GetCodegen();
541 auto paramInst = inst->CastToParameter();
542 auto sf = paramInst->GetLocationData();
543 if (sf.GetSrc() == sf.GetDst()) {
544 return;
545 }
546 auto tmpSf = codegen->GetGraph()->CreateInstSpillFill();
547 tmpSf->AddSpillFill(sf);
548 SpillFillEncoder(codegen, tmpSf).EncodeSpillFill();
549 }
550
VisitStoreArray(GraphVisitor * visitor,Inst * inst)551 void EncodeVisitor::VisitStoreArray(GraphVisitor *visitor, Inst *inst)
552 {
553 auto *enc = static_cast<EncodeVisitor *>(visitor);
554 auto array = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE);
555 auto index = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32);
556 constexpr int64_t IMM_2 = 2;
557 auto storedValue = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_2), inst->GetType());
558 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch());
559 auto scale = DataType::ShiftByType(inst->GetType(), enc->GetCodegen()->GetArch());
560 auto memRef = [enc, inst, array, index, offset, scale]() {
561 if (inst->CastToStoreArray()->GetNeedBarrier()) {
562 auto tmpOffset =
563 enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::GetIntTypeForReference(enc->GetArch()));
564 enc->GetEncoder()->EncodeShl(tmpOffset, index, Imm(scale));
565 enc->GetEncoder()->EncodeAdd(tmpOffset, tmpOffset, Imm(offset));
566 return MemRef(array, tmpOffset, 0);
567 }
568 auto tmp = enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::REFERENCE);
569 enc->GetEncoder()->EncodeAdd(tmp, array, Imm(offset));
570 return MemRef(tmp, index, scale);
571 };
572 auto mem = memRef();
573 if (inst->CastToStoreArray()->GetNeedBarrier()) {
574 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(array.GetId(), storedValue.GetId()));
575 }
576 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
577 enc->GetEncoder()->EncodeStr(storedValue, mem);
578 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
579 if (inst->CastToStoreArray()->GetNeedBarrier()) {
580 enc->GetCodegen()->CreatePostWRB(inst, mem, storedValue, INVALID_REGISTER);
581 }
582 }
583
VisitSpillFill(GraphVisitor * visitor,Inst * inst)584 void EncodeVisitor::VisitSpillFill(GraphVisitor *visitor, Inst *inst)
585 {
586 auto codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
587 SpillFillEncoder(codegen, inst).EncodeSpillFill();
588 }
589
VisitSaveState(GraphVisitor * visitor,Inst * inst)590 void EncodeVisitor::VisitSaveState([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
591 {
592 // Nothing to do, SaveState is processed in its users.
593 }
594
VisitSaveStateDeoptimize(GraphVisitor * visitor,Inst * inst)595 void EncodeVisitor::VisitSaveStateDeoptimize([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
596 {
597 // Nothing to do, SaveStateDeoptimize is processed in its users.
598 }
599
VisitSaveStateOsr(GraphVisitor * visitor,Inst * inst)600 void EncodeVisitor::VisitSaveStateOsr(GraphVisitor *visitor, Inst *inst)
601 {
602 static_cast<EncodeVisitor *>(visitor)->GetCodegen()->CreateOsrEntry(inst->CastToSaveStateOsr());
603 }
604
VisitLoadArray(GraphVisitor * visitor,Inst * inst)605 void EncodeVisitor::VisitLoadArray(GraphVisitor *visitor, Inst *inst)
606 {
607 auto instLoadArray = inst->CastToLoadArray();
608 auto enc = static_cast<EncodeVisitor *>(visitor);
609 auto runtime = enc->cg_->GetGraph()->GetRuntime();
610 ASSERT(instLoadArray->IsArray() || !runtime->IsCompressedStringsEnabled());
611 if (static_cast<LoadInst *>(inst)->GetNeedBarrier()) {
612 // Consider inserting barriers for GC
613 }
614 auto type = inst->GetType();
615 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
616 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32); // index
617 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
618 auto offset = instLoadArray->IsArray() ? runtime->GetArrayDataOffset(enc->GetCodegen()->GetArch())
619 : runtime->GetStringDataOffset(enc->GetArch());
620 auto encoder = enc->GetEncoder();
621 auto arch = encoder->GetArch();
622 auto shift = DataType::ShiftByType(type, arch);
623 ScopedTmpReg scopedTmp(encoder, Codegen::ConvertDataType(DataType::GetIntTypeForReference(arch), arch));
624 auto tmp = scopedTmp.GetReg();
625 encoder->EncodeAdd(tmp, src0, Imm(offset));
626 auto mem = MemRef(tmp, src1, shift);
627 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
628 encoder->EncodeLdr(dst, IsTypeSigned(type), mem);
629 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
630 }
631
VisitLoadCompressedStringChar(GraphVisitor * visitor,Inst * inst)632 void EncodeVisitor::VisitLoadCompressedStringChar(GraphVisitor *visitor, Inst *inst)
633 {
634 auto *enc = static_cast<EncodeVisitor *>(visitor);
635 auto runtime = enc->cg_->GetGraph()->GetRuntime();
636 auto type = inst->GetType();
637 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
638 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32); // index
639 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(2), DataType::INT32); // length
640 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
641 auto offset = runtime->GetStringDataOffset(enc->GetArch());
642 auto encoder = enc->GetEncoder();
643 auto arch = encoder->GetArch();
644 auto shift = DataType::ShiftByType(type, arch);
645 ScopedTmpReg scopedTmp(encoder, Codegen::ConvertDataType(DataType::GetIntTypeForReference(arch), arch));
646 auto tmp = scopedTmp.GetReg();
647 ASSERT(encoder->CanEncodeCompressedStringCharAt());
648 auto mask = runtime->GetStringCompressionMask();
649 if (mask != 1) {
650 UNREACHABLE(); // mask is hardcoded in JCL, but verify it just in case it's changed
651 }
652 enc->GetEncoder()->EncodeCompressedStringCharAt({dst, src0, src1, src2, tmp, offset, shift});
653 }
654
VisitLenArray(GraphVisitor * visitor,Inst * inst)655 void EncodeVisitor::VisitLenArray(GraphVisitor *visitor, Inst *inst)
656 {
657 auto *enc = static_cast<EncodeVisitor *>(visitor);
658 auto type = inst->GetType();
659 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
660 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // len array
661 auto lenArrayInst = inst->CastToLenArray();
662 auto runtime = enc->cg_->GetGraph()->GetRuntime();
663 int64_t offset = lenArrayInst->IsArray() ? runtime->GetArrayLengthOffset(enc->GetCodegen()->GetArch())
664 : runtime->GetStringLengthOffset(enc->GetArch());
665 auto mem = MemRef(src0, offset);
666 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
667 enc->GetEncoder()->EncodeLdr(dst, IsTypeSigned(type), mem);
668 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
669 }
670
VisitBuiltin(GraphVisitor * visitor,Inst * inst)671 void EncodeVisitor::VisitBuiltin([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
672 {
673 UNREACHABLE();
674 }
675
VisitNullCheck(GraphVisitor * visitor,Inst * inst)676 void EncodeVisitor::VisitNullCheck(GraphVisitor *visitor, Inst *inst)
677 {
678 if (inst->CastToNullCheck()->IsImplicit()) {
679 return;
680 }
681 auto *enc = static_cast<EncodeVisitor *>(visitor);
682 enc->GetCodegen()->template CreateUnaryCheck<SlowPathImplicitNullCheck>(inst, EntrypointId::NULL_POINTER_EXCEPTION,
683 DeoptimizeType::NULL_CHECK, Condition::EQ);
684 }
685
VisitBoundsCheck(GraphVisitor * visitor,Inst * inst)686 void EncodeVisitor::VisitBoundsCheck(GraphVisitor *visitor, Inst *inst)
687 {
688 auto *enc = static_cast<EncodeVisitor *>(visitor);
689 auto lenType = inst->GetInputType(0);
690 auto len = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), lenType);
691 auto indexType = inst->GetInputType(1);
692 auto index = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), indexType);
693 [[maybe_unused]] constexpr int64_t IMM_2 = 2;
694 ASSERT(inst->GetInput(IMM_2).GetInst()->GetOpcode() == Opcode::SaveState ||
695 inst->GetInput(IMM_2).GetInst()->GetOpcode() == Opcode::SaveStateDeoptimize);
696 EntrypointId entrypoint = inst->CastToBoundsCheck()->IsArray() ? EntrypointId::ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
697 : EntrypointId::STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION;
698 LabelHolder::LabelId label;
699 if (inst->CanDeoptimize()) {
700 DeoptimizeType type = DeoptimizeType::BOUNDS_CHECK_WITH_DEOPT;
701 label = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, type)->GetLabel();
702 } else {
703 label = enc->GetCodegen()->CreateSlowPath<SlowPathCheck>(inst, entrypoint)->GetLabel();
704 }
705 enc->GetEncoder()->EncodeJump(label, index, len, Condition::HS);
706 }
707
VisitRefTypeCheck(GraphVisitor * visitor,Inst * inst)708 void EncodeVisitor::VisitRefTypeCheck(GraphVisitor *visitor, Inst *inst)
709 {
710 auto *enc = static_cast<EncodeVisitor *>(visitor);
711 auto encoder = enc->GetEncoder();
712 auto arrayReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE);
713 auto refReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
714 [[maybe_unused]] constexpr int64_t IMM_2 = 2;
715 ASSERT(inst->GetInput(IMM_2).GetInst()->GetOpcode() == Opcode::SaveState ||
716 inst->GetInput(IMM_2).GetInst()->GetOpcode() == Opcode::SaveStateDeoptimize);
717 auto runtime = enc->cg_->GetGraph()->GetRuntime();
718 auto eid = inst->CanDeoptimize() ? RuntimeInterface::EntrypointId::CHECK_STORE_ARRAY_REFERENCE_DEOPTIMIZE
719 : RuntimeInterface::EntrypointId::CHECK_STORE_ARRAY_REFERENCE;
720 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathRefCheck>(inst, eid);
721 slowPath->SetRegs(arrayReg, refReg);
722 slowPath->CreateBackLabel(encoder);
723 // We don't check if stored object is nullptr
724 encoder->EncodeJump(slowPath->GetBackLabel(), refReg, Condition::EQ);
725 ScopedTmpReg tmpReg(encoder, Codegen::ConvertDataType(DataType::REFERENCE, enc->GetCodegen()->GetArch()));
726 ScopedTmpReg tmpReg1(encoder, Codegen::ConvertDataType(DataType::REFERENCE, enc->GetCodegen()->GetArch()));
727 // Get Class from array
728 enc->GetCodegen()->LoadClassFromObject(tmpReg, arrayReg);
729 // Get element type Class from array class
730 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
731 // Get Class from stored object
732 enc->GetCodegen()->LoadClassFromObject(tmpReg1, refReg);
733 // If the object's and array element's types match we do not check further
734 encoder->EncodeJump(slowPath->GetBackLabel(), tmpReg, tmpReg1, Condition::EQ);
735 // If the array's element class is not Object (baseclass == null)
736 // we call CheckStoreArrayReference, otherwise we fall through
737 encoder->EncodeLdr(tmpReg1, false, MemRef(tmpReg, runtime->GetClassBaseOffset(enc->GetArch())));
738 encoder->EncodeJump(slowPath->GetLabel(), tmpReg1, Condition::NE);
739 slowPath->BindBackLabel(encoder);
740 }
741
VisitZeroCheck(GraphVisitor * visitor,Inst * inst)742 void EncodeVisitor::VisitZeroCheck(GraphVisitor *visitor, Inst *inst)
743 {
744 auto *enc = static_cast<EncodeVisitor *>(visitor);
745 enc->GetCodegen()->template CreateUnaryCheck<SlowPathCheck>(inst, EntrypointId::ARITHMETIC_EXCEPTION,
746 DeoptimizeType::ZERO_CHECK, Condition::EQ);
747 }
748
VisitNegativeCheck(GraphVisitor * visitor,Inst * inst)749 void EncodeVisitor::VisitNegativeCheck(GraphVisitor *visitor, Inst *inst)
750 {
751 auto *enc = static_cast<EncodeVisitor *>(visitor);
752 enc->GetCodegen()->template CreateUnaryCheck<SlowPathCheck>(inst, EntrypointId::NEGATIVE_ARRAY_SIZE_EXCEPTION,
753 DeoptimizeType::NEGATIVE_CHECK, Condition::LT);
754 }
755
VisitNotPositiveCheck(GraphVisitor * visitor,Inst * inst)756 void EncodeVisitor::VisitNotPositiveCheck(GraphVisitor *visitor, Inst *inst)
757 {
758 auto *enc = static_cast<EncodeVisitor *>(visitor);
759 auto srcType = inst->GetInputType(0);
760 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), srcType);
761 ASSERT(inst->GetInput(1).GetInst()->GetOpcode() == Opcode::SaveState ||
762 inst->GetInput(1).GetInst()->GetOpcode() == Opcode::SaveStateDeoptimize);
763 ASSERT(inst->CanDeoptimize());
764 DeoptimizeType type = DeoptimizeType::NEGATIVE_CHECK;
765 auto label = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, type)->GetLabel();
766 enc->GetEncoder()->EncodeJump(label, src, Condition::LE);
767 }
768
VisitDeoptimizeIf(GraphVisitor * visitor,Inst * inst)769 void EncodeVisitor::VisitDeoptimizeIf(GraphVisitor *visitor, Inst *inst)
770 {
771 auto *enc = static_cast<EncodeVisitor *>(visitor);
772 auto srcType = inst->GetInput(0).GetInst()->GetType();
773 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), srcType);
774 auto slowPath =
775 enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, inst->CastToDeoptimizeIf()->GetDeoptimizeType());
776 // create jump to slow path if src is true
777 enc->GetEncoder()->EncodeJump(slowPath->GetLabel(), src, Condition::NE);
778 }
779
780 template <typename T>
EncodeJump(Encoder * encoder,LabelHolder::LabelId label,Reg src0,T src1,Condition cc)781 void EncodeJump(Encoder *encoder, LabelHolder::LabelId label, Reg src0, T src1, Condition cc)
782 {
783 if (IsTestCc(cc)) {
784 encoder->EncodeJumpTest(label, src0, src1, cc);
785 } else {
786 encoder->EncodeJump(label, src0, src1, cc);
787 }
788 }
789
VisitDeoptimizeCompare(GraphVisitor * visitor,Inst * inst)790 void EncodeVisitor::VisitDeoptimizeCompare(GraphVisitor *visitor, Inst *inst)
791 {
792 auto *enc = static_cast<EncodeVisitor *>(visitor);
793 auto deopt = inst->CastToDeoptimizeCompare();
794 ASSERT(deopt->GetOperandsType() != DataType::NO_TYPE);
795 auto src0 = enc->GetCodegen()->ConvertRegister(deopt->GetSrcReg(0), deopt->GetOperandsType());
796 auto src1 = enc->GetCodegen()->ConvertRegister(deopt->GetSrcReg(1), deopt->GetOperandsType());
797 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(
798 inst, inst->CastToDeoptimizeCompare()->GetDeoptimizeType());
799 EncodeJump(enc->GetEncoder(), slowPath->GetLabel(), src0, src1, enc->GetCodegen()->ConvertCc(deopt->GetCc()));
800 }
801
VisitDeoptimizeCompareImm(GraphVisitor * visitor,Inst * inst)802 void EncodeVisitor::VisitDeoptimizeCompareImm(GraphVisitor *visitor, Inst *inst)
803 {
804 auto *enc = static_cast<EncodeVisitor *>(visitor);
805 auto encoder = enc->GetEncoder();
806 auto deopt = inst->CastToDeoptimizeCompareImm();
807 ASSERT(deopt->GetOperandsType() != DataType::NO_TYPE);
808 auto cc = deopt->GetCc();
809 auto src0 = enc->GetCodegen()->ConvertRegister(deopt->GetSrcReg(0), deopt->GetOperandsType());
810 auto slowPathLabel =
811 enc->GetCodegen()
812 ->CreateSlowPath<SlowPathDeoptimize>(inst, inst->CastToDeoptimizeCompareImm()->GetDeoptimizeType())
813 ->GetLabel();
814
815 if (deopt->GetImm() == 0) {
816 Arch arch = enc->GetCodegen()->GetArch();
817 DataType::Type type = deopt->GetInput(0).GetInst()->GetType();
818 ASSERT(!IsFloatType(type));
819 if (IsTypeSigned(type) && (cc == ConditionCode::CC_LT || cc == ConditionCode::CC_GE)) {
820 auto signBit = GetTypeSize(type, arch) - 1;
821 if (cc == ConditionCode::CC_LT) {
822 // x < 0
823 encoder->EncodeBitTestAndBranch(slowPathLabel, src0, signBit, true);
824 return;
825 }
826 if (cc == ConditionCode::CC_GE) {
827 // x >= 0
828 encoder->EncodeBitTestAndBranch(slowPathLabel, src0, signBit, false);
829 return;
830 }
831 }
832 if (enc->GetCodegen()->GetTarget().SupportZeroReg()) {
833 auto zreg = enc->GetRegfile()->GetZeroReg();
834 EncodeJump(encoder, slowPathLabel, src0, zreg, enc->GetCodegen()->ConvertCc(cc));
835 } else {
836 EncodeJump(encoder, slowPathLabel, src0, Imm(0), enc->GetCodegen()->ConvertCc(cc));
837 }
838 return;
839 }
840 EncodeJump(encoder, slowPathLabel, src0, Imm(deopt->GetImm()), enc->GetCodegen()->ConvertCc(cc));
841 }
842
VisitLoadString(GraphVisitor * visitor,Inst * inst)843 void EncodeVisitor::VisitLoadString(GraphVisitor *visitor, Inst *inst)
844 {
845 auto *enc = static_cast<EncodeVisitor *>(visitor);
846 auto method = inst->CastToLoadString()->GetMethod();
847 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
848 auto stringType = inst->CastToLoadString()->GetTypeId();
849 auto graph = enc->cg_->GetGraph();
850 auto encoder = enc->GetEncoder();
851 ASSERT(inst->IsRuntimeCall());
852
853 // Static constructor invoked only once, so there is no sense in replacing regular
854 // ResolveString runtime call with optimized version that will only slow down constructor's execution.
855 auto isCctor = graph->GetRuntime()->IsMethodStaticConstructor(method);
856 if (graph->IsAotMode() && g_options.IsCompilerAotLoadStringPlt() && !isCctor) {
857 auto aotData = graph->GetAotData();
858 intptr_t slotOffset = aotData->GetStringSlotOffset(encoder->GetCursorOffset(), stringType);
859 ScopedTmpRegU64 addrReg(encoder);
860 ScopedTmpRegU64 tmpDst(encoder);
861 encoder->MakeLoadAotTableAddr(slotOffset, addrReg, tmpDst);
862
863 auto slowPath =
864 enc->GetCodegen()->CreateSlowPath<SlowPathResolveStringAot>(inst, EntrypointId::RESOLVE_STRING_AOT);
865 slowPath->SetDstReg(dst);
866 slowPath->SetAddrReg(addrReg);
867 slowPath->SetStringId(stringType);
868 slowPath->SetMethod(method);
869 encoder->EncodeJump(slowPath->GetLabel(), tmpDst, Imm(RuntimeInterface::RESOLVE_STRING_AOT_COUNTER_LIMIT),
870 Condition::LT);
871 encoder->EncodeMov(dst, Reg(tmpDst.GetReg().GetId(), dst.GetType()));
872 slowPath->BindBackLabel(encoder);
873 return;
874 }
875 if (!graph->IsAotMode()) {
876 ObjectPointerType stringPtr = graph->GetRuntime()->GetNonMovableString(method, stringType);
877 if (stringPtr != 0) {
878 encoder->EncodeMov(dst, Imm(stringPtr));
879 EVENT_JIT_USE_RESOLVED_STRING(graph->GetRuntime()->GetMethodName(method), stringType);
880 return;
881 }
882 }
883 enc->GetCodegen()->CallRuntimeWithMethod(inst, method, EntrypointId::RESOLVE_STRING, dst, TypedImm(stringType));
884 }
885
VisitLoadObject(GraphVisitor * visitor,Inst * inst)886 void EncodeVisitor::VisitLoadObject(GraphVisitor *visitor, Inst *inst)
887 {
888 auto *enc = static_cast<EncodeVisitor *>(visitor);
889 auto loadObj = inst->CastToLoadObject();
890 if (loadObj->GetNeedBarrier()) {
891 // Consider inserting barriers for GC
892 }
893 auto type = inst->GetType();
894 auto typeInput = inst->GetInput(0).GetInst()->GetType();
895 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), typeInput); // obj
896 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
897 auto graph = enc->cg_->GetGraph();
898 auto field = loadObj->GetObjField();
899 size_t offset = GetObjectOffset(graph, loadObj->GetObjectType(), field, loadObj->GetTypeId());
900 auto mem = MemRef(src, offset);
901 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
902 if (loadObj->GetVolatile()) {
903 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), mem);
904 } else {
905 enc->GetEncoder()->EncodeLdr(dst, IsTypeSigned(type), mem);
906 }
907 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
908 }
909
VisitResolveObjectField(GraphVisitor * visitor,Inst * inst)910 void EncodeVisitor::VisitResolveObjectField(GraphVisitor *visitor, Inst *inst)
911 {
912 auto *enc = static_cast<EncodeVisitor *>(visitor);
913 auto graph = enc->cg_->GetGraph();
914 auto resolver = inst->CastToResolveObjectField();
915 if (resolver->GetNeedBarrier()) {
916 // Inserts barriers for GC
917 }
918 auto type = inst->GetType();
919 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
920 auto typeId = resolver->GetTypeId();
921 auto method = resolver->GetMethod();
922 if (graph->IsAotMode()) {
923 enc->GetCodegen()->CallRuntimeWithMethod(inst, method, EntrypointId::GET_FIELD_OFFSET, dst, TypedImm(typeId));
924 } else {
925 auto skind = UnresolvedTypesInterface::SlotKind::FIELD;
926 ASSERT(graph->GetRuntime()->GetUnresolvedTypes() != nullptr);
927 auto fieldOffsetAddr = graph->GetRuntime()->GetUnresolvedTypes()->GetTableSlot(method, typeId, skind);
928 ScopedTmpReg tmpReg(enc->GetEncoder());
929 // load field offset and if it's 0 then call runtime EntrypointId::GET_FIELD_OFFSET
930 enc->GetEncoder()->EncodeMov(tmpReg, Imm(fieldOffsetAddr));
931 enc->GetEncoder()->EncodeLdr(tmpReg, false, MemRef(tmpReg));
932 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathUnresolved>(inst, EntrypointId::GET_FIELD_OFFSET);
933 slowPath->SetUnresolvedType(method, typeId);
934 slowPath->SetDstReg(tmpReg);
935 slowPath->SetSlotAddr(fieldOffsetAddr);
936 enc->GetEncoder()->EncodeJump(slowPath->GetLabel(), tmpReg, Condition::EQ);
937 slowPath->BindBackLabel(enc->GetEncoder());
938 enc->GetEncoder()->EncodeMov(dst, tmpReg);
939 }
940 }
941
VisitLoadResolvedObjectField(GraphVisitor * visitor,Inst * inst)942 void EncodeVisitor::VisitLoadResolvedObjectField([[maybe_unused]] GraphVisitor *visitor, Inst *inst)
943 {
944 auto *enc = static_cast<EncodeVisitor *>(visitor);
945 auto load = inst->CastToLoadResolvedObjectField();
946 if (load->GetNeedBarrier()) {
947 // Inserts barriers for GC
948 }
949 auto type = inst->GetType();
950 auto obj = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
951 auto ofs = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::UINT32); // field offset
952 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
953 ScopedTmpReg tmpReg(enc->GetEncoder());
954 enc->GetEncoder()->EncodeAdd(tmpReg, obj, ofs);
955 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), MemRef(tmpReg));
956 }
957
VisitLoad(GraphVisitor * visitor,Inst * inst)958 void EncodeVisitor::VisitLoad(GraphVisitor *visitor, Inst *inst)
959 {
960 auto *enc = static_cast<EncodeVisitor *>(visitor);
961 auto loadByOffset = inst->CastToLoad();
962 auto type = inst->GetType();
963 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0U), DataType::POINTER); // pointer
964 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1U), DataType::UINT32); // offset
965 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
966 auto mem = MemRef(src0, src1, loadByOffset->GetScale());
967 if (loadByOffset->GetVolatile()) {
968 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), mem);
969 } else {
970 enc->GetEncoder()->EncodeLdr(dst, IsTypeSigned(type), mem);
971 }
972 }
973
VisitLoadI(GraphVisitor * visitor,Inst * inst)974 void EncodeVisitor::VisitLoadI(GraphVisitor *visitor, Inst *inst)
975 {
976 auto *enc = static_cast<EncodeVisitor *>(visitor);
977 auto loadByOffset = inst->CastToLoadI();
978 auto type = inst->GetType();
979 auto base = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0U), DataType::POINTER); // pointer
980 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
981 if (loadByOffset->GetVolatile()) {
982 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), MemRef(base, loadByOffset->GetImm()));
983 } else {
984 enc->GetEncoder()->EncodeLdr(dst, IsTypeSigned(type), MemRef(base, loadByOffset->GetImm()));
985 }
986 }
987
VisitStoreI(GraphVisitor * visitor,Inst * inst)988 void EncodeVisitor::VisitStoreI(GraphVisitor *visitor, Inst *inst)
989 {
990 auto *enc = static_cast<EncodeVisitor *>(visitor);
991 auto storeInst = inst->CastToStoreI();
992 auto base = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0U), DataType::POINTER);
993 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1U), inst->GetType());
994 auto mem = MemRef(base, storeInst->GetImm());
995 if (inst->CastToStoreI()->GetNeedBarrier()) {
996 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(base.GetId(), src.GetId()));
997 }
998 if (storeInst->GetVolatile()) {
999 enc->GetEncoder()->EncodeStrRelease(src, mem);
1000 } else {
1001 enc->GetEncoder()->EncodeStr(src, mem);
1002 }
1003 if (inst->CastToStoreI()->GetNeedBarrier()) {
1004 enc->GetCodegen()->CreatePostWRB(inst, mem, src, INVALID_REGISTER);
1005 }
1006 }
1007
VisitStoreObject(GraphVisitor * visitor,Inst * inst)1008 void EncodeVisitor::VisitStoreObject(GraphVisitor *visitor, Inst *inst)
1009 {
1010 auto *enc = static_cast<EncodeVisitor *>(visitor);
1011 auto storeObj = inst->CastToStoreObject();
1012 auto codegen = enc->GetCodegen();
1013 auto src0 = codegen->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
1014 auto src1 = codegen->ConvertRegister(inst->GetSrcReg(1), inst->GetType()); // store value
1015 auto graph = enc->cg_->GetGraph();
1016 auto field = storeObj->GetObjField();
1017 size_t offset = GetObjectOffset(graph, storeObj->GetObjectType(), field, storeObj->GetTypeId());
1018 if (!enc->GetCodegen()->OffsetFitReferenceTypeSize(offset)) {
1019 // such code should not be executed
1020 enc->GetEncoder()->EncodeAbort();
1021 return;
1022 }
1023 auto mem = MemRef(src0, offset);
1024 auto encoder = enc->GetEncoder();
1025 if (inst->CastToStoreObject()->GetNeedBarrier()) {
1026 if (storeObj->GetObjectType() == ObjectType::MEM_DYN_CLASS) {
1027 codegen->CreatePreWRB<true>(inst, mem, MakeMask(src0.GetId(), src1.GetId()));
1028 } else {
1029 codegen->CreatePreWRB(inst, mem, MakeMask(src0.GetId(), src1.GetId()));
1030 }
1031 }
1032 auto prevOffset = encoder->GetCursorOffset();
1033 if (storeObj->GetVolatile()) {
1034 encoder->EncodeStrRelease(src1, mem);
1035 } else {
1036 encoder->EncodeStr(src1, mem);
1037 }
1038 codegen->TryInsertImplicitNullCheck(inst, prevOffset);
1039 if (inst->CastToStoreObject()->GetNeedBarrier()) {
1040 ScopedTmpRegLazy tmp(encoder);
1041 if (storeObj->GetObjectType() == ObjectType::MEM_DYN_CLASS) {
1042 tmp.AcquireIfInvalid();
1043 encoder->EncodeLdr(tmp, false, MemRef(src1, graph->GetRuntime()->GetManagedClassOffset(graph->GetArch())));
1044 src1 = tmp;
1045 }
1046 codegen->CreatePostWRB(inst, mem, src1, INVALID_REGISTER);
1047 }
1048 }
1049
VisitStoreResolvedObjectField(GraphVisitor * visitor,Inst * inst)1050 void EncodeVisitor::VisitStoreResolvedObjectField(GraphVisitor *visitor, Inst *inst)
1051 {
1052 auto *enc = static_cast<EncodeVisitor *>(visitor);
1053 auto store = inst->CastToStoreResolvedObjectField();
1054 auto obj = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // object
1055 auto val = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), inst->GetType()); // store value
1056 auto ofs = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(2), DataType::UINT32); // field offset
1057 auto mem = MemRef(obj, ofs, 0);
1058 if (store->GetNeedBarrier()) {
1059 enc->GetCodegen()->CreatePreWRB(inst, mem);
1060 }
1061 // Unknown store, assume it can be volatile
1062 enc->GetEncoder()->EncodeStrRelease(val, mem);
1063 if (store->GetNeedBarrier()) {
1064 enc->GetCodegen()->CreatePostWRB(inst, mem, val, INVALID_REGISTER);
1065 }
1066 }
1067
VisitStore(GraphVisitor * visitor,Inst * inst)1068 void EncodeVisitor::VisitStore(GraphVisitor *visitor, Inst *inst)
1069 {
1070 auto *enc = static_cast<EncodeVisitor *>(visitor);
1071 auto storeByOffset = inst->CastToStore();
1072 auto type = inst->GetType();
1073 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0U), DataType::POINTER); // pointer
1074 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1U), DataType::UINT32); // offset
1075 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(2U), type); // store value
1076 auto mem = MemRef(src0, src1, storeByOffset->GetScale());
1077 if (inst->CastToStore()->GetNeedBarrier()) {
1078 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(src0.GetId(), src2.GetId()));
1079 }
1080 if (storeByOffset->GetVolatile()) {
1081 enc->GetEncoder()->EncodeStrRelease(src2, mem);
1082 } else {
1083 enc->GetEncoder()->EncodeStr(src2, mem);
1084 }
1085 if (inst->CastToStore()->GetNeedBarrier()) {
1086 enc->GetCodegen()->CreatePostWRB(inst, mem, src2, INVALID_REGISTER);
1087 }
1088 }
1089
VisitInitClass(GraphVisitor * visitor,Inst * inst)1090 void EncodeVisitor::VisitInitClass(GraphVisitor *visitor, Inst *inst)
1091 {
1092 auto *enc = static_cast<EncodeVisitor *>(visitor);
1093 auto graph = enc->cg_->GetGraph();
1094 auto runtime = graph->GetRuntime();
1095 auto classId = inst->CastToInitClass()->GetTypeId();
1096 auto encoder = enc->GetEncoder();
1097 ASSERT(inst->IsRuntimeCall());
1098 if (graph->IsAotMode()) {
1099 ScopedTmpReg tmpReg(encoder);
1100 ScopedTmpReg classReg(encoder);
1101 auto aotData = graph->GetAotData();
1102 intptr_t offset = aotData->GetClassSlotOffset(encoder->GetCursorOffset(), classId, true);
1103 encoder->MakeLoadAotTableAddr(offset, tmpReg, classReg);
1104 auto label = encoder->CreateLabel();
1105 encoder->EncodeJump(label, classReg, Condition::NE);
1106 // PLT Class Init Resolver has special calling convention:
1107 // First encoder temporary (tmp_reg) works as parameter and return value (which is unnecessary here)
1108 CHECK_EQ(tmpReg.GetReg().GetId(), encoder->GetTarget().GetTempRegsMask().GetMinRegister());
1109 enc->GetCodegen()->CreateJumpToClassResolverPltShared(inst, tmpReg.GetReg(), EntrypointId::CLASS_INIT_RESOLVER);
1110 encoder->BindLabel(label);
1111 } else { // JIT mode
1112 auto klass = reinterpret_cast<uintptr_t>(inst->CastToInitClass()->GetClass());
1113 ASSERT(klass != 0);
1114 if (!runtime->IsClassInitialized(klass)) {
1115 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::INITIALIZE_CLASS);
1116 auto stateOffset = runtime->GetClassStateOffset(enc->GetArch());
1117 int64_t initValue = runtime->GetClassInitializedValue();
1118 ScopedTmpReg tmpReg(encoder);
1119 encoder->EncodeMov(tmpReg, Imm(klass + stateOffset));
1120 auto tmpI8 = enc->GetCodegen()->ConvertRegister(tmpReg.GetReg().GetId(), DataType::INT8);
1121 encoder->EncodeLdr(tmpI8, false, MemRef(tmpReg));
1122 encoder->EncodeJump(slowPath->GetLabel(), tmpI8, Imm(initValue), Condition::NE);
1123 slowPath->BindBackLabel(encoder);
1124 }
1125 }
1126 }
1127
VisitLoadClass(GraphVisitor * visitor,Inst * inst)1128 void EncodeVisitor::VisitLoadClass(GraphVisitor *visitor, Inst *inst)
1129 {
1130 auto *enc = static_cast<EncodeVisitor *>(visitor);
1131 auto encoder = enc->GetEncoder();
1132 auto loadClass = inst->CastToLoadClass();
1133 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1134 auto graph = enc->cg_->GetGraph();
1135 auto typeId = loadClass->GetTypeId();
1136 ASSERT(inst->IsRuntimeCall());
1137 if (graph->IsAotMode()) {
1138 auto methodClassId = graph->GetRuntime()->GetClassIdForMethod(graph->GetMethod());
1139 if (methodClassId == typeId) {
1140 auto dstPtr = dst.As(Codegen::ConvertDataType(DataType::POINTER, graph->GetArch()));
1141 enc->GetCodegen()->LoadMethod(dstPtr);
1142 auto mem = MemRef(dstPtr, graph->GetRuntime()->GetClassOffset(graph->GetArch()));
1143 encoder->EncodeLdr(dst.As(Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch())), false, mem);
1144 return;
1145 }
1146 ScopedTmpReg tmpReg(encoder);
1147 enc->GetCodegen()->CreateLoadClassFromPLT(inst, tmpReg, dst, typeId);
1148 } else { // JIT mode
1149 auto klass = loadClass->GetClass();
1150 if (klass == nullptr) {
1151 FillLoadClassUnresolved(visitor, inst);
1152 } else {
1153 encoder->EncodeMov(dst, Imm(reinterpret_cast<uintptr_t>(klass)));
1154 }
1155 }
1156 }
1157
FillLoadClassUnresolved(GraphVisitor * visitor,Inst * inst)1158 void EncodeVisitor::FillLoadClassUnresolved(GraphVisitor *visitor, Inst *inst)
1159 {
1160 auto *enc = static_cast<EncodeVisitor *>(visitor);
1161 auto encoder = enc->GetEncoder();
1162 auto loadClass = inst->CastToLoadClass();
1163 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1164 auto graph = enc->cg_->GetGraph();
1165 auto typeId = loadClass->GetTypeId();
1166 auto method = loadClass->GetMethod();
1167 auto utypes = graph->GetRuntime()->GetUnresolvedTypes();
1168 ASSERT(utypes != nullptr);
1169 auto klassAddr = utypes->GetTableSlot(method, typeId, UnresolvedTypesInterface::SlotKind::CLASS);
1170 Reg dstPtr(dst.GetId(), enc->GetCodegen()->GetPtrRegType());
1171 encoder->EncodeMov(dstPtr, Imm(klassAddr));
1172 encoder->EncodeLdr(dst, false, MemRef(dstPtr));
1173 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathUnresolved>(inst, EntrypointId::RESOLVE_CLASS);
1174 slowPath->SetUnresolvedType(method, typeId);
1175 slowPath->SetDstReg(dst);
1176 slowPath->SetSlotAddr(klassAddr);
1177 encoder->EncodeJump(slowPath->GetLabel(), dst, Condition::EQ);
1178 slowPath->BindBackLabel(encoder);
1179 }
1180
VisitGetGlobalVarAddress(GraphVisitor * visitor,Inst * inst)1181 void EncodeVisitor::VisitGetGlobalVarAddress(GraphVisitor *visitor, Inst *inst)
1182 {
1183 auto *enc = static_cast<EncodeVisitor *>(visitor);
1184 auto graph = enc->cg_->GetGraph();
1185 auto runtime = graph->GetRuntime();
1186 auto id = inst->CastToGetGlobalVarAddress()->GetTypeId();
1187 auto encoder = enc->GetEncoder();
1188 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType()); // load value
1189 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::ANY);
1190 auto entrypointId = runtime->GetGlobalVarEntrypointId();
1191 ASSERT(inst->IsRuntimeCall());
1192 if (graph->IsAotMode()) {
1193 ScopedTmpReg addr(encoder);
1194 auto aotData = graph->GetAotData();
1195 Reg constPool = src;
1196 ScopedTmpRegLazy tmpReg(encoder);
1197 if (dst.GetId() == src.GetId()) {
1198 tmpReg.AcquireIfInvalid();
1199 constPool = tmpReg.GetReg().As(src.GetType());
1200 encoder->EncodeMov(constPool, src);
1201 }
1202 intptr_t offset = aotData->GetCommonSlotOffset(encoder->GetCursorOffset(), id);
1203 encoder->MakeLoadAotTableAddr(offset, addr, dst);
1204 auto label = encoder->CreateLabel();
1205 encoder->EncodeJump(label, dst, Condition::NE);
1206 enc->GetCodegen()->CallRuntime(inst, entrypointId, dst, RegMask::GetZeroMask(), constPool, TypedImm(id));
1207 encoder->EncodeStr(dst, MemRef(addr));
1208 encoder->BindLabel(label);
1209 } else {
1210 auto address = inst->CastToGetGlobalVarAddress()->GetAddress();
1211 if (address == 0) {
1212 address = runtime->GetGlobalVarAddress(graph->GetMethod(), id);
1213 }
1214 if (address == 0) {
1215 enc->GetCodegen()->CallRuntime(inst, entrypointId, dst, RegMask::GetZeroMask(), src, TypedImm(id));
1216 } else {
1217 encoder->EncodeMov(dst, Imm(address));
1218 }
1219 }
1220 }
1221
VisitLoadRuntimeClass(GraphVisitor * visitor,Inst * inst)1222 void EncodeVisitor::VisitLoadRuntimeClass(GraphVisitor *visitor, Inst *inst)
1223 {
1224 auto *enc = static_cast<EncodeVisitor *>(visitor);
1225 auto codegen = enc->GetCodegen();
1226 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType()); // load value
1227 size_t classAddrOffset = codegen->GetGraph()->GetRuntime()->GetTlsPromiseClassPointerOffset(codegen->GetArch());
1228 auto mem = MemRef(codegen->ThreadReg(), classAddrOffset);
1229 enc->GetEncoder()->EncodeLdr(dst, false, mem);
1230 }
1231
EncodeLoadAndInitClassInAot(EncodeVisitor * enc,Encoder * encoder,Inst * inst,uint32_t classId,Reg dst)1232 void EncodeVisitor::EncodeLoadAndInitClassInAot(EncodeVisitor *enc, Encoder *encoder, Inst *inst, uint32_t classId,
1233 Reg dst)
1234 {
1235 auto graph = enc->cg_->GetGraph();
1236 ScopedTmpReg tmpReg(encoder);
1237 auto aotData = graph->GetAotData();
1238 intptr_t offset = aotData->GetClassSlotOffset(encoder->GetCursorOffset(), classId, true);
1239 encoder->MakeLoadAotTableAddr(offset, tmpReg, dst);
1240 auto label = encoder->CreateLabel();
1241 encoder->EncodeJump(label, dst, Condition::NE);
1242 // PLT Class Init Resolver has special calling convention:
1243 // First encoder temporary (tmp_reg) works as parameter and return value
1244 CHECK_EQ(tmpReg.GetReg().GetId(), encoder->GetTarget().GetTempRegsMask().GetMinRegister());
1245 enc->GetCodegen()->CreateJumpToClassResolverPltShared(inst, tmpReg.GetReg(), EntrypointId::CLASS_INIT_RESOLVER);
1246 encoder->EncodeMov(dst, tmpReg);
1247 encoder->BindLabel(label);
1248 }
1249
VisitLoadAndInitClass(GraphVisitor * visitor,Inst * inst)1250 void EncodeVisitor::VisitLoadAndInitClass(GraphVisitor *visitor, Inst *inst)
1251 {
1252 auto *enc = static_cast<EncodeVisitor *>(visitor);
1253 auto graph = enc->cg_->GetGraph();
1254 auto runtime = graph->GetRuntime();
1255 auto classId = inst->CastToLoadAndInitClass()->GetTypeId();
1256 auto encoder = enc->GetEncoder();
1257 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType()); // load value
1258 ASSERT(inst->IsRuntimeCall());
1259 if (graph->IsAotMode()) {
1260 auto methodClassId = runtime->GetClassIdForMethod(graph->GetMethod());
1261 if (methodClassId == classId) {
1262 auto dstPtr = dst.As(Codegen::ConvertDataType(DataType::POINTER, graph->GetArch()));
1263 enc->GetCodegen()->LoadMethod(dstPtr);
1264 auto mem = MemRef(dstPtr, graph->GetRuntime()->GetClassOffset(graph->GetArch()));
1265 encoder->EncodeLdr(dst.As(Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch())), false, mem);
1266 return;
1267 }
1268 EncodeLoadAndInitClassInAot(enc, encoder, inst, classId, dst);
1269 } else { // JIT mode
1270 auto klass = reinterpret_cast<uintptr_t>(inst->CastToLoadAndInitClass()->GetClass());
1271 encoder->EncodeMov(dst, Imm(klass));
1272 if (runtime->IsClassInitialized(klass)) {
1273 return;
1274 }
1275 auto methodClass = runtime->GetClass(graph->GetMethod());
1276 if (methodClass == inst->CastToLoadAndInitClass()->GetClass()) {
1277 return;
1278 }
1279 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::INITIALIZE_CLASS);
1280 auto stateOffset = runtime->GetClassStateOffset(enc->GetArch());
1281 int64_t initValue = runtime->GetClassInitializedValue();
1282 ScopedTmpReg stateReg(encoder, INT8_TYPE);
1283 encoder->EncodeLdr(stateReg, false, MemRef(dst, stateOffset));
1284 encoder->EncodeJump(slowPath->GetLabel(), stateReg, Imm(initValue), Condition::NE);
1285 slowPath->BindBackLabel(encoder);
1286 }
1287 }
1288
VisitUnresolvedLoadAndInitClass(GraphVisitor * visitor,Inst * inst)1289 void EncodeVisitor::VisitUnresolvedLoadAndInitClass(GraphVisitor *visitor, Inst *inst)
1290 {
1291 auto *enc = static_cast<EncodeVisitor *>(visitor);
1292 auto graph = enc->cg_->GetGraph();
1293 auto classId = inst->CastToUnresolvedLoadAndInitClass()->GetTypeId();
1294 auto encoder = enc->GetEncoder();
1295 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType()); // load value
1296 ASSERT(inst->IsRuntimeCall());
1297 if (graph->IsAotMode()) {
1298 EncodeLoadAndInitClassInAot(enc, encoder, inst, classId, dst);
1299 } else { // JIT mode
1300 auto method = inst->CastToUnresolvedLoadAndInitClass()->GetMethod();
1301 auto utypes = graph->GetRuntime()->GetUnresolvedTypes();
1302 ASSERT(utypes != nullptr);
1303 auto klassAddr = utypes->GetTableSlot(method, classId, UnresolvedTypesInterface::SlotKind::CLASS);
1304 Reg dstPtr(dst.GetId(), enc->GetCodegen()->GetPtrRegType());
1305 encoder->EncodeMov(dstPtr, Imm(klassAddr));
1306 encoder->EncodeLdr(dst, false, MemRef(dstPtr));
1307 static constexpr auto ENTRYPOINT_ID = RuntimeInterface::EntrypointId::INITIALIZE_CLASS_BY_ID;
1308 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathUnresolved>(inst, ENTRYPOINT_ID);
1309 slowPath->SetUnresolvedType(method, classId);
1310 slowPath->SetDstReg(dst);
1311 slowPath->SetSlotAddr(klassAddr);
1312 encoder->EncodeJump(slowPath->GetLabel(), dst, Condition::EQ);
1313 slowPath->BindBackLabel(encoder);
1314 }
1315 }
1316
VisitLoadStatic(GraphVisitor * visitor,Inst * inst)1317 void EncodeVisitor::VisitLoadStatic(GraphVisitor *visitor, Inst *inst)
1318 {
1319 auto *enc = static_cast<EncodeVisitor *>(visitor);
1320 auto loadStatic = inst->CastToLoadStatic();
1321 if (loadStatic->GetNeedBarrier()) {
1322 // Consider inserting barriers for GC
1323 }
1324 auto type = inst->GetType();
1325 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
1326 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // class
1327 auto graph = enc->cg_->GetGraph();
1328 auto field = loadStatic->GetObjField();
1329 auto offset = graph->GetRuntime()->GetFieldOffset(field);
1330 auto mem = MemRef(src0, offset);
1331 if (loadStatic->GetVolatile()) {
1332 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), mem);
1333 } else {
1334 enc->GetEncoder()->EncodeLdr(dst, IsTypeSigned(type), mem);
1335 }
1336 }
1337
VisitResolveObjectFieldStatic(GraphVisitor * visitor,Inst * inst)1338 void EncodeVisitor::VisitResolveObjectFieldStatic(GraphVisitor *visitor, Inst *inst)
1339 {
1340 auto *enc = static_cast<EncodeVisitor *>(visitor);
1341 auto graph = enc->cg_->GetGraph();
1342 auto resolver = inst->CastToResolveObjectFieldStatic();
1343 ASSERT(resolver->GetType() == DataType::REFERENCE);
1344 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1345 auto typeId = resolver->GetTypeId();
1346 auto method = resolver->GetMethod();
1347 EntrypointId entrypoint = EntrypointId::GET_UNKNOWN_STATIC_FIELD_MEMORY_ADDRESS; // REFERENCE
1348 UnresolvedTypesInterface::SlotKind slotKind = UnresolvedTypesInterface::SlotKind::FIELD;
1349 if (graph->IsAotMode()) {
1350 enc->GetCodegen()->CallRuntimeWithMethod(inst, method, entrypoint, dst, TypedImm(typeId), TypedImm(0));
1351 } else {
1352 ScopedTmpReg tmpReg(enc->GetEncoder());
1353 ASSERT(graph->GetRuntime()->GetUnresolvedTypes() != nullptr);
1354 auto fieldAddr = graph->GetRuntime()->GetUnresolvedTypes()->GetTableSlot(method, typeId, slotKind);
1355 enc->GetEncoder()->EncodeMov(tmpReg, Imm(fieldAddr));
1356 enc->GetEncoder()->EncodeLdr(tmpReg, false, MemRef(tmpReg));
1357 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathUnresolved>(inst, entrypoint);
1358 slowPath->SetUnresolvedType(method, typeId);
1359 slowPath->SetDstReg(tmpReg);
1360 slowPath->SetSlotAddr(fieldAddr);
1361 enc->GetEncoder()->EncodeJump(slowPath->GetLabel(), tmpReg, Condition::EQ);
1362 slowPath->BindBackLabel(enc->GetEncoder());
1363 enc->GetEncoder()->EncodeMov(dst, tmpReg);
1364 }
1365 }
1366
VisitLoadResolvedObjectFieldStatic(GraphVisitor * visitor,Inst * inst)1367 void EncodeVisitor::VisitLoadResolvedObjectFieldStatic(GraphVisitor *visitor, Inst *inst)
1368 {
1369 auto *enc = static_cast<EncodeVisitor *>(visitor);
1370 auto load = inst->CastToLoadResolvedObjectFieldStatic();
1371 if (load->GetNeedBarrier()) {
1372 // Insert barriers for GC
1373 }
1374 auto type = inst->GetType();
1375 auto fieldAddr = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE);
1376 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
1377 // Unknown load, assume it can be volatile
1378 enc->GetEncoder()->EncodeLdrAcquire(dst, IsTypeSigned(type), MemRef(fieldAddr));
1379 }
1380
VisitStoreStatic(GraphVisitor * visitor,Inst * inst)1381 void EncodeVisitor::VisitStoreStatic(GraphVisitor *visitor, Inst *inst)
1382 {
1383 auto *enc = static_cast<EncodeVisitor *>(visitor);
1384 auto storeStatic = inst->CastToStoreStatic();
1385 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // class
1386 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), inst->GetType()); // store value
1387 auto graph = enc->cg_->GetGraph();
1388 auto runtime = graph->GetRuntime();
1389 auto field = storeStatic->GetObjField();
1390 auto offset = runtime->GetFieldOffset(field);
1391 auto mem = MemRef(src0, offset);
1392 if (inst->CastToStoreStatic()->GetNeedBarrier()) {
1393 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(src1.GetId()));
1394 }
1395 if (storeStatic->GetVolatile()) {
1396 enc->GetEncoder()->EncodeStrRelease(src1, mem);
1397 } else {
1398 enc->GetEncoder()->EncodeStr(src1, mem);
1399 }
1400 if (!inst->CastToStoreStatic()->GetNeedBarrier()) {
1401 return;
1402 }
1403 auto barrierType {runtime->GetPostType()};
1404 // We should decide here pass to barrier class+offset or managed object.
1405 // For other store we already pass obj+offset and while call EncodeInterGenerationalBarrier offset is ignored.
1406 // StaticStore is specific case where gen GC expects barrier for managed object instead of class which field is
1407 // updated.
1408 if (barrierType == ark::mem::BarrierType::POST_INTERREGION_BARRIER) {
1409 enc->GetCodegen()->CreatePostWRB(inst, mem, src1, INVALID_REGISTER);
1410 } else {
1411 auto arch = enc->GetEncoder()->GetArch();
1412 auto tmpReg = enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::GetIntTypeForReference(arch));
1413 enc->GetEncoder()->EncodeLdr(tmpReg, false, MemRef(src0, runtime->GetManagedClassOffset(enc->GetArch())));
1414 auto classHeaderMem = MemRef(tmpReg);
1415 enc->GetCodegen()->CreatePostWRB(inst, classHeaderMem, src1, INVALID_REGISTER);
1416 }
1417 }
1418
VisitLoadObjectDynamic(GraphVisitor * visitor,Inst * inst)1419 void EncodeVisitor::VisitLoadObjectDynamic(GraphVisitor *visitor, Inst *inst)
1420 {
1421 auto *enc = static_cast<EncodeVisitor *>(visitor);
1422 auto *codegen = enc->GetCodegen();
1423 codegen->CreateLoadObjectDynamic(inst);
1424 }
1425
VisitStoreObjectDynamic(GraphVisitor * visitor,Inst * inst)1426 void EncodeVisitor::VisitStoreObjectDynamic(GraphVisitor *visitor, Inst *inst)
1427 {
1428 auto *enc = static_cast<EncodeVisitor *>(visitor);
1429 auto *codegen = enc->GetCodegen();
1430 codegen->CreateStoreObjectDynamic(inst);
1431 }
1432
VisitUnresolvedStoreStatic(GraphVisitor * visitor,Inst * inst)1433 void EncodeVisitor::VisitUnresolvedStoreStatic(GraphVisitor *visitor, Inst *inst)
1434 {
1435 auto *enc = static_cast<EncodeVisitor *>(visitor);
1436 auto storeStatic = inst->CastToUnresolvedStoreStatic();
1437 ASSERT(storeStatic->GetType() == DataType::REFERENCE);
1438 ASSERT(storeStatic->GetNeedBarrier());
1439 auto typeId = storeStatic->GetTypeId();
1440 auto value = enc->GetCodegen()->ConvertRegister(storeStatic->GetSrcReg(0), storeStatic->GetType());
1441 auto entrypoint = RuntimeInterface::EntrypointId::UNRESOLVED_STORE_STATIC_BARRIERED;
1442 auto method = storeStatic->GetMethod();
1443 ASSERT(method != nullptr);
1444 enc->GetCodegen()->CallRuntimeWithMethod(storeStatic, method, entrypoint, Reg(), TypedImm(typeId), value);
1445 }
1446
VisitStoreResolvedObjectFieldStatic(GraphVisitor * visitor,Inst * inst)1447 void EncodeVisitor::VisitStoreResolvedObjectFieldStatic(GraphVisitor *visitor, Inst *inst)
1448 {
1449 auto *enc = static_cast<EncodeVisitor *>(visitor);
1450 auto store = inst->CastToStoreResolvedObjectFieldStatic();
1451 ASSERT(store->GetType() != DataType::REFERENCE);
1452 ASSERT(!store->GetNeedBarrier());
1453 auto val = enc->GetCodegen()->ConvertRegister(store->GetSrcReg(1), store->GetType());
1454 auto reg = enc->GetCodegen()->ConvertRegister(store->GetSrcReg(0), DataType::REFERENCE);
1455 // Non-barriered case. Unknown store, assume it can be volatile
1456 enc->GetEncoder()->EncodeStrRelease(val, MemRef(reg));
1457 }
1458
VisitNewObject(GraphVisitor * visitor,Inst * inst)1459 void EncodeVisitor::VisitNewObject(GraphVisitor *visitor, Inst *inst)
1460 {
1461 auto *enc = static_cast<EncodeVisitor *>(visitor);
1462 // NOTE(msherstennikov): use irtoced entrypoint once spill-fills will be supported for entrypoints mode.
1463 if (enc->cg_->GetArch() == Arch::AARCH32) {
1464 enc->GetCodegen()->CreateNewObjCallOld(inst->CastToNewObject());
1465 } else {
1466 enc->GetCodegen()->CreateNewObjCall(inst->CastToNewObject());
1467 }
1468 if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
1469 enc->GetEncoder()->EncodeMemoryBarrier(memory_order::RELEASE);
1470 }
1471 }
1472
VisitUnresolvedLoadType(GraphVisitor * visitor,Inst * inst)1473 void EncodeVisitor::VisitUnresolvedLoadType(GraphVisitor *visitor, Inst *inst)
1474 {
1475 auto *enc = static_cast<EncodeVisitor *>(visitor);
1476 auto encoder = enc->GetEncoder();
1477 auto codegen = enc->GetCodegen();
1478 auto loadType = inst->CastToUnresolvedLoadType();
1479 if (loadType->GetNeedBarrier()) {
1480 // Consider inserting barriers for GC
1481 }
1482 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
1483 auto graph = enc->cg_->GetGraph();
1484 auto typeId = loadType->GetTypeId();
1485 auto runtime = graph->GetRuntime();
1486 auto method = loadType->GetMethod();
1487 if (graph->IsAotMode()) {
1488 ScopedTmpReg tmpReg(encoder);
1489 // Load pointer to klass from PLT
1490 codegen->CreateLoadClassFromPLT(inst, tmpReg, dst, typeId);
1491 // Finally load Object
1492 encoder->EncodeLdr(dst, false, MemRef(dst, runtime->GetManagedClassOffset(enc->GetArch())));
1493 } else {
1494 auto utypes = runtime->GetUnresolvedTypes();
1495 ASSERT(utypes != nullptr);
1496 auto clsAddr = utypes->GetTableSlot(method, typeId, UnresolvedTypesInterface::SlotKind::MANAGED_CLASS);
1497 Reg dstPtr(dst.GetId(), codegen->GetPtrRegType());
1498 encoder->EncodeMov(dstPtr, Imm(clsAddr));
1499 encoder->EncodeLdr(dst, false, MemRef(dstPtr));
1500 auto slowPath = codegen->CreateSlowPath<SlowPathUnresolved>(inst, EntrypointId::RESOLVE_CLASS_OBJECT);
1501 slowPath->SetUnresolvedType(method, typeId);
1502 slowPath->SetDstReg(dst);
1503 slowPath->SetSlotAddr(clsAddr);
1504 encoder->EncodeJump(slowPath->GetLabel(), dst, Condition::EQ);
1505 slowPath->BindBackLabel(encoder);
1506 }
1507 }
1508
VisitLoadType(GraphVisitor * visitor,Inst * inst)1509 void EncodeVisitor::VisitLoadType(GraphVisitor *visitor, Inst *inst)
1510 {
1511 auto *enc = static_cast<EncodeVisitor *>(visitor);
1512 auto encoder = enc->GetEncoder();
1513 auto loadType = inst->CastToLoadType();
1514 if (loadType->GetNeedBarrier()) {
1515 // Consider inserting barriers for GC
1516 }
1517 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1518 auto graph = enc->cg_->GetGraph();
1519 auto typeId = loadType->GetTypeId();
1520 auto runtime = graph->GetRuntime();
1521 auto method = loadType->GetMethod();
1522 if (graph->IsAotMode()) {
1523 auto methodClassId = runtime->GetClassIdForMethod(graph->GetMethod());
1524 if (methodClassId == typeId) {
1525 auto dstPtr = dst.As(Codegen::ConvertDataType(DataType::POINTER, graph->GetArch()));
1526 enc->GetCodegen()->LoadMethod(dstPtr);
1527 auto mem = MemRef(dstPtr, graph->GetRuntime()->GetClassOffset(graph->GetArch()));
1528 encoder->EncodeLdr(dst.As(Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch())), false, mem);
1529 } else {
1530 ScopedTmpReg tmpReg(encoder);
1531 // Load pointer to klass from PLT
1532 enc->GetCodegen()->CreateLoadClassFromPLT(inst, tmpReg, dst, typeId);
1533 }
1534 // Finally load ManagedClass object
1535 encoder->EncodeLdr(dst, false, MemRef(dst, runtime->GetManagedClassOffset(enc->GetArch())));
1536 } else { // JIT mode
1537 auto klass = reinterpret_cast<uintptr_t>(runtime->ResolveType(method, typeId));
1538 auto managedKlass = runtime->GetManagedType(klass);
1539 encoder->EncodeMov(dst, Imm(managedKlass));
1540 }
1541 }
1542
FillUnresolvedClass(GraphVisitor * visitor,Inst * inst)1543 void EncodeVisitor::FillUnresolvedClass(GraphVisitor *visitor, Inst *inst)
1544 {
1545 auto *enc = static_cast<EncodeVisitor *>(visitor);
1546 auto graph = enc->cg_->GetGraph();
1547 auto encoder = enc->GetEncoder();
1548 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1549 auto eid = inst->CanDeoptimize() ? RuntimeInterface::EntrypointId::CHECK_CAST_DEOPTIMIZE
1550 : RuntimeInterface::EntrypointId::CHECK_CAST;
1551 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, eid);
1552 encoder->EncodeJump(slowPath->GetLabel(), classReg, Condition::EQ);
1553 slowPath->CreateBackLabel(encoder);
1554 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
1555 encoder->EncodeJump(slowPath->GetBackLabel(), src, Condition::EQ);
1556 ScopedTmpReg tmpReg(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1557 enc->GetCodegen()->LoadClassFromObject(tmpReg, src);
1558 encoder->EncodeJump(slowPath->GetLabel(), tmpReg, classReg, Condition::NE);
1559 slowPath->BindBackLabel(encoder);
1560 }
1561
FillObjectClass(GraphVisitor * visitor,Reg tmpReg,LabelHolder::LabelId throwLabel)1562 void EncodeVisitor::FillObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel)
1563 {
1564 auto *enc = static_cast<EncodeVisitor *>(visitor);
1565 auto graph = enc->cg_->GetGraph();
1566 auto runtime = graph->GetRuntime();
1567 auto encoder = enc->GetEncoder();
1568 Reg typeReg(tmpReg.GetId(), INT8_TYPE);
1569 // Load type class
1570 encoder->EncodeLdr(typeReg, false, MemRef(tmpReg, runtime->GetClassTypeOffset(enc->GetArch())));
1571 // Jump to EH if type not reference
1572 encoder->EncodeJump(throwLabel, typeReg, Imm(runtime->GetReferenceTypeMask()), Condition::NE);
1573 }
1574
1575 /* The CheckCast class should be a subclass of input class:
1576 ......................
1577 bool Class::IsSubClassOf(const Class *klass) const {
1578 const Class *current = this;
1579 do {
1580 if (current == klass) {
1581 return true;
1582 }
1583 current = current->GetBase();
1584 } while (current != nullptr);
1585 return false;
1586 }
1587 */
1588
FillOtherClass(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId throwLabel)1589 void EncodeVisitor::FillOtherClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel)
1590 {
1591 auto *enc = static_cast<EncodeVisitor *>(visitor);
1592 auto graph = enc->cg_->GetGraph();
1593 auto encoder = enc->GetEncoder();
1594 auto loopLabel = encoder->CreateLabel();
1595 // First compare `current == klass` we make before switch
1596 encoder->BindLabel(loopLabel);
1597 // Load base klass
1598 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, graph->GetRuntime()->GetClassBaseOffset(enc->GetArch())));
1599 encoder->EncodeJump(throwLabel, tmpReg, Condition::EQ);
1600 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1601 encoder->EncodeJump(loopLabel, tmpReg, classReg, Condition::NE);
1602 }
1603
FillArrayObjectClass(GraphVisitor * visitor,Reg tmpReg,LabelHolder::LabelId throwLabel)1604 void EncodeVisitor::FillArrayObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel)
1605 {
1606 auto *enc = static_cast<EncodeVisitor *>(visitor);
1607 auto graph = enc->cg_->GetGraph();
1608 auto runtime = graph->GetRuntime();
1609 auto encoder = enc->GetEncoder();
1610 Reg typeReg(tmpReg.GetId(), INT8_TYPE);
1611 // Load Component class
1612 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1613 // Jump to EH if src is not array class
1614 encoder->EncodeJump(throwLabel, tmpReg, Condition::EQ);
1615 // Load type of the component class
1616 encoder->EncodeLdr(typeReg, false, MemRef(tmpReg, runtime->GetClassTypeOffset(enc->GetArch())));
1617 // Jump to EH if type not reference
1618 encoder->EncodeJump(throwLabel, typeReg, Imm(runtime->GetReferenceTypeMask()), Condition::NE);
1619 }
1620
FillArrayClass(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId throwLabel)1621 void EncodeVisitor::FillArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel)
1622 {
1623 auto *enc = static_cast<EncodeVisitor *>(visitor);
1624 auto graph = enc->cg_->GetGraph();
1625 auto runtime = graph->GetRuntime();
1626 auto encoder = enc->GetEncoder();
1627 auto eid = inst->CanDeoptimize() ? RuntimeInterface::EntrypointId::CHECK_CAST_DEOPTIMIZE
1628 : RuntimeInterface::EntrypointId::CHECK_CAST;
1629 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, eid);
1630 // Load Component type of Input
1631 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1632 // Check that src is array class
1633 encoder->EncodeJump(throwLabel, tmpReg, Condition::EQ);
1634 // Load Component type of the instance
1635 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1636 ScopedTmpReg tmpReg1(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1637 encoder->EncodeLdr(tmpReg1, false, MemRef(classReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1638 // Compare component types
1639 encoder->EncodeJump(slowPath->GetLabel(), tmpReg, tmpReg1, Condition::NE);
1640 slowPath->BindBackLabel(encoder);
1641 }
1642
FillInterfaceClass(GraphVisitor * visitor,Inst * inst)1643 void EncodeVisitor::FillInterfaceClass(GraphVisitor *visitor, Inst *inst)
1644 {
1645 auto enc = static_cast<EncodeVisitor *>(visitor);
1646 auto encoder = enc->GetEncoder();
1647 auto codegen = enc->GetCodegen();
1648 if (inst->CanDeoptimize() || codegen->GetArch() == Arch::AARCH32) {
1649 auto eid = inst->CanDeoptimize() ? RuntimeInterface::EntrypointId::CHECK_CAST_DEOPTIMIZE
1650 : RuntimeInterface::EntrypointId::CHECK_CAST;
1651 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, eid);
1652 encoder->EncodeJump(slowPath->GetLabel());
1653 slowPath->BindBackLabel(encoder);
1654 } else {
1655 codegen->CreateCheckCastInterfaceCall(inst);
1656 }
1657 }
1658
FillCheckCast(GraphVisitor * visitor,Inst * inst,Reg src,LabelHolder::LabelId endLabel,compiler::ClassType klassType)1659 void EncodeVisitor::FillCheckCast(GraphVisitor *visitor, Inst *inst, Reg src, LabelHolder::LabelId endLabel,
1660 compiler::ClassType klassType)
1661 {
1662 if (klassType == ClassType::INTERFACE_CLASS) {
1663 FillInterfaceClass(visitor, inst);
1664 return;
1665 }
1666 auto *enc = static_cast<EncodeVisitor *>(visitor);
1667 auto graph = enc->cg_->GetGraph();
1668 auto encoder = enc->GetEncoder();
1669 // class_reg - CheckCast class
1670 // tmp_reg - input class
1671 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1672 ScopedTmpReg tmpReg(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1673 enc->GetCodegen()->LoadClassFromObject(tmpReg, src);
1674 // There is no exception if the classes are equal
1675 encoder->EncodeJump(endLabel, classReg, tmpReg, Condition::EQ);
1676 LabelHolder::LabelId throwLabel;
1677 if (inst->CanDeoptimize()) {
1678 throwLabel =
1679 enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::CHECK_CAST)->GetLabel();
1680 } else {
1681 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathCheckCast>(inst, EntrypointId::CLASS_CAST_EXCEPTION);
1682 slowPath->SetClassReg(classReg);
1683 throwLabel = slowPath->GetLabel();
1684 }
1685 switch (klassType) {
1686 // The input class should be not primitive type
1687 case ClassType::OBJECT_CLASS: {
1688 FillObjectClass(visitor, tmpReg, throwLabel);
1689 break;
1690 }
1691 case ClassType::OTHER_CLASS: {
1692 FillOtherClass(visitor, inst, tmpReg, throwLabel);
1693 break;
1694 }
1695 // The input class should be array class and component type should be not primitive type
1696 case ClassType::ARRAY_OBJECT_CLASS: {
1697 FillArrayObjectClass(visitor, tmpReg, throwLabel);
1698 break;
1699 }
1700 // Check that components types are equals, else call slow path
1701 case ClassType::ARRAY_CLASS: {
1702 FillArrayClass(visitor, inst, tmpReg, throwLabel);
1703 break;
1704 }
1705 case ClassType::FINAL_CLASS: {
1706 EVENT_CODEGEN_SIMPLIFICATION(events::CodegenSimplificationInst::CHECKCAST,
1707 events::CodegenSimplificationReason::FINAL_CLASS);
1708 encoder->EncodeJump(throwLabel);
1709 break;
1710 }
1711 default: {
1712 UNREACHABLE();
1713 }
1714 }
1715 }
1716
VisitCheckCast(GraphVisitor * visitor,Inst * inst)1717 void EncodeVisitor::VisitCheckCast(GraphVisitor *visitor, Inst *inst)
1718 {
1719 auto *enc = static_cast<EncodeVisitor *>(visitor);
1720 auto method = inst->CastToCheckCast()->GetMethod();
1721 auto typeId = inst->CastToCheckCast()->GetTypeId();
1722 auto encoder = enc->GetEncoder();
1723 auto klassType = inst->CastToCheckCast()->GetClassType();
1724 if (klassType == ClassType::UNRESOLVED_CLASS) {
1725 FillUnresolvedClass(visitor, inst);
1726 return;
1727 }
1728 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
1729 auto endLabel = encoder->CreateLabel();
1730 if (inst->CastToCheckCast()->GetOmitNullCheck()) {
1731 EVENT_CODEGEN_SIMPLIFICATION(events::CodegenSimplificationInst::CHECKCAST,
1732 events::CodegenSimplificationReason::SKIP_NULLCHECK);
1733 } else {
1734 // Compare with nullptr
1735 encoder->EncodeJump(endLabel, src, Condition::EQ);
1736 }
1737 [[maybe_unused]] auto klass = enc->cg_->GetGraph()->GetRuntime()->GetClass(method, typeId);
1738 ASSERT(klass != nullptr);
1739 FillCheckCast(visitor, inst, src, endLabel, klassType);
1740 encoder->BindLabel(endLabel);
1741 }
1742
FillIsInstanceUnresolved(GraphVisitor * visitor,Inst * inst)1743 void EncodeVisitor::FillIsInstanceUnresolved(GraphVisitor *visitor, Inst *inst)
1744 {
1745 auto *enc = static_cast<EncodeVisitor *>(visitor);
1746 auto graph = enc->cg_->GetGraph();
1747 auto encoder = enc->GetEncoder();
1748 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
1749 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1750 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1751 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::IS_INSTANCE);
1752 encoder->EncodeJump(slowPath->GetLabel(), classReg, Condition::EQ);
1753 slowPath->CreateBackLabel(encoder);
1754 auto endLabel = slowPath->GetBackLabel();
1755 // Compare with nullptr
1756 auto nextLabel = encoder->CreateLabel();
1757 encoder->EncodeJump(nextLabel, src, Condition::NE);
1758 encoder->EncodeMov(dst, Imm(0));
1759 encoder->EncodeJump(endLabel);
1760 encoder->BindLabel(nextLabel);
1761 // Get instance class
1762 ScopedTmpReg tmpReg(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1763 enc->GetCodegen()->LoadClassFromObject(tmpReg, src);
1764 // Sets true if the classes are equal
1765 encoder->EncodeJump(slowPath->GetLabel(), tmpReg, classReg, Condition::NE);
1766 encoder->EncodeMov(dst, Imm(1));
1767 slowPath->BindBackLabel(encoder);
1768 }
1769
FillIsInstanceCaseObject(GraphVisitor * visitor,Inst * inst,Reg tmpReg)1770 void EncodeVisitor::FillIsInstanceCaseObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg)
1771 {
1772 auto *enc = static_cast<EncodeVisitor *>(visitor);
1773 auto encoder = enc->GetEncoder();
1774 auto runtime = enc->cg_->GetGraph()->GetRuntime();
1775 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1776 // ClassType::OBJECT_CLASS
1777 Reg typeReg(tmpReg.GetId(), INT8_TYPE);
1778 // Load type class
1779 encoder->EncodeLdr(typeReg, false, MemRef(tmpReg, runtime->GetClassTypeOffset(enc->GetArch())));
1780 ScopedTmpReg typeMaskReg(encoder, INT8_TYPE);
1781 encoder->EncodeMov(typeMaskReg, Imm(runtime->GetReferenceTypeMask()));
1782 encoder->EncodeCompare(dst, typeMaskReg, typeReg, Condition::EQ);
1783 }
1784
1785 /* Sets true if IsInstance class is a subclass of input class:
1786 ......................
1787 bool Class::IsSubClassOf(const Class *klass) const {
1788 const Class *current = this;
1789 do {
1790 if (current == klass) {
1791 return true;
1792 }
1793 current = current->GetBase();
1794 } while (current != nullptr);
1795 return false;
1796 }
1797 */
1798
FillIsInstanceCaseOther(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId endLabel)1799 void EncodeVisitor::FillIsInstanceCaseOther(GraphVisitor *visitor, Inst *inst, Reg tmpReg,
1800 LabelHolder::LabelId endLabel)
1801 {
1802 auto *enc = static_cast<EncodeVisitor *>(visitor);
1803 auto encoder = enc->GetEncoder();
1804 auto runtime = enc->cg_->GetGraph()->GetRuntime();
1805 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1806 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1807 // ClassType::OTHER_CLASS
1808 auto loopLabel = encoder->CreateLabel();
1809 auto falseLabel = encoder->CreateLabel();
1810 // First compare `current == klass` we make before switch
1811 encoder->BindLabel(loopLabel);
1812 // Load base klass
1813 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, runtime->GetClassBaseOffset(enc->GetArch())));
1814 encoder->EncodeJump(falseLabel, tmpReg, Condition::EQ);
1815 encoder->EncodeJump(loopLabel, tmpReg, classReg, Condition::NE);
1816 // Set true result and jump to exit
1817 encoder->EncodeMov(dst, Imm(1));
1818 encoder->EncodeJump(endLabel);
1819 // Set false result and jump to exit
1820 encoder->BindLabel(falseLabel);
1821 encoder->EncodeMov(dst, Imm(0));
1822 }
1823
1824 // Sets true if the Input class is array class and component type is not primitive type
FillIsInstanceCaseArrayObject(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId endLabel)1825 void EncodeVisitor::FillIsInstanceCaseArrayObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg,
1826 LabelHolder::LabelId endLabel)
1827 {
1828 auto *enc = static_cast<EncodeVisitor *>(visitor);
1829 auto encoder = enc->GetEncoder();
1830 auto graph = enc->cg_->GetGraph();
1831 auto runtime = graph->GetRuntime();
1832 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1833 // ClassType::ARRAY_OBJECT_CLASS
1834 Reg dstRef(dst.GetId(), Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1835 Reg typeReg(tmpReg.GetId(), INT8_TYPE);
1836 // Load Component class
1837 encoder->EncodeLdr(dstRef, false, MemRef(tmpReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1838 // Check that src is array class
1839 encoder->EncodeJump(endLabel, dstRef, Condition::EQ);
1840 // Load type of the component class
1841 encoder->EncodeLdr(typeReg, false, MemRef(dstRef, runtime->GetClassTypeOffset(enc->GetArch())));
1842 ScopedTmpReg typeMaskReg(encoder, INT8_TYPE);
1843 encoder->EncodeMov(typeMaskReg, Imm(runtime->GetReferenceTypeMask()));
1844 encoder->EncodeCompare(dst, typeMaskReg, typeReg, Condition::EQ);
1845 }
1846
1847 // Check that components types are equals, else call slow path
FillIsInstanceCaseArrayClass(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId endLabel)1848 void EncodeVisitor::FillIsInstanceCaseArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg,
1849 LabelHolder::LabelId endLabel)
1850 {
1851 auto *enc = static_cast<EncodeVisitor *>(visitor);
1852 auto encoder = enc->GetEncoder();
1853 auto graph = enc->cg_->GetGraph();
1854 auto runtime = graph->GetRuntime();
1855 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1856 // ClassType::ARRAY_CLASS
1857 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::IS_INSTANCE);
1858 auto nextLabel1 = encoder->CreateLabel();
1859 // Load Component type of Input
1860 encoder->EncodeLdr(tmpReg, false, MemRef(tmpReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1861 // Check that src is array class
1862 encoder->EncodeJump(nextLabel1, tmpReg, Condition::NE);
1863 encoder->EncodeMov(dst, Imm(0));
1864 encoder->EncodeJump(endLabel);
1865 encoder->BindLabel(nextLabel1);
1866 // Load Component type of the instance
1867 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1868 ScopedTmpReg tmpReg1(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1869 encoder->EncodeLdr(tmpReg1, false, MemRef(classReg, runtime->GetClassComponentTypeOffset(enc->GetArch())));
1870 // Compare component types
1871 encoder->EncodeJump(slowPath->GetLabel(), tmpReg, tmpReg1, Condition::NE);
1872 encoder->EncodeMov(dst, Imm(1));
1873 slowPath->BindBackLabel(encoder);
1874 }
1875
FillIsInstanceCaseInterface(GraphVisitor * visitor,Inst * inst)1876 void EncodeVisitor::FillIsInstanceCaseInterface(GraphVisitor *visitor, Inst *inst)
1877 {
1878 auto *enc = static_cast<EncodeVisitor *>(visitor);
1879 auto encoder = enc->GetEncoder();
1880 // ClassType::INTERFACE_CLASS
1881 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::IS_INSTANCE);
1882 encoder->EncodeJump(slowPath->GetLabel());
1883 slowPath->BindBackLabel(encoder);
1884 }
1885
FillIsInstance(GraphVisitor * visitor,Inst * inst,Reg tmpReg,LabelHolder::LabelId endLabel)1886 void EncodeVisitor::FillIsInstance(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId endLabel)
1887 {
1888 auto *enc = static_cast<EncodeVisitor *>(visitor);
1889 auto encoder = enc->GetEncoder();
1890 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
1891 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
1892 if (inst->CastToIsInstance()->GetOmitNullCheck()) {
1893 EVENT_CODEGEN_SIMPLIFICATION(events::CodegenSimplificationInst::ISINSTANCE,
1894 events::CodegenSimplificationReason::SKIP_NULLCHECK);
1895 } else {
1896 // Compare with nullptr
1897 auto nextLabel = encoder->CreateLabel();
1898 encoder->EncodeJump(nextLabel, src, Condition::NE);
1899 encoder->EncodeMov(dst, Imm(0));
1900 encoder->EncodeJump(endLabel);
1901 encoder->BindLabel(nextLabel);
1902 }
1903 auto classReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::REFERENCE);
1904 enc->GetCodegen()->LoadClassFromObject(tmpReg, src);
1905 // Sets true if the classes are equals
1906 if (inst->CastToIsInstance()->GetClassType() == ClassType::FINAL_CLASS) {
1907 encoder->EncodeCompare(dst, classReg, tmpReg, Condition::EQ);
1908 } else if (dst.GetId() != src.GetId() && dst.GetId() != classReg.GetId()) {
1909 encoder->EncodeCompare(dst, classReg, tmpReg, Condition::EQ);
1910 encoder->EncodeJump(endLabel, dst, Condition::NE);
1911 } else {
1912 auto nextLabel1 = encoder->CreateLabel();
1913 encoder->EncodeJump(nextLabel1, classReg, tmpReg, Condition::NE);
1914 encoder->EncodeMov(dst, Imm(1));
1915 encoder->EncodeJump(endLabel);
1916 encoder->BindLabel(nextLabel1);
1917 }
1918 }
1919
VisitIsInstance(GraphVisitor * visitor,Inst * inst)1920 void EncodeVisitor::VisitIsInstance(GraphVisitor *visitor, Inst *inst)
1921 {
1922 auto *enc = static_cast<EncodeVisitor *>(visitor);
1923 auto graph = enc->cg_->GetGraph();
1924 auto encoder = enc->GetEncoder();
1925 auto klassType = inst->CastToIsInstance()->GetClassType();
1926 if (klassType == ClassType::UNRESOLVED_CLASS) {
1927 FillIsInstanceUnresolved(visitor, inst);
1928 return;
1929 }
1930 // tmp_reg - input class
1931 ScopedTmpReg tmpReg(encoder, Codegen::ConvertDataType(DataType::REFERENCE, graph->GetArch()));
1932 auto endLabel = encoder->CreateLabel();
1933 FillIsInstance(visitor, inst, tmpReg, endLabel);
1934 switch (klassType) {
1935 // Sets true if the Input class is not primitive type
1936 case ClassType::OBJECT_CLASS: {
1937 FillIsInstanceCaseObject(visitor, inst, tmpReg);
1938 break;
1939 }
1940 case ClassType::OTHER_CLASS: {
1941 FillIsInstanceCaseOther(visitor, inst, tmpReg, endLabel);
1942 break;
1943 }
1944 // Sets true if the Input class is array class and component type is not primitive type
1945 case ClassType::ARRAY_OBJECT_CLASS: {
1946 FillIsInstanceCaseArrayObject(visitor, inst, tmpReg, endLabel);
1947 break;
1948 }
1949 // Check that components types are equals, else call slow path
1950 case ClassType::ARRAY_CLASS: {
1951 FillIsInstanceCaseArrayClass(visitor, inst, tmpReg, endLabel);
1952 break;
1953 }
1954 case ClassType::INTERFACE_CLASS: {
1955 FillIsInstanceCaseInterface(visitor, inst);
1956 break;
1957 }
1958 case ClassType::FINAL_CLASS: {
1959 EVENT_CODEGEN_SIMPLIFICATION(events::CodegenSimplificationInst::ISINSTANCE,
1960 events::CodegenSimplificationReason::FINAL_CLASS);
1961 break;
1962 }
1963 default: {
1964 UNREACHABLE();
1965 }
1966 }
1967 encoder->BindLabel(endLabel);
1968 }
1969
VisitMonitor(GraphVisitor * visitor,Inst * inst)1970 void EncodeVisitor::VisitMonitor(GraphVisitor *visitor, Inst *inst)
1971 {
1972 auto *enc = static_cast<EncodeVisitor *>(visitor);
1973 if (enc->GetCodegen()->GetArch() == Arch::AARCH32) {
1974 enc->GetCodegen()->CreateMonitorCallOld(inst->CastToMonitor());
1975 } else {
1976 enc->GetCodegen()->CreateMonitorCall(inst->CastToMonitor());
1977 }
1978 }
1979
VisitIntrinsic(GraphVisitor * visitor,Inst * inst)1980 void EncodeVisitor::VisitIntrinsic(GraphVisitor *visitor, Inst *inst)
1981 {
1982 auto *enc = static_cast<EncodeVisitor *>(visitor);
1983 auto codegen = enc->GetCodegen();
1984 auto intrinsic = inst->CastToIntrinsic();
1985 auto id = intrinsic->GetIntrinsicId();
1986 auto arch = codegen->GetGraph()->GetArch();
1987 auto runtime = codegen->GetGraph()->GetRuntime();
1988 if (EncodesBuiltin(runtime, id, arch) || IsIrtocIntrinsic(id)) {
1989 codegen->CreateBuiltinIntrinsic(intrinsic);
1990 return;
1991 }
1992 codegen->CreateCallIntrinsic(intrinsic);
1993 }
1994
VisitBoundsCheckI(GraphVisitor * visitor,Inst * inst)1995 void EncodeVisitor::VisitBoundsCheckI(GraphVisitor *visitor, Inst *inst)
1996 {
1997 auto *enc = static_cast<EncodeVisitor *>(visitor);
1998 auto lenReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), inst->GetInputType(0));
1999
2000 ASSERT(inst->GetInput(1).GetInst()->GetOpcode() == Opcode::SaveState ||
2001 inst->GetInput(1).GetInst()->GetOpcode() == Opcode::SaveStateDeoptimize);
2002 EntrypointId entrypoint = inst->CastToBoundsCheckI()->IsArray()
2003 ? EntrypointId::ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
2004 : EntrypointId::STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION;
2005 LabelHolder::LabelId label;
2006 if (inst->CanDeoptimize()) {
2007 label = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::BOUNDS_CHECK)->GetLabel();
2008 } else {
2009 label = enc->GetCodegen()->CreateSlowPath<SlowPathCheck>(inst, entrypoint)->GetLabel();
2010 }
2011 auto value = inst->CastToBoundsCheckI()->GetImm();
2012 if (enc->GetEncoder()->CanEncodeImmAddSubCmp(value, WORD_SIZE, false)) {
2013 enc->GetEncoder()->EncodeJump(label, lenReg, Imm(value), Condition::LS);
2014 } else {
2015 ScopedTmpReg tmp(enc->GetEncoder(), lenReg.GetType());
2016 enc->GetEncoder()->EncodeMov(tmp, Imm(value));
2017 enc->GetEncoder()->EncodeJump(label, lenReg, tmp, Condition::LS);
2018 }
2019 }
2020
VisitStoreArrayI(GraphVisitor * visitor,Inst * inst)2021 void EncodeVisitor::VisitStoreArrayI(GraphVisitor *visitor, Inst *inst)
2022 {
2023 auto *enc = static_cast<EncodeVisitor *>(visitor);
2024 auto arrayReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE);
2025 auto type = inst->GetType();
2026 auto value = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
2027 auto index = inst->CastToStoreArrayI()->GetImm();
2028 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch()) +
2029 (index << DataType::ShiftByType(type, enc->GetCodegen()->GetArch()));
2030 if (!enc->GetCodegen()->OffsetFitReferenceTypeSize(offset)) {
2031 // such code should not be executed
2032 enc->GetEncoder()->EncodeAbort();
2033 return;
2034 }
2035 auto mem = MemRef(arrayReg, offset);
2036 if (inst->CastToStoreArrayI()->GetNeedBarrier()) {
2037 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(arrayReg.GetId(), value.GetId()));
2038 }
2039 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2040 enc->GetEncoder()->EncodeStr(value, mem);
2041 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2042 if (inst->CastToStoreArrayI()->GetNeedBarrier()) {
2043 enc->GetCodegen()->CreatePostWRB(inst, mem, value, INVALID_REGISTER);
2044 }
2045 }
2046
VisitLoadArrayI(GraphVisitor * visitor,Inst * inst)2047 void EncodeVisitor::VisitLoadArrayI(GraphVisitor *visitor, Inst *inst)
2048 {
2049 auto *enc = static_cast<EncodeVisitor *>(visitor);
2050 auto instLoadArrayI = inst->CastToLoadArrayI();
2051 auto runtime = enc->cg_->GetGraph()->GetRuntime();
2052 ASSERT(instLoadArrayI->IsArray() || !runtime->IsCompressedStringsEnabled());
2053 if (instLoadArrayI->GetNeedBarrier()) {
2054 // Consider inserting barriers for GC
2055 }
2056 auto arrayReg = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0));
2057 uint32_t index = instLoadArrayI->GetImm();
2058 auto type = inst->GetType();
2059 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type);
2060 auto dataOffset = instLoadArrayI->IsArray() ? runtime->GetArrayDataOffset(enc->GetArch())
2061 : runtime->GetStringDataOffset(enc->GetArch());
2062 uint32_t shift = DataType::ShiftByType(type, enc->GetArch());
2063 auto offset = dataOffset + (index << shift);
2064 auto mem = MemRef(arrayReg, offset);
2065 auto encoder = enc->GetEncoder();
2066 auto arch = enc->GetArch();
2067 ScopedTmpReg scopedTmp(encoder, Codegen::ConvertDataType(DataType::GetIntTypeForReference(arch), arch));
2068 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2069 encoder->EncodeLdr(dst, IsTypeSigned(type), mem);
2070 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2071 }
2072
VisitLoadCompressedStringCharI(GraphVisitor * visitor,Inst * inst)2073 void EncodeVisitor::VisitLoadCompressedStringCharI(GraphVisitor *visitor, Inst *inst)
2074 {
2075 auto *enc = static_cast<EncodeVisitor *>(visitor);
2076 auto runtime = enc->cg_->GetGraph()->GetRuntime();
2077 auto type = inst->GetType();
2078 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0)); // array
2079 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32); // length
2080 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), type); // load value
2081 auto offset = runtime->GetStringDataOffset(enc->GetArch());
2082 auto encoder = enc->GetEncoder();
2083 auto arch = encoder->GetArch();
2084 uint8_t shift = DataType::ShiftByType(type, arch);
2085 uint32_t index = inst->CastToLoadCompressedStringCharI()->GetImm();
2086 ASSERT(encoder->CanEncodeCompressedStringCharAt());
2087 auto mask = runtime->GetStringCompressionMask();
2088 if (mask != 1) {
2089 UNREACHABLE(); // mask is hardcoded in JCL, but verify it just in case it's changed
2090 }
2091 enc->GetEncoder()->EncodeCompressedStringCharAtI({dst, src0, src1, offset, index, shift});
2092 }
2093
VisitMultiArray(GraphVisitor * visitor,Inst * inst)2094 void EncodeVisitor::VisitMultiArray(GraphVisitor *visitor, Inst *inst)
2095 {
2096 auto *enc = static_cast<EncodeVisitor *>(visitor);
2097 auto codegen = enc->GetCodegen();
2098 auto arrayInst = inst->CastToMultiArray();
2099 codegen->CreateMultiArrayCall(arrayInst);
2100 if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
2101 enc->GetEncoder()->EncodeMemoryBarrier(memory_order::RELEASE);
2102 }
2103 }
2104
VisitInitEmptyString(GraphVisitor * visitor,Inst * inst)2105 void EncodeVisitor::VisitInitEmptyString(GraphVisitor *visitor, Inst *inst)
2106 {
2107 auto codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2108 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2109 codegen->CallRuntime(inst, EntrypointId::CREATE_EMPTY_STRING, dst, RegMask::GetZeroMask());
2110 }
2111
VisitInitString(GraphVisitor * visitor,Inst * inst)2112 void EncodeVisitor::VisitInitString(GraphVisitor *visitor, Inst *inst)
2113 {
2114 auto cg = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2115 auto initStr = inst->CastToInitString();
2116 auto dst = cg->ConvertRegister(initStr->GetDstReg(), initStr->GetType());
2117 auto ctorArg = cg->ConvertRegister(initStr->GetSrcReg(0), initStr->GetInputType(0));
2118 if (cg->GetArch() == Arch::AARCH32) {
2119 auto entryId =
2120 initStr->IsFromString() ? EntrypointId::CREATE_STRING_FROM_STRING : EntrypointId::CREATE_STRING_FROM_CHARS;
2121 cg->CallRuntime(initStr, entryId, dst, RegMask::GetZeroMask(), ctorArg);
2122 return;
2123 }
2124 if (initStr->IsFromString()) {
2125 auto entryId = cg->GetRuntime()->IsCompressedStringsEnabled()
2126 ? compiler::RuntimeInterface::EntrypointId::CREATE_STRING_FROM_STRING_TLAB_COMPRESSED
2127 : compiler::RuntimeInterface::EntrypointId::CREATE_STRING_FROM_STRING_TLAB;
2128 cg->CallFastPath(initStr, entryId, dst, RegMask::GetZeroMask(), ctorArg);
2129 } else {
2130 auto enc = cg->GetEncoder();
2131 auto runtime = cg->GetGraph()->GetRuntime();
2132 auto mem = MemRef(ctorArg, static_cast<int64_t>(runtime->GetArrayLengthOffset(cg->GetArch())));
2133 ScopedTmpReg lengthReg(enc);
2134 enc->EncodeLdr(lengthReg, IsTypeSigned(initStr->GetType()), mem);
2135 cg->CreateStringFromCharArrayTlab(initStr, dst,
2136 Codegen::SRCREGS {cg->GetRegfile()->GetZeroReg(), lengthReg, ctorArg});
2137 }
2138 }
2139
VisitResolveStatic(GraphVisitor * visitor,Inst * inst)2140 void EncodeVisitor::VisitResolveStatic(GraphVisitor *visitor, Inst *inst)
2141 {
2142 auto *enc = static_cast<EncodeVisitor *>(visitor);
2143 enc->GetCodegen()->EmitResolveStatic(inst->CastToResolveStatic());
2144 }
2145
VisitCallResolvedStatic(GraphVisitor * visitor,Inst * inst)2146 void EncodeVisitor::VisitCallResolvedStatic(GraphVisitor *visitor, Inst *inst)
2147 {
2148 auto *enc = static_cast<EncodeVisitor *>(visitor);
2149 enc->GetCodegen()->EmitCallResolvedStatic(inst->CastToCallResolvedStatic());
2150 }
2151
VisitCallStatic(GraphVisitor * visitor,Inst * inst)2152 void EncodeVisitor::VisitCallStatic(GraphVisitor *visitor, Inst *inst)
2153 {
2154 auto *enc = static_cast<EncodeVisitor *>(visitor);
2155 enc->GetCodegen()->EmitCallStatic(inst->CastToCallStatic());
2156 }
2157
VisitCallVirtual(GraphVisitor * visitor,Inst * inst)2158 void EncodeVisitor::VisitCallVirtual(GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2159 {
2160 auto *enc = static_cast<EncodeVisitor *>(visitor);
2161 enc->GetCodegen()->EmitCallVirtual(inst->CastToCallVirtual());
2162 }
2163
VisitResolveVirtual(GraphVisitor * visitor,Inst * inst)2164 void EncodeVisitor::VisitResolveVirtual(GraphVisitor *visitor, Inst *inst)
2165 {
2166 auto *enc = static_cast<EncodeVisitor *>(visitor);
2167 enc->GetCodegen()->EmitResolveVirtual(inst->CastToResolveVirtual());
2168 }
2169
VisitCallResolvedVirtual(GraphVisitor * visitor,Inst * inst)2170 void EncodeVisitor::VisitCallResolvedVirtual(GraphVisitor *visitor, Inst *inst)
2171 {
2172 auto *enc = static_cast<EncodeVisitor *>(visitor);
2173 enc->GetCodegen()->EmitCallResolvedVirtual(inst->CastToCallResolvedVirtual());
2174 }
2175
VisitCallDynamic(GraphVisitor * visitor,Inst * inst)2176 void EncodeVisitor::VisitCallDynamic(GraphVisitor *visitor, Inst *inst)
2177 {
2178 auto *enc = static_cast<EncodeVisitor *>(visitor);
2179 enc->GetCodegen()->EmitCallDynamic(inst->CastToCallDynamic());
2180 }
2181
VisitCallNative(GraphVisitor * visitor,Inst * inst)2182 void EncodeVisitor::VisitCallNative(GraphVisitor *visitor, Inst *inst)
2183 {
2184 auto *enc = static_cast<EncodeVisitor *>(visitor);
2185 enc->GetCodegen()->EmitCallNative(inst->CastToCallNative());
2186 }
2187
VisitWrapObjectNative(GraphVisitor * visitor,Inst * inst)2188 void EncodeVisitor::VisitWrapObjectNative(GraphVisitor *visitor, Inst *inst)
2189 {
2190 auto *enc = static_cast<EncodeVisitor *>(visitor);
2191 enc->GetCodegen()->WrapObjectNative(inst->CastToWrapObjectNative());
2192 }
2193
VisitLoadConstantPool(GraphVisitor * visitor,Inst * inst)2194 void EncodeVisitor::VisitLoadConstantPool(GraphVisitor *visitor, Inst *inst)
2195 {
2196 if (TryLoadConstantPoolGen(inst, static_cast<EncodeVisitor *>(visitor))) {
2197 return;
2198 }
2199 UNREACHABLE();
2200 }
2201
VisitLoadLexicalEnv(GraphVisitor * visitor,Inst * inst)2202 void EncodeVisitor::VisitLoadLexicalEnv(GraphVisitor *visitor, Inst *inst)
2203 {
2204 if (TryLoadLexicalEnvGen(inst, static_cast<EncodeVisitor *>(visitor))) {
2205 return;
2206 }
2207 UNREACHABLE();
2208 }
2209
VisitLoadFromConstantPool(GraphVisitor * visitor,Inst * inst)2210 void EncodeVisitor::VisitLoadFromConstantPool([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2211 {
2212 UNREACHABLE();
2213 }
2214
VisitSafePoint(GraphVisitor * visitor,Inst * inst)2215 void EncodeVisitor::VisitSafePoint(GraphVisitor *visitor, Inst *inst)
2216 {
2217 auto *enc = static_cast<EncodeVisitor *>(visitor);
2218 auto codegen = enc->GetCodegen();
2219 auto graph = codegen->GetGraph();
2220 auto encoder = enc->GetEncoder();
2221 int64_t flagAddrOffset = graph->GetRuntime()->GetFlagAddrOffset(codegen->GetArch());
2222 ScopedTmpRegU16 tmp(encoder);
2223 // TMP <= Flag
2224 auto mem = MemRef(codegen->ThreadReg(), flagAddrOffset);
2225 encoder->EncodeLdr(tmp, false, mem);
2226 // check value and jump to call GC
2227 auto slowPath = codegen->CreateSlowPath<SlowPathEntrypoint>(inst, EntrypointId::SAFEPOINT);
2228 encoder->EncodeJump(slowPath->GetLabel(), tmp, Condition::NE);
2229 slowPath->BindBackLabel(encoder);
2230 }
2231
VisitSelect(GraphVisitor * visitor,Inst * inst)2232 void EncodeVisitor::VisitSelect(GraphVisitor *visitor, Inst *inst)
2233 {
2234 auto *enc = static_cast<EncodeVisitor *>(visitor);
2235 auto cmpType = inst->CastToSelect()->GetOperandsType();
2236 constexpr int32_t IMM_2 = 2;
2237 constexpr int32_t IMM_3 = 3;
2238 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
2239 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_2), cmpType);
2240 auto src3 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_3), cmpType);
2241 auto cc = enc->GetCodegen()->ConvertCc(inst->CastToSelect()->GetCc());
2242 if (IsTestCc(cc)) {
2243 enc->GetEncoder()->EncodeSelectTest({dst, src0, src1, src2, src3, cc});
2244 } else {
2245 enc->GetEncoder()->EncodeSelect({dst, src0, src1, src2, src3, cc});
2246 }
2247 }
2248
VisitSelectImm(GraphVisitor * visitor,Inst * inst)2249 void EncodeVisitor::VisitSelectImm(GraphVisitor *visitor, Inst *inst)
2250 {
2251 auto *enc = static_cast<EncodeVisitor *>(visitor);
2252 auto cmpType = inst->CastToSelectImm()->GetOperandsType();
2253 constexpr int32_t IMM_2 = 2;
2254 auto [dst, src0, src1] = enc->GetCodegen()->ConvertRegisters<2U>(inst);
2255 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_2), cmpType);
2256 auto imm = Imm(inst->CastToSelectImm()->GetImm());
2257 auto cc = enc->GetCodegen()->ConvertCc(inst->CastToSelectImm()->GetCc());
2258 if (IsTestCc(cc)) {
2259 enc->GetEncoder()->EncodeSelectTest({dst, src0, src1, src2, imm, cc});
2260 } else {
2261 enc->GetEncoder()->EncodeSelect({dst, src0, src1, src2, imm, cc});
2262 }
2263 }
2264
VisitIf(GraphVisitor * visitor,Inst * inst)2265 void EncodeVisitor::VisitIf(GraphVisitor *visitor, Inst *inst)
2266 {
2267 auto *enc = static_cast<EncodeVisitor *>(visitor);
2268 auto bb = inst->GetBasicBlock();
2269 auto label = bb->GetTrueSuccessor()->GetId();
2270 auto type = inst->CastToIf()->GetOperandsType();
2271 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
2272 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
2273 auto cc = enc->GetCodegen()->ConvertCc(inst->CastToIf()->GetCc());
2274 if (IsTestCc(cc)) {
2275 enc->GetEncoder()->EncodeJumpTest(label, src0, src1, cc);
2276 } else {
2277 enc->GetEncoder()->EncodeJump(label, src0, src1, cc);
2278 }
2279 }
2280
VisitIfImm(GraphVisitor * visitor,Inst * inst)2281 void EncodeVisitor::VisitIfImm(GraphVisitor *visitor, Inst *inst)
2282 {
2283 auto *enc = static_cast<EncodeVisitor *>(visitor);
2284 auto bb = inst->GetBasicBlock();
2285 auto label = bb->GetTrueSuccessor()->GetId();
2286 auto type = inst->CastToIfImm()->GetOperandsType();
2287 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
2288 auto imm = Imm(inst->CastToIfImm()->GetImm());
2289 auto cc = enc->GetCodegen()->ConvertCc(inst->CastToIfImm()->GetCc());
2290 if (IsTestCc(cc)) {
2291 enc->GetEncoder()->EncodeJumpTest(label, src0, imm, cc);
2292 } else {
2293 enc->GetEncoder()->EncodeJump(label, src0, imm, cc);
2294 }
2295 }
2296
VisitAddOverflow(GraphVisitor * visitor,Inst * inst)2297 void EncodeVisitor::VisitAddOverflow(GraphVisitor *visitor, Inst *inst)
2298 {
2299 auto *enc = static_cast<EncodeVisitor *>(visitor);
2300 auto bb = inst->GetBasicBlock();
2301 auto label = bb->GetTrueSuccessor()->GetId();
2302 auto type = inst->CastToAddOverflow()->GetOperandsType();
2303 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2304 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
2305 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
2306 auto cc = enc->GetCodegen()->ConvertCcOverflow(inst->CastToAddOverflow()->GetCc());
2307 enc->GetEncoder()->EncodeAddOverflow(label, dst, src0, src1, cc);
2308 }
2309
VisitAddOverflowCheck(GraphVisitor * visitor,Inst * inst)2310 void EncodeVisitor::VisitAddOverflowCheck(GraphVisitor *visitor, Inst *inst)
2311 {
2312 ASSERT(DataType::IsTypeNumeric(inst->GetInput(0).GetInst()->GetType()));
2313 ASSERT(DataType::IsTypeNumeric(inst->GetInput(1).GetInst()->GetType()));
2314 auto *enc = static_cast<EncodeVisitor *>(visitor);
2315 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::OVERFLOW_TYPE);
2316 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2317 auto src0 = Reg(inst->GetSrcReg(0), INT32_TYPE);
2318 auto src1 = Reg(inst->GetSrcReg(1), INT32_TYPE);
2319 enc->GetEncoder()->EncodeAddOverflow(slowPath->GetLabel(), dst, src0, src1, Condition::VS);
2320 }
2321
VisitSubOverflow(GraphVisitor * visitor,Inst * inst)2322 void EncodeVisitor::VisitSubOverflow(GraphVisitor *visitor, Inst *inst)
2323 {
2324 auto *enc = static_cast<EncodeVisitor *>(visitor);
2325 auto bb = inst->GetBasicBlock();
2326 auto label = bb->GetTrueSuccessor()->GetId();
2327 auto type = inst->CastToSubOverflow()->GetOperandsType();
2328 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2329 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), type);
2330 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type);
2331 auto cc = enc->GetCodegen()->ConvertCcOverflow(inst->CastToSubOverflow()->GetCc());
2332 enc->GetEncoder()->EncodeSubOverflow(label, dst, src0, src1, cc);
2333 }
2334
VisitSubOverflowCheck(GraphVisitor * visitor,Inst * inst)2335 void EncodeVisitor::VisitSubOverflowCheck(GraphVisitor *visitor, Inst *inst)
2336 {
2337 ASSERT(DataType::IsTypeNumeric(inst->GetInput(0).GetInst()->GetType()));
2338 ASSERT(DataType::IsTypeNumeric(inst->GetInput(1).GetInst()->GetType()));
2339 auto *enc = static_cast<EncodeVisitor *>(visitor);
2340 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::OVERFLOW_TYPE);
2341 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2342 auto src0 = Reg(inst->GetSrcReg(0), INT32_TYPE);
2343 auto src1 = Reg(inst->GetSrcReg(1), INT32_TYPE);
2344 enc->GetEncoder()->EncodeSubOverflow(slowPath->GetLabel(), dst, src0, src1, Condition::VS);
2345 }
2346
VisitNegOverflowAndZeroCheck(GraphVisitor * visitor,Inst * inst)2347 void EncodeVisitor::VisitNegOverflowAndZeroCheck(GraphVisitor *visitor, Inst *inst)
2348 {
2349 ASSERT(DataType::IsTypeNumeric(inst->GetInput(0).GetInst()->GetType()));
2350 auto *enc = static_cast<EncodeVisitor *>(visitor);
2351 auto slowPath = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::OVERFLOW_TYPE);
2352 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2353 auto src = Reg(inst->GetSrcReg(0), INT32_TYPE);
2354 enc->GetEncoder()->EncodeNegOverflowAndZero(slowPath->GetLabel(), dst, src);
2355 }
2356
VisitLoadArrayPair(GraphVisitor * visitor,Inst * inst)2357 void EncodeVisitor::VisitLoadArrayPair(GraphVisitor *visitor, Inst *inst)
2358 {
2359 auto *enc = static_cast<EncodeVisitor *>(visitor);
2360 if (inst->CastToLoadArrayPair()->GetNeedBarrier()) {
2361 // Consider inserting barriers for GC
2362 }
2363 auto type = inst->GetType();
2364 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
2365 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32); // index
2366 auto dst0 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(0), type); // first value
2367 auto dst1 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(1), type); // second value
2368 uint64_t index = inst->CastToLoadArrayPair()->GetImm();
2369 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch()) +
2370 (index << DataType::ShiftByType(type, enc->GetCodegen()->GetArch()));
2371 ScopedTmpReg tmp(enc->GetEncoder());
2372 int32_t scale = DataType::ShiftByType(type, enc->GetCodegen()->GetArch());
2373 enc->GetEncoder()->EncodeAdd(tmp, src0, Shift(src1, scale));
2374 auto mem = MemRef(tmp, offset);
2375 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2376 enc->GetEncoder()->EncodeLdp(dst0, dst1, IsTypeSigned(type), mem);
2377 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2378 }
2379
VisitLoadObjectPair(GraphVisitor * visitor,Inst * inst)2380 void EncodeVisitor::VisitLoadObjectPair(GraphVisitor *visitor, Inst *inst)
2381 {
2382 auto *enc = static_cast<EncodeVisitor *>(visitor);
2383 auto loadObj = inst->CastToLoadObjectPair();
2384 if (loadObj->GetNeedBarrier()) {
2385 // Consider inserting barriers for GC
2386 }
2387 auto type = inst->GetType();
2388 auto typeInput = inst->GetInput(0).GetInst()->GetType();
2389 auto src = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), typeInput); // obj
2390 auto dst0 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(0), type);
2391 auto dst1 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(1), type);
2392 auto graph = enc->cg_->GetGraph();
2393 auto field0 = loadObj->GetObjField0();
2394 size_t offset0 = GetObjectOffset(graph, loadObj->GetObjectType(), field0, loadObj->GetTypeId0());
2395 auto mem = MemRef(src, offset0);
2396 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2397 enc->GetEncoder()->EncodeLdp(dst0, dst1, IsTypeSigned(type), mem);
2398 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2399 }
2400
VisitLoadArrayPairI(GraphVisitor * visitor,Inst * inst)2401 void EncodeVisitor::VisitLoadArrayPairI(GraphVisitor *visitor, Inst *inst)
2402 {
2403 auto *enc = static_cast<EncodeVisitor *>(visitor);
2404 if (inst->CastToLoadArrayPairI()->GetNeedBarrier()) {
2405 // Consider inserting barriers for GC
2406 }
2407 auto type = inst->GetType();
2408 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
2409 auto dst0 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(0), type); // first value
2410 auto dst1 = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(1), type); // second value
2411 uint64_t index = inst->CastToLoadArrayPairI()->GetImm();
2412 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch()) +
2413 (index << DataType::ShiftByType(type, enc->GetCodegen()->GetArch()));
2414 auto mem = MemRef(src0, offset);
2415 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2416 enc->GetEncoder()->EncodeLdp(dst0, dst1, IsTypeSigned(type), mem);
2417 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2418 }
2419
2420 /**
2421 * It is a pseudo instruction that is needed to separate multiple outputs
2422 * from a single instruction in SSA such as LoadArrayPair and LoadArrayPairI.
2423 */
VisitLoadPairPart(GraphVisitor * visitor,Inst * inst)2424 void EncodeVisitor::VisitLoadPairPart([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2425 {
2426 // No codegeneration is required.
2427 }
2428
VisitStoreArrayPair(GraphVisitor * visitor,Inst * inst)2429 void EncodeVisitor::VisitStoreArrayPair(GraphVisitor *visitor, Inst *inst)
2430 {
2431 auto *enc = static_cast<EncodeVisitor *>(visitor);
2432 auto type = inst->GetType();
2433 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
2434 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), DataType::INT32); // index
2435 constexpr auto IMM_2 = 2U;
2436 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_2), type); // first value
2437 constexpr auto IMM_3 = 3U;
2438 auto src3 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_3), type); // second value
2439 uint64_t index = inst->CastToStoreArrayPair()->GetImm();
2440 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch()) +
2441 (index << DataType::ShiftByType(type, enc->GetCodegen()->GetArch()));
2442 auto scale = DataType::ShiftByType(type, enc->GetCodegen()->GetArch());
2443 auto tmp = enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::REFERENCE);
2444 enc->GetEncoder()->EncodeAdd(tmp, src0, Shift(src1, scale));
2445 auto mem = MemRef(tmp, offset);
2446 if (inst->CastToStoreArrayPair()->GetNeedBarrier()) {
2447 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(src0.GetId(), src2.GetId(), src3.GetId()), true);
2448 }
2449 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2450 enc->GetEncoder()->EncodeStp(src2, src3, mem);
2451 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2452 if (inst->CastToStoreArrayPair()->GetNeedBarrier()) {
2453 auto tmpOffset = enc->GetCodegen()->ConvertInstTmpReg(inst, DataType::GetIntTypeForReference(enc->GetArch()));
2454 enc->GetEncoder()->EncodeShl(tmpOffset, src1, Imm(scale));
2455 enc->GetEncoder()->EncodeAdd(tmpOffset, tmpOffset, Imm(offset));
2456 auto mem1 = MemRef(src0, tmpOffset, 0);
2457 enc->GetCodegen()->CreatePostWRB(inst, mem1, src2, src3);
2458 }
2459 }
2460
VisitStoreObjectPair(GraphVisitor * visitor,Inst * inst)2461 void EncodeVisitor::VisitStoreObjectPair(GraphVisitor *visitor, Inst *inst)
2462 {
2463 auto *enc = static_cast<EncodeVisitor *>(visitor);
2464 auto encoder = enc->GetEncoder();
2465 auto storeObj = inst->CastToStoreObjectPair();
2466 ASSERT(storeObj->GetObjectType() == ObjectType::MEM_OBJECT || storeObj->GetObjectType() == ObjectType::MEM_STATIC);
2467 auto codegen = enc->GetCodegen();
2468 auto type = inst->GetType();
2469 auto src0 = codegen->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // obj
2470 auto src1 = codegen->ConvertRegister(inst->GetSrcReg(1), type); // store value 1
2471 auto src2 = codegen->ConvertRegister(inst->GetSrcReg(2), type); // store value 2
2472 auto graph = enc->cg_->GetGraph();
2473 auto field0 = storeObj->GetObjField0();
2474 auto field1 = storeObj->GetObjField1();
2475 size_t offset0 = GetObjectOffset(graph, storeObj->GetObjectType(), field0, storeObj->GetTypeId0());
2476 size_t offset1 = GetObjectOffset(graph, storeObj->GetObjectType(), field1, storeObj->GetTypeId1());
2477 if (!codegen->OffsetFitReferenceTypeSize(offset1)) {
2478 // such code should not be executed
2479 encoder->EncodeAbort();
2480 }
2481 auto mem = MemRef(src0, offset0);
2482 if (storeObj->GetNeedBarrier()) {
2483 codegen->CreatePreWRB(inst, mem, MakeMask(src1.GetId(), src2.GetId()));
2484 }
2485 auto prevOffset = encoder->GetCursorOffset();
2486 encoder->EncodeStp(src1, src2, mem);
2487 codegen->TryInsertImplicitNullCheck(inst, prevOffset);
2488 if (storeObj->GetNeedBarrier()) {
2489 codegen->CreatePostWRB(inst, mem, src1, src2);
2490 }
2491 }
2492
VisitStoreArrayPairI(GraphVisitor * visitor,Inst * inst)2493 void EncodeVisitor::VisitStoreArrayPairI(GraphVisitor *visitor, Inst *inst)
2494 {
2495 auto *enc = static_cast<EncodeVisitor *>(visitor);
2496 auto type = inst->GetType();
2497 auto src0 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(0), DataType::REFERENCE); // array
2498 auto src1 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(1), type); // first value
2499 constexpr int32_t IMM_2 = 2;
2500 auto src2 = enc->GetCodegen()->ConvertRegister(inst->GetSrcReg(IMM_2), type); // second value
2501 auto index = inst->CastToStoreArrayPairI()->GetImm();
2502 auto offset = enc->cg_->GetGraph()->GetRuntime()->GetArrayDataOffset(enc->GetCodegen()->GetArch()) +
2503 (index << DataType::ShiftByType(type, enc->GetCodegen()->GetArch()));
2504 if (!enc->GetCodegen()->OffsetFitReferenceTypeSize(offset)) {
2505 // such code should not be executed
2506 enc->GetEncoder()->EncodeAbort();
2507 return;
2508 }
2509 auto mem = MemRef(src0, offset);
2510 if (inst->CastToStoreArrayPairI()->GetNeedBarrier()) {
2511 enc->GetCodegen()->CreatePreWRB(inst, mem, MakeMask(src0.GetId(), src1.GetId(), src2.GetId()), true);
2512 }
2513 auto prevOffset = enc->GetEncoder()->GetCursorOffset();
2514 enc->GetEncoder()->EncodeStp(src1, src2, mem);
2515 enc->GetCodegen()->TryInsertImplicitNullCheck(inst, prevOffset);
2516 if (inst->CastToStoreArrayPairI()->GetNeedBarrier()) {
2517 enc->GetCodegen()->CreatePostWRB(inst, mem, src1, src2);
2518 }
2519 }
2520
VisitNOP(GraphVisitor * visitor,Inst * inst)2521 void EncodeVisitor::VisitNOP([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2522 {
2523 #ifndef NDEBUG
2524 COMPILER_LOG(DEBUG, CODEGEN) << "The NOP wasn't removed before " << *inst;
2525 #endif
2526 }
2527
VisitThrow(GraphVisitor * visitor,Inst * inst)2528 void EncodeVisitor::VisitThrow(GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2529 {
2530 auto codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2531 SlowPathCheck slowPath(codegen->GetEncoder()->CreateLabel(), inst, EntrypointId::THROW_EXCEPTION);
2532 slowPath.Generate(codegen);
2533 }
2534
VisitDeoptimize(GraphVisitor * visitor,Inst * inst)2535 void EncodeVisitor::VisitDeoptimize(GraphVisitor *visitor, Inst *inst)
2536 {
2537 auto codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2538 ASSERT(inst->GetSaveState() != nullptr);
2539 SlowPathDeoptimize slowPath(codegen->GetEncoder()->CreateLabel(), inst,
2540 inst->CastToDeoptimize()->GetDeoptimizeType());
2541 slowPath.Generate(codegen);
2542 }
2543
VisitIsMustDeoptimize(GraphVisitor * visitor,Inst * inst)2544 void EncodeVisitor::VisitIsMustDeoptimize(GraphVisitor *visitor, Inst *inst)
2545 {
2546 auto *codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2547 auto *enc = static_cast<EncodeVisitor *>(visitor)->GetEncoder();
2548 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2549 auto offset = CFrameFlags::GetOffsetFromSpInBytes(codegen->GetFrameLayout());
2550 enc->EncodeLdr(dst, false, MemRef(codegen->SpReg(), offset));
2551 enc->EncodeAnd(dst, dst, Imm(1));
2552 }
2553
VisitGetInstanceClass(GraphVisitor * visitor,Inst * inst)2554 void EncodeVisitor::VisitGetInstanceClass(GraphVisitor *visitor, Inst *inst)
2555 {
2556 auto *codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2557 auto [dst, objReg] = codegen->ConvertRegisters<1U>(inst);
2558 ASSERT(objReg.IsValid());
2559 codegen->LoadClassFromObject(dst, objReg);
2560 }
2561
VisitLoadImmediate(GraphVisitor * visitor,Inst * inst)2562 void EncodeVisitor::VisitLoadImmediate(GraphVisitor *visitor, Inst *inst)
2563 {
2564 auto codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2565 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2566 auto loadImm = inst->CastToLoadImmediate();
2567 if (loadImm->GetObjectType() == LoadImmediateInst::ObjectType::PANDA_FILE_OFFSET) {
2568 auto runtime = codegen->GetGraph()->GetRuntime();
2569 auto pfOffset = runtime->GetPandaFileOffset(codegen->GetGraph()->GetArch());
2570 codegen->LoadMethod(dst);
2571 // load pointer to panda file
2572 codegen->GetEncoder()->EncodeLdr(dst, false, MemRef(dst, pfOffset));
2573 codegen->GetEncoder()->EncodeLdr(dst, false, MemRef(dst, cross_values::GetFileBaseOffset(codegen->GetArch())));
2574 // add pointer to pf with offset to str
2575 codegen->GetEncoder()->EncodeAdd(dst, dst, Imm(loadImm->GetPandaFileOffset()));
2576 } else if (loadImm->GetObjectType() == LoadImmediateInst::ObjectType::TLS_OFFSET) {
2577 codegen->GetEncoder()->EncodeLdr(dst, false, MemRef(codegen->ThreadReg(), loadImm->GetTlsOffset()));
2578 } else {
2579 codegen->GetEncoder()->EncodeMov(dst, Imm(reinterpret_cast<uintptr_t>(loadImm->GetObject())));
2580 }
2581 }
2582
VisitFunctionImmediate(GraphVisitor * visitor,Inst * inst)2583 void EncodeVisitor::VisitFunctionImmediate(GraphVisitor *visitor, Inst *inst)
2584 {
2585 auto *codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2586 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2587 codegen->GetEncoder()->EncodeMov(dst, Imm(inst->CastToFunctionImmediate()->GetFunctionPtr()));
2588 codegen->GetEncoder()->EncodeLdr(dst, false, MemRef(dst, 0U));
2589 }
2590
VisitLoadObjFromConst(GraphVisitor * visitor,Inst * inst)2591 void EncodeVisitor::VisitLoadObjFromConst(GraphVisitor *visitor, Inst *inst)
2592 {
2593 auto *codegen = static_cast<EncodeVisitor *>(visitor)->GetCodegen();
2594 auto dst = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2595 Reg dstPointer(dst.As(TypeInfo::FromDataType(DataType::POINTER, codegen->GetArch())));
2596 codegen->GetEncoder()->EncodeMov(dstPointer, Imm(inst->CastToLoadObjFromConst()->GetObjPtr()));
2597 codegen->GetEncoder()->EncodeLdr(dst, false, MemRef(dstPointer, 0U));
2598 }
2599
VisitRegDef(GraphVisitor * visitor,Inst * inst)2600 void EncodeVisitor::VisitRegDef([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2601 {
2602 // No codegeneration is required.
2603 }
2604
VisitLiveIn(GraphVisitor * visitor,Inst * inst)2605 void EncodeVisitor::VisitLiveIn([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2606 {
2607 // No codegeneration is required.
2608 }
2609
VisitLiveOut(GraphVisitor * visitor,Inst * inst)2610 void EncodeVisitor::VisitLiveOut([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst)
2611 {
2612 auto enc = static_cast<EncodeVisitor *>(visitor);
2613 auto codegen = enc->GetCodegen();
2614 codegen->AddLiveOut(inst->GetBasicBlock(), inst->GetDstReg());
2615 auto dstReg = codegen->ConvertRegister(inst->GetDstReg(), inst->GetType());
2616 if (codegen->GetTarget().GetTempRegsMask().Test(dstReg.GetId()) &&
2617 enc->GetEncoder()->IsScratchRegisterReleased(dstReg)) {
2618 enc->GetEncoder()->AcquireScratchRegister(dstReg);
2619 }
2620 if (inst->GetLocation(0) != inst->GetDstLocation()) {
2621 auto *src = inst->GetInput(0).GetInst();
2622 enc->GetEncoder()->EncodeMov(dstReg, codegen->ConvertRegister(inst->GetSrcReg(0), src->GetType()));
2623 }
2624 }
2625
VisitCompareAnyType(GraphVisitor * visitor,Inst * inst)2626 void EncodeVisitor::VisitCompareAnyType(GraphVisitor *visitor, Inst *inst)
2627 {
2628 auto enc = static_cast<EncodeVisitor *>(visitor);
2629 const auto *cati = inst->CastToCompareAnyType();
2630 if (cati->GetInputType(0) != DataType::Type::ANY) {
2631 enc->GetEncoder()->EncodeAbort();
2632 UNREACHABLE();
2633 return;
2634 }
2635 if (TryCompareAnyTypePluginGen(cati, enc)) {
2636 return;
2637 }
2638 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), inst->GetType());
2639 if (cati->GetAnyType() == AnyBaseType::UNDEFINED_TYPE) {
2640 enc->GetEncoder()->EncodeMov(dst, Imm(true));
2641 } else {
2642 enc->GetEncoder()->EncodeMov(dst, Imm(false));
2643 }
2644 }
2645
VisitGetAnyTypeName(GraphVisitor * visitor,Inst * inst)2646 void EncodeVisitor::VisitGetAnyTypeName(GraphVisitor *visitor, Inst *inst)
2647 {
2648 auto enc = static_cast<EncodeVisitor *>(visitor);
2649 const auto *cati = inst->CastToGetAnyTypeName();
2650 if (TryGetAnyTypeNamePluginGen(cati, enc)) {
2651 return;
2652 }
2653 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), DataType::Type::BOOL);
2654 enc->GetEncoder()->EncodeMov(dst, Imm(0));
2655 }
2656
VisitCastAnyTypeValue(GraphVisitor * visitor,Inst * inst)2657 void EncodeVisitor::VisitCastAnyTypeValue(GraphVisitor *visitor, Inst *inst)
2658 {
2659 auto enc = static_cast<EncodeVisitor *>(visitor);
2660 const auto *cati = inst->CastToCastAnyTypeValue();
2661 if (cati->GetInputType(0) != DataType::Type::ANY) {
2662 enc->GetEncoder()->EncodeAbort();
2663 UNREACHABLE();
2664 return;
2665 }
2666 if (TryCastAnyTypeValuePluginGen(cati, enc)) {
2667 return;
2668 }
2669 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), DataType::Type::BOOL);
2670 enc->GetEncoder()->EncodeMov(dst, Imm(0));
2671 }
2672
VisitCastValueToAnyType(GraphVisitor * visitor,Inst * inst)2673 void EncodeVisitor::VisitCastValueToAnyType(GraphVisitor *visitor, Inst *inst)
2674 {
2675 auto enc = static_cast<EncodeVisitor *>(visitor);
2676 const auto *cvai = inst->CastToCastValueToAnyType();
2677 if (TryCastValueToAnyTypePluginGen(cvai, enc)) {
2678 return;
2679 }
2680 auto dst = enc->GetCodegen()->ConvertRegister(inst->GetDstReg(), DataType::Type::BOOL);
2681 enc->GetEncoder()->EncodeMov(dst, Imm(0));
2682 }
2683
VisitAnyTypeCheck(GraphVisitor * visitor,Inst * inst)2684 void EncodeVisitor::VisitAnyTypeCheck(GraphVisitor *visitor, Inst *inst)
2685 {
2686 auto enc = static_cast<EncodeVisitor *>(visitor);
2687 auto *checkInst = inst->CastToAnyTypeCheck();
2688 if (checkInst->GetInputType(0) != DataType::Type::ANY) {
2689 enc->GetEncoder()->EncodeAbort();
2690 UNREACHABLE();
2691 }
2692 // Empty check
2693 if (checkInst->GetAnyType() == AnyBaseType::UNDEFINED_TYPE) {
2694 return;
2695 }
2696 if (TryAnyTypeCheckPluginGen(checkInst, enc)) {
2697 return;
2698 }
2699 UNREACHABLE();
2700 }
2701
VisitHclassCheck(GraphVisitor * visitor,Inst * inst)2702 void EncodeVisitor::VisitHclassCheck(GraphVisitor *visitor, Inst *inst)
2703 {
2704 auto enc = static_cast<EncodeVisitor *>(visitor);
2705 auto *checkInst = inst->CastToHclassCheck();
2706 if (checkInst->GetInputType(0) != DataType::Type::REFERENCE) {
2707 enc->GetEncoder()->EncodeAbort();
2708 UNREACHABLE();
2709 }
2710 if (TryHclassCheckPluginGen(checkInst, enc)) {
2711 return;
2712 }
2713 UNREACHABLE();
2714 }
2715
VisitObjByIndexCheck(GraphVisitor * visitor,Inst * inst)2716 void EncodeVisitor::VisitObjByIndexCheck(GraphVisitor *visitor, Inst *inst)
2717 {
2718 auto enc = static_cast<EncodeVisitor *>(visitor);
2719 const auto *checkInst = inst->CastToObjByIndexCheck();
2720 if (checkInst->GetInputType(0) != DataType::Type::ANY) {
2721 enc->GetEncoder()->EncodeAbort();
2722 UNREACHABLE();
2723 }
2724 auto id = enc->GetCodegen()->CreateSlowPath<SlowPathDeoptimize>(inst, DeoptimizeType::ANY_TYPE_CHECK)->GetLabel();
2725 if (TryObjByIndexCheckPluginGen(checkInst, enc, id)) {
2726 return;
2727 }
2728 UNREACHABLE();
2729 }
2730
VisitResolveByName(GraphVisitor * visitor,Inst * inst)2731 void EncodeVisitor::VisitResolveByName(GraphVisitor *visitor, Inst *inst)
2732 {
2733 auto *enc = static_cast<EncodeVisitor *>(visitor);
2734 enc->GetCodegen()->ResolveCallByName(inst->CastToResolveByName());
2735 }
2736
2737 } // namespace ark::compiler
2738