• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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