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