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