• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "aarch64_emitter.h"
17 #include "metadata_layout.h"
18 #include "aarch64_obj_emitter.h"
19 
20 namespace {
21 using namespace maple;
22 }  // namespace
23 
24 namespace maplebe {
25 using namespace maple;
26 
EmitBBHeaderLabel(FuncEmitInfo & funcEmitInfo,const std::string & name,LabelIdx labIdx)27 void AArch64AsmEmitter::EmitBBHeaderLabel(FuncEmitInfo &funcEmitInfo, const std::string &name, LabelIdx labIdx)
28 {
29 #ifdef ARK_LITECG_DEBUG
30     (void)name;
31     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
32     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
33     CG *currCG = cgFunc.GetCG();
34     LabelOperand &label = aarchCGFunc.GetOrCreateLabelOperand(labIdx);
35     /* if label order is default value -1, set new order */
36     if (label.GetLabelOrder() == 0xFFFFFFFF) {
37         label.SetLabelOrder(currCG->GetLabelOrderCnt());
38         currCG->IncreaseLabelOrderCnt();
39     }
40     CHECK_NULL_FATAL(currCG->GetMIRModule()->CurFunction());
41     PUIdx pIdx = currCG->GetMIRModule()->CurFunction()->GetPuidx();
42     char *puIdx = strdup(std::to_string(pIdx).c_str());
43     CHECK_FATAL(puIdx != nullptr, "strdup failed");
44     currCG->template Emit<CG::EmitterType::AsmEmitter>([&cgFunc, currCG, puIdx, labIdx, label](Emitter* emitter) {
45         const std::string &labelName = cgFunc.GetFunction().GetLabelTab()->GetName(labIdx);
46         if (currCG->GenerateVerboseCG()) {
47             (void)emitter->Emit(".L.")
48                 .Emit(puIdx)
49                 .Emit("__")
50                 .Emit(labIdx)
51                 .Emit(":\t//label order ")
52                 .Emit(label.GetLabelOrder());
53             if (!labelName.empty() && labelName.at(0) != '@') {
54                 /* If label name has @ as its first char, it is not from MIR */
55                 (void)emitter->Emit(", MIR: @").Emit(labelName).Emit("\n");
56             } else {
57                 (void)emitter->Emit("\n");
58             }
59         } else {
60             (void)emitter->Emit(".L.").Emit(puIdx).Emit("__").Emit(labIdx).Emit(":\n");
61         }
62     });
63     free(puIdx);
64     puIdx = nullptr;
65 #endif
66 }
67 
RecordRegInfo(FuncEmitInfo & funcEmitInfo) const68 void AArch64AsmEmitter::RecordRegInfo(FuncEmitInfo &funcEmitInfo) const
69 {
70 #ifdef ARK_LITECG_DEBUG
71     if (!CGOptions::DoIPARA()) {
72         return;
73     }
74     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
75     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
76 
77     std::set<regno_t> referedRegs;
78     MIRFunction &mirFunc = cgFunc.GetFunction();
79     FOR_ALL_BB_REV(bb, &aarchCGFunc)
80     {
81         FOR_BB_INSNS_REV(insn, bb)
82         {
83             if (!insn->IsMachineInstruction()) {
84                 continue;
85             }
86             if (insn->IsCall() || insn->IsTailCall()) {
87                 auto *targetOpnd = insn->GetCallTargetOperand();
88                 bool safeCheck = false;
89                 CHECK_FATAL(targetOpnd != nullptr,
90                             "target is null in AArch64Emitter::IsCallToFunctionThatNeverReturns");
91                 if (targetOpnd->IsFuncNameOpnd()) {
92                     FuncNameOperand *target = static_cast<FuncNameOperand *>(targetOpnd);
93                     const MIRSymbol *funcSt = target->GetFunctionSymbol();
94                     DEBUG_ASSERT(funcSt->GetSKind() == maple::kStFunc, "funcst must be a function name symbol");
95                     MIRFunction *func = funcSt->GetFunction();
96                     if (func != nullptr && func->IsReferedRegsValid()) {
97                         safeCheck = true;
98                         for (auto preg : func->GetReferedRegs()) {
99                             referedRegs.insert(preg);
100                         }
101                     }
102                 }
103                 if (!safeCheck) {
104                     mirFunc.SetReferedRegsValid(false);
105                     return;
106                 }
107             }
108             if (referedRegs.size() == kMaxRegNum) {
109                 break;
110             }
111             uint32 opndNum = insn->GetOperandSize();
112             const InsnDesc *md = &AArch64CG::kMd[insn->GetMachineOpcode()];
113             for (uint32 i = 0; i < opndNum; ++i) {
114                 if (insn->GetMachineOpcode() == MOP_asm) {
115                     if (i == kAsmOutputListOpnd || i == kAsmClobberListOpnd) {
116                         for (auto opnd : static_cast<ListOperand &>(insn->GetOperand(i)).GetOperands()) {
117                             if (opnd->IsRegister()) {
118                                 referedRegs.insert(static_cast<RegOperand *>(opnd)->GetRegisterNumber());
119                             }
120                         }
121                     }
122                     continue;
123                 }
124                 Operand &opnd = insn->GetOperand(i);
125                 if (opnd.IsList()) {
126                     /* all use, skip it */
127                 } else if (opnd.IsMemoryAccessOperand()) {
128                     auto &memOpnd = static_cast<MemOperand &>(opnd);
129                     RegOperand *base = memOpnd.GetBaseRegister();
130                     if (!memOpnd.IsIntactIndexed()) {
131                         referedRegs.insert(base->GetRegisterNumber());
132                     }
133                 } else if (opnd.IsRegister()) {
134                     RegType regType = static_cast<RegOperand &>(opnd).GetRegisterType();
135                     if (regType == kRegTyCc || regType == kRegTyVary) {
136                         continue;
137                     }
138                     bool isDef = md->GetOpndDes(i)->IsRegDef();
139                     if (isDef) {
140                         referedRegs.insert(static_cast<RegOperand &>(opnd).GetRegisterNumber());
141                     }
142                 }
143             }
144         }
145     }
146     mirFunc.SetReferedRegsValid(true);
147 #ifdef DEBUG
148     for (auto reg : referedRegs) {
149         if (reg > kMaxRegNum) {
150             DEBUG_ASSERT(0, "unexpected preg");
151         }
152     }
153 #endif
154     mirFunc.CopyReferedRegs(referedRegs);
155 #endif
156 }
157 
Run(FuncEmitInfo & funcEmitInfo)158 void AArch64AsmEmitter::Run(FuncEmitInfo &funcEmitInfo)
159 {
160 #ifdef ARK_LITECG_DEBUG
161     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
162     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
163     CG *currCG = cgFunc.GetCG();
164     /* emit header of this function */
165     currCG->template Emit<CG::EmitterType::AsmEmitter>(
166     [this, &cgFunc, &aarchCGFunc, currCG, &funcEmitInfo](Emitter *emitter) {
167         // insert for  __cxx_global_var_init
168         if (cgFunc.GetName() == "__cxx_global_var_init") {
169             (void)emitter->Emit("\t.section\t.init_array,\"aw\"\n");
170             (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
171         }
172         if (cgFunc.GetFunction().GetAttr(FUNCATTR_initialization)) {
173             (void)emitter->Emit("\t.section\t.init_array,\"aw\"\n");
174             (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
175         }
176         if (cgFunc.GetFunction().GetAttr(FUNCATTR_termination)) {
177             (void)emitter->Emit("\t.section\t.fini_array,\"aw\"\n");
178             (void)emitter->Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
179         }
180         (void)emitter->Emit("\n");
181         if (cgFunc.GetFunction().GetAttr(FUNCATTR_section)) {
182             const std::string &sectionName = cgFunc.GetFunction().GetAttrs().GetPrefixSectionName();
183             (void)emitter->Emit("\t.section  " + sectionName).Emit(",\"ax\",@progbits\n");
184         } else if (cgFunc.GetFunction().GetAttr(FUNCATTR_constructor_priority)) {
185             (void)emitter->Emit("\t.section\t.text.startup").Emit(",\"ax\",@progbits\n");
186         } else {
187             (void)emitter->Emit("\t.text\n");
188         }
189         if (CGOptions::GetFuncAlignPow() != 0) {
190             (void)emitter->Emit("\t.align ").Emit(CGOptions::GetFuncAlignPow()).Emit("\n");
191         }
192         MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc.GetFunction().GetStIdx().Idx());
193         const std::string &funcName = std::string(cgFunc.GetShortFuncName().c_str());
194 
195         CHECK_NULL_FATAL(funcSt);
196         std::string funcStName = funcSt->GetName();
197         if (funcSt->GetFunction()->GetAttr(FUNCATTR_weak)) {
198             (void)emitter->Emit("\t.weak\t" + funcStName + "\n");
199             (void)emitter->Emit("\t.hidden\t" + funcStName + "\n");
200         } else if (funcSt->GetFunction()->GetAttr(FUNCATTR_local)) {
201             (void)emitter->Emit("\t.local\t" + funcStName + "\n");
202         } else if (funcSt->GetFunction() && funcSt->GetFunction()->IsStatic()) {
203             // nothing
204         } else {
205             /* should refer to function attribute */
206             (void)emitter->Emit("\t.globl\t").Emit(funcSt->GetName()).Emit("\n");
207             (void)emitter->Emit("\t.hidden\t").Emit(funcSt->GetName()).Emit("\n");
208         }
209         (void)emitter->Emit("\t.type\t" + funcStName + ", %function\n");
210         (void)emitter->Emit(funcStName + ":\n");
211 
212         /* if the last  insn is call, then insert nop */
213         bool found = false;
214         FOR_ALL_BB_REV(bb, &aarchCGFunc)
215         {
216             FOR_BB_INSNS_REV(insn, bb)
217             {
218                 if (insn->IsMachineInstruction()) {
219                     if (insn->IsCall()) {
220                         Insn &newInsn = aarchCGFunc.GetInsnBuilder()->BuildInsn<AArch64CG>(MOP_nop);
221                         bb->InsertInsnAfter(*insn, newInsn);
222                     }
223                     found = true;
224                     break;
225                 }
226             }
227             if (found) {
228                 break;
229             }
230         }
231 
232         RecordRegInfo(funcEmitInfo);
233 
234         /* emit instructions */
235         FOR_ALL_BB(bb, &aarchCGFunc)
236         {
237             if (bb->IsUnreachable()) {
238                 continue;
239             }
240             if (currCG->GenerateVerboseCG()) {
241                 (void)emitter->Emit("#    freq:").Emit(bb->GetFrequency()).Emit("\n");
242             }
243             /* emit bb headers */
244             if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
245                 EmitBBHeaderLabel(funcEmitInfo, funcName, bb->GetLabIdx());
246             }
247 
248             FOR_BB_INSNS(insn, bb)
249             {
250                 auto dbgComment = insn->GetDebugComment();
251                 if (currDebugComment != dbgComment) {
252                     currDebugComment = dbgComment;
253                     if (dbgComment != nullptr) {
254                         emitter->Emit("\t// ");
255                         emitter->Emit(dbgComment->c_str());
256                         emitter->Emit("\n ");
257                     } else {
258                         emitter->Emit("\t// \n");
259                     }
260                 }
261                 if (insn->IsCfiInsn()) {
262                     EmitAArch64CfiInsn(*emitter, *insn);
263                 } else {
264                     EmitAArch64Insn(*emitter, *insn);
265                 }
266             }
267         }
268         (void)emitter->Emit("\t.size\t" + funcStName + ", .-").Emit(funcStName + "\n");
269 
270         auto constructorAttr = funcSt->GetFunction()->GetAttrs().GetConstructorPriority();
271         if (constructorAttr != -1) {
272             (void)emitter->Emit("\t.section\t.init_array." + std::to_string(constructorAttr) + ",\"aw\"\n");
273             (void)emitter->Emit("\t.align 3\n");
274             (void)emitter->Emit("\t.xword\t" + funcStName + "\n");
275         }
276 
277         EmitFunctionSymbolTable(funcEmitInfo);
278 
279         for (auto &it : cgFunc.GetEmitStVec()) {
280             /* emit switch table only here */
281             MIRSymbol *st = it.second;
282             DEBUG_ASSERT(st->IsReadOnly(), "NYI");
283             (void)emitter->Emit("\n");
284             (void)emitter->Emit("\t.align 3\n");
285             (void)emitter->Emit(st->GetName() + ":\n");
286             MIRAggConst *arrayConst = safe_cast<MIRAggConst>(st->GetKonst());
287             CHECK_NULL_FATAL(cgFunc.GetMirModule().CurFunction());
288             PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
289             char *idx = strdup(std::to_string(pIdx).c_str());
290             CHECK_FATAL(arrayConst != nullptr, "null ptr check");
291             for (size_t i = 0; i < arrayConst->GetConstVec().size(); i++) {
292                 MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
293                 CHECK_FATAL(lblConst != nullptr, "null ptr check");
294                 CHECK_FATAL(idx != nullptr, "strdup failed");
295                 (void)emitter->Emit("\t.quad\t.L.").Emit(idx).Emit("__").Emit(lblConst->GetValue());
296                 (void)emitter->Emit(" - " + st->GetName() + "\n");
297             }
298             free(idx);
299             idx = nullptr;
300         }
301 
302         for (const auto &mpPair : cgFunc.GetLabelAndValueMap()) {
303             LabelOperand &labelOpnd = aarchCGFunc.GetOrCreateLabelOperand(mpPair.first);
304             A64OpndEmitVisitor visitor(*emitter, nullptr);
305             labelOpnd.Accept(visitor);
306             (void)emitter->Emit(":\n");
307             (void)emitter->Emit("\t.quad ").Emit(static_cast<int64>(mpPair.second)).Emit("\n");
308         }
309     });
310 #endif
311 }
312 
EmitAArch64Insn(maplebe::Emitter & emitter,Insn & insn) const313 void AArch64AsmEmitter::EmitAArch64Insn(maplebe::Emitter &emitter, Insn &insn) const
314 {
315 #ifdef ARK_LITECG_DEBUG
316     MOperator mOp = insn.GetMachineOpcode();
317     emitter.SetCurrentMOP(mOp);
318     const InsnDesc *md = insn.GetDesc();
319 
320     if (!GetCG()->GenerateVerboseAsm() && !GetCG()->GenerateVerboseCG() && insn.IsComment()) {
321         return;
322     }
323 
324     switch (mOp) {
325         case MOP_adrp_ldr: {
326             EmitAdrpLdr(emitter, insn);
327             if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) {
328                 EmitLazyBindingRoutine(emitter, insn);
329             }
330             return;
331         }
332         case MOP_counter: {
333             EmitCounter(emitter, insn);
334             return;
335         }
336         case MOP_asm: {
337             EmitInlineAsm(emitter, insn);
338             return;
339         }
340         case MOP_clinit_tail: {
341             EmitClinitTail(emitter, insn);
342             return;
343         }
344         case MOP_lazy_ldr: {
345             EmitLazyLoad(emitter, insn);
346             return;
347         }
348         case MOP_adrp_label: {
349             EmitAdrpLabel(emitter, insn);
350             return;
351         }
352         case MOP_get_heap_const_table: {
353             EmitGetHeapConstTable(emitter, insn);
354             return;
355         }
356         case MOP_heap_const: {
357             EmitHeapConstant(emitter, insn);
358             return;
359         }
360         case MOP_lazy_tail: {
361             /* No need to emit this pseudo instruction. */
362             return;
363         }
364         case MOP_lazy_ldr_static: {
365             EmitLazyLoadStatic(emitter, insn);
366             return;
367         }
368         case MOP_arrayclass_cache_ldr: {
369             EmitArrayClassCacheLoad(emitter, insn);
370             return;
371         }
372         case MOP_get_and_addI:
373         case MOP_get_and_addL: {
374             EmitGetAndAddInt(emitter, insn);
375             return;
376         }
377         case MOP_get_and_setI:
378         case MOP_get_and_setL: {
379             EmitGetAndSetInt(emitter, insn);
380             return;
381         }
382         case MOP_compare_and_swapI:
383         case MOP_compare_and_swapL: {
384             EmitCompareAndSwapInt(emitter, insn);
385             return;
386         }
387         case MOP_string_indexof: {
388             EmitStringIndexOf(emitter, insn);
389             return;
390         }
391         case MOP_pseudo_none:
392         case MOP_pseduo_tls_release: {
393             return;
394         }
395         case MOP_tls_desc_call: {
396             EmitCTlsDescCall(emitter, insn);
397             return;
398         }
399         case MOP_tls_desc_rel: {
400             EmitCTlsDescRel(emitter, insn);
401             return;
402         }
403         case MOP_sync_lock_test_setI:
404         case MOP_sync_lock_test_setL: {
405             EmitSyncLockTestSet(emitter, insn);
406             return;
407         }
408         case MOP_pure_call: {
409             EmitPureCall(emitter, insn);
410             return;
411         }
412         default:
413             break;
414     }
415 
416     std::string format(md->format);
417     (void)emitter.Emit("\t").Emit(md->name).Emit("\t");
418     size_t opndSize = insn.GetOperandSize();
419     std::vector<int32> seq(opndSize, -1);
420     std::vector<std::string> prefix(opndSize); /* used for print prefix like "*" in icall *rax */
421     uint32 index = 0;
422     uint32 commaNum = 0;
423     for (uint32 i = 0; i < format.length(); ++i) {
424         char c = format[i];
425         if (c >= '0' && c <= '5') {
426             seq[index++] = c - '0';
427             ++commaNum;
428         } else if (c != ',') {
429             prefix[index].push_back(c);
430         }
431     }
432 
433     bool isRefField =
434         (opndSize == 0) ? false : CheckInsnRefField(insn, static_cast<size_t>(static_cast<uint32>(seq[0])));
435     uint32 compositeOpnds = 0;
436     for (uint32 i = 0; i < commaNum; ++i) {
437         if (seq[i] == -1) {
438             continue;
439         }
440         if (prefix[i].length() > 0) {
441             (void)emitter.Emit(prefix[i]);
442         }
443         if (emitter.NeedToDealWithHugeSo() && (mOp == MOP_xbl || mOp == MOP_tail_call_opt_xbl)) {
444             auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
445             emitter.InsertHugeSoTarget(nameOpnd->GetName());
446             (void)emitter.Emit(nameOpnd->GetName() + emitter.HugeSoPostFix());
447             break;
448         }
449         A64OpndEmitVisitor visitor(emitter, md->opndMD[static_cast<uint32>(seq[i])]);
450 
451         insn.GetOperand(static_cast<uint32>(seq[i])).Accept(visitor);
452         if (compositeOpnds == 1) {
453             (void)emitter.Emit("}");
454         }
455         if (compositeOpnds > 0) {
456             --compositeOpnds;
457         }
458         /* reset opnd0 ref-field flag, so following instruction has correct register */
459         if (isRefField && (i == 0)) {
460             static_cast<RegOperand *>(&insn.GetOperand(static_cast<uint32>(seq[0])))->SetRefField(false);
461         }
462         /* Temporary comment the label:.Label.debug.callee */
463         if (i != (commaNum - 1)) {
464             (void)emitter.Emit(", ");
465         }
466         const uint32 commaNumForEmitLazy = 2;
467         if (!CGOptions::IsLazyBinding() || GetCG()->IsLibcore() || (mOp != MOP_wldr && mOp != MOP_xldr) ||
468             commaNum != commaNumForEmitLazy || i != 1 ||
469             !insn.GetOperand(static_cast<uint32>(seq[1])).IsMemoryAccessOperand()) {
470             continue;
471         }
472         /*
473          * Only check the last operand of ldr in lo12 mode.
474          * Check the second operand, if it's [AArch64MemOperand::kAddrModeLo12Li]
475          */
476         auto *memOpnd = static_cast<MemOperand *>(&insn.GetOperand(static_cast<uint32>(seq[1])));
477         if (memOpnd == nullptr || memOpnd->GetAddrMode() != MemOperand::kAddrModeLo12Li) {
478             continue;
479         }
480         const MIRSymbol *sym = memOpnd->GetSymbol();
481         if (sym->IsMuidFuncDefTab() || sym->IsMuidFuncUndefTab() || sym->IsMuidDataDefTab() ||
482             sym->IsMuidDataUndefTab()) {
483             (void)emitter.Emit("\n");
484             EmitLazyBindingRoutine(emitter, insn);
485         }
486     }
487     if (GetCG()->GenerateVerboseCG() || (GetCG()->GenerateVerboseAsm() && insn.IsComment())) {
488         const char *comment = insn.GetComment().c_str();
489         if (comment != nullptr && strlen(comment) > 0) {
490             (void)emitter.Emit("\t\t// ").Emit(comment);
491         }
492     }
493 
494     (void)emitter.Emit("\n");
495 #endif
496 }
497 
498 #ifdef ARK_LITECG_DEBUG
AsmStringOutputRegNum(bool isInt,uint32 regno,uint32 intBase,uint32 fpBase,std::string & strToEmit)499 static void AsmStringOutputRegNum(bool isInt, uint32 regno, uint32 intBase, uint32 fpBase, std::string &strToEmit)
500 {
501     regno_t newRegno;
502     if (isInt) {
503         CHECK_FATAL(regno >= intBase, "value overflow");
504         newRegno = regno - intBase;
505     } else {
506         newRegno = regno - fpBase;
507     }
508     if (newRegno > (kDecimalMax - 1)) {
509         uint32 tenth = newRegno / kDecimalMax;
510         strToEmit += '0' + static_cast<char>(tenth);
511         newRegno -= (kDecimalMax * tenth);
512     }
513     strToEmit += newRegno + '0';
514 }
515 #endif
516 
EmitInlineAsm(Emitter & emitter,const Insn & insn) const517 void AArch64AsmEmitter::EmitInlineAsm(Emitter &emitter, const Insn &insn) const
518 {
519 #ifdef ARK_LITECG_DEBUG
520     (void)emitter.Emit("\t//Inline asm begin\n\t");
521     auto &list1 = static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd));
522     std::vector<RegOperand *> outOpnds;
523     for (auto *regOpnd : list1.GetOperands()) {
524         outOpnds.push_back(regOpnd);
525     }
526     auto &list2 = static_cast<ListOperand &>(insn.GetOperand(kAsmInputListOpnd));
527     std::vector<RegOperand *> inOpnds;
528     for (auto *regOpnd : list2.GetOperands()) {
529         inOpnds.push_back(regOpnd);
530     }
531     auto &list6 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmOutputRegPrefixOpnd));
532     auto &list7 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmInputRegPrefixOpnd));
533     MapleString asmStr = static_cast<StringOperand &>(insn.GetOperand(kAsmStringOpnd)).GetComment();
534     std::string stringToEmit;
535     auto IsMemAccess = [](char c) -> bool { return c == '['; };
536     auto EmitRegister = [&](const char *p, bool isInt, uint32 regNO, bool unDefRegSize) -> void {
537         if (IsMemAccess(p[0])) {
538             stringToEmit += "[x";
539             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
540             stringToEmit += "]";
541         } else {
542             DEBUG_ASSERT((p[0] == 'w' || p[0] == 'x' || p[0] == 's' || p[0] == 'd' || p[0] == 'v'),
543                          "Asm invalid register type");
544             if ((p[0] == 'w' || p[0] == 'x') && unDefRegSize) {
545                 stringToEmit += 'x';
546             } else {
547                 stringToEmit += p[0];
548             }
549             if (!unDefRegSize) {
550                 isInt = (p[0] == 'w' || p[0] == 'x');
551             }
552             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
553         }
554     };
555     for (size_t i = 0; i < asmStr.length(); ++i) {
556         switch (asmStr[i]) {
557             case '$': {
558                 char c = asmStr[++i];
559                 if ((c >= '0') && (c <= '9')) {
560                     auto val = static_cast<uint32>(c - '0');
561                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
562                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
563                     }
564                     if (val < outOpnds.size()) {
565                         const char *prefix = list6.stringList[val]->GetComment().c_str();
566                         RegOperand *opnd = outOpnds[val];
567                         EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
568                     } else {
569                         val -= static_cast<uint32>(outOpnds.size());
570                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
571                         RegOperand *opnd = inOpnds[val];
572                         /* input is a immediate */
573                         const char *prefix = list7.stringList[val]->GetComment().c_str();
574                         if (prefix[0] == 'i') {
575                             stringToEmit += '#';
576                             for (size_t k = 1; k < list7.stringList[val]->GetComment().length(); ++k) {
577                                 stringToEmit += prefix[k];
578                             }
579                         } else {
580                             EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
581                         }
582                     }
583                 } else if (c == '{') {
584                     c = asmStr[++i];
585                     CHECK_FATAL(((c >= '0') && (c <= '9')), "Inline asm : invalid register constraint number");
586                     auto val = static_cast<uint32>(c - '0');
587                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
588                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
589                     }
590                     regno_t regno;
591                     bool isAddr = false;
592                     if (val < outOpnds.size()) {
593                         RegOperand *opnd = outOpnds[val];
594                         regno = opnd->GetRegisterNumber();
595                         isAddr = IsMemAccess(list6.stringList[val]->GetComment().c_str()[0]);
596                     } else {
597                         val -= static_cast<uint32>(outOpnds.size());
598                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
599                         RegOperand *opnd = inOpnds[val];
600                         regno = opnd->GetRegisterNumber();
601                         DEBUG_ASSERT(list7.stringList[val]->GetComment().c_str() != nullptr,
602                             "list7 GetComment.c_str should not be nullptr");
603                         isAddr = IsMemAccess(list7.stringList[val]->GetComment().c_str()[0]);
604                     }
605                     c = asmStr[++i];
606                     CHECK_FATAL(c == ':', "Parsing error in inline asm string during emit");
607                     c = asmStr[++i];
608                     std::string prefix(1, c);
609                     if (c == 'a' || isAddr) {
610                         prefix = "[x";
611                     }
612                     EmitRegister(prefix.c_str(), true, regno, false);
613                     c = asmStr[++i];
614                     CHECK_FATAL(c == '}', "Parsing error in inline asm string during emit");
615                 }
616                 break;
617             }
618             case '\n': {
619                 stringToEmit += "\n\t";
620                 break;
621             }
622             default:
623                 stringToEmit += asmStr[i];
624         }
625     }
626     (void)emitter.Emit(stringToEmit);
627     (void)emitter.Emit("\n\t//Inline asm end\n");
628 #endif
629 }
630 
EmitClinitTail(Emitter & emitter,const Insn & insn) const631 void AArch64AsmEmitter::EmitClinitTail(Emitter &emitter, const Insn &insn) const
632 {
633 #ifdef ARK_LITECG_DEBUG
634     /*
635      * ldr x17, [xs, #112]
636      * ldr wzr, [x17]
637      */
638     const InsnDesc *md = &AArch64CG::kMd[MOP_clinit_tail];
639 
640     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
641 
642     const OpndDesc *prop0 = md->opndMD[0];
643     A64OpndEmitVisitor visitor(emitter, prop0);
644 
645     /* emit "ldr  x17,[xs,#112]" */
646     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx17, [");
647     opnd0->Accept(visitor);
648     (void)emitter.Emit(", #");
649     (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
650     (void)emitter.Emit("]");
651     (void)emitter.Emit("\n");
652 
653     /* emit "ldr  xzr, [x17]" */
654     (void)emitter.Emit("\t").Emit("ldr\txzr, [x17]\n");
655 #endif
656 }
657 
EmitLazyLoad(Emitter & emitter,const Insn & insn) const658 void AArch64AsmEmitter::EmitLazyLoad(Emitter &emitter, const Insn &insn) const
659 {
660 #ifdef ARK_LITECG_DEBUG
661     /*
662      * ldr wd, [xs]  # xd and xs should be differenct register
663      * ldr wd, [xd]
664      */
665     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr];
666 
667     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
668     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
669     const OpndDesc *prop0 = md->opndMD[0];
670     const OpndDesc *prop1 = md->opndMD[1];
671     A64OpndEmitVisitor visitor(emitter, prop0);
672     A64OpndEmitVisitor visitor1(emitter, prop1);
673 
674     /* emit  "ldr wd, [xs]" */
675     (void)emitter.Emit("\t").Emit("ldr\t");
676 #ifdef USE_32BIT_REF
677     opnd0->Accept(visitor);
678 #else
679     opnd0->Accept(visitor1);
680 #endif
681     (void)emitter.Emit(", [");
682     opnd1->Accept(visitor1);
683     (void)emitter.Emit("]\t// lazy load.\n");
684 
685     /* emit "ldr wd, [xd]" */
686     (void)emitter.Emit("\t").Emit("ldr\t");
687     opnd0->Accept(visitor);
688     (void)emitter.Emit(", [");
689     opnd1->Accept(visitor1);
690     (void)emitter.Emit("]\t// lazy load.\n");
691 #endif
692 }
693 
EmitCounter(Emitter & emitter,const Insn & insn) const694 void AArch64AsmEmitter::EmitCounter(Emitter &emitter, const Insn &insn) const
695 {
696 #ifdef ARK_LITECG_DEBUG
697     /*
698      * adrp    x1, __profile_bb_table$$GetBoolean_bytecode+4
699      * ldr     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
700      * add     w17, w17, #1
701      * str     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
702      */
703     const InsnDesc *md = &AArch64CG::kMd[MOP_counter];
704 
705     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
706     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
707     const OpndDesc *prop0 = md->opndMD[kInsnFirstOpnd];
708     A64OpndEmitVisitor visitor(emitter, prop0);
709     StImmOperand *stImmOpnd = static_cast<StImmOperand *>(opnd1);
710     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitCounter");
711     /* emit adrp */
712     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
713     opnd0->Accept(visitor);
714     (void)emitter.Emit(",");
715     (void)emitter.Emit(stImmOpnd->GetName());
716     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
717     (void)emitter.Emit("\n");
718     /* emit ldr */
719     (void)emitter.Emit("\t").Emit("ldr").Emit("\tw17, [");
720     opnd0->Accept(visitor);
721     (void)emitter.Emit(",");
722     (void)emitter.Emit("#");
723     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
724     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
725     (void)emitter.Emit("]");
726     (void)emitter.Emit("\n");
727     /* emit add */
728     (void)emitter.Emit("\t").Emit("add").Emit("\tw17, w17, #1");
729     (void)emitter.Emit("\n");
730     /* emit str */
731     (void)emitter.Emit("\t").Emit("str").Emit("\tw17, [");
732     opnd0->Accept(visitor);
733     (void)emitter.Emit(",");
734     (void)emitter.Emit("#");
735     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
736     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
737     (void)emitter.Emit("]");
738     (void)emitter.Emit("\n");
739 #endif
740 }
741 
EmitAdrpLabel(Emitter & emitter,const Insn & insn) const742 void AArch64AsmEmitter::EmitAdrpLabel(Emitter &emitter, const Insn &insn) const
743 {
744 #ifdef ARK_LITECG_DEBUG
745     /* adrp    xd, label
746      * add     xd, xd, #lo12:label
747      */
748     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_label];
749 
750     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
751     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
752     const OpndDesc *prop0 = md->opndMD[0];
753     A64OpndEmitVisitor visitor(emitter, prop0);
754     auto lidx = static_cast<ImmOperand *>(opnd1)->GetValue();
755 
756     /* adrp    xd, label */
757     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
758     opnd0->Accept(visitor);
759     (void)emitter.Emit(", ");
760     CHECK_NULL_FATAL(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction());
761     char *idx = strdup(std::to_string(
762         Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction()->GetPuidx()).c_str());
763     CHECK_FATAL(idx != nullptr, "strdup failed");
764     (void)emitter.Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
765 
766     /* add     xd, xd, #lo12:label */
767     (void)emitter.Emit("\tadd\t");
768     opnd0->Accept(visitor);
769     (void)emitter.Emit(", ");
770     opnd0->Accept(visitor);
771     (void)emitter.Emit(", ");
772     (void)emitter.Emit(":lo12:").Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
773     (void)emitter.Emit("\n");
774     free(idx);
775     idx = nullptr;
776 #endif
777 }
778 
EmitHeapConstant(Emitter & emitter,const Insn & insn) const779 void AArch64AsmEmitter::EmitHeapConstant(Emitter &emitter, const Insn &insn) const
780 {
781 #ifdef ARK_LITECG_DEBUG
782     /* ldr    reg1, [reg0, offset]
783      */
784     const InsnDesc *md = &AArch64CG::kMd[MOP_heap_const];
785 
786     Operand &opnd0 = insn.GetOperand(kInsnFirstOpnd);
787     Operand &opnd1 = insn.GetOperand(kInsnSecondOpnd);
788     Operand &opnd2 = insn.GetOperand(kInsnThirdOpnd);
789     const OpndDesc *prop0 = md->opndMD[0];
790     A64OpndEmitVisitor visitor(emitter, prop0);
791     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
792     opnd0.Accept(visitor);
793     (void)emitter.Emit(", [");
794     opnd1.Accept(visitor);
795     (void)emitter.Emit(",#");
796     int64_t slotIndex = static_cast<ImmOperand&>(opnd2).GetValue();
797     (void)emitter.Emit(slotIndex * k8ByteSize).Emit("]  // __heap_constant(");
798     opnd2.Accept(visitor);
799     (void)emitter.Emit(")\n");
800 #endif
801 }
802 
EmitGetHeapConstTable(Emitter & emitter,const Insn & insn) const803 void AArch64AsmEmitter::EmitGetHeapConstTable(Emitter &emitter, const Insn &insn) const
804 {
805 #ifdef ARK_LITECG_DEBUG
806     /* ldr    reg0, [reg1, offset1]
807      * ldr    reg0, [reg0, offset2]
808      */
809     const InsnDesc *md = &AArch64CG::kMd[MOP_get_heap_const_table];
810 
811     Operand &opnd0 = insn.GetOperand(kInsnFirstOpnd);
812     Operand &opnd1 = insn.GetOperand(kInsnSecondOpnd);
813     Operand &opnd2 = insn.GetOperand(kInsnThirdOpnd);
814     Operand &opnd3 = insn.GetOperand(kInsnFourthOpnd);
815     const OpndDesc *prop0 = md->opndMD[0];
816     A64OpndEmitVisitor visitor(emitter, prop0);
817     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
818     opnd0.Accept(visitor);
819     (void)emitter.Emit(", [");
820     opnd1.Accept(visitor);
821     (void)emitter.Emit(",");
822     opnd2.Accept(visitor);
823     (void)emitter.Emit("]\n");
824 
825     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
826     opnd0.Accept(visitor);
827     (void)emitter.Emit(", [");
828     opnd0.Accept(visitor);
829     (void)emitter.Emit(",");
830     opnd3.Accept(visitor);
831     (void)emitter.Emit("]    // __ get_heap_constant_table\n");
832 #endif
833 }
834 
EmitAdrpLdr(Emitter & emitter,const Insn & insn) const835 void AArch64AsmEmitter::EmitAdrpLdr(Emitter &emitter, const Insn &insn) const
836 {
837 #ifdef ARK_LITECG_DEBUG
838     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
839     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
840     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
841     const OpndDesc *prop0 = md->opndMD[0];
842     A64OpndEmitVisitor visitor(emitter, prop0);
843     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
844     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitAdrpLdr");
845 
846     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
847     opnd0->Accept(visitor);
848     (void)emitter.Emit(", ");
849     (void)emitter.Emit(stImmOpnd->GetName());
850     if (stImmOpnd->GetOffset() != 0) {
851         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
852     }
853     (void)emitter.Emit("\n");
854 
855     (void)emitter.Emit("\tldr\t");
856     static_cast<RegOperand *>(opnd0)->SetRefField(true);
857     opnd0->Accept(visitor);
858     static_cast<RegOperand *>(opnd0)->SetRefField(false);
859     (void)emitter.Emit(", ");
860     (void)emitter.Emit("[");
861     opnd0->Accept(visitor);
862     (void)emitter.Emit(",");
863     (void)emitter.Emit("#");
864     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
865     if (stImmOpnd->GetOffset() != 0) {
866         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
867     }
868     (void)emitter.Emit("]\n");
869 #endif
870 }
871 
EmitLazyLoadStatic(Emitter & emitter,const Insn & insn) const872 void AArch64AsmEmitter::EmitLazyLoadStatic(Emitter &emitter, const Insn &insn) const
873 {
874 #ifdef ARK_LITECG_DEBUG
875     /* adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset
876      * ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]
877      * ldr wzr, [xd]
878      */
879     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr_static];
880 
881     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
882     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
883     const OpndDesc *prop0 = md->GetOpndDes(0);
884     A64OpndEmitVisitor visitor(emitter, prop0);
885     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
886     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
887 
888     /* emit "adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset" */
889     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
890     opnd0->Accept(visitor);
891     (void)emitter.Emit(", ");
892     (void)emitter.Emit(stImmOpnd->GetName());
893     if (stImmOpnd->GetOffset() != 0) {
894         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
895     }
896     (void)emitter.Emit("\t// lazy load static.\n");
897 
898     /* emit "ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]" */
899     (void)emitter.Emit("\tldr\t");
900     static_cast<RegOperand *>(opnd0)->SetRefField(true);
901 #ifdef USE_32BIT_REF
902     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
903     opnd0->Emit(emitter, &prop2); /* ldr wd, ... for terminal system */
904 #else
905     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
906 #endif /* USE_32BIT_REF */
907     static_cast<RegOperand *>(opnd0)->SetRefField(false);
908     (void)emitter.Emit(", ");
909     (void)emitter.Emit("[");
910     opnd0->Accept(visitor);
911     (void)emitter.Emit(",");
912     (void)emitter.Emit("#");
913     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
914     if (stImmOpnd->GetOffset() != 0) {
915         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
916     }
917     (void)emitter.Emit("]\t// lazy load static.\n");
918 
919     /* emit "ldr wzr, [xd]" */
920     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
921     opnd0->Accept(visitor);
922     (void)emitter.Emit("]\t// lazy load static.\n");
923 #endif
924 }
925 
EmitArrayClassCacheLoad(Emitter & emitter,const Insn & insn) const926 void AArch64AsmEmitter::EmitArrayClassCacheLoad(Emitter &emitter, const Insn &insn) const
927 {
928 #ifdef ARK_LITECG_DEBUG
929     /* adrp xd, :got:__arrayClassCacheTable$$xxx+offset
930      * ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]
931      * ldr wzr, [xd]
932      */
933     const InsnDesc *md = &AArch64CG::kMd[MOP_arrayclass_cache_ldr];
934     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
935     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
936     const OpndDesc *prop0 = md->GetOpndDes(kInsnFirstOpnd);
937     A64OpndEmitVisitor visitor(emitter, prop0);
938     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
939     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
940 
941     /* emit "adrp xd, :got:__arrayClassCacheTable$$xxx+offset" */
942     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
943     opnd0->Accept(visitor);
944     (void)emitter.Emit(", ");
945     (void)emitter.Emit(stImmOpnd->GetName());
946     if (stImmOpnd->GetOffset() != 0) {
947         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
948     }
949     (void)emitter.Emit("\t// load array class.\n");
950 
951     /* emit "ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]" */
952     (void)emitter.Emit("\tldr\t");
953     static_cast<RegOperand *>(opnd0)->SetRefField(true);
954 #ifdef USE_32BIT_REF
955     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
956     A64OpndEmitVisitor visitor2(emitter, prop2);
957     opnd0->Accept(visitor2); /* ldr wd, ... for terminal system */
958 #else
959     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
960 #endif /* USE_32BIT_REF */
961     static_cast<RegOperand *>(opnd0)->SetRefField(false);
962     (void)emitter.Emit(", ");
963     (void)emitter.Emit("[");
964     opnd0->Accept(visitor);
965     (void)emitter.Emit(",");
966     (void)emitter.Emit("#");
967     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
968     if (stImmOpnd->GetOffset() != 0) {
969         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
970     }
971     (void)emitter.Emit("]\t// load array class.\n");
972 
973     /* emit "ldr wzr, [xd]" */
974     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
975     opnd0->Accept(visitor);
976     (void)emitter.Emit("]\t// check resolve array class.\n");
977 #endif
978 }
979 
980 /*
981  * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label
982  * add    xt, x1, x2
983  * label:
984  * ldaxr  w0, [xt]
985  * add    wt, w0, w3
986  * stlxr  ws, wt, [xt]
987  * cbnz   ws, label
988  */
EmitGetAndAddInt(Emitter & emitter,const Insn & insn) const989 void AArch64AsmEmitter::EmitGetAndAddInt(Emitter &emitter, const Insn &insn) const
990 {
991 #ifdef ARK_LITECG_DEBUG
992     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the oprands number");
993     (void)emitter.Emit("\t//\tstart of Unsafe.getAndAddInt.\n");
994     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
995     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
996     Operand *tempOpnd2 = &insn.GetOperand(kInsnFourthOpnd);
997     Operand *objOpnd = &insn.GetOperand(kInsnFifthOpnd);
998     Operand *offsetOpnd = &insn.GetOperand(kInsnSixthOpnd);
999     Operand *deltaOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1000     Operand *labelOpnd = &insn.GetOperand(kInsnEighthOpnd);
1001     A64OpndEmitVisitor visitor(emitter, nullptr);
1002     /* emit add. */
1003     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1004     tempOpnd0->Accept(visitor);
1005     (void)emitter.Emit(", ");
1006     objOpnd->Accept(visitor);
1007     (void)emitter.Emit(", ");
1008     offsetOpnd->Accept(visitor);
1009     (void)emitter.Emit("\n");
1010     /* emit label. */
1011     labelOpnd->Accept(visitor);
1012     (void)emitter.Emit(":\n");
1013     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1014     const MOperator mOp = insn.GetMachineOpcode();
1015     const InsnDesc *md = &AArch64CG::kMd[mOp];
1016     const OpndDesc *retProp = md->opndMD[kInsnFirstOpnd];
1017     A64OpndEmitVisitor retVisitor(emitter, retProp);
1018     /* emit ldaxr */
1019     (void)emitter.Emit("\t").Emit("ldaxr").Emit("\t");
1020     retVal->Accept(retVisitor);
1021     (void)emitter.Emit(", [");
1022     tempOpnd0->Accept(visitor);
1023     (void)emitter.Emit("]\n");
1024     /* emit add. */
1025     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1026     tempOpnd1->Accept(retVisitor);
1027     (void)emitter.Emit(", ");
1028     retVal->Accept(retVisitor);
1029     (void)emitter.Emit(", ");
1030     deltaOpnd->Accept(retVisitor);
1031     (void)emitter.Emit("\n");
1032     /* emit stlxr. */
1033     (void)emitter.Emit("\t").Emit("stlxr").Emit("\t");
1034     tempOpnd2->Accept(visitor);
1035     (void)emitter.Emit(", ");
1036     tempOpnd1->Accept(retVisitor);
1037     (void)emitter.Emit(", [");
1038     tempOpnd0->Accept(visitor);
1039     (void)emitter.Emit("]\n");
1040     /* emit cbnz. */
1041     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1042     tempOpnd2->Accept(visitor);
1043     (void)emitter.Emit(", ");
1044     labelOpnd->Accept(visitor);
1045     (void)emitter.Emit("\n");
1046     (void)emitter.Emit("\t//\tend of Unsafe.getAndAddInt.\n");
1047 #endif
1048 }
1049 
1050 /*
1051  * intrinsic_get_set_int w0, xt, ws, x1, x2, w3, label
1052  * add    xt, x1, x2
1053  * label:
1054  * ldaxr  w0, [xt]
1055  * stlxr  ws, w3, [xt]
1056  * cbnz   ws, label
1057  */
EmitGetAndSetInt(Emitter & emitter,const Insn & insn) const1058 void AArch64AsmEmitter::EmitGetAndSetInt(Emitter &emitter, const Insn &insn) const
1059 {
1060 #ifdef ARK_LITECG_DEBUG
1061     /* MOP_get_and_setI and MOP_get_and_setL have 7 operands */
1062     DEBUG_ASSERT(insn.GetOperandSize() > kInsnSeventhOpnd, "ensure the operands number");
1063     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1064     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1065     Operand *objOpnd = &insn.GetOperand(kInsnFourthOpnd);
1066     Operand *offsetOpnd = &insn.GetOperand(kInsnFifthOpnd);
1067     A64OpndEmitVisitor visitor(emitter, nullptr);
1068     /* add    x1, x1, x2 */
1069     (void)emitter.Emit("\tadd\t");
1070     tempOpnd0->Accept(visitor);
1071     (void)emitter.Emit(", ");
1072     objOpnd->Accept(visitor);
1073     (void)emitter.Emit(", ");
1074     offsetOpnd->Accept(visitor);
1075     (void)emitter.Emit("\n");
1076     Operand *labelOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1077     /* label: */
1078     labelOpnd->Accept(visitor);
1079     (void)emitter.Emit(":\n");
1080     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1081     /* ldaxr  w0, [xt] */
1082     (void)emitter.Emit("\tldaxr\t");
1083     retVal->Accept(visitor);
1084     (void)emitter.Emit(", [");
1085     tempOpnd0->Accept(visitor);
1086     (void)emitter.Emit("]\n");
1087     Operand *newValueOpnd = &insn.GetOperand(kInsnSixthOpnd);
1088     /* stlxr  ws, w3, [xt] */
1089     (void)emitter.Emit("\tstlxr\t");
1090     tempOpnd1->Accept(visitor);
1091     (void)emitter.Emit(", ");
1092     newValueOpnd->Accept(visitor);
1093     (void)emitter.Emit(", [");
1094     tempOpnd0->Accept(visitor);
1095     (void)emitter.Emit("]\n");
1096     /* cbnz   w2, label */
1097     (void)emitter.Emit("\tcbnz\t");
1098     tempOpnd1->Accept(visitor);
1099     (void)emitter.Emit(", ");
1100     labelOpnd->Accept(visitor);
1101     (void)emitter.Emit("\n");
1102 #endif
1103 }
1104 
1105 /*
1106  * intrinsic_string_indexof w0, x1, w2, x3, w4, x5, x6, x7, x8, x9, w10,
1107  *                          Label.FIRST_LOOP, Label.STR2_NEXT, Label.STR1_LOOP,
1108  *                          Label.STR1_NEXT, Label.LAST_WORD, Label.NOMATCH, Label.RET
1109  * cmp       w4, w2
1110  * b.gt      .Label.NOMATCH
1111  * sub       w2, w2, w4
1112  * sub       w4, w4, #8
1113  * mov       w10, w2
1114  * uxtw      x4, w4
1115  * uxtw      x2, w2
1116  * add       x3, x3, x4
1117  * add       x1, x1, x2
1118  * neg       x4, x4
1119  * neg       x2, x2
1120  * ldr       x5, [x3,x4]
1121  * .Label.FIRST_LOOP:
1122  * ldr       x7, [x1,x2]
1123  * cmp       x5, x7
1124  * b.eq      .Label.STR1_LOOP
1125  * .Label.STR2_NEXT:
1126  * adds      x2, x2, #1
1127  * b.le      .Label.FIRST_LOOP
1128  * b         .Label.NOMATCH
1129  * .Label.STR1_LOOP:
1130  * adds      x8, x4, #8
1131  * add       x9, x2, #8
1132  * b.ge      .Label.LAST_WORD
1133  * .Label.STR1_NEXT:
1134  * ldr       x6, [x3,x8]
1135  * ldr       x7, [x1,x9]
1136  * cmp       x6, x7
1137  * b.ne      .Label.STR2_NEXT
1138  * adds      x8, x8, #8
1139  * add       x9, x9, #8
1140  * b.lt      .Label.STR1_NEXT
1141  * .Label.LAST_WORD:
1142  * ldr       x6, [x3]
1143  * sub       x9, x1, x4
1144  * ldr       x7, [x9,x2]
1145  * cmp       x6, x7
1146  * b.ne      .Label.STR2_NEXT
1147  * add       w0, w10, w2
1148  * b         .Label.RET
1149  * .Label.NOMATCH:
1150  * mov       w0, #-1
1151  * .Label.RET:
1152  */
EmitStringIndexOf(Emitter & emitter,const Insn & insn) const1153 void AArch64AsmEmitter::EmitStringIndexOf(Emitter &emitter, const Insn &insn) const
1154 {
1155 #ifdef ARK_LITECG_DEBUG
1156     /* MOP_string_indexof has 18 operands */
1157     DEBUG_ASSERT(insn.GetOperandSize() == 18, "ensure the operands number");
1158     Operand *patternLengthOpnd = &insn.GetOperand(kInsnFifthOpnd);
1159     Operand *srcLengthOpnd = &insn.GetOperand(kInsnThirdOpnd);
1160     const std::string patternLengthReg =
1161         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(patternLengthOpnd)->GetRegisterNumber()];
1162     const std::string srcLengthReg =
1163         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(srcLengthOpnd)->GetRegisterNumber()];
1164     A64OpndEmitVisitor visitor(emitter, nullptr);
1165     /* cmp       w4, w2 */
1166     (void)emitter.Emit("\tcmp\t");
1167     patternLengthOpnd->Accept(visitor);
1168     (void)emitter.Emit(", ");
1169     srcLengthOpnd->Accept(visitor);
1170     (void)emitter.Emit("\n");
1171     /* the 16th operand of MOP_string_indexof is Label.NOMATCH */
1172     Operand *labelNoMatch = &insn.GetOperand(16);
1173     /* b.gt      Label.NOMATCH */
1174     (void)emitter.Emit("\tb.gt\t");
1175     labelNoMatch->Accept(visitor);
1176     (void)emitter.Emit("\n");
1177     /* sub       w2, w2, w4 */
1178     (void)emitter.Emit("\tsub\t");
1179     srcLengthOpnd->Accept(visitor);
1180     (void)emitter.Emit(", ");
1181     srcLengthOpnd->Accept(visitor);
1182     (void)emitter.Emit(", ");
1183     patternLengthOpnd->Accept(visitor);
1184     (void)emitter.Emit("\n");
1185     /* sub       w4, w4, #8 */
1186     (void)emitter.Emit("\tsub\t");
1187     patternLengthOpnd->Accept(visitor);
1188     (void)emitter.Emit(", ");
1189     patternLengthOpnd->Accept(visitor);
1190     (void)emitter.Emit(", #8\n");
1191     /* the 10th operand of MOP_string_indexof is w10 */
1192     Operand *resultTmp = &insn.GetOperand(10);
1193     /* mov       w10, w2 */
1194     (void)emitter.Emit("\tmov\t");
1195     resultTmp->Accept(visitor);
1196     (void)emitter.Emit(", ");
1197     srcLengthOpnd->Accept(visitor);
1198     (void)emitter.Emit("\n");
1199     /* uxtw      x4, w4 */
1200     (void)emitter.Emit("\tuxtw\t").Emit(patternLengthReg);
1201     (void)emitter.Emit(", ");
1202     patternLengthOpnd->Accept(visitor);
1203     (void)emitter.Emit("\n");
1204     /* uxtw      x2, w2 */
1205     (void)emitter.Emit("\tuxtw\t").Emit(srcLengthReg);
1206     (void)emitter.Emit(", ");
1207     srcLengthOpnd->Accept(visitor);
1208     (void)emitter.Emit("\n");
1209     Operand *patternStringBaseOpnd = &insn.GetOperand(kInsnFourthOpnd);
1210     /* add       x3, x3, x4 */
1211     (void)emitter.Emit("\tadd\t");
1212     patternStringBaseOpnd->Accept(visitor);
1213     (void)emitter.Emit(", ");
1214     patternStringBaseOpnd->Accept(visitor);
1215     (void)emitter.Emit(", ").Emit(patternLengthReg);
1216     (void)emitter.Emit("\n");
1217     Operand *srcStringBaseOpnd = &insn.GetOperand(kInsnSecondOpnd);
1218     /* add       x1, x1, x2 */
1219     (void)emitter.Emit("\tadd\t");
1220     srcStringBaseOpnd->Accept(visitor);
1221     (void)emitter.Emit(", ");
1222     srcStringBaseOpnd->Accept(visitor);
1223     (void)emitter.Emit(", ").Emit(srcLengthReg);
1224     (void)emitter.Emit("\n");
1225     /* neg       x4, x4 */
1226     (void)emitter.Emit("\tneg\t").Emit(patternLengthReg);
1227     (void)emitter.Emit(", ").Emit(patternLengthReg);
1228     (void)emitter.Emit("\n");
1229     /* neg       x2, x2 */
1230     (void)emitter.Emit("\tneg\t").Emit(srcLengthReg);
1231     (void)emitter.Emit(", ").Emit(srcLengthReg);
1232     (void)emitter.Emit("\n");
1233     Operand *first = &insn.GetOperand(kInsnSixthOpnd);
1234     /* ldr       x5, [x3,x4] */
1235     (void)emitter.Emit("\tldr\t");
1236     first->Accept(visitor);
1237     (void)emitter.Emit(", [");
1238     patternStringBaseOpnd->Accept(visitor);
1239     (void)emitter.Emit(",").Emit(patternLengthReg);
1240     (void)emitter.Emit("]\n");
1241     /* the 11th operand of MOP_string_indexof is Label.FIRST_LOOP */
1242     Operand *labelFirstLoop = &insn.GetOperand(11);
1243     /* .Label.FIRST_LOOP: */
1244     labelFirstLoop->Accept(visitor);
1245     (void)emitter.Emit(":\n");
1246     /* the 7th operand of MOP_string_indexof is x7 */
1247     Operand *ch2 = &insn.GetOperand(7);
1248     /* ldr       x7, [x1,x2] */
1249     (void)emitter.Emit("\tldr\t");
1250     ch2->Accept(visitor);
1251     (void)emitter.Emit(", [");
1252     srcStringBaseOpnd->Accept(visitor);
1253     (void)emitter.Emit(",").Emit(srcLengthReg);
1254     (void)emitter.Emit("]\n");
1255     /* cmp       x5, x7 */
1256     (void)emitter.Emit("\tcmp\t");
1257     first->Accept(visitor);
1258     (void)emitter.Emit(", ");
1259     ch2->Accept(visitor);
1260     (void)emitter.Emit("\n");
1261     /* the 13th operand of MOP_string_indexof is Label.STR1_LOOP */
1262     Operand *labelStr1Loop = &insn.GetOperand(13);
1263     /* b.eq      .Label.STR1_LOOP */
1264     (void)emitter.Emit("\tb.eq\t");
1265     labelStr1Loop->Accept(visitor);
1266     (void)emitter.Emit("\n");
1267     /* the 12th operand of MOP_string_indexof is Label.STR2_NEXT */
1268     Operand *labelStr2Next = &insn.GetOperand(12);
1269     /* .Label.STR2_NEXT: */
1270     labelStr2Next->Accept(visitor);
1271     (void)emitter.Emit(":\n");
1272     /* adds      x2, x2, #1 */
1273     (void)emitter.Emit("\tadds\t").Emit(srcLengthReg);
1274     (void)emitter.Emit(", ").Emit(srcLengthReg);
1275     (void)emitter.Emit(", #1\n");
1276     /* b.le      .Label.FIRST_LOOP */
1277     (void)emitter.Emit("\tb.le\t");
1278     labelFirstLoop->Accept(visitor);
1279     (void)emitter.Emit("\n");
1280     /* b         .Label.NOMATCH */
1281     (void)emitter.Emit("\tb\t");
1282     labelNoMatch->Accept(visitor);
1283     (void)emitter.Emit("\n");
1284     /* .Label.STR1_LOOP: */
1285     labelStr1Loop->Accept(visitor);
1286     (void)emitter.Emit(":\n");
1287     /* the 8th operand of MOP_string_indexof is x8 */
1288     Operand *tmp1 = &insn.GetOperand(kInsnEighthOpnd);
1289     /* adds      x8, x4, #8 */
1290     (void)emitter.Emit("\tadds\t");
1291     tmp1->Accept(visitor);
1292     (void)emitter.Emit(", ").Emit(patternLengthReg);
1293     (void)emitter.Emit(", #8\n");
1294     /* the 9th operand of MOP_string_indexof is x9 */
1295     Operand *tmp2 = &insn.GetOperand(9);
1296     /* add       x9, x2, #8 */
1297     (void)emitter.Emit("\tadd\t");
1298     tmp2->Accept(visitor);
1299     (void)emitter.Emit(", ").Emit(srcLengthReg);
1300     (void)emitter.Emit(", #8\n");
1301     /* the 15th operand of MOP_string_indexof is Label.LAST_WORD */
1302     Operand *labelLastWord = &insn.GetOperand(15);
1303     /* b.ge      .Label.LAST_WORD */
1304     (void)emitter.Emit("\tb.ge\t");
1305     labelLastWord->Accept(visitor);
1306     (void)emitter.Emit("\n");
1307     /* the 14th operand of MOP_string_indexof is Label.STR1_NEXT */
1308     Operand *labelStr1Next = &insn.GetOperand(14);
1309     /* .Label.STR1_NEXT: */
1310     labelStr1Next->Accept(visitor);
1311     (void)emitter.Emit(":\n");
1312     /* the 6th operand of MOP_string_indexof is x6 */
1313     Operand *ch1 = &insn.GetOperand(6);
1314     /* ldr       x6, [x3,x8] */
1315     (void)emitter.Emit("\tldr\t");
1316     ch1->Accept(visitor);
1317     (void)emitter.Emit(", [");
1318     patternStringBaseOpnd->Accept(visitor);
1319     (void)emitter.Emit(",");
1320     tmp1->Accept(visitor);
1321     (void)emitter.Emit("]\n");
1322     /* ldr       x7, [x1,x9] */
1323     (void)emitter.Emit("\tldr\t");
1324     ch2->Accept(visitor);
1325     (void)emitter.Emit(", [");
1326     srcStringBaseOpnd->Accept(visitor);
1327     (void)emitter.Emit(",");
1328     tmp2->Accept(visitor);
1329     (void)emitter.Emit("]\n");
1330     /* cmp       x6, x7 */
1331     (void)emitter.Emit("\tcmp\t");
1332     ch1->Accept(visitor);
1333     (void)emitter.Emit(", ");
1334     ch2->Accept(visitor);
1335     (void)emitter.Emit("\n");
1336     /* b.ne      .Label.STR2_NEXT */
1337     (void)emitter.Emit("\tb.ne\t");
1338     labelStr2Next->Accept(visitor);
1339     (void)emitter.Emit("\n");
1340     /* adds      x8, x8, #8 */
1341     (void)emitter.Emit("\tadds\t");
1342     tmp1->Accept(visitor);
1343     (void)emitter.Emit(", ");
1344     tmp1->Accept(visitor);
1345     (void)emitter.Emit(", #8\n");
1346     /* add       x9, x9, #8 */
1347     (void)emitter.Emit("\tadd\t");
1348     tmp2->Accept(visitor);
1349     (void)emitter.Emit(", ");
1350     tmp2->Accept(visitor);
1351     (void)emitter.Emit(", #8\n");
1352     /* b.lt      .Label.STR1_NEXT */
1353     (void)emitter.Emit("\tb.lt\t");
1354     labelStr1Next->Accept(visitor);
1355     (void)emitter.Emit("\n");
1356     /* .Label.LAST_WORD: */
1357     labelLastWord->Accept(visitor);
1358     (void)emitter.Emit(":\n");
1359     /* ldr       x6, [x3] */
1360     (void)emitter.Emit("\tldr\t");
1361     ch1->Accept(visitor);
1362     (void)emitter.Emit(", [");
1363     patternStringBaseOpnd->Accept(visitor);
1364     (void)emitter.Emit("]\n");
1365     /* sub       x9, x1, x4 */
1366     (void)emitter.Emit("\tsub\t");
1367     tmp2->Accept(visitor);
1368     (void)emitter.Emit(", ");
1369     srcStringBaseOpnd->Accept(visitor);
1370     (void)emitter.Emit(", ").Emit(patternLengthReg);
1371     (void)emitter.Emit("\n");
1372     /* ldr       x7, [x9,x2] */
1373     (void)emitter.Emit("\tldr\t");
1374     ch2->Accept(visitor);
1375     (void)emitter.Emit(", [");
1376     tmp2->Accept(visitor);
1377     (void)emitter.Emit(", ").Emit(srcLengthReg);
1378     (void)emitter.Emit("]\n");
1379     /* cmp       x6, x7 */
1380     (void)emitter.Emit("\tcmp\t");
1381     ch1->Accept(visitor);
1382     (void)emitter.Emit(", ");
1383     ch2->Accept(visitor);
1384     (void)emitter.Emit("\n");
1385     /* b.ne      .Label.STR2_NEXT */
1386     (void)emitter.Emit("\tb.ne\t");
1387     labelStr2Next->Accept(visitor);
1388     (void)emitter.Emit("\n");
1389     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1390     /* add       w0, w10, w2 */
1391     (void)emitter.Emit("\tadd\t");
1392     retVal->Accept(visitor);
1393     (void)emitter.Emit(", ");
1394     resultTmp->Accept(visitor);
1395     (void)emitter.Emit(", ");
1396     srcLengthOpnd->Accept(visitor);
1397     (void)emitter.Emit("\n");
1398     /* the 17th operand of MOP_string_indexof Label.ret */
1399     Operand *labelRet = &insn.GetOperand(17);
1400     /* b         .Label.ret */
1401     (void)emitter.Emit("\tb\t");
1402     labelRet->Accept(visitor);
1403     (void)emitter.Emit("\n");
1404     /* .Label.NOMATCH: */
1405     labelNoMatch->Accept(visitor);
1406     (void)emitter.Emit(":\n");
1407     /* mov       w0, #-1 */
1408     (void)emitter.Emit("\tmov\t");
1409     retVal->Accept(visitor);
1410     (void)emitter.Emit(", #-1\n");
1411     /* .Label.ret: */
1412     labelRet->Accept(visitor);
1413     (void)emitter.Emit(":\n");
1414 #endif
1415 }
1416 
1417 /*
1418  * intrinsic_compare_swap_int x0, xt, xs, x1, x2, w3, w4, lable1, label2
1419  * add       xt, x1, x2
1420  * label1:
1421  * ldaxr     ws, [xt]
1422  * cmp       ws, w3
1423  * b.ne      label2
1424  * stlxr     ws, w4, [xt]
1425  * cbnz      ws, label1
1426  * label2:
1427  * cset      x0, eq
1428  */
EmitCompareAndSwapInt(Emitter & emitter,const Insn & insn) const1429 void AArch64AsmEmitter::EmitCompareAndSwapInt(Emitter &emitter, const Insn &insn) const
1430 {
1431 #ifdef ARK_LITECG_DEBUG
1432     /* MOP_compare_and_swapI and MOP_compare_and_swapL have 8 operands */
1433     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the operands number");
1434     const MOperator mOp = insn.GetMachineOpcode();
1435     const InsnDesc *md = &AArch64CG::kMd[mOp];
1436     Operand *temp0 = &insn.GetOperand(kInsnSecondOpnd);
1437     Operand *temp1 = &insn.GetOperand(kInsnThirdOpnd);
1438     Operand *obj = &insn.GetOperand(kInsnFourthOpnd);
1439     Operand *offset = &insn.GetOperand(kInsnFifthOpnd);
1440     A64OpndEmitVisitor visitor(emitter, nullptr);
1441     /* add       xt, x1, x2 */
1442     (void)emitter.Emit("\tadd\t");
1443     temp0->Accept(visitor);
1444     (void)emitter.Emit(", ");
1445     obj->Accept(visitor);
1446     (void)emitter.Emit(", ");
1447     offset->Accept(visitor);
1448     (void)emitter.Emit("\n");
1449     Operand *label1 = &insn.GetOperand(kInsnEighthOpnd);
1450     /* label1: */
1451     label1->Accept(visitor);
1452     (void)emitter.Emit(":\n");
1453     /* ldaxr     ws, [xt] */
1454     (void)emitter.Emit("\tldaxr\t");
1455     temp1->Accept(visitor);
1456     (void)emitter.Emit(", [");
1457     temp0->Accept(visitor);
1458     (void)emitter.Emit("]\n");
1459     Operand *expectedValue = &insn.GetOperand(kInsnSixthOpnd);
1460     const OpndDesc *expectedValueProp = md->opndMD[kInsnSixthOpnd];
1461     /* cmp       ws, w3 */
1462     (void)emitter.Emit("\tcmp\t");
1463     temp1->Accept(visitor);
1464     (void)emitter.Emit(", ");
1465     A64OpndEmitVisitor visitorExpect(emitter, expectedValueProp);
1466     expectedValue->Accept(visitorExpect);
1467     (void)emitter.Emit("\n");
1468     constexpr uint32 kInsnNinethOpnd = 8;
1469     Operand *label2 = &insn.GetOperand(kInsnNinethOpnd);
1470     /* b.ne      label2 */
1471     (void)emitter.Emit("\tbne\t");
1472     label2->Accept(visitor);
1473     (void)emitter.Emit("\n");
1474     Operand *newValue = &insn.GetOperand(kInsnSeventhOpnd);
1475     /* stlxr     ws, w4, [xt] */
1476     (void)emitter.Emit("\tstlxr\t");
1477     (void)emitter.Emit(
1478         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1479     (void)emitter.Emit(", ");
1480     newValue->Accept(visitor);
1481     (void)emitter.Emit(", [");
1482     temp0->Accept(visitor);
1483     (void)emitter.Emit("]\n");
1484     /* cbnz      ws, label1 */
1485     (void)emitter.Emit("\tcbnz\t");
1486     (void)emitter.Emit(
1487         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1488     (void)emitter.Emit(", ");
1489     label1->Accept(visitor);
1490     (void)emitter.Emit("\n");
1491     /* label2: */
1492     label2->Accept(visitor);
1493     (void)emitter.Emit(":\n");
1494     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1495     /* cset      x0, eq */
1496     (void)emitter.Emit("\tcset\t");
1497     retVal->Accept(visitor);
1498     (void)emitter.Emit(", EQ\n");
1499 #endif
1500 }
1501 
EmitCTlsDescRel(Emitter & emitter,const Insn & insn) const1502 void AArch64AsmEmitter::EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const
1503 {
1504 #ifdef ARK_LITECG_DEBUG
1505     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_rel];
1506     Operand *result = &insn.GetOperand(kInsnFirstOpnd);
1507     Operand *src = &insn.GetOperand(kInsnSecondOpnd);
1508     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1509     auto stImmOpnd = static_cast<StImmOperand *>(symbol);
1510     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[0]);
1511     A64OpndEmitVisitor srcVisitor(emitter, md->opndMD[1]);
1512     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1513     result->Accept(resultVisitor);
1514     (void)emitter.Emit(", ");
1515     src->Accept(srcVisitor);
1516     (void)emitter.Emit(", #:tprel_hi12:").Emit(stImmOpnd->GetName()).Emit(", lsl #12\n");
1517     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1518     result->Accept(resultVisitor);
1519     (void)emitter.Emit(", ");
1520     result->Accept(resultVisitor);
1521     (void)emitter.Emit(", #:tprel_lo12_nc:").Emit(stImmOpnd->GetName()).Emit("\n");
1522 #endif
1523 }
1524 
EmitCTlsDescCall(Emitter & emitter,const Insn & insn) const1525 void AArch64AsmEmitter::EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const
1526 {
1527 #ifdef ARK_LITECG_DEBUG
1528     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_call];
1529     Operand *func = &insn.GetOperand(kInsnFirstOpnd);
1530     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1531     const OpndDesc *prop = md->opndMD[0];
1532     auto *stImmOpnd = static_cast<StImmOperand *>(symbol);
1533     const std::string &symName = stImmOpnd->GetName();
1534     A64OpndEmitVisitor funcVisitor(emitter, prop);
1535     /*  adrp    x0, :tlsdesc:symbol */
1536     (void)emitter.Emit("\t").Emit("adrp\tx0, :tlsdesc:").Emit(symName).Emit("\n");
1537     /*  ldr x1, [x0, #tlsdesc_lo12:symbol] */
1538     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
1539     func->Accept(funcVisitor);
1540     (void)emitter.Emit(", [x0, #:tlsdesc_lo12:").Emit(symName).Emit("]\n");
1541     /*  add x0 ,#tlsdesc_lo12:symbol */
1542     (void)emitter.Emit("\t").Emit("add\tx0, x0, :tlsdesc_lo12:").Emit(symName).Emit("\n");
1543     /* .tlsdesccall <symbolName> */
1544     (void)emitter.Emit("\t").Emit(".tlsdesccall").Emit("\t").Emit(symName).Emit("\n");
1545     /* blr xd */
1546     (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1547     func->Accept(funcVisitor);
1548     (void)emitter.Emit("\n");
1549 #endif
1550 }
1551 
EmitSyncLockTestSet(Emitter & emitter,const Insn & insn) const1552 void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const
1553 {
1554 #ifdef ARK_LITECG_DEBUG
1555     const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1556     auto *result = &insn.GetOperand(kInsnFirstOpnd);
1557     auto *temp = &insn.GetOperand(kInsnSecondOpnd);
1558     auto *addr = &insn.GetOperand(kInsnThirdOpnd);
1559     auto *value = &insn.GetOperand(kInsnFourthOpnd);
1560     auto *label = &insn.GetOperand(kInsnFifthOpnd);
1561     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1562     A64OpndEmitVisitor tempVisitor(emitter, md->opndMD[kInsnSecondOpnd]);
1563     A64OpndEmitVisitor addrVisitor(emitter, md->opndMD[kInsnThirdOpnd]);
1564     A64OpndEmitVisitor valueVisitor(emitter, md->opndMD[kInsnFourthOpnd]);
1565     A64OpndEmitVisitor labelVisitor(emitter, md->opndMD[kInsnFifthOpnd]);
1566     /* label: */
1567     label->Accept(labelVisitor);
1568     (void)emitter.Emit(":\n");
1569     /* ldxr x0, [x2] */
1570     (void)emitter.Emit("\t").Emit("ldxr").Emit("\t");
1571     result->Accept(resultVisitor);
1572     (void)emitter.Emit(", [");
1573     addr->Accept(addrVisitor);
1574     (void)emitter.Emit("]\n");
1575     /* stxr w1, x3, [x2] */
1576     (void)emitter.Emit("\t").Emit("stxr").Emit("\t");
1577     temp->Accept(tempVisitor);
1578     (void)emitter.Emit(", ");
1579     value->Accept(valueVisitor);
1580     (void)emitter.Emit(", [");
1581     addr->Accept(addrVisitor);
1582     (void)emitter.Emit("]\n");
1583     /* cbnz w1, label */
1584     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1585     temp->Accept(tempVisitor);
1586     (void)emitter.Emit(", ");
1587     label->Accept(labelVisitor);
1588     (void)emitter.Emit("\n");
1589     /* dmb ish */
1590     (void)emitter.Emit("\t").Emit("dmb").Emit("\t").Emit("ish").Emit("\n");
1591 #endif
1592 }
1593 
EmitPureCall(Emitter & emitter,const Insn & insn) const1594 void AArch64AsmEmitter::EmitPureCall(Emitter &emitter, const Insn &insn) const
1595 {
1596 #ifdef ARK_LITECG_DEBUG
1597     const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1598     auto *callee = &insn.GetOperand(kInsnFirstOpnd);
1599     A64OpndEmitVisitor calleeVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1600     (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1601     callee->Accept(calleeVisitor);
1602     (void)emitter.Emit("\n");
1603 #endif
1604 }
1605 
EmitCheckThrowPendingException(Emitter & emitter,Insn & insn) const1606 void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const
1607 {
1608 #ifdef ARK_LITECG_DEBUG
1609     /*
1610      * mrs x16, TPIDR_EL0
1611      * ldr x16, [x16, #64]
1612      * ldr x16, [x16, #8]
1613      * cbz x16, .lnoexception
1614      * bl MCC_ThrowPendingException
1615      * .lnoexception:
1616      */
1617     (void)emitter.Emit("\t").Emit("mrs").Emit("\tx16, TPIDR_EL0");
1618     (void)emitter.Emit("\n");
1619     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #64]");
1620     (void)emitter.Emit("\n");
1621     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #8]");
1622     (void)emitter.Emit("\n");
1623     (void)emitter.Emit("\t").Emit("cbz").Emit("\tx16, .lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName());
1624     (void)emitter.Emit("\n");
1625     (void)emitter.Emit("\t").Emit("bl").Emit("\tMCC_ThrowPendingException");
1626     (void)emitter.Emit("\n");
1627     (void)emitter.Emit(".lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName()).Emit(":");
1628     (void)emitter.Emit("\n");
1629 #endif
1630 }
1631 
EmitLazyBindingRoutine(Emitter & emitter,const Insn & insn) const1632 void AArch64AsmEmitter::EmitLazyBindingRoutine(Emitter &emitter, const Insn &insn) const
1633 {
1634 #ifdef ARK_LITECG_DEBUG
1635     /* ldr xzr, [xs] */
1636     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1637 
1638     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1639     const OpndDesc *prop0 = md->opndMD[0];
1640     A64OpndEmitVisitor visitor(emitter, prop0);
1641 
1642     /* emit "ldr  xzr,[xs]" */
1643 #ifdef USE_32BIT_REF
1644     (void)emitter.Emit("\t").Emit("ldr").Emit("\twzr, [");
1645 #else
1646     (void)emitter.Emit("\t").Emit("ldr").Emit("\txzr, [");
1647 #endif /* USE_32BIT_REF */
1648     opnd0->Accept(visitor);
1649     (void)emitter.Emit("]");
1650     (void)emitter.Emit("\t// Lazy binding\n");
1651 #endif
1652 }
1653 
1654 #ifdef ARK_LITECG_DEBUG
1655 struct CfiDescr {
1656     const std::string name;
1657     uint32 opndCount;
1658     /* create 3 OperandType array to store cfi instruction's operand type */
1659     std::array<Operand::OperandType, 3> opndTypes;
1660 };
1661 
1662 static CfiDescr cfiDescrTable[cfi::kOpCfiLast + 1] = {
1663 #define CFI_DEFINE(k, sub, n, o0, o1, o2) {".cfi_" #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1664 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) \
1665     {"." #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1666 #include "cfi.def"
1667 #undef CFI_DEFINE
1668 #undef ARM_DIRECTIVES_DEFINE
1669     {".cfi_undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
1670 #endif
1671 
EmitAArch64CfiInsn(Emitter & emitter,const Insn & insn) const1672 void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) const
1673 {
1674 #ifdef ARK_LITECG_DEBUG
1675     MOperator mOp = insn.GetMachineOpcode();
1676     CHECK_FATAL(mOp <= cfi::kOpCfiLast, "check overflow");
1677     CfiDescr &cfiDescr = cfiDescrTable[mOp];
1678     (void)emitter.Emit("\t").Emit(cfiDescr.name);
1679     for (uint32 i = 0; i < cfiDescr.opndCount; ++i) {
1680         (void)emitter.Emit(" ");
1681         Operand &curOperand = insn.GetOperand(i);
1682         cfi::CFIOpndEmitVisitor cfiOpndEmitVisitor(emitter);
1683         curOperand.Accept(cfiOpndEmitVisitor);
1684         if (i < (cfiDescr.opndCount - 1)) {
1685             (void)emitter.Emit(",");
1686         }
1687     }
1688     (void)emitter.Emit("\n");
1689 #endif
1690 }
1691 
CheckInsnRefField(const Insn & insn,size_t opndIndex) const1692 bool AArch64AsmEmitter::CheckInsnRefField(const Insn &insn, size_t opndIndex) const
1693 {
1694 #ifdef ARK_LITECG_DEBUG
1695     if (insn.IsAccessRefField() && insn.AccessMem()) {
1696         Operand &opnd0 = insn.GetOperand(opndIndex);
1697         if (opnd0.IsRegister()) {
1698             static_cast<RegOperand &>(opnd0).SetRefField(true);
1699             return true;
1700         }
1701     }
1702 #endif
1703     return false;
1704 }
1705 } /* namespace maplebe */
1706