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