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