• 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_lazy_tail: {
353             /* No need to emit this pseudo instruction. */
354             return;
355         }
356         case MOP_lazy_ldr_static: {
357             EmitLazyLoadStatic(emitter, insn);
358             return;
359         }
360         case MOP_arrayclass_cache_ldr: {
361             EmitArrayClassCacheLoad(emitter, insn);
362             return;
363         }
364         case MOP_get_and_addI:
365         case MOP_get_and_addL: {
366             EmitGetAndAddInt(emitter, insn);
367             return;
368         }
369         case MOP_get_and_setI:
370         case MOP_get_and_setL: {
371             EmitGetAndSetInt(emitter, insn);
372             return;
373         }
374         case MOP_compare_and_swapI:
375         case MOP_compare_and_swapL: {
376             EmitCompareAndSwapInt(emitter, insn);
377             return;
378         }
379         case MOP_string_indexof: {
380             EmitStringIndexOf(emitter, insn);
381             return;
382         }
383         case MOP_pseudo_none:
384         case MOP_pseduo_tls_release: {
385             return;
386         }
387         case MOP_tls_desc_call: {
388             EmitCTlsDescCall(emitter, insn);
389             return;
390         }
391         case MOP_tls_desc_rel: {
392             EmitCTlsDescRel(emitter, insn);
393             return;
394         }
395         case MOP_sync_lock_test_setI:
396         case MOP_sync_lock_test_setL: {
397             EmitSyncLockTestSet(emitter, insn);
398             return;
399         }
400         case MOP_pure_call: {
401             EmitPureCall(emitter, insn);
402             return;
403         }
404         default:
405             break;
406     }
407 
408     std::string format(md->format);
409     (void)emitter.Emit("\t").Emit(md->name).Emit("\t");
410     size_t opndSize = insn.GetOperandSize();
411     std::vector<int32> seq(opndSize, -1);
412     std::vector<std::string> prefix(opndSize); /* used for print prefix like "*" in icall *rax */
413     uint32 index = 0;
414     uint32 commaNum = 0;
415     for (uint32 i = 0; i < format.length(); ++i) {
416         char c = format[i];
417         if (c >= '0' && c <= '5') {
418             seq[index++] = c - '0';
419             ++commaNum;
420         } else if (c != ',') {
421             prefix[index].push_back(c);
422         }
423     }
424 
425     bool isRefField =
426         (opndSize == 0) ? false : CheckInsnRefField(insn, static_cast<size_t>(static_cast<uint32>(seq[0])));
427     uint32 compositeOpnds = 0;
428     for (uint32 i = 0; i < commaNum; ++i) {
429         if (seq[i] == -1) {
430             continue;
431         }
432         if (prefix[i].length() > 0) {
433             (void)emitter.Emit(prefix[i]);
434         }
435         if (emitter.NeedToDealWithHugeSo() && (mOp == MOP_xbl || mOp == MOP_tail_call_opt_xbl)) {
436             auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
437             emitter.InsertHugeSoTarget(nameOpnd->GetName());
438             (void)emitter.Emit(nameOpnd->GetName() + emitter.HugeSoPostFix());
439             break;
440         }
441         A64OpndEmitVisitor visitor(emitter, md->opndMD[static_cast<uint32>(seq[i])]);
442 
443         insn.GetOperand(static_cast<uint32>(seq[i])).Accept(visitor);
444         if (compositeOpnds == 1) {
445             (void)emitter.Emit("}");
446         }
447         if (compositeOpnds > 0) {
448             --compositeOpnds;
449         }
450         /* reset opnd0 ref-field flag, so following instruction has correct register */
451         if (isRefField && (i == 0)) {
452             static_cast<RegOperand *>(&insn.GetOperand(static_cast<uint32>(seq[0])))->SetRefField(false);
453         }
454         /* Temporary comment the label:.Label.debug.callee */
455         if (i != (commaNum - 1)) {
456             (void)emitter.Emit(", ");
457         }
458         const uint32 commaNumForEmitLazy = 2;
459         if (!CGOptions::IsLazyBinding() || GetCG()->IsLibcore() || (mOp != MOP_wldr && mOp != MOP_xldr) ||
460             commaNum != commaNumForEmitLazy || i != 1 ||
461             !insn.GetOperand(static_cast<uint32>(seq[1])).IsMemoryAccessOperand()) {
462             continue;
463         }
464         /*
465          * Only check the last operand of ldr in lo12 mode.
466          * Check the second operand, if it's [AArch64MemOperand::kAddrModeLo12Li]
467          */
468         auto *memOpnd = static_cast<MemOperand *>(&insn.GetOperand(static_cast<uint32>(seq[1])));
469         if (memOpnd == nullptr || memOpnd->GetAddrMode() != MemOperand::kAddrModeLo12Li) {
470             continue;
471         }
472         const MIRSymbol *sym = memOpnd->GetSymbol();
473         if (sym->IsMuidFuncDefTab() || sym->IsMuidFuncUndefTab() || sym->IsMuidDataDefTab() ||
474             sym->IsMuidDataUndefTab()) {
475             (void)emitter.Emit("\n");
476             EmitLazyBindingRoutine(emitter, insn);
477         }
478     }
479     if (GetCG()->GenerateVerboseCG() || (GetCG()->GenerateVerboseAsm() && insn.IsComment())) {
480         const char *comment = insn.GetComment().c_str();
481         if (comment != nullptr && strlen(comment) > 0) {
482             (void)emitter.Emit("\t\t// ").Emit(comment);
483         }
484     }
485 
486     (void)emitter.Emit("\n");
487 #endif
488 }
489 
490 #ifdef ARK_LITECG_DEBUG
AsmStringOutputRegNum(bool isInt,uint32 regno,uint32 intBase,uint32 fpBase,std::string & strToEmit)491 static void AsmStringOutputRegNum(bool isInt, uint32 regno, uint32 intBase, uint32 fpBase, std::string &strToEmit)
492 {
493     regno_t newRegno;
494     if (isInt) {
495         CHECK_FATAL(regno >= intBase, "value overflow");
496         newRegno = regno - intBase;
497     } else {
498         newRegno = regno - fpBase;
499     }
500     if (newRegno > (kDecimalMax - 1)) {
501         uint32 tenth = newRegno / kDecimalMax;
502         strToEmit += '0' + static_cast<char>(tenth);
503         newRegno -= (kDecimalMax * tenth);
504     }
505     strToEmit += newRegno + '0';
506 }
507 #endif
508 
EmitInlineAsm(Emitter & emitter,const Insn & insn) const509 void AArch64AsmEmitter::EmitInlineAsm(Emitter &emitter, const Insn &insn) const
510 {
511 #ifdef ARK_LITECG_DEBUG
512     (void)emitter.Emit("\t//Inline asm begin\n\t");
513     auto &list1 = static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd));
514     std::vector<RegOperand *> outOpnds;
515     for (auto *regOpnd : list1.GetOperands()) {
516         outOpnds.push_back(regOpnd);
517     }
518     auto &list2 = static_cast<ListOperand &>(insn.GetOperand(kAsmInputListOpnd));
519     std::vector<RegOperand *> inOpnds;
520     for (auto *regOpnd : list2.GetOperands()) {
521         inOpnds.push_back(regOpnd);
522     }
523     auto &list6 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmOutputRegPrefixOpnd));
524     auto &list7 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmInputRegPrefixOpnd));
525     MapleString asmStr = static_cast<StringOperand &>(insn.GetOperand(kAsmStringOpnd)).GetComment();
526     std::string stringToEmit;
527     auto IsMemAccess = [](char c) -> bool { return c == '['; };
528     auto EmitRegister = [&](const char *p, bool isInt, uint32 regNO, bool unDefRegSize) -> void {
529         if (IsMemAccess(p[0])) {
530             stringToEmit += "[x";
531             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
532             stringToEmit += "]";
533         } else {
534             DEBUG_ASSERT((p[0] == 'w' || p[0] == 'x' || p[0] == 's' || p[0] == 'd' || p[0] == 'v'),
535                          "Asm invalid register type");
536             if ((p[0] == 'w' || p[0] == 'x') && unDefRegSize) {
537                 stringToEmit += 'x';
538             } else {
539                 stringToEmit += p[0];
540             }
541             if (!unDefRegSize) {
542                 isInt = (p[0] == 'w' || p[0] == 'x');
543             }
544             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
545         }
546     };
547     for (size_t i = 0; i < asmStr.length(); ++i) {
548         switch (asmStr[i]) {
549             case '$': {
550                 char c = asmStr[++i];
551                 if ((c >= '0') && (c <= '9')) {
552                     auto val = static_cast<uint32>(c - '0');
553                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
554                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
555                     }
556                     if (val < outOpnds.size()) {
557                         const char *prefix = list6.stringList[val]->GetComment().c_str();
558                         RegOperand *opnd = outOpnds[val];
559                         EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
560                     } else {
561                         val -= static_cast<uint32>(outOpnds.size());
562                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
563                         RegOperand *opnd = inOpnds[val];
564                         /* input is a immediate */
565                         const char *prefix = list7.stringList[val]->GetComment().c_str();
566                         if (prefix[0] == 'i') {
567                             stringToEmit += '#';
568                             for (size_t k = 1; k < list7.stringList[val]->GetComment().length(); ++k) {
569                                 stringToEmit += prefix[k];
570                             }
571                         } else {
572                             EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
573                         }
574                     }
575                 } else if (c == '{') {
576                     c = asmStr[++i];
577                     CHECK_FATAL(((c >= '0') && (c <= '9')), "Inline asm : invalid register constraint number");
578                     auto val = static_cast<uint32>(c - '0');
579                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
580                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
581                     }
582                     regno_t regno;
583                     bool isAddr = false;
584                     if (val < outOpnds.size()) {
585                         RegOperand *opnd = outOpnds[val];
586                         regno = opnd->GetRegisterNumber();
587                         isAddr = IsMemAccess(list6.stringList[val]->GetComment().c_str()[0]);
588                     } else {
589                         val -= static_cast<uint32>(outOpnds.size());
590                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
591                         RegOperand *opnd = inOpnds[val];
592                         regno = opnd->GetRegisterNumber();
593                         DEBUG_ASSERT(list7.stringList[val]->GetComment().c_str() != nullptr,
594                             "list7 GetComment.c_str should not be nullptr");
595                         isAddr = IsMemAccess(list7.stringList[val]->GetComment().c_str()[0]);
596                     }
597                     c = asmStr[++i];
598                     CHECK_FATAL(c == ':', "Parsing error in inline asm string during emit");
599                     c = asmStr[++i];
600                     std::string prefix(1, c);
601                     if (c == 'a' || isAddr) {
602                         prefix = "[x";
603                     }
604                     EmitRegister(prefix.c_str(), true, regno, false);
605                     c = asmStr[++i];
606                     CHECK_FATAL(c == '}', "Parsing error in inline asm string during emit");
607                 }
608                 break;
609             }
610             case '\n': {
611                 stringToEmit += "\n\t";
612                 break;
613             }
614             default:
615                 stringToEmit += asmStr[i];
616         }
617     }
618     (void)emitter.Emit(stringToEmit);
619     (void)emitter.Emit("\n\t//Inline asm end\n");
620 #endif
621 }
622 
EmitClinitTail(Emitter & emitter,const Insn & insn) const623 void AArch64AsmEmitter::EmitClinitTail(Emitter &emitter, const Insn &insn) const
624 {
625 #ifdef ARK_LITECG_DEBUG
626     /*
627      * ldr x17, [xs, #112]
628      * ldr wzr, [x17]
629      */
630     const InsnDesc *md = &AArch64CG::kMd[MOP_clinit_tail];
631 
632     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
633 
634     const OpndDesc *prop0 = md->opndMD[0];
635     A64OpndEmitVisitor visitor(emitter, prop0);
636 
637     /* emit "ldr  x17,[xs,#112]" */
638     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx17, [");
639     opnd0->Accept(visitor);
640     (void)emitter.Emit(", #");
641     (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
642     (void)emitter.Emit("]");
643     (void)emitter.Emit("\n");
644 
645     /* emit "ldr  xzr, [x17]" */
646     (void)emitter.Emit("\t").Emit("ldr\txzr, [x17]\n");
647 #endif
648 }
649 
EmitLazyLoad(Emitter & emitter,const Insn & insn) const650 void AArch64AsmEmitter::EmitLazyLoad(Emitter &emitter, const Insn &insn) const
651 {
652 #ifdef ARK_LITECG_DEBUG
653     /*
654      * ldr wd, [xs]  # xd and xs should be differenct register
655      * ldr wd, [xd]
656      */
657     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr];
658 
659     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
660     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
661     const OpndDesc *prop0 = md->opndMD[0];
662     const OpndDesc *prop1 = md->opndMD[1];
663     A64OpndEmitVisitor visitor(emitter, prop0);
664     A64OpndEmitVisitor visitor1(emitter, prop1);
665 
666     /* emit  "ldr wd, [xs]" */
667     (void)emitter.Emit("\t").Emit("ldr\t");
668 #ifdef USE_32BIT_REF
669     opnd0->Accept(visitor);
670 #else
671     opnd0->Accept(visitor1);
672 #endif
673     (void)emitter.Emit(", [");
674     opnd1->Accept(visitor1);
675     (void)emitter.Emit("]\t// lazy load.\n");
676 
677     /* emit "ldr wd, [xd]" */
678     (void)emitter.Emit("\t").Emit("ldr\t");
679     opnd0->Accept(visitor);
680     (void)emitter.Emit(", [");
681     opnd1->Accept(visitor1);
682     (void)emitter.Emit("]\t// lazy load.\n");
683 #endif
684 }
685 
EmitCounter(Emitter & emitter,const Insn & insn) const686 void AArch64AsmEmitter::EmitCounter(Emitter &emitter, const Insn &insn) const
687 {
688 #ifdef ARK_LITECG_DEBUG
689     /*
690      * adrp    x1, __profile_bb_table$$GetBoolean_bytecode+4
691      * ldr     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
692      * add     w17, w17, #1
693      * str     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
694      */
695     const InsnDesc *md = &AArch64CG::kMd[MOP_counter];
696 
697     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
698     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
699     const OpndDesc *prop0 = md->opndMD[kInsnFirstOpnd];
700     A64OpndEmitVisitor visitor(emitter, prop0);
701     StImmOperand *stImmOpnd = static_cast<StImmOperand *>(opnd1);
702     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitCounter");
703     /* emit adrp */
704     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
705     opnd0->Accept(visitor);
706     (void)emitter.Emit(",");
707     (void)emitter.Emit(stImmOpnd->GetName());
708     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
709     (void)emitter.Emit("\n");
710     /* emit ldr */
711     (void)emitter.Emit("\t").Emit("ldr").Emit("\tw17, [");
712     opnd0->Accept(visitor);
713     (void)emitter.Emit(",");
714     (void)emitter.Emit("#");
715     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
716     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
717     (void)emitter.Emit("]");
718     (void)emitter.Emit("\n");
719     /* emit add */
720     (void)emitter.Emit("\t").Emit("add").Emit("\tw17, w17, #1");
721     (void)emitter.Emit("\n");
722     /* emit str */
723     (void)emitter.Emit("\t").Emit("str").Emit("\tw17, [");
724     opnd0->Accept(visitor);
725     (void)emitter.Emit(",");
726     (void)emitter.Emit("#");
727     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
728     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
729     (void)emitter.Emit("]");
730     (void)emitter.Emit("\n");
731 #endif
732 }
733 
EmitAdrpLabel(Emitter & emitter,const Insn & insn) const734 void AArch64AsmEmitter::EmitAdrpLabel(Emitter &emitter, const Insn &insn) const
735 {
736 #ifdef ARK_LITECG_DEBUG
737     /* adrp    xd, label
738      * add     xd, xd, #lo12:label
739      */
740     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_label];
741 
742     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
743     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
744     const OpndDesc *prop0 = md->opndMD[0];
745     A64OpndEmitVisitor visitor(emitter, prop0);
746     auto lidx = static_cast<ImmOperand *>(opnd1)->GetValue();
747 
748     /* adrp    xd, label */
749     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
750     opnd0->Accept(visitor);
751     (void)emitter.Emit(", ");
752     char *idx;
753     CHECK_NULL_FATAL(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction());
754     idx =
755         strdup(std::to_string(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction()->GetPuidx()).c_str());
756     CHECK_FATAL(idx != nullptr, "strdup failed");
757     (void)emitter.Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
758 
759     /* add     xd, xd, #lo12:label */
760     (void)emitter.Emit("\tadd\t");
761     opnd0->Accept(visitor);
762     (void)emitter.Emit(", ");
763     opnd0->Accept(visitor);
764     (void)emitter.Emit(", ");
765     (void)emitter.Emit(":lo12:").Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
766     (void)emitter.Emit("\n");
767     free(idx);
768     idx = nullptr;
769 #endif
770 }
771 
EmitAdrpLdr(Emitter & emitter,const Insn & insn) const772 void AArch64AsmEmitter::EmitAdrpLdr(Emitter &emitter, const Insn &insn) const
773 {
774 #ifdef ARK_LITECG_DEBUG
775     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
776     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
777     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
778     const OpndDesc *prop0 = md->opndMD[0];
779     A64OpndEmitVisitor visitor(emitter, prop0);
780     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
781     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitAdrpLdr");
782 
783     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
784     opnd0->Accept(visitor);
785     (void)emitter.Emit(", ");
786     (void)emitter.Emit(stImmOpnd->GetName());
787     if (stImmOpnd->GetOffset() != 0) {
788         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
789     }
790     (void)emitter.Emit("\n");
791 
792     (void)emitter.Emit("\tldr\t");
793     static_cast<RegOperand *>(opnd0)->SetRefField(true);
794     opnd0->Accept(visitor);
795     static_cast<RegOperand *>(opnd0)->SetRefField(false);
796     (void)emitter.Emit(", ");
797     (void)emitter.Emit("[");
798     opnd0->Accept(visitor);
799     (void)emitter.Emit(",");
800     (void)emitter.Emit("#");
801     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
802     if (stImmOpnd->GetOffset() != 0) {
803         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
804     }
805     (void)emitter.Emit("]\n");
806 #endif
807 }
808 
EmitLazyLoadStatic(Emitter & emitter,const Insn & insn) const809 void AArch64AsmEmitter::EmitLazyLoadStatic(Emitter &emitter, const Insn &insn) const
810 {
811 #ifdef ARK_LITECG_DEBUG
812     /* adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset
813      * ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]
814      * ldr wzr, [xd]
815      */
816     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr_static];
817 
818     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
819     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
820     const OpndDesc *prop0 = md->GetOpndDes(0);
821     A64OpndEmitVisitor visitor(emitter, prop0);
822     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
823     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
824 
825     /* emit "adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset" */
826     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
827     opnd0->Accept(visitor);
828     (void)emitter.Emit(", ");
829     (void)emitter.Emit(stImmOpnd->GetName());
830     if (stImmOpnd->GetOffset() != 0) {
831         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
832     }
833     (void)emitter.Emit("\t// lazy load static.\n");
834 
835     /* emit "ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]" */
836     (void)emitter.Emit("\tldr\t");
837     static_cast<RegOperand *>(opnd0)->SetRefField(true);
838 #ifdef USE_32BIT_REF
839     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
840     opnd0->Emit(emitter, &prop2); /* ldr wd, ... for terminal system */
841 #else
842     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
843 #endif /* USE_32BIT_REF */
844     static_cast<RegOperand *>(opnd0)->SetRefField(false);
845     (void)emitter.Emit(", ");
846     (void)emitter.Emit("[");
847     opnd0->Accept(visitor);
848     (void)emitter.Emit(",");
849     (void)emitter.Emit("#");
850     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
851     if (stImmOpnd->GetOffset() != 0) {
852         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
853     }
854     (void)emitter.Emit("]\t// lazy load static.\n");
855 
856     /* emit "ldr wzr, [xd]" */
857     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
858     opnd0->Accept(visitor);
859     (void)emitter.Emit("]\t// lazy load static.\n");
860 #endif
861 }
862 
EmitArrayClassCacheLoad(Emitter & emitter,const Insn & insn) const863 void AArch64AsmEmitter::EmitArrayClassCacheLoad(Emitter &emitter, const Insn &insn) const
864 {
865 #ifdef ARK_LITECG_DEBUG
866     /* adrp xd, :got:__arrayClassCacheTable$$xxx+offset
867      * ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]
868      * ldr wzr, [xd]
869      */
870     const InsnDesc *md = &AArch64CG::kMd[MOP_arrayclass_cache_ldr];
871     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
872     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
873     const OpndDesc *prop0 = md->GetOpndDes(kInsnFirstOpnd);
874     A64OpndEmitVisitor visitor(emitter, prop0);
875     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
876     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
877 
878     /* emit "adrp xd, :got:__arrayClassCacheTable$$xxx+offset" */
879     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
880     opnd0->Accept(visitor);
881     (void)emitter.Emit(", ");
882     (void)emitter.Emit(stImmOpnd->GetName());
883     if (stImmOpnd->GetOffset() != 0) {
884         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
885     }
886     (void)emitter.Emit("\t// load array class.\n");
887 
888     /* emit "ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]" */
889     (void)emitter.Emit("\tldr\t");
890     static_cast<RegOperand *>(opnd0)->SetRefField(true);
891 #ifdef USE_32BIT_REF
892     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
893     A64OpndEmitVisitor visitor2(emitter, prop2);
894     opnd0->Accept(visitor2); /* ldr wd, ... for terminal system */
895 #else
896     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
897 #endif /* USE_32BIT_REF */
898     static_cast<RegOperand *>(opnd0)->SetRefField(false);
899     (void)emitter.Emit(", ");
900     (void)emitter.Emit("[");
901     opnd0->Accept(visitor);
902     (void)emitter.Emit(",");
903     (void)emitter.Emit("#");
904     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
905     if (stImmOpnd->GetOffset() != 0) {
906         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
907     }
908     (void)emitter.Emit("]\t// load array class.\n");
909 
910     /* emit "ldr wzr, [xd]" */
911     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
912     opnd0->Accept(visitor);
913     (void)emitter.Emit("]\t// check resolve array class.\n");
914 #endif
915 }
916 
917 /*
918  * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label
919  * add    xt, x1, x2
920  * label:
921  * ldaxr  w0, [xt]
922  * add    wt, w0, w3
923  * stlxr  ws, wt, [xt]
924  * cbnz   ws, label
925  */
EmitGetAndAddInt(Emitter & emitter,const Insn & insn) const926 void AArch64AsmEmitter::EmitGetAndAddInt(Emitter &emitter, const Insn &insn) const
927 {
928 #ifdef ARK_LITECG_DEBUG
929     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the oprands number");
930     (void)emitter.Emit("\t//\tstart of Unsafe.getAndAddInt.\n");
931     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
932     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
933     Operand *tempOpnd2 = &insn.GetOperand(kInsnFourthOpnd);
934     Operand *objOpnd = &insn.GetOperand(kInsnFifthOpnd);
935     Operand *offsetOpnd = &insn.GetOperand(kInsnSixthOpnd);
936     Operand *deltaOpnd = &insn.GetOperand(kInsnSeventhOpnd);
937     Operand *labelOpnd = &insn.GetOperand(kInsnEighthOpnd);
938     A64OpndEmitVisitor visitor(emitter, nullptr);
939     /* emit add. */
940     (void)emitter.Emit("\t").Emit("add").Emit("\t");
941     tempOpnd0->Accept(visitor);
942     (void)emitter.Emit(", ");
943     objOpnd->Accept(visitor);
944     (void)emitter.Emit(", ");
945     offsetOpnd->Accept(visitor);
946     (void)emitter.Emit("\n");
947     /* emit label. */
948     labelOpnd->Accept(visitor);
949     (void)emitter.Emit(":\n");
950     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
951     const MOperator mOp = insn.GetMachineOpcode();
952     const InsnDesc *md = &AArch64CG::kMd[mOp];
953     const OpndDesc *retProp = md->opndMD[kInsnFirstOpnd];
954     A64OpndEmitVisitor retVisitor(emitter, retProp);
955     /* emit ldaxr */
956     (void)emitter.Emit("\t").Emit("ldaxr").Emit("\t");
957     retVal->Accept(retVisitor);
958     (void)emitter.Emit(", [");
959     tempOpnd0->Accept(visitor);
960     (void)emitter.Emit("]\n");
961     /* emit add. */
962     (void)emitter.Emit("\t").Emit("add").Emit("\t");
963     tempOpnd1->Accept(retVisitor);
964     (void)emitter.Emit(", ");
965     retVal->Accept(retVisitor);
966     (void)emitter.Emit(", ");
967     deltaOpnd->Accept(retVisitor);
968     (void)emitter.Emit("\n");
969     /* emit stlxr. */
970     (void)emitter.Emit("\t").Emit("stlxr").Emit("\t");
971     tempOpnd2->Accept(visitor);
972     (void)emitter.Emit(", ");
973     tempOpnd1->Accept(retVisitor);
974     (void)emitter.Emit(", [");
975     tempOpnd0->Accept(visitor);
976     (void)emitter.Emit("]\n");
977     /* emit cbnz. */
978     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
979     tempOpnd2->Accept(visitor);
980     (void)emitter.Emit(", ");
981     labelOpnd->Accept(visitor);
982     (void)emitter.Emit("\n");
983     (void)emitter.Emit("\t//\tend of Unsafe.getAndAddInt.\n");
984 #endif
985 }
986 
987 /*
988  * intrinsic_get_set_int w0, xt, ws, x1, x2, w3, label
989  * add    xt, x1, x2
990  * label:
991  * ldaxr  w0, [xt]
992  * stlxr  ws, w3, [xt]
993  * cbnz   ws, label
994  */
EmitGetAndSetInt(Emitter & emitter,const Insn & insn) const995 void AArch64AsmEmitter::EmitGetAndSetInt(Emitter &emitter, const Insn &insn) const
996 {
997 #ifdef ARK_LITECG_DEBUG
998     /* MOP_get_and_setI and MOP_get_and_setL have 7 operands */
999     DEBUG_ASSERT(insn.GetOperandSize() > kInsnSeventhOpnd, "ensure the operands number");
1000     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1001     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1002     Operand *objOpnd = &insn.GetOperand(kInsnFourthOpnd);
1003     Operand *offsetOpnd = &insn.GetOperand(kInsnFifthOpnd);
1004     A64OpndEmitVisitor visitor(emitter, nullptr);
1005     /* add    x1, x1, x2 */
1006     (void)emitter.Emit("\tadd\t");
1007     tempOpnd0->Accept(visitor);
1008     (void)emitter.Emit(", ");
1009     objOpnd->Accept(visitor);
1010     (void)emitter.Emit(", ");
1011     offsetOpnd->Accept(visitor);
1012     (void)emitter.Emit("\n");
1013     Operand *labelOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1014     /* label: */
1015     labelOpnd->Accept(visitor);
1016     (void)emitter.Emit(":\n");
1017     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1018     /* ldaxr  w0, [xt] */
1019     (void)emitter.Emit("\tldaxr\t");
1020     retVal->Accept(visitor);
1021     (void)emitter.Emit(", [");
1022     tempOpnd0->Accept(visitor);
1023     (void)emitter.Emit("]\n");
1024     Operand *newValueOpnd = &insn.GetOperand(kInsnSixthOpnd);
1025     /* stlxr  ws, w3, [xt] */
1026     (void)emitter.Emit("\tstlxr\t");
1027     tempOpnd1->Accept(visitor);
1028     (void)emitter.Emit(", ");
1029     newValueOpnd->Accept(visitor);
1030     (void)emitter.Emit(", [");
1031     tempOpnd0->Accept(visitor);
1032     (void)emitter.Emit("]\n");
1033     /* cbnz   w2, label */
1034     (void)emitter.Emit("\tcbnz\t");
1035     tempOpnd1->Accept(visitor);
1036     (void)emitter.Emit(", ");
1037     labelOpnd->Accept(visitor);
1038     (void)emitter.Emit("\n");
1039 #endif
1040 }
1041 
1042 /*
1043  * intrinsic_string_indexof w0, x1, w2, x3, w4, x5, x6, x7, x8, x9, w10,
1044  *                          Label.FIRST_LOOP, Label.STR2_NEXT, Label.STR1_LOOP,
1045  *                          Label.STR1_NEXT, Label.LAST_WORD, Label.NOMATCH, Label.RET
1046  * cmp       w4, w2
1047  * b.gt      .Label.NOMATCH
1048  * sub       w2, w2, w4
1049  * sub       w4, w4, #8
1050  * mov       w10, w2
1051  * uxtw      x4, w4
1052  * uxtw      x2, w2
1053  * add       x3, x3, x4
1054  * add       x1, x1, x2
1055  * neg       x4, x4
1056  * neg       x2, x2
1057  * ldr       x5, [x3,x4]
1058  * .Label.FIRST_LOOP:
1059  * ldr       x7, [x1,x2]
1060  * cmp       x5, x7
1061  * b.eq      .Label.STR1_LOOP
1062  * .Label.STR2_NEXT:
1063  * adds      x2, x2, #1
1064  * b.le      .Label.FIRST_LOOP
1065  * b         .Label.NOMATCH
1066  * .Label.STR1_LOOP:
1067  * adds      x8, x4, #8
1068  * add       x9, x2, #8
1069  * b.ge      .Label.LAST_WORD
1070  * .Label.STR1_NEXT:
1071  * ldr       x6, [x3,x8]
1072  * ldr       x7, [x1,x9]
1073  * cmp       x6, x7
1074  * b.ne      .Label.STR2_NEXT
1075  * adds      x8, x8, #8
1076  * add       x9, x9, #8
1077  * b.lt      .Label.STR1_NEXT
1078  * .Label.LAST_WORD:
1079  * ldr       x6, [x3]
1080  * sub       x9, x1, x4
1081  * ldr       x7, [x9,x2]
1082  * cmp       x6, x7
1083  * b.ne      .Label.STR2_NEXT
1084  * add       w0, w10, w2
1085  * b         .Label.RET
1086  * .Label.NOMATCH:
1087  * mov       w0, #-1
1088  * .Label.RET:
1089  */
EmitStringIndexOf(Emitter & emitter,const Insn & insn) const1090 void AArch64AsmEmitter::EmitStringIndexOf(Emitter &emitter, const Insn &insn) const
1091 {
1092 #ifdef ARK_LITECG_DEBUG
1093     /* MOP_string_indexof has 18 operands */
1094     DEBUG_ASSERT(insn.GetOperandSize() == 18, "ensure the operands number");
1095     Operand *patternLengthOpnd = &insn.GetOperand(kInsnFifthOpnd);
1096     Operand *srcLengthOpnd = &insn.GetOperand(kInsnThirdOpnd);
1097     const std::string patternLengthReg =
1098         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(patternLengthOpnd)->GetRegisterNumber()];
1099     const std::string srcLengthReg =
1100         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(srcLengthOpnd)->GetRegisterNumber()];
1101     A64OpndEmitVisitor visitor(emitter, nullptr);
1102     /* cmp       w4, w2 */
1103     (void)emitter.Emit("\tcmp\t");
1104     patternLengthOpnd->Accept(visitor);
1105     (void)emitter.Emit(", ");
1106     srcLengthOpnd->Accept(visitor);
1107     (void)emitter.Emit("\n");
1108     /* the 16th operand of MOP_string_indexof is Label.NOMATCH */
1109     Operand *labelNoMatch = &insn.GetOperand(16);
1110     /* b.gt      Label.NOMATCH */
1111     (void)emitter.Emit("\tb.gt\t");
1112     labelNoMatch->Accept(visitor);
1113     (void)emitter.Emit("\n");
1114     /* sub       w2, w2, w4 */
1115     (void)emitter.Emit("\tsub\t");
1116     srcLengthOpnd->Accept(visitor);
1117     (void)emitter.Emit(", ");
1118     srcLengthOpnd->Accept(visitor);
1119     (void)emitter.Emit(", ");
1120     patternLengthOpnd->Accept(visitor);
1121     (void)emitter.Emit("\n");
1122     /* sub       w4, w4, #8 */
1123     (void)emitter.Emit("\tsub\t");
1124     patternLengthOpnd->Accept(visitor);
1125     (void)emitter.Emit(", ");
1126     patternLengthOpnd->Accept(visitor);
1127     (void)emitter.Emit(", #8\n");
1128     /* the 10th operand of MOP_string_indexof is w10 */
1129     Operand *resultTmp = &insn.GetOperand(10);
1130     /* mov       w10, w2 */
1131     (void)emitter.Emit("\tmov\t");
1132     resultTmp->Accept(visitor);
1133     (void)emitter.Emit(", ");
1134     srcLengthOpnd->Accept(visitor);
1135     (void)emitter.Emit("\n");
1136     /* uxtw      x4, w4 */
1137     (void)emitter.Emit("\tuxtw\t").Emit(patternLengthReg);
1138     (void)emitter.Emit(", ");
1139     patternLengthOpnd->Accept(visitor);
1140     (void)emitter.Emit("\n");
1141     /* uxtw      x2, w2 */
1142     (void)emitter.Emit("\tuxtw\t").Emit(srcLengthReg);
1143     (void)emitter.Emit(", ");
1144     srcLengthOpnd->Accept(visitor);
1145     (void)emitter.Emit("\n");
1146     Operand *patternStringBaseOpnd = &insn.GetOperand(kInsnFourthOpnd);
1147     /* add       x3, x3, x4 */
1148     (void)emitter.Emit("\tadd\t");
1149     patternStringBaseOpnd->Accept(visitor);
1150     (void)emitter.Emit(", ");
1151     patternStringBaseOpnd->Accept(visitor);
1152     (void)emitter.Emit(", ").Emit(patternLengthReg);
1153     (void)emitter.Emit("\n");
1154     Operand *srcStringBaseOpnd = &insn.GetOperand(kInsnSecondOpnd);
1155     /* add       x1, x1, x2 */
1156     (void)emitter.Emit("\tadd\t");
1157     srcStringBaseOpnd->Accept(visitor);
1158     (void)emitter.Emit(", ");
1159     srcStringBaseOpnd->Accept(visitor);
1160     (void)emitter.Emit(", ").Emit(srcLengthReg);
1161     (void)emitter.Emit("\n");
1162     /* neg       x4, x4 */
1163     (void)emitter.Emit("\tneg\t").Emit(patternLengthReg);
1164     (void)emitter.Emit(", ").Emit(patternLengthReg);
1165     (void)emitter.Emit("\n");
1166     /* neg       x2, x2 */
1167     (void)emitter.Emit("\tneg\t").Emit(srcLengthReg);
1168     (void)emitter.Emit(", ").Emit(srcLengthReg);
1169     (void)emitter.Emit("\n");
1170     Operand *first = &insn.GetOperand(kInsnSixthOpnd);
1171     /* ldr       x5, [x3,x4] */
1172     (void)emitter.Emit("\tldr\t");
1173     first->Accept(visitor);
1174     (void)emitter.Emit(", [");
1175     patternStringBaseOpnd->Accept(visitor);
1176     (void)emitter.Emit(",").Emit(patternLengthReg);
1177     (void)emitter.Emit("]\n");
1178     /* the 11th operand of MOP_string_indexof is Label.FIRST_LOOP */
1179     Operand *labelFirstLoop = &insn.GetOperand(11);
1180     /* .Label.FIRST_LOOP: */
1181     labelFirstLoop->Accept(visitor);
1182     (void)emitter.Emit(":\n");
1183     /* the 7th operand of MOP_string_indexof is x7 */
1184     Operand *ch2 = &insn.GetOperand(7);
1185     /* ldr       x7, [x1,x2] */
1186     (void)emitter.Emit("\tldr\t");
1187     ch2->Accept(visitor);
1188     (void)emitter.Emit(", [");
1189     srcStringBaseOpnd->Accept(visitor);
1190     (void)emitter.Emit(",").Emit(srcLengthReg);
1191     (void)emitter.Emit("]\n");
1192     /* cmp       x5, x7 */
1193     (void)emitter.Emit("\tcmp\t");
1194     first->Accept(visitor);
1195     (void)emitter.Emit(", ");
1196     ch2->Accept(visitor);
1197     (void)emitter.Emit("\n");
1198     /* the 13th operand of MOP_string_indexof is Label.STR1_LOOP */
1199     Operand *labelStr1Loop = &insn.GetOperand(13);
1200     /* b.eq      .Label.STR1_LOOP */
1201     (void)emitter.Emit("\tb.eq\t");
1202     labelStr1Loop->Accept(visitor);
1203     (void)emitter.Emit("\n");
1204     /* the 12th operand of MOP_string_indexof is Label.STR2_NEXT */
1205     Operand *labelStr2Next = &insn.GetOperand(12);
1206     /* .Label.STR2_NEXT: */
1207     labelStr2Next->Accept(visitor);
1208     (void)emitter.Emit(":\n");
1209     /* adds      x2, x2, #1 */
1210     (void)emitter.Emit("\tadds\t").Emit(srcLengthReg);
1211     (void)emitter.Emit(", ").Emit(srcLengthReg);
1212     (void)emitter.Emit(", #1\n");
1213     /* b.le      .Label.FIRST_LOOP */
1214     (void)emitter.Emit("\tb.le\t");
1215     labelFirstLoop->Accept(visitor);
1216     (void)emitter.Emit("\n");
1217     /* b         .Label.NOMATCH */
1218     (void)emitter.Emit("\tb\t");
1219     labelNoMatch->Accept(visitor);
1220     (void)emitter.Emit("\n");
1221     /* .Label.STR1_LOOP: */
1222     labelStr1Loop->Accept(visitor);
1223     (void)emitter.Emit(":\n");
1224     /* the 8th operand of MOP_string_indexof is x8 */
1225     Operand *tmp1 = &insn.GetOperand(kInsnEighthOpnd);
1226     /* adds      x8, x4, #8 */
1227     (void)emitter.Emit("\tadds\t");
1228     tmp1->Accept(visitor);
1229     (void)emitter.Emit(", ").Emit(patternLengthReg);
1230     (void)emitter.Emit(", #8\n");
1231     /* the 9th operand of MOP_string_indexof is x9 */
1232     Operand *tmp2 = &insn.GetOperand(9);
1233     /* add       x9, x2, #8 */
1234     (void)emitter.Emit("\tadd\t");
1235     tmp2->Accept(visitor);
1236     (void)emitter.Emit(", ").Emit(srcLengthReg);
1237     (void)emitter.Emit(", #8\n");
1238     /* the 15th operand of MOP_string_indexof is Label.LAST_WORD */
1239     Operand *labelLastWord = &insn.GetOperand(15);
1240     /* b.ge      .Label.LAST_WORD */
1241     (void)emitter.Emit("\tb.ge\t");
1242     labelLastWord->Accept(visitor);
1243     (void)emitter.Emit("\n");
1244     /* the 14th operand of MOP_string_indexof is Label.STR1_NEXT */
1245     Operand *labelStr1Next = &insn.GetOperand(14);
1246     /* .Label.STR1_NEXT: */
1247     labelStr1Next->Accept(visitor);
1248     (void)emitter.Emit(":\n");
1249     /* the 6th operand of MOP_string_indexof is x6 */
1250     Operand *ch1 = &insn.GetOperand(6);
1251     /* ldr       x6, [x3,x8] */
1252     (void)emitter.Emit("\tldr\t");
1253     ch1->Accept(visitor);
1254     (void)emitter.Emit(", [");
1255     patternStringBaseOpnd->Accept(visitor);
1256     (void)emitter.Emit(",");
1257     tmp1->Accept(visitor);
1258     (void)emitter.Emit("]\n");
1259     /* ldr       x7, [x1,x9] */
1260     (void)emitter.Emit("\tldr\t");
1261     ch2->Accept(visitor);
1262     (void)emitter.Emit(", [");
1263     srcStringBaseOpnd->Accept(visitor);
1264     (void)emitter.Emit(",");
1265     tmp2->Accept(visitor);
1266     (void)emitter.Emit("]\n");
1267     /* cmp       x6, x7 */
1268     (void)emitter.Emit("\tcmp\t");
1269     ch1->Accept(visitor);
1270     (void)emitter.Emit(", ");
1271     ch2->Accept(visitor);
1272     (void)emitter.Emit("\n");
1273     /* b.ne      .Label.STR2_NEXT */
1274     (void)emitter.Emit("\tb.ne\t");
1275     labelStr2Next->Accept(visitor);
1276     (void)emitter.Emit("\n");
1277     /* adds      x8, x8, #8 */
1278     (void)emitter.Emit("\tadds\t");
1279     tmp1->Accept(visitor);
1280     (void)emitter.Emit(", ");
1281     tmp1->Accept(visitor);
1282     (void)emitter.Emit(", #8\n");
1283     /* add       x9, x9, #8 */
1284     (void)emitter.Emit("\tadd\t");
1285     tmp2->Accept(visitor);
1286     (void)emitter.Emit(", ");
1287     tmp2->Accept(visitor);
1288     (void)emitter.Emit(", #8\n");
1289     /* b.lt      .Label.STR1_NEXT */
1290     (void)emitter.Emit("\tb.lt\t");
1291     labelStr1Next->Accept(visitor);
1292     (void)emitter.Emit("\n");
1293     /* .Label.LAST_WORD: */
1294     labelLastWord->Accept(visitor);
1295     (void)emitter.Emit(":\n");
1296     /* ldr       x6, [x3] */
1297     (void)emitter.Emit("\tldr\t");
1298     ch1->Accept(visitor);
1299     (void)emitter.Emit(", [");
1300     patternStringBaseOpnd->Accept(visitor);
1301     (void)emitter.Emit("]\n");
1302     /* sub       x9, x1, x4 */
1303     (void)emitter.Emit("\tsub\t");
1304     tmp2->Accept(visitor);
1305     (void)emitter.Emit(", ");
1306     srcStringBaseOpnd->Accept(visitor);
1307     (void)emitter.Emit(", ").Emit(patternLengthReg);
1308     (void)emitter.Emit("\n");
1309     /* ldr       x7, [x9,x2] */
1310     (void)emitter.Emit("\tldr\t");
1311     ch2->Accept(visitor);
1312     (void)emitter.Emit(", [");
1313     tmp2->Accept(visitor);
1314     (void)emitter.Emit(", ").Emit(srcLengthReg);
1315     (void)emitter.Emit("]\n");
1316     /* cmp       x6, x7 */
1317     (void)emitter.Emit("\tcmp\t");
1318     ch1->Accept(visitor);
1319     (void)emitter.Emit(", ");
1320     ch2->Accept(visitor);
1321     (void)emitter.Emit("\n");
1322     /* b.ne      .Label.STR2_NEXT */
1323     (void)emitter.Emit("\tb.ne\t");
1324     labelStr2Next->Accept(visitor);
1325     (void)emitter.Emit("\n");
1326     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1327     /* add       w0, w10, w2 */
1328     (void)emitter.Emit("\tadd\t");
1329     retVal->Accept(visitor);
1330     (void)emitter.Emit(", ");
1331     resultTmp->Accept(visitor);
1332     (void)emitter.Emit(", ");
1333     srcLengthOpnd->Accept(visitor);
1334     (void)emitter.Emit("\n");
1335     /* the 17th operand of MOP_string_indexof Label.ret */
1336     Operand *labelRet = &insn.GetOperand(17);
1337     /* b         .Label.ret */
1338     (void)emitter.Emit("\tb\t");
1339     labelRet->Accept(visitor);
1340     (void)emitter.Emit("\n");
1341     /* .Label.NOMATCH: */
1342     labelNoMatch->Accept(visitor);
1343     (void)emitter.Emit(":\n");
1344     /* mov       w0, #-1 */
1345     (void)emitter.Emit("\tmov\t");
1346     retVal->Accept(visitor);
1347     (void)emitter.Emit(", #-1\n");
1348     /* .Label.ret: */
1349     labelRet->Accept(visitor);
1350     (void)emitter.Emit(":\n");
1351 #endif
1352 }
1353 
1354 /*
1355  * intrinsic_compare_swap_int x0, xt, xs, x1, x2, w3, w4, lable1, label2
1356  * add       xt, x1, x2
1357  * label1:
1358  * ldaxr     ws, [xt]
1359  * cmp       ws, w3
1360  * b.ne      label2
1361  * stlxr     ws, w4, [xt]
1362  * cbnz      ws, label1
1363  * label2:
1364  * cset      x0, eq
1365  */
EmitCompareAndSwapInt(Emitter & emitter,const Insn & insn) const1366 void AArch64AsmEmitter::EmitCompareAndSwapInt(Emitter &emitter, const Insn &insn) const
1367 {
1368 #ifdef ARK_LITECG_DEBUG
1369     /* MOP_compare_and_swapI and MOP_compare_and_swapL have 8 operands */
1370     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the operands number");
1371     const MOperator mOp = insn.GetMachineOpcode();
1372     const InsnDesc *md = &AArch64CG::kMd[mOp];
1373     Operand *temp0 = &insn.GetOperand(kInsnSecondOpnd);
1374     Operand *temp1 = &insn.GetOperand(kInsnThirdOpnd);
1375     Operand *obj = &insn.GetOperand(kInsnFourthOpnd);
1376     Operand *offset = &insn.GetOperand(kInsnFifthOpnd);
1377     A64OpndEmitVisitor visitor(emitter, nullptr);
1378     /* add       xt, x1, x2 */
1379     (void)emitter.Emit("\tadd\t");
1380     temp0->Accept(visitor);
1381     (void)emitter.Emit(", ");
1382     obj->Accept(visitor);
1383     (void)emitter.Emit(", ");
1384     offset->Accept(visitor);
1385     (void)emitter.Emit("\n");
1386     Operand *label1 = &insn.GetOperand(kInsnEighthOpnd);
1387     /* label1: */
1388     label1->Accept(visitor);
1389     (void)emitter.Emit(":\n");
1390     /* ldaxr     ws, [xt] */
1391     (void)emitter.Emit("\tldaxr\t");
1392     temp1->Accept(visitor);
1393     (void)emitter.Emit(", [");
1394     temp0->Accept(visitor);
1395     (void)emitter.Emit("]\n");
1396     Operand *expectedValue = &insn.GetOperand(kInsnSixthOpnd);
1397     const OpndDesc *expectedValueProp = md->opndMD[kInsnSixthOpnd];
1398     /* cmp       ws, w3 */
1399     (void)emitter.Emit("\tcmp\t");
1400     temp1->Accept(visitor);
1401     (void)emitter.Emit(", ");
1402     A64OpndEmitVisitor visitorExpect(emitter, expectedValueProp);
1403     expectedValue->Accept(visitorExpect);
1404     (void)emitter.Emit("\n");
1405     constexpr uint32 kInsnNinethOpnd = 8;
1406     Operand *label2 = &insn.GetOperand(kInsnNinethOpnd);
1407     /* b.ne      label2 */
1408     (void)emitter.Emit("\tbne\t");
1409     label2->Accept(visitor);
1410     (void)emitter.Emit("\n");
1411     Operand *newValue = &insn.GetOperand(kInsnSeventhOpnd);
1412     /* stlxr     ws, w4, [xt] */
1413     (void)emitter.Emit("\tstlxr\t");
1414     (void)emitter.Emit(
1415         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1416     (void)emitter.Emit(", ");
1417     newValue->Accept(visitor);
1418     (void)emitter.Emit(", [");
1419     temp0->Accept(visitor);
1420     (void)emitter.Emit("]\n");
1421     /* cbnz      ws, label1 */
1422     (void)emitter.Emit("\tcbnz\t");
1423     (void)emitter.Emit(
1424         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1425     (void)emitter.Emit(", ");
1426     label1->Accept(visitor);
1427     (void)emitter.Emit("\n");
1428     /* label2: */
1429     label2->Accept(visitor);
1430     (void)emitter.Emit(":\n");
1431     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1432     /* cset      x0, eq */
1433     (void)emitter.Emit("\tcset\t");
1434     retVal->Accept(visitor);
1435     (void)emitter.Emit(", EQ\n");
1436 #endif
1437 }
1438 
EmitCTlsDescRel(Emitter & emitter,const Insn & insn) const1439 void AArch64AsmEmitter::EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const
1440 {
1441 #ifdef ARK_LITECG_DEBUG
1442     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_rel];
1443     Operand *result = &insn.GetOperand(kInsnFirstOpnd);
1444     Operand *src = &insn.GetOperand(kInsnSecondOpnd);
1445     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1446     auto stImmOpnd = static_cast<StImmOperand *>(symbol);
1447     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[0]);
1448     A64OpndEmitVisitor srcVisitor(emitter, md->opndMD[1]);
1449     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1450     result->Accept(resultVisitor);
1451     (void)emitter.Emit(", ");
1452     src->Accept(srcVisitor);
1453     (void)emitter.Emit(", #:tprel_hi12:").Emit(stImmOpnd->GetName()).Emit(", lsl #12\n");
1454     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1455     result->Accept(resultVisitor);
1456     (void)emitter.Emit(", ");
1457     result->Accept(resultVisitor);
1458     (void)emitter.Emit(", #:tprel_lo12_nc:").Emit(stImmOpnd->GetName()).Emit("\n");
1459 #endif
1460 }
1461 
EmitCTlsDescCall(Emitter & emitter,const Insn & insn) const1462 void AArch64AsmEmitter::EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const
1463 {
1464 #ifdef ARK_LITECG_DEBUG
1465     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_call];
1466     Operand *func = &insn.GetOperand(kInsnFirstOpnd);
1467     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1468     const OpndDesc *prop = md->opndMD[0];
1469     auto *stImmOpnd = static_cast<StImmOperand *>(symbol);
1470     const std::string &symName = stImmOpnd->GetName();
1471     A64OpndEmitVisitor funcVisitor(emitter, prop);
1472     /*  adrp    x0, :tlsdesc:symbol */
1473     (void)emitter.Emit("\t").Emit("adrp\tx0, :tlsdesc:").Emit(symName).Emit("\n");
1474     /*  ldr x1, [x0, #tlsdesc_lo12:symbol] */
1475     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
1476     func->Accept(funcVisitor);
1477     (void)emitter.Emit(", [x0, #:tlsdesc_lo12:").Emit(symName).Emit("]\n");
1478     /*  add x0 ,#tlsdesc_lo12:symbol */
1479     (void)emitter.Emit("\t").Emit("add\tx0, x0, :tlsdesc_lo12:").Emit(symName).Emit("\n");
1480     /* .tlsdesccall <symbolName> */
1481     (void)emitter.Emit("\t").Emit(".tlsdesccall").Emit("\t").Emit(symName).Emit("\n");
1482     /* blr xd */
1483     (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1484     func->Accept(funcVisitor);
1485     (void)emitter.Emit("\n");
1486 #endif
1487 }
1488 
EmitSyncLockTestSet(Emitter & emitter,const Insn & insn) const1489 void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const
1490 {
1491 #ifdef ARK_LITECG_DEBUG
1492     const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1493     auto *result = &insn.GetOperand(kInsnFirstOpnd);
1494     auto *temp = &insn.GetOperand(kInsnSecondOpnd);
1495     auto *addr = &insn.GetOperand(kInsnThirdOpnd);
1496     auto *value = &insn.GetOperand(kInsnFourthOpnd);
1497     auto *label = &insn.GetOperand(kInsnFifthOpnd);
1498     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1499     A64OpndEmitVisitor tempVisitor(emitter, md->opndMD[kInsnSecondOpnd]);
1500     A64OpndEmitVisitor addrVisitor(emitter, md->opndMD[kInsnThirdOpnd]);
1501     A64OpndEmitVisitor valueVisitor(emitter, md->opndMD[kInsnFourthOpnd]);
1502     A64OpndEmitVisitor labelVisitor(emitter, md->opndMD[kInsnFifthOpnd]);
1503     /* label: */
1504     label->Accept(labelVisitor);
1505     (void)emitter.Emit(":\n");
1506     /* ldxr x0, [x2] */
1507     (void)emitter.Emit("\t").Emit("ldxr").Emit("\t");
1508     result->Accept(resultVisitor);
1509     (void)emitter.Emit(", [");
1510     addr->Accept(addrVisitor);
1511     (void)emitter.Emit("]\n");
1512     /* stxr w1, x3, [x2] */
1513     (void)emitter.Emit("\t").Emit("stxr").Emit("\t");
1514     temp->Accept(tempVisitor);
1515     (void)emitter.Emit(", ");
1516     value->Accept(valueVisitor);
1517     (void)emitter.Emit(", [");
1518     addr->Accept(addrVisitor);
1519     (void)emitter.Emit("]\n");
1520     /* cbnz w1, label */
1521     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1522     temp->Accept(tempVisitor);
1523     (void)emitter.Emit(", ");
1524     label->Accept(labelVisitor);
1525     (void)emitter.Emit("\n");
1526     /* dmb ish */
1527     (void)emitter.Emit("\t").Emit("dmb").Emit("\t").Emit("ish").Emit("\n");
1528 #endif
1529 }
1530 
EmitPureCall(Emitter & emitter,const Insn & insn) const1531 void AArch64AsmEmitter::EmitPureCall(Emitter &emitter, const Insn &insn) const
1532 {
1533 #ifdef ARK_LITECG_DEBUG
1534     const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1535     auto *callee = &insn.GetOperand(kInsnFirstOpnd);
1536     A64OpndEmitVisitor calleeVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1537     (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1538     callee->Accept(calleeVisitor);
1539     (void)emitter.Emit("\n");
1540 #endif
1541 }
1542 
EmitCheckThrowPendingException(Emitter & emitter,Insn & insn) const1543 void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const
1544 {
1545 #ifdef ARK_LITECG_DEBUG
1546     /*
1547      * mrs x16, TPIDR_EL0
1548      * ldr x16, [x16, #64]
1549      * ldr x16, [x16, #8]
1550      * cbz x16, .lnoexception
1551      * bl MCC_ThrowPendingException
1552      * .lnoexception:
1553      */
1554     (void)emitter.Emit("\t").Emit("mrs").Emit("\tx16, TPIDR_EL0");
1555     (void)emitter.Emit("\n");
1556     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #64]");
1557     (void)emitter.Emit("\n");
1558     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #8]");
1559     (void)emitter.Emit("\n");
1560     (void)emitter.Emit("\t").Emit("cbz").Emit("\tx16, .lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName());
1561     (void)emitter.Emit("\n");
1562     (void)emitter.Emit("\t").Emit("bl").Emit("\tMCC_ThrowPendingException");
1563     (void)emitter.Emit("\n");
1564     (void)emitter.Emit(".lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName()).Emit(":");
1565     (void)emitter.Emit("\n");
1566 #endif
1567 }
1568 
EmitLazyBindingRoutine(Emitter & emitter,const Insn & insn) const1569 void AArch64AsmEmitter::EmitLazyBindingRoutine(Emitter &emitter, const Insn &insn) const
1570 {
1571 #ifdef ARK_LITECG_DEBUG
1572     /* ldr xzr, [xs] */
1573     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1574 
1575     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1576     const OpndDesc *prop0 = md->opndMD[0];
1577     A64OpndEmitVisitor visitor(emitter, prop0);
1578 
1579     /* emit "ldr  xzr,[xs]" */
1580 #ifdef USE_32BIT_REF
1581     (void)emitter.Emit("\t").Emit("ldr").Emit("\twzr, [");
1582 #else
1583     (void)emitter.Emit("\t").Emit("ldr").Emit("\txzr, [");
1584 #endif /* USE_32BIT_REF */
1585     opnd0->Accept(visitor);
1586     (void)emitter.Emit("]");
1587     (void)emitter.Emit("\t// Lazy binding\n");
1588 #endif
1589 }
1590 
1591 #ifdef ARK_LITECG_DEBUG
1592 struct CfiDescr {
1593     const std::string name;
1594     uint32 opndCount;
1595     /* create 3 OperandType array to store cfi instruction's operand type */
1596     std::array<Operand::OperandType, 3> opndTypes;
1597 };
1598 
1599 static CfiDescr cfiDescrTable[cfi::kOpCfiLast + 1] = {
1600 #define CFI_DEFINE(k, sub, n, o0, o1, o2) {".cfi_" #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1601 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) \
1602     {"." #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
1603 #include "cfi.def"
1604 #undef CFI_DEFINE
1605 #undef ARM_DIRECTIVES_DEFINE
1606     {".cfi_undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
1607 #endif
1608 
EmitAArch64CfiInsn(Emitter & emitter,const Insn & insn) const1609 void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) const
1610 {
1611 #ifdef ARK_LITECG_DEBUG
1612     MOperator mOp = insn.GetMachineOpcode();
1613     CHECK_FATAL(mOp <= cfi::kOpCfiLast, "check overflow");
1614     CfiDescr &cfiDescr = cfiDescrTable[mOp];
1615     (void)emitter.Emit("\t").Emit(cfiDescr.name);
1616     for (uint32 i = 0; i < cfiDescr.opndCount; ++i) {
1617         (void)emitter.Emit(" ");
1618         Operand &curOperand = insn.GetOperand(i);
1619         cfi::CFIOpndEmitVisitor cfiOpndEmitVisitor(emitter);
1620         curOperand.Accept(cfiOpndEmitVisitor);
1621         if (i < (cfiDescr.opndCount - 1)) {
1622             (void)emitter.Emit(",");
1623         }
1624     }
1625     (void)emitter.Emit("\n");
1626 #endif
1627 }
1628 
CheckInsnRefField(const Insn & insn,size_t opndIndex) const1629 bool AArch64AsmEmitter::CheckInsnRefField(const Insn &insn, size_t opndIndex) const
1630 {
1631 #ifdef ARK_LITECG_DEBUG
1632     if (insn.IsAccessRefField() && insn.AccessMem()) {
1633         Operand &opnd0 = insn.GetOperand(opndIndex);
1634         if (opnd0.IsRegister()) {
1635             static_cast<RegOperand &>(opnd0).SetRefField(true);
1636             return true;
1637         }
1638     }
1639 #endif
1640     return false;
1641 }
1642 } /* namespace maplebe */
1643