• 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 <sys/stat.h>
18 #include "aarch64_cgfunc.h"
19 #include "aarch64_cg.h"
20 #include "metadata_layout.h"
21 #include "cfi.h"
22 #include "dbg.h"
23 #include "aarch64_obj_emitter.h"
24 
25 namespace {
26 using namespace maple;
27 // map func name to <filename, insnCount> pair
28 using Func2CodeInsnMap = std::unordered_map<std::string, std::pair<std::string, uint32>>;
29 Func2CodeInsnMap func2CodeInsnMap {
30     {"Ljava_2Flang_2FString_3B_7ChashCode_7C_28_29I", {"maple/mrt/codetricks/arch/arm64/hashCode.s", 29}},
31     {"Ljava_2Flang_2FString_3B_7Cequals_7C_28Ljava_2Flang_2FObject_3B_29Z",
32      {"maple/mrt/codetricks/arch/arm64/stringEquals.s", 50}}};
33 constexpr uint32 kQuadInsnCount = 2;
34 
GetMethodLabel(const std::string & methodName,std::string & methodLabel)35 void GetMethodLabel(const std::string &methodName, std::string &methodLabel)
36 {
37     methodLabel = ".Lmethod_desc." + methodName;
38 }
39 }  // namespace
40 
41 namespace maplebe {
42 using namespace maple;
43 
EmitRefToMethodDesc(FuncEmitInfo & funcEmitInfo,Emitter & emitter)44 void AArch64AsmEmitter::EmitRefToMethodDesc(FuncEmitInfo &funcEmitInfo, Emitter &emitter)
45 {
46     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
47     if (!cgFunc.GetFunction().IsJava()) {
48         return;
49     }
50     std::string methodDescLabel;
51     GetMethodLabel(cgFunc.GetFunction().GetName(), methodDescLabel);
52     (void)emitter.Emit("\t.word " + methodDescLabel + "-.\n");
53     emitter.IncreaseJavaInsnCount();
54 }
55 
EmitRefToMethodInfo(FuncEmitInfo & funcEmitInfo,Emitter & emitter)56 void AArch64AsmEmitter::EmitRefToMethodInfo(FuncEmitInfo &funcEmitInfo, Emitter &emitter)
57 {
58     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
59     if (cgFunc.GetFunction().GetModule()->IsJavaModule()) {
60         std::string labelName = ".Label.name." + cgFunc.GetFunction().GetName();
61         (void)emitter.Emit("\t.word " + labelName + " - .\n");
62     }
63 }
64 
65 /*
66  * emit java method description which contains address and size of local reference area
67  * as well as method metadata.
68  */
EmitMethodDesc(FuncEmitInfo & funcEmitInfo,Emitter & emitter)69 void AArch64AsmEmitter::EmitMethodDesc(FuncEmitInfo &funcEmitInfo, Emitter &emitter)
70 {
71     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
72     if (!cgFunc.GetFunction().IsJava()) {
73         return;
74     }
75     (void)emitter.Emit("\t.section\t.rodata\n");
76     (void)emitter.Emit("\t.align\t2\n");
77     std::string methodInfoLabel;
78     GetMethodLabel(cgFunc.GetFunction().GetName(), methodInfoLabel);
79     (void)emitter.Emit(methodInfoLabel + ":\n");
80     EmitRefToMethodInfo(funcEmitInfo, emitter);
81     /* local reference area */
82     AArch64MemLayout *memLayout = static_cast<AArch64MemLayout *>(cgFunc.GetMemlayout());
83     int32 refOffset = memLayout->GetRefLocBaseLoc();
84     uint32 refNum = memLayout->GetSizeOfRefLocals() / kOffsetAlign;
85     /* for ea usage */
86     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
87     IntrinsiccallNode *cleanEANode = aarchCGFunc.GetCleanEANode();
88     if (cleanEANode != nullptr) {
89         refNum += static_cast<uint32>(cleanEANode->NumOpnds());
90         refOffset -= static_cast<int32>(cleanEANode->NumOpnds() * kIntregBytelen);
91     }
92     (void)emitter.Emit("\t.short ").Emit(refOffset).Emit("\n");
93     (void)emitter.Emit("\t.short ").Emit(refNum).Emit("\n");
94 }
95 
96 /* the fast_exception_handling lsda */
EmitFastLSDA(FuncEmitInfo & funcEmitInfo)97 void AArch64AsmEmitter::EmitFastLSDA(FuncEmitInfo &funcEmitInfo)
98 {
99     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
100     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
101     CG *currCG = cgFunc.GetCG();
102 
103     Emitter *emitter = currCG->GetEmitter();
104     PUIdx pIdx = currCG->GetMIRModule()->CurFunction()->GetPuidx();
105     const std::string &idx = strdup(std::to_string(pIdx).c_str());
106     /*
107      * .word 0xFFFFFFFF
108      * .word .Label.LTest_3B_7C_3Cinit_3E_7C_28_29V3-func_start_label
109      */
110     (void)emitter->Emit("\t.word 0xFFFFFFFF\n");
111     (void)emitter->Emit("\t.word .L." + idx + "__");
112     if (aarchCGFunc.NeedCleanup()) {
113         emitter->Emit(cgFunc.GetCleanupLabel()->GetLabelIdx());
114     } else {
115         DEBUG_ASSERT(!cgFunc.GetExitBBsVec().empty(), "exitbbsvec is empty in AArch64AsmEmitter::EmitFastLSDA");
116         emitter->Emit(cgFunc.GetExitBB(0)->GetLabIdx());
117     }
118     emitter->Emit("-.L." + idx + "__").Emit(cgFunc.GetStartLabel()->GetLabelIdx()).Emit("\n");
119     emitter->IncreaseJavaInsnCount();
120 }
121 
122 /* the normal gcc_except_table */
EmitFullLSDA(FuncEmitInfo & funcEmitInfo)123 void AArch64AsmEmitter::EmitFullLSDA(FuncEmitInfo &funcEmitInfo)
124 {
125     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
126     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
127     CG *currCG = cgFunc.GetCG();
128     EHFunc *ehFunc = cgFunc.GetEHFunc();
129     Emitter *emitter = currCG->GetEmitter();
130     /* emit header */
131     emitter->Emit("\t.align 3\n");
132     emitter->Emit("\t.section .gcc_except_table,\"a\",@progbits\n");
133     emitter->Emit("\t.align 3\n");
134     /* emit LSDA header */
135     LSDAHeader *lsdaHeader = ehFunc->GetLSDAHeader();
136     emitter->EmitStmtLabel(lsdaHeader->GetLSDALabel()->GetLabelIdx());
137     emitter->Emit("\t.byte ").Emit(lsdaHeader->GetLPStartEncoding()).Emit("\n");
138     emitter->Emit("\t.byte ").Emit(lsdaHeader->GetTTypeEncoding()).Emit("\n");
139     emitter->Emit("\t.uleb128 ");
140     emitter->EmitLabelPair(lsdaHeader->GetTTypeOffset());
141     emitter->EmitStmtLabel(lsdaHeader->GetTTypeOffset().GetStartOffset()->GetLabelIdx());
142     /* emit call site table */
143     emitter->Emit("\t.byte ").Emit(lsdaHeader->GetCallSiteEncoding()).Emit("\n");
144     /* callsite table size */
145     emitter->Emit("\t.uleb128 ");
146     emitter->EmitLabelPair(ehFunc->GetLSDACallSiteTable()->GetCSTable());
147     /* callsite start */
148     emitter->EmitStmtLabel(ehFunc->GetLSDACallSiteTable()->GetCSTable().GetStartOffset()->GetLabelIdx());
149     ehFunc->GetLSDACallSiteTable()->SortCallSiteTable([&aarchCGFunc](const LSDACallSite *a, const LSDACallSite *b) {
150         CHECK_FATAL(a != nullptr, "nullptr check");
151         CHECK_FATAL(b != nullptr, "nullptr check");
152         LabelIDOrder id1 = aarchCGFunc.GetLabelOperand(a->csStart.GetEndOffset()->GetLabelIdx())->GetLabelOrder();
153         LabelIDOrder id2 = aarchCGFunc.GetLabelOperand(b->csStart.GetEndOffset()->GetLabelIdx())->GetLabelOrder();
154         /* id1 and id2 should not be default value -1u */
155         CHECK_FATAL(id1 != 0xFFFFFFFF, "illegal label order assigned");
156         CHECK_FATAL(id2 != 0xFFFFFFFF, "illegal label order assigned");
157         return id1 < id2;
158     });
159     const MapleVector<LSDACallSite *> &callSiteTable = ehFunc->GetLSDACallSiteTable()->GetCallSiteTable();
160     for (size_t i = 0; i < callSiteTable.size(); ++i) {
161         LSDACallSite *lsdaCallSite = callSiteTable[i];
162         emitter->Emit("\t.uleb128 ");
163         emitter->EmitLabelPair(lsdaCallSite->csStart);
164 
165         emitter->Emit("\t.uleb128 ");
166         emitter->EmitLabelPair(lsdaCallSite->csLength);
167 
168         if (lsdaCallSite->csLandingPad.GetStartOffset()) {
169             emitter->Emit("\t.uleb128 ");
170             emitter->EmitLabelPair(lsdaCallSite->csLandingPad);
171         } else {
172             DEBUG_ASSERT(lsdaCallSite->csAction == 0, "csAction error!");
173             emitter->Emit("\t.uleb128 ");
174             if (aarchCGFunc.NeedCleanup()) {
175                 /* if landing pad is 0, we emit this call site as cleanup code */
176                 LabelPair cleaupCode;
177                 cleaupCode.SetStartOffset(cgFunc.GetStartLabel());
178                 cleaupCode.SetEndOffset(cgFunc.GetCleanupLabel());
179                 emitter->EmitLabelPair(cleaupCode);
180             } else if (cgFunc.GetFunction().IsJava()) {
181                 DEBUG_ASSERT(!cgFunc.GetExitBBsVec().empty(), "exitbbsvec is empty in AArch64Emitter::EmitFullLSDA");
182                 PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
183                 const std::string &idx = strdup(std::to_string(pIdx).c_str());
184                 (void)emitter->Emit(".L." + idx).Emit("__").Emit(cgFunc.GetExitBB(0)->GetLabIdx());
185                 (void)emitter->Emit(" - .L." + idx).Emit("__").Emit(cgFunc.GetStartLabel()->GetLabelIdx()).Emit("\n");
186             } else {
187                 emitter->Emit("0\n");
188             }
189         }
190         emitter->Emit("\t.uleb128 ").Emit(lsdaCallSite->csAction).Emit("\n");
191     }
192 
193     /*
194      * quick hack: insert a call site entry for the whole function body.
195      * this will hand in any pending (uncaught) exception to its caller. Note that
196      * __gxx_personality_v0 in libstdc++ is coded so that if exception table exists,
197      * the call site table must have an entry for any possibly raised exception,
198      * otherwise __cxa_call_terminate will be invoked immediately, thus the caller
199      * does not get the chance to take charge.
200      */
201     if (aarchCGFunc.NeedCleanup() || cgFunc.GetFunction().IsJava()) {
202         /* call site for clean-up */
203         LabelPair funcStart;
204         funcStart.SetStartOffset(cgFunc.GetStartLabel());
205         funcStart.SetEndOffset(cgFunc.GetStartLabel());
206         emitter->Emit("\t.uleb128 ");
207         emitter->EmitLabelPair(funcStart);
208         LabelPair funcLength;
209         funcLength.SetStartOffset(cgFunc.GetStartLabel());
210         funcLength.SetEndOffset(cgFunc.GetCleanupLabel());
211         emitter->Emit("\t.uleb128 ");
212         emitter->EmitLabelPair(funcLength);
213         LabelPair cleaupCode;
214         cleaupCode.SetStartOffset(cgFunc.GetStartLabel());
215         cleaupCode.SetEndOffset(cgFunc.GetCleanupLabel());
216         emitter->Emit("\t.uleb128 ");
217         if (aarchCGFunc.NeedCleanup()) {
218             emitter->EmitLabelPair(cleaupCode);
219         } else {
220             DEBUG_ASSERT(!cgFunc.GetExitBBsVec().empty(), "exitbbsvec is empty in AArch64AsmEmitter::EmitFullLSDA");
221             PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
222             const std::string &idx = strdup(std::to_string(pIdx).c_str());
223             (void)emitter->Emit(".L." + idx).Emit("__").Emit(cgFunc.GetExitBB(0)->GetLabIdx());
224             (void)emitter->Emit(" - .L." + idx).Emit("__").Emit(cgFunc.GetStartLabel()->GetLabelIdx()).Emit("\n");
225         }
226         emitter->Emit("\t.uleb128 0\n");
227         if (!cgFunc.GetFunction().IsJava()) {
228             /* call site for stack unwind */
229             LabelPair unwindStart;
230             unwindStart.SetStartOffset(cgFunc.GetStartLabel());
231             unwindStart.SetEndOffset(cgFunc.GetCleanupLabel());
232             emitter->Emit("\t.uleb128 ");
233             emitter->EmitLabelPair(unwindStart);
234             LabelPair unwindLength;
235             unwindLength.SetStartOffset(cgFunc.GetCleanupLabel());
236             unwindLength.SetEndOffset(cgFunc.GetEndLabel());
237             emitter->Emit("\t.uleb128 ");
238             emitter->EmitLabelPair(unwindLength);
239             emitter->Emit("\t.uleb128 0\n");
240             emitter->Emit("\t.uleb128 0\n");
241         }
242     }
243     /* callsite end label */
244     emitter->EmitStmtLabel(ehFunc->GetLSDACallSiteTable()->GetCSTable().GetEndOffset()->GetLabelIdx());
245     /* tt */
246     const LSDAActionTable *lsdaActionTable = ehFunc->GetLSDAActionTable();
247     for (size_t i = 0; i < lsdaActionTable->Size(); ++i) {
248         LSDAAction *lsdaAction = lsdaActionTable->GetActionTable().at(i);
249         emitter->Emit("\t.byte ").Emit(lsdaAction->GetActionIndex()).Emit("\n");
250         emitter->Emit("\t.byte ").Emit(lsdaAction->GetActionFilter()).Emit("\n");
251     }
252     emitter->Emit("\t.align 3\n");
253     for (int32 i = ehFunc->GetEHTyTableSize() - 1; i >= 0; i--) {
254         MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ehFunc->GetEHTyTableMember(i));
255         MIRTypeKind typeKind = mirType->GetKind();
256         if (((typeKind == kTypeScalar) && (mirType->GetPrimType() == PTY_void)) ||
257             (typeKind == kTypeStructIncomplete) || (typeKind == kTypeInterfaceIncomplete)) {
258             continue;
259         }
260         CHECK_FATAL((typeKind == kTypeClass) || (typeKind == kTypeClassIncomplete), "NYI");
261         const std::string &tyName = GlobalTables::GetStrTable().GetStringFromStrIdx(mirType->GetNameStrIdx());
262         std::string dwRefString(".LDW.ref.");
263         dwRefString += CLASSINFO_PREFIX_STR;
264         dwRefString += tyName;
265         dwRefString += " - .";
266         emitter->Emit("\t.4byte " + dwRefString + "\n");
267     }
268     /* end of lsda */
269     emitter->EmitStmtLabel(lsdaHeader->GetTTypeOffset().GetEndOffset()->GetLabelIdx());
270 }
271 
EmitBBHeaderLabel(FuncEmitInfo & funcEmitInfo,const std::string & name,LabelIdx labIdx)272 void AArch64AsmEmitter::EmitBBHeaderLabel(FuncEmitInfo &funcEmitInfo, const std::string &name, LabelIdx labIdx)
273 {
274     (void)name;
275     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
276     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
277     CG *currCG = cgFunc.GetCG();
278     Emitter &emitter = *(currCG->GetEmitter());
279     LabelOperand &label = aarchCGFunc.GetOrCreateLabelOperand(labIdx);
280     /* if label order is default value -1, set new order */
281     if (label.GetLabelOrder() == 0xFFFFFFFF) {
282         label.SetLabelOrder(currCG->GetLabelOrderCnt());
283         currCG->IncreaseLabelOrderCnt();
284     }
285     PUIdx pIdx = currCG->GetMIRModule()->CurFunction()->GetPuidx();
286     char *puIdx = strdup(std::to_string(pIdx).c_str());
287     const std::string &labelName = cgFunc.GetFunction().GetLabelTab()->GetName(labIdx);
288     if (currCG->GenerateVerboseCG()) {
289         (void)emitter.Emit(".L.")
290             .Emit(puIdx)
291             .Emit("__")
292             .Emit(labIdx)
293             .Emit(":\t//label order ")
294             .Emit(label.GetLabelOrder());
295         if (!labelName.empty() && labelName.at(0) != '@') {
296             /* If label name has @ as its first char, it is not from MIR */
297             (void)emitter.Emit(", MIR: @").Emit(labelName).Emit("\n");
298         } else {
299             (void)emitter.Emit("\n");
300         }
301     } else {
302         (void)emitter.Emit(".L.").Emit(puIdx).Emit("__").Emit(labIdx).Emit(":\n");
303     }
304     free(puIdx);
305     puIdx = nullptr;
306 }
307 
EmitJavaInsnAddr(FuncEmitInfo & funcEmitInfo)308 void AArch64AsmEmitter::EmitJavaInsnAddr(FuncEmitInfo &funcEmitInfo)
309 {
310     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
311     if (cgFunc.GetFunction().IsJava()) {
312         Emitter *emitter = cgFunc.GetCG()->GetEmitter();
313         /* emit a comment of current address from the begining of java text section */
314         std::stringstream ss;
315         ss << "\n\t// addr: 0x" << std::hex << (emitter->GetJavaInsnCount() * kInsnSize) << "\n";
316         cgFunc.GetCG()->GetEmitter()->Emit(ss.str());
317     }
318 }
319 
RecordRegInfo(FuncEmitInfo & funcEmitInfo) const320 void AArch64AsmEmitter::RecordRegInfo(FuncEmitInfo &funcEmitInfo) const
321 {
322     if (!CGOptions::DoIPARA() || funcEmitInfo.GetCGFunc().GetFunction().IsJava()) {
323         return;
324     }
325     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
326     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
327 
328     std::set<regno_t> referedRegs;
329     MIRFunction &mirFunc = cgFunc.GetFunction();
330     FOR_ALL_BB_REV(bb, &aarchCGFunc) {
331         FOR_BB_INSNS_REV(insn, bb) {
332             if (!insn->IsMachineInstruction()) {
333                 continue;
334             }
335             if (insn->IsCall() || insn->IsTailCall()) {
336                 auto *targetOpnd = insn->GetCallTargetOperand();
337                 bool safeCheck = false;
338                 CHECK_FATAL(targetOpnd != nullptr,
339                             "target is null in AArch64Emitter::IsCallToFunctionThatNeverReturns");
340                 if (targetOpnd->IsFuncNameOpnd()) {
341                     FuncNameOperand *target = static_cast<FuncNameOperand *>(targetOpnd);
342                     const MIRSymbol *funcSt = target->GetFunctionSymbol();
343                     DEBUG_ASSERT(funcSt->GetSKind() == maple::kStFunc, "funcst must be a function name symbol");
344                     MIRFunction *func = funcSt->GetFunction();
345                     if (func != nullptr && func->IsReferedRegsValid()) {
346                         safeCheck = true;
347                         for (auto preg : func->GetReferedRegs()) {
348                             referedRegs.insert(preg);
349                         }
350                     }
351                 }
352                 if (!safeCheck) {
353                     mirFunc.SetReferedRegsValid(false);
354                     return;
355                 }
356             }
357             if (referedRegs.size() == kMaxRegNum) {
358                 break;
359             }
360             uint32 opndNum = insn->GetOperandSize();
361             const InsnDesc *md = &AArch64CG::kMd[insn->GetMachineOpcode()];
362             for (uint32 i = 0; i < opndNum; ++i) {
363                 if (insn->GetMachineOpcode() == MOP_asm) {
364                     if (i == kAsmOutputListOpnd || i == kAsmClobberListOpnd) {
365                         for (auto opnd : static_cast<ListOperand &>(insn->GetOperand(i)).GetOperands()) {
366                             if (opnd->IsRegister()) {
367                                 referedRegs.insert(static_cast<RegOperand *>(opnd)->GetRegisterNumber());
368                             }
369                         }
370                     }
371                     continue;
372                 }
373                 Operand &opnd = insn->GetOperand(i);
374                 if (opnd.IsList()) {
375                     /* all use, skip it */
376                 } else if (opnd.IsMemoryAccessOperand()) {
377                     auto &memOpnd = static_cast<MemOperand &>(opnd);
378                     RegOperand *base = memOpnd.GetBaseRegister();
379                     if (!memOpnd.IsIntactIndexed()) {
380                         referedRegs.insert(base->GetRegisterNumber());
381                     }
382                 } else if (opnd.IsRegister()) {
383                     RegType regType = static_cast<RegOperand &>(opnd).GetRegisterType();
384                     if (regType == kRegTyCc || regType == kRegTyVary) {
385                         continue;
386                     }
387                     bool isDef = md->GetOpndDes(i)->IsRegDef();
388                     if (isDef) {
389                         referedRegs.insert(static_cast<RegOperand &>(opnd).GetRegisterNumber());
390                     }
391                 }
392             }
393         }
394     }
395     mirFunc.SetReferedRegsValid(true);
396 #ifdef DEBUG
397     for (auto reg : referedRegs) {
398         if (reg > kMaxRegNum) {
399             DEBUG_ASSERT(0, "unexpected preg");
400         }
401     }
402 #endif
403     mirFunc.CopyReferedRegs(referedRegs);
404 }
405 
Run(FuncEmitInfo & funcEmitInfo)406 void AArch64AsmEmitter::Run(FuncEmitInfo &funcEmitInfo)
407 {
408     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
409     AArch64CGFunc &aarchCGFunc = static_cast<AArch64CGFunc &>(cgFunc);
410     CG *currCG = cgFunc.GetCG();
411     /* emit header of this function */
412     Emitter &emitter = *currCG->GetEmitter();
413     // insert for  __cxx_global_var_init
414     if (cgFunc.GetName() == "__cxx_global_var_init") {
415         (void)emitter.Emit("\t.section\t.init_array,\"aw\"\n");
416         (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
417     }
418     if (cgFunc.GetFunction().GetAttr(FUNCATTR_initialization)) {
419         (void)emitter.Emit("\t.section\t.init_array,\"aw\"\n");
420         (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
421     }
422     if (cgFunc.GetFunction().GetAttr(FUNCATTR_termination)) {
423         (void)emitter.Emit("\t.section\t.fini_array,\"aw\"\n");
424         (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n");
425     }
426     (void)emitter.Emit("\n");
427     EmitMethodDesc(funcEmitInfo, emitter);
428     /* emit java code to the java section. */
429     if (cgFunc.GetFunction().IsJava()) {
430         std::string sectionName = namemangler::kMuidJavatextPrefixStr;
431         (void)emitter.Emit("\t.section  ." + sectionName + ",\"ax\"\n");
432     } else if (cgFunc.GetFunction().GetAttr(FUNCATTR_section)) {
433         const std::string &sectionName = cgFunc.GetFunction().GetAttrs().GetPrefixSectionName();
434         (void)emitter.Emit("\t.section  " + sectionName).Emit(",\"ax\",@progbits\n");
435     } else if (CGOptions::IsFunctionSections()) {
436         (void)emitter.Emit("\t.section  .text.").Emit(cgFunc.GetName()).Emit(",\"ax\",@progbits\n");
437     } else if (cgFunc.GetFunction().GetAttr(FUNCATTR_constructor_priority)) {
438         (void)emitter.Emit("\t.section\t.text.startup").Emit(",\"ax\",@progbits\n");
439     } else {
440         (void)emitter.Emit("\t.text\n");
441     }
442     if (CGOptions::GetFuncAlignPow() != 0) {
443         (void)emitter.Emit("\t.align ").Emit(CGOptions::GetFuncAlignPow()).Emit("\n");
444     }
445     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc.GetFunction().GetStIdx().Idx());
446     const std::string &funcName = std::string(cgFunc.GetShortFuncName().c_str());
447 
448     // manually replace function with optimized assembly language
449     if (CGOptions::IsReplaceASM()) {
450         auto it = func2CodeInsnMap.find(funcSt->GetName());
451         if (it != func2CodeInsnMap.end()) {
452             std::string optFile = it->second.first;
453             struct stat buffer;
454             if (stat(optFile.c_str(), &buffer) == 0) {
455                 std::ifstream codetricksFd(optFile);
456                 if (!codetricksFd.is_open()) {
457                     ERR(kLncErr, " %s open failed!", optFile.c_str());
458                     LogInfo::MapleLogger() << "wrong" << '\n';
459                 } else {
460                     std::string contend;
461                     while (getline(codetricksFd, contend)) {
462                         (void)emitter.Emit(contend + "\n");
463                     }
464                 }
465             }
466             emitter.IncreaseJavaInsnCount(it->second.second);
467 #ifdef EMIT_INSN_COUNT
468             EmitJavaInsnAddr(funcEmitInfo);
469 #endif /* ~EMIT_INSN_COUNT */
470             return;
471         }
472     }
473     std::string funcStName = funcSt->GetName();
474     if (funcSt->GetFunction()->GetAttr(FUNCATTR_weak)) {
475         (void)emitter.Emit("\t.weak\t" + funcStName + "\n");
476         (void)emitter.Emit("\t.hidden\t" + funcStName + "\n");
477     } else if (funcSt->GetFunction()->GetAttr(FUNCATTR_local)) {
478         (void)emitter.Emit("\t.local\t" + funcStName + "\n");
479     } else if (funcSt->GetFunction() && (!funcSt->GetFunction()->IsJava()) && funcSt->GetFunction()->IsStatic()) {
480         // nothing
481     } else {
482         /* should refer to function attribute */
483         (void)emitter.Emit("\t.globl\t").Emit(funcSt->GetName()).Emit("\n");
484         if (!currCG->GetMIRModule()->IsCModule()) {
485             (void)emitter.Emit("\t.hidden\t").Emit(funcSt->GetName()).Emit("\n");
486         }
487     }
488     (void)emitter.Emit("\t.type\t" + funcStName + ", %function\n");
489     /* add these messege , solve the performance tool error */
490     EmitRefToMethodDesc(funcEmitInfo, emitter);
491     (void)emitter.Emit(funcStName + ":\n");
492 
493     /* if the last  insn is call, then insert nop */
494     bool found = false;
495     FOR_ALL_BB_REV(bb, &aarchCGFunc) {
496         FOR_BB_INSNS_REV(insn, bb) {
497             if (insn->IsMachineInstruction()) {
498                 if (insn->IsCall()) {
499                     Insn &newInsn = aarchCGFunc.GetInsnBuilder()->BuildInsn<AArch64CG>(MOP_nop);
500                     bb->InsertInsnAfter(*insn, newInsn);
501                 }
502                 found = true;
503                 break;
504             }
505         }
506         if (found) {
507             break;
508         }
509     }
510 
511     RecordRegInfo(funcEmitInfo);
512 
513     /* emit instructions */
514     FOR_ALL_BB(bb, &aarchCGFunc) {
515         if (bb->IsUnreachable()) {
516             continue;
517         }
518         if (currCG->GenerateVerboseCG()) {
519             (void)emitter.Emit("#    freq:").Emit(bb->GetFrequency()).Emit("\n");
520         }
521         /* emit bb headers */
522         if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
523             if (aarchCGFunc.GetMirModule().IsCModule() && bb->IsBBNeedAlign() &&
524                 bb->GetAlignNopNum() != kAlignMovedFlag) {
525                 uint32 power = bb->GetAlignPower();
526                 (void)emitter.Emit("\t.p2align ").Emit(power).Emit("\n");
527             }
528             EmitBBHeaderLabel(funcEmitInfo, funcName, bb->GetLabIdx());
529         }
530 
531         FOR_BB_INSNS(insn, bb) {
532             if (insn->IsCfiInsn()) {
533                 EmitAArch64CfiInsn(emitter, *insn);
534             } else if (insn->IsDbgInsn()) {
535                 EmitAArch64DbgInsn(emitter, *insn);
536             } else {
537                 EmitAArch64Insn(emitter, *insn);
538             }
539         }
540     }
541     if (CGOptions::IsMapleLinker()) {
542         /* Emit a label for calculating method size */
543         (void)emitter.Emit(".Label.end." + funcStName + ":\n");
544     }
545     (void)emitter.Emit("\t.size\t" + funcStName + ", .-").Emit(funcStName + "\n");
546 
547     auto constructorAttr = funcSt->GetFunction()->GetAttrs().GetConstructorPriority();
548     if (constructorAttr != -1) {
549         (void)emitter.Emit("\t.section\t.init_array." + std::to_string(constructorAttr) + ",\"aw\"\n");
550         (void)emitter.Emit("\t.align 3\n");
551         (void)emitter.Emit("\t.xword\t" + funcStName + "\n");
552     }
553 
554     EHFunc *ehFunc = cgFunc.GetEHFunc();
555     /* emit LSDA */
556     if (cgFunc.GetFunction().IsJava() && (ehFunc != nullptr)) {
557         if (!cgFunc.GetHasProEpilogue()) {
558             (void)emitter.Emit("\t.word 0x55555555\n");
559             emitter.IncreaseJavaInsnCount();
560         } else if (ehFunc->NeedFullLSDA()) {
561             LSDAHeader *lsdaHeader = ehFunc->GetLSDAHeader();
562             PUIdx pIdx = emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
563             const std::string &idx = strdup(std::to_string(pIdx).c_str());
564             /*  .word .Label.lsda_label-func_start_label */
565             (void)emitter.Emit("\t.word .L." + idx).Emit("__").Emit(lsdaHeader->GetLSDALabel()->GetLabelIdx());
566             (void)emitter.Emit("-.L." + idx).Emit("__").Emit(cgFunc.GetStartLabel()->GetLabelIdx()).Emit("\n");
567             emitter.IncreaseJavaInsnCount();
568         } else if (ehFunc->NeedFastLSDA()) {
569             EmitFastLSDA(funcEmitInfo);
570         }
571     }
572 
573     for (auto &it : cgFunc.GetEmitStVec()) {
574         /* emit switch table only here */
575         MIRSymbol *st = it.second;
576         DEBUG_ASSERT(st->IsReadOnly(), "NYI");
577         (void)emitter.Emit("\n");
578         (void)emitter.Emit("\t.align 3\n");
579         emitter.IncreaseJavaInsnCount(0, true); /* just aligned */
580         (void)emitter.Emit(st->GetName() + ":\n");
581         MIRAggConst *arrayConst = safe_cast<MIRAggConst>(st->GetKonst());
582         CHECK_FATAL(arrayConst != nullptr, "null ptr check");
583         PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
584         char *idx = strdup(std::to_string(pIdx).c_str());
585         for (size_t i = 0; i < arrayConst->GetConstVec().size(); i++) {
586             MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
587             CHECK_FATAL(lblConst != nullptr, "null ptr check");
588             (void)emitter.Emit("\t.quad\t.L.").Emit(idx).Emit("__").Emit(lblConst->GetValue());
589             (void)emitter.Emit(" - " + st->GetName() + "\n");
590             emitter.IncreaseJavaInsnCount(kQuadInsnCount);
591         }
592         free(idx);
593         idx = nullptr;
594     }
595 
596     for (const auto &mpPair : cgFunc.GetLabelAndValueMap()) {
597         LabelOperand &labelOpnd = aarchCGFunc.GetOrCreateLabelOperand(mpPair.first);
598         A64OpndEmitVisitor visitor(emitter, nullptr);
599         labelOpnd.Accept(visitor);
600         (void)emitter.Emit(":\n");
601         (void)emitter.Emit("\t.quad ").Emit(static_cast<int64>(mpPair.second)).Emit("\n");
602         emitter.IncreaseJavaInsnCount(kQuadInsnCount);
603     }
604 
605     if (ehFunc != nullptr && ehFunc->NeedFullLSDA()) {
606         EmitFullLSDA(funcEmitInfo);
607     }
608 #ifdef EMIT_INSN_COUNT
609     if (cgFunc.GetFunction().IsJava()) {
610         EmitJavaInsnAddr(funcEmitInfo);
611     }
612 #endif /* ~EMIT_INSN_COUNT */
613 }
614 
EmitAArch64Insn(maplebe::Emitter & emitter,Insn & insn) const615 void AArch64AsmEmitter::EmitAArch64Insn(maplebe::Emitter &emitter, Insn &insn) const
616 {
617     MOperator mOp = insn.GetMachineOpcode();
618     emitter.SetCurrentMOP(mOp);
619     const InsnDesc *md = insn.GetDesc();
620 
621     if (!GetCG()->GenerateVerboseAsm() && !GetCG()->GenerateVerboseCG() && insn.IsComment()) {
622         return;
623     }
624 
625     switch (mOp) {
626         case MOP_clinit: {
627             EmitClinit(emitter, insn);
628             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
629             return;
630         }
631         case MOP_adrp_ldr: {
632             uint32 adrpldrInsnCount = md->GetAtomicNum();
633             emitter.IncreaseJavaInsnCount(adrpldrInsnCount);
634             EmitAdrpLdr(emitter, insn);
635             if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) {
636                 EmitLazyBindingRoutine(emitter, insn);
637                 emitter.IncreaseJavaInsnCount(adrpldrInsnCount + 1);
638             }
639             return;
640         }
641         case MOP_counter: {
642             EmitCounter(emitter, insn);
643             return;
644         }
645         case MOP_asm: {
646             EmitInlineAsm(emitter, insn);
647             return;
648         }
649         case MOP_clinit_tail: {
650             EmitClinitTail(emitter, insn);
651             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
652             return;
653         }
654         case MOP_lazy_ldr: {
655             EmitLazyLoad(emitter, insn);
656             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
657             return;
658         }
659         case MOP_adrp_label: {
660             EmitAdrpLabel(emitter, insn);
661             return;
662         }
663         case MOP_lazy_tail: {
664             /* No need to emit this pseudo instruction. */
665             return;
666         }
667         case MOP_lazy_ldr_static: {
668             EmitLazyLoadStatic(emitter, insn);
669             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
670             return;
671         }
672         case MOP_arrayclass_cache_ldr: {
673             EmitArrayClassCacheLoad(emitter, insn);
674             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
675             return;
676         }
677         case MOP_get_and_addI:
678         case MOP_get_and_addL: {
679             EmitGetAndAddInt(emitter, insn);
680             return;
681         }
682         case MOP_get_and_setI:
683         case MOP_get_and_setL: {
684             EmitGetAndSetInt(emitter, insn);
685             return;
686         }
687         case MOP_compare_and_swapI:
688         case MOP_compare_and_swapL: {
689             EmitCompareAndSwapInt(emitter, insn);
690             return;
691         }
692         case MOP_string_indexof: {
693             EmitStringIndexOf(emitter, insn);
694             return;
695         }
696         case MOP_pseudo_none:
697         case MOP_pseduo_tls_release: {
698             return;
699         }
700         case MOP_tls_desc_call: {
701             EmitCTlsDescCall(emitter, insn);
702             return;
703         }
704         case MOP_tls_desc_rel: {
705             EmitCTlsDescRel(emitter, insn);
706             return;
707         }
708         case MOP_sync_lock_test_setI:
709         case MOP_sync_lock_test_setL: {
710             EmitSyncLockTestSet(emitter, insn);
711             return;
712         }
713         default:
714             break;
715     }
716 
717     if (CGOptions::IsNativeOpt() && mOp == MOP_xbl) {
718         auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
719         if (nameOpnd->GetName() == "MCC_CheckThrowPendingException") {
720             EmitCheckThrowPendingException(emitter, insn);
721             emitter.IncreaseJavaInsnCount(md->GetAtomicNum());
722             return;
723         }
724     }
725 
726     std::string format(md->format);
727     (void)emitter.Emit("\t").Emit(md->name).Emit("\t");
728     size_t opndSize = insn.GetOperandSize();
729     std::vector<int32> seq(opndSize, -1);
730     std::vector<std::string> prefix(opndSize); /* used for print prefix like "*" in icall *rax */
731     uint32 index = 0;
732     uint32 commaNum = 0;
733     for (uint32 i = 0; i < format.length(); ++i) {
734         char c = format[i];
735         if (c >= '0' && c <= '5') {
736             seq[index++] = c - '0';
737             ++commaNum;
738         } else if (c != ',') {
739             prefix[index].push_back(c);
740         }
741     }
742 
743     bool isRefField =
744         (opndSize == 0) ? false : CheckInsnRefField(insn, static_cast<size_t>(static_cast<uint32>(seq[0])));
745     if (insn.IsComment()) {
746         emitter.IncreaseJavaInsnCount();
747     }
748     uint32 compositeOpnds = 0;
749     for (uint32 i = 0; i < commaNum; ++i) {
750         if (seq[i] == -1) {
751             continue;
752         }
753         if (prefix[i].length() > 0) {
754             (void)emitter.Emit(prefix[i]);
755         }
756         if (emitter.NeedToDealWithHugeSo() && (mOp == MOP_xbl || mOp == MOP_tail_call_opt_xbl)) {
757             auto *nameOpnd = static_cast<FuncNameOperand *>(&insn.GetOperand(kInsnFirstOpnd));
758             /* Suport huge so here
759              * As the PLT section is just before java_text section, when java_text section is larger
760              * then 128M, instrunction of "b" and "bl" would fault to branch to PLT stub functions. Here, to save
761              * instuctions space, we change the branch target to a local target within 120M address, and add non-plt
762              * call to the target function.
763              */
764             emitter.InsertHugeSoTarget(nameOpnd->GetName());
765             (void)emitter.Emit(nameOpnd->GetName() + emitter.HugeSoPostFix());
766             break;
767         }
768         auto *opnd = &insn.GetOperand(static_cast<uint32>(seq[i]));
769         if (opnd && opnd->IsRegister()) {
770             auto *regOpnd = static_cast<RegOperand *>(opnd);
771             if ((md->opndMD[static_cast<uint32>(seq[i])])->IsVectorOperand()) {
772                 regOpnd->SetVecLanePosition(-1);
773                 regOpnd->SetVecLaneSize(0);
774                 regOpnd->SetVecElementSize(0);
775                 if (insn.IsVectorOp()) {
776                     PrepareVectorOperand(regOpnd, compositeOpnds, insn);
777                     if (compositeOpnds != 0) {
778                         (void)emitter.Emit("{");
779                     }
780                 }
781             }
782         }
783         A64OpndEmitVisitor visitor(emitter, md->opndMD[static_cast<uint32>(seq[i])]);
784 
785         insn.GetOperand(static_cast<uint32>(seq[i])).Accept(visitor);
786         if (compositeOpnds == 1) {
787             (void)emitter.Emit("}");
788         }
789         if (compositeOpnds > 0) {
790             --compositeOpnds;
791         }
792         /* reset opnd0 ref-field flag, so following instruction has correct register */
793         if (isRefField && (i == 0)) {
794             static_cast<RegOperand *>(&insn.GetOperand(static_cast<uint32>(seq[0])))->SetRefField(false);
795         }
796         /* Temporary comment the label:.Label.debug.callee */
797         if (i != (commaNum - 1)) {
798             (void)emitter.Emit(", ");
799         }
800         const uint32 commaNumForEmitLazy = 2;
801         if (!CGOptions::IsLazyBinding() || GetCG()->IsLibcore() || (mOp != MOP_wldr && mOp != MOP_xldr) ||
802             commaNum != commaNumForEmitLazy || i != 1 ||
803             !insn.GetOperand(static_cast<uint32>(seq[1])).IsMemoryAccessOperand()) {
804             continue;
805         }
806         /*
807          * Only check the last operand of ldr in lo12 mode.
808          * Check the second operand, if it's [AArch64MemOperand::kAddrModeLo12Li]
809          */
810         auto *memOpnd = static_cast<MemOperand *>(&insn.GetOperand(static_cast<uint32>(seq[1])));
811         if (memOpnd == nullptr || memOpnd->GetAddrMode() != MemOperand::kAddrModeLo12Li) {
812             continue;
813         }
814         const MIRSymbol *sym = memOpnd->GetSymbol();
815         if (sym->IsMuidFuncDefTab() || sym->IsMuidFuncUndefTab() || sym->IsMuidDataDefTab() ||
816             sym->IsMuidDataUndefTab()) {
817             (void)emitter.Emit("\n");
818             EmitLazyBindingRoutine(emitter, insn);
819             emitter.IncreaseJavaInsnCount(1);
820         }
821     }
822     if (GetCG()->GenerateVerboseCG() || (GetCG()->GenerateVerboseAsm() && insn.IsComment())) {
823         const char *comment = insn.GetComment().c_str();
824         if (comment != nullptr && strlen(comment) > 0) {
825             (void)emitter.Emit("\t\t// ").Emit(comment);
826         }
827     }
828 
829     (void)emitter.Emit("\n");
830 }
831 
EmitClinit(Emitter & emitter,const Insn & insn) const832 void AArch64AsmEmitter::EmitClinit(Emitter &emitter, const Insn &insn) const
833 {
834     /*
835      * adrp    x3, __muid_data_undef_tab$$GetBoolean_bytecode+144
836      * ldr     x3, [x3, #:lo12:__muid_data_undef_tab$$GetBoolean_bytecode+144]
837      * or,
838      * adrp    x3, _PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B
839      * ldr     x3, [x3, #:lo12:_PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B]
840      *
841      * ldr x3, [x3,#112]
842      * ldr wzr, [x3]
843      */
844     const InsnDesc *md = &AArch64CG::kMd[MOP_clinit];
845 
846     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
847     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
848     const OpndDesc *prop0 = md->opndMD[0];
849     A64OpndEmitVisitor visitor(emitter, prop0);
850     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
851     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitClinit");
852     /* emit nop for breakpoint */
853     if (GetCG()->GetCGOptions().WithDwarf()) {
854         (void)emitter.Emit("\t").Emit("nop").Emit("\n");
855     }
856 
857     if (stImmOpnd->GetSymbol()->IsMuidDataUndefTab()) {
858         /* emit adrp */
859         (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
860         opnd0->Accept(visitor);
861         (void)emitter.Emit(",");
862         (void)emitter.Emit(stImmOpnd->GetName());
863         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
864         (void)emitter.Emit("\n");
865         /* emit ldr */
866         (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
867         opnd0->Accept(visitor);
868         (void)emitter.Emit(",");
869         (void)emitter.Emit("[");
870         opnd0->Accept(visitor);
871         (void)emitter.Emit(",");
872         (void)emitter.Emit("#");
873         (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
874         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
875         (void)emitter.Emit("]");
876         (void)emitter.Emit("\n");
877     } else {
878         /* adrp    x3, _PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B */
879         (void)emitter.Emit("\tadrp\t");
880         opnd0->Accept(visitor);
881         (void)emitter.Emit(",");
882         (void)emitter.Emit(namemangler::kPtrPrefixStr + stImmOpnd->GetName());
883         (void)emitter.Emit("\n");
884 
885         /* ldr     x3, [x3, #:lo12:_PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B] */
886         (void)emitter.Emit("\tldr\t");
887         opnd0->Accept(visitor);
888         (void)emitter.Emit(", [");
889         opnd0->Accept(visitor);
890         (void)emitter.Emit(", #:lo12:");
891         (void)emitter.Emit(namemangler::kPtrPrefixStr + stImmOpnd->GetName());
892         (void)emitter.Emit("]\n");
893     }
894     /* emit "ldr  x0,[x0,#48]" */
895     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
896     opnd0->Accept(visitor);
897     (void)emitter.Emit(",");
898     (void)emitter.Emit("[");
899     opnd0->Accept(visitor);
900     (void)emitter.Emit(",#");
901     (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
902     (void)emitter.Emit("]");
903     (void)emitter.Emit("\n");
904 
905     /* emit "ldr  xzr, [x0]" */
906     (void)emitter.Emit("\t").Emit("ldr\txzr, [");
907     opnd0->Accept(visitor);
908     (void)emitter.Emit("]\n");
909 }
910 
AsmStringOutputRegNum(bool isInt,uint32 regno,uint32 intBase,uint32 fpBase,std::string & strToEmit)911 static void AsmStringOutputRegNum(bool isInt, uint32 regno, uint32 intBase, uint32 fpBase, std::string &strToEmit)
912 {
913     regno_t newRegno;
914     if (isInt) {
915         newRegno = regno - intBase;
916     } else {
917         newRegno = regno - fpBase;
918     }
919     if (newRegno > (kDecimalMax - 1)) {
920         uint32 tenth = newRegno / kDecimalMax;
921         strToEmit += '0' + static_cast<char>(tenth);
922         newRegno -= (kDecimalMax * tenth);
923     }
924     strToEmit += newRegno + '0';
925 }
926 
EmitInlineAsm(Emitter & emitter,const Insn & insn) const927 void AArch64AsmEmitter::EmitInlineAsm(Emitter &emitter, const Insn &insn) const
928 {
929     (void)emitter.Emit("\t//Inline asm begin\n\t");
930     auto &list1 = static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd));
931     std::vector<RegOperand *> outOpnds;
932     for (auto *regOpnd : list1.GetOperands()) {
933         outOpnds.push_back(regOpnd);
934     }
935     auto &list2 = static_cast<ListOperand &>(insn.GetOperand(kAsmInputListOpnd));
936     std::vector<RegOperand *> inOpnds;
937     for (auto *regOpnd : list2.GetOperands()) {
938         inOpnds.push_back(regOpnd);
939     }
940     auto &list6 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmOutputRegPrefixOpnd));
941     auto &list7 = static_cast<ListConstraintOperand &>(insn.GetOperand(kAsmInputRegPrefixOpnd));
942     MapleString asmStr = static_cast<StringOperand &>(insn.GetOperand(kAsmStringOpnd)).GetComment();
943     std::string stringToEmit;
944     auto IsMemAccess = [](char c) -> bool { return c == '['; };
945     auto EmitRegister = [&](const char *p, bool isInt, uint32 regNO, bool unDefRegSize) -> void {
946         if (IsMemAccess(p[0])) {
947             stringToEmit += "[x";
948             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
949             stringToEmit += "]";
950         } else {
951             DEBUG_ASSERT((p[0] == 'w' || p[0] == 'x' || p[0] == 's' || p[0] == 'd' || p[0] == 'v'),
952                          "Asm invalid register type");
953             if ((p[0] == 'w' || p[0] == 'x') && unDefRegSize) {
954                 stringToEmit += 'x';
955             } else {
956                 stringToEmit += p[0];
957             }
958             if (!unDefRegSize) {
959                 isInt = (p[0] == 'w' || p[0] == 'x');
960             }
961             AsmStringOutputRegNum(isInt, regNO, R0, V0, stringToEmit);
962         }
963     };
964     for (size_t i = 0; i < asmStr.length(); ++i) {
965         switch (asmStr[i]) {
966             case '$': {
967                 char c = asmStr[++i];
968                 if ((c >= '0') && (c <= '9')) {
969                     auto val = static_cast<uint32>(c - '0');
970                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
971                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
972                     }
973                     if (val < outOpnds.size()) {
974                         const char *prefix = list6.stringList[val]->GetComment().c_str();
975                         RegOperand *opnd = outOpnds[val];
976                         EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
977                     } else {
978                         val -= static_cast<uint32>(outOpnds.size());
979                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
980                         RegOperand *opnd = inOpnds[val];
981                         /* input is a immediate */
982                         const char *prefix = list7.stringList[val]->GetComment().c_str();
983                         if (prefix[0] == 'i') {
984                             stringToEmit += '#';
985                             for (size_t k = 1; k < list7.stringList[val]->GetComment().length(); ++k) {
986                                 stringToEmit += prefix[k];
987                             }
988                         } else {
989                             EmitRegister(prefix, opnd->IsOfIntClass(), opnd->GetRegisterNumber(), true);
990                         }
991                     }
992                 } else if (c == '{') {
993                     c = asmStr[++i];
994                     CHECK_FATAL(((c >= '0') && (c <= '9')), "Inline asm : invalid register constraint number");
995                     auto val = static_cast<uint32>(c - '0');
996                     if (asmStr[i + 1] >= '0' && asmStr[i + 1] <= '9') {
997                         val = val * kDecimalMax + static_cast<uint32>(asmStr[++i] - '0');
998                     }
999                     regno_t regno;
1000                     bool isAddr = false;
1001                     if (val < outOpnds.size()) {
1002                         RegOperand *opnd = outOpnds[val];
1003                         regno = opnd->GetRegisterNumber();
1004                         isAddr = IsMemAccess(list6.stringList[val]->GetComment().c_str()[0]);
1005                     } else {
1006                         val -= static_cast<uint32>(outOpnds.size());
1007                         CHECK_FATAL(val < inOpnds.size(), "Inline asm : invalid register constraint number");
1008                         RegOperand *opnd = inOpnds[val];
1009                         regno = opnd->GetRegisterNumber();
1010                         isAddr = IsMemAccess(list7.stringList[val]->GetComment().c_str()[0]);
1011                     }
1012                     c = asmStr[++i];
1013                     CHECK_FATAL(c == ':', "Parsing error in inline asm string during emit");
1014                     c = asmStr[++i];
1015                     std::string prefix(1, c);
1016                     if (c == 'a' || isAddr) {
1017                         prefix = "[x";
1018                     }
1019                     EmitRegister(prefix.c_str(), true, regno, false);
1020                     c = asmStr[++i];
1021                     CHECK_FATAL(c == '}', "Parsing error in inline asm string during emit");
1022                 }
1023                 break;
1024             }
1025             case '\n': {
1026                 stringToEmit += "\n\t";
1027                 break;
1028             }
1029             default:
1030                 stringToEmit += asmStr[i];
1031         }
1032     }
1033     (void)emitter.Emit(stringToEmit);
1034     (void)emitter.Emit("\n\t//Inline asm end\n");
1035 }
1036 
EmitClinitTail(Emitter & emitter,const Insn & insn) const1037 void AArch64AsmEmitter::EmitClinitTail(Emitter &emitter, const Insn &insn) const
1038 {
1039     /*
1040      * ldr x17, [xs, #112]
1041      * ldr wzr, [x17]
1042      */
1043     const InsnDesc *md = &AArch64CG::kMd[MOP_clinit_tail];
1044 
1045     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1046 
1047     const OpndDesc *prop0 = md->opndMD[0];
1048     A64OpndEmitVisitor visitor(emitter, prop0);
1049 
1050     /* emit "ldr  x17,[xs,#112]" */
1051     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx17, [");
1052     opnd0->Accept(visitor);
1053     (void)emitter.Emit(", #");
1054     (void)emitter.Emit(static_cast<uint32>(ClassMetadata::OffsetOfInitState()));
1055     (void)emitter.Emit("]");
1056     (void)emitter.Emit("\n");
1057 
1058     /* emit "ldr  xzr, [x17]" */
1059     (void)emitter.Emit("\t").Emit("ldr\txzr, [x17]\n");
1060 }
1061 
EmitLazyLoad(Emitter & emitter,const Insn & insn) const1062 void AArch64AsmEmitter::EmitLazyLoad(Emitter &emitter, const Insn &insn) const
1063 {
1064     /*
1065      * ldr wd, [xs]  # xd and xs should be differenct register
1066      * ldr wd, [xd]
1067      */
1068     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr];
1069 
1070     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1071     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1072     const OpndDesc *prop0 = md->opndMD[0];
1073     const OpndDesc *prop1 = md->opndMD[1];
1074     A64OpndEmitVisitor visitor(emitter, prop0);
1075     A64OpndEmitVisitor visitor1(emitter, prop1);
1076 
1077     /* emit  "ldr wd, [xs]" */
1078     (void)emitter.Emit("\t").Emit("ldr\t");
1079 #ifdef USE_32BIT_REF
1080     opnd0->Accept(visitor);
1081 #else
1082     opnd0->Accept(visitor1);
1083 #endif
1084     (void)emitter.Emit(", [");
1085     opnd1->Accept(visitor1);
1086     (void)emitter.Emit("]\t// lazy load.\n");
1087 
1088     /* emit "ldr wd, [xd]" */
1089     (void)emitter.Emit("\t").Emit("ldr\t");
1090     opnd0->Accept(visitor);
1091     (void)emitter.Emit(", [");
1092     opnd1->Accept(visitor1);
1093     (void)emitter.Emit("]\t// lazy load.\n");
1094 }
1095 
EmitCounter(Emitter & emitter,const Insn & insn) const1096 void AArch64AsmEmitter::EmitCounter(Emitter &emitter, const Insn &insn) const
1097 {
1098     /*
1099      * adrp    x1, __profile_bb_table$$GetBoolean_bytecode+4
1100      * ldr     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
1101      * add     w17, w17, #1
1102      * str     w17, [x1, #:lo12:__profile_bb_table$$GetBoolean_bytecode+4]
1103      */
1104     const InsnDesc *md = &AArch64CG::kMd[MOP_counter];
1105 
1106     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1107     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1108     const OpndDesc *prop0 = md->opndMD[kInsnFirstOpnd];
1109     A64OpndEmitVisitor visitor(emitter, prop0);
1110     StImmOperand *stImmOpnd = static_cast<StImmOperand *>(opnd1);
1111     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitCounter");
1112     /* emit nop for breakpoint */
1113     if (GetCG()->GetCGOptions().WithDwarf()) {
1114         (void)emitter.Emit("\t").Emit("nop").Emit("\n");
1115     }
1116 
1117     /* emit adrp */
1118     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
1119     opnd0->Accept(visitor);
1120     (void)emitter.Emit(",");
1121     (void)emitter.Emit(stImmOpnd->GetName());
1122     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1123     (void)emitter.Emit("\n");
1124     /* emit ldr */
1125     (void)emitter.Emit("\t").Emit("ldr").Emit("\tw17, [");
1126     opnd0->Accept(visitor);
1127     (void)emitter.Emit(",");
1128     (void)emitter.Emit("#");
1129     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
1130     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1131     (void)emitter.Emit("]");
1132     (void)emitter.Emit("\n");
1133     /* emit add */
1134     (void)emitter.Emit("\t").Emit("add").Emit("\tw17, w17, #1");
1135     (void)emitter.Emit("\n");
1136     /* emit str */
1137     (void)emitter.Emit("\t").Emit("str").Emit("\tw17, [");
1138     opnd0->Accept(visitor);
1139     (void)emitter.Emit(",");
1140     (void)emitter.Emit("#");
1141     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
1142     (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1143     (void)emitter.Emit("]");
1144     (void)emitter.Emit("\n");
1145 }
1146 
EmitAdrpLabel(Emitter & emitter,const Insn & insn) const1147 void AArch64AsmEmitter::EmitAdrpLabel(Emitter &emitter, const Insn &insn) const
1148 {
1149     /* adrp    xd, label
1150      * add     xd, xd, #lo12:label
1151      */
1152     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_label];
1153 
1154     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1155     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1156     const OpndDesc *prop0 = md->opndMD[0];
1157     A64OpndEmitVisitor visitor(emitter, prop0);
1158     auto lidx = static_cast<ImmOperand *>(opnd1)->GetValue();
1159 
1160     /* adrp    xd, label */
1161     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
1162     opnd0->Accept(visitor);
1163     (void)emitter.Emit(", ");
1164     char *idx;
1165     idx =
1166         strdup(std::to_string(Globals::GetInstance()->GetBECommon()->GetMIRModule().CurFunction()->GetPuidx()).c_str());
1167     (void)emitter.Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
1168 
1169     /* add     xd, xd, #lo12:label */
1170     (void)emitter.Emit("\tadd\t");
1171     opnd0->Accept(visitor);
1172     (void)emitter.Emit(", ");
1173     opnd0->Accept(visitor);
1174     (void)emitter.Emit(", ");
1175     (void)emitter.Emit(":lo12:").Emit(".L.").Emit(idx).Emit("__").Emit(lidx).Emit("\n");
1176     (void)emitter.Emit("\n");
1177     free(idx);
1178     idx = nullptr;
1179 }
1180 
EmitAdrpLdr(Emitter & emitter,const Insn & insn) const1181 void AArch64AsmEmitter::EmitAdrpLdr(Emitter &emitter, const Insn &insn) const
1182 {
1183     /*
1184      * adrp    xd, _PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B
1185      * ldr     xd, [xd, #:lo12:_PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B]
1186      */
1187     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1188     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1189     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1190     const OpndDesc *prop0 = md->opndMD[0];
1191     A64OpndEmitVisitor visitor(emitter, prop0);
1192     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
1193     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitAdrpLdr");
1194     /* emit nop for breakpoint */
1195     if (GetCG()->GetCGOptions().WithDwarf()) {
1196         (void)emitter.Emit("\t").Emit("nop").Emit("\n");
1197     }
1198 
1199     /* adrp    xd, _PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B */
1200     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
1201     opnd0->Accept(visitor);
1202     (void)emitter.Emit(", ");
1203     (void)emitter.Emit(stImmOpnd->GetName());
1204     if (stImmOpnd->GetOffset() != 0) {
1205         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1206     }
1207     (void)emitter.Emit("\n");
1208 
1209     /* ldr     xd, [xd, #:lo12:_PTR__cinf_Ljava_2Futil_2Fconcurrent_2Fatomic_2FAtomicInteger_3B] */
1210     (void)emitter.Emit("\tldr\t");
1211     static_cast<RegOperand *>(opnd0)->SetRefField(true);
1212     opnd0->Accept(visitor);
1213     static_cast<RegOperand *>(opnd0)->SetRefField(false);
1214     (void)emitter.Emit(", ");
1215     (void)emitter.Emit("[");
1216     opnd0->Accept(visitor);
1217     (void)emitter.Emit(",");
1218     (void)emitter.Emit("#");
1219     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
1220     if (stImmOpnd->GetOffset() != 0) {
1221         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1222     }
1223     (void)emitter.Emit("]\n");
1224 }
1225 
EmitLazyLoadStatic(Emitter & emitter,const Insn & insn) const1226 void AArch64AsmEmitter::EmitLazyLoadStatic(Emitter &emitter, const Insn &insn) const
1227 {
1228     /* adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset
1229      * ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]
1230      * ldr wzr, [xd]
1231      */
1232     const InsnDesc *md = &AArch64CG::kMd[MOP_lazy_ldr_static];
1233 
1234     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1235     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1236     const OpndDesc *prop0 = md->GetOpndDes(0);
1237     A64OpndEmitVisitor visitor(emitter, prop0);
1238     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
1239     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
1240 
1241     /* emit "adrp xd, :got:__staticDecoupleValueOffset$$xxx+offset" */
1242     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
1243     opnd0->Accept(visitor);
1244     (void)emitter.Emit(", ");
1245     (void)emitter.Emit(stImmOpnd->GetName());
1246     if (stImmOpnd->GetOffset() != 0) {
1247         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1248     }
1249     (void)emitter.Emit("\t// lazy load static.\n");
1250 
1251     /* emit "ldr wd, [xd, #:got_lo12:__staticDecoupleValueOffset$$xxx+offset]" */
1252     (void)emitter.Emit("\tldr\t");
1253     static_cast<RegOperand *>(opnd0)->SetRefField(true);
1254 #ifdef USE_32BIT_REF
1255     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
1256     opnd0->Emit(emitter, &prop2); /* ldr wd, ... for terminal system */
1257 #else
1258     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
1259 #endif /* USE_32BIT_REF */
1260     static_cast<RegOperand *>(opnd0)->SetRefField(false);
1261     (void)emitter.Emit(", ");
1262     (void)emitter.Emit("[");
1263     opnd0->Accept(visitor);
1264     (void)emitter.Emit(",");
1265     (void)emitter.Emit("#");
1266     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
1267     if (stImmOpnd->GetOffset() != 0) {
1268         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1269     }
1270     (void)emitter.Emit("]\t// lazy load static.\n");
1271 
1272     /* emit "ldr wzr, [xd]" */
1273     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
1274     opnd0->Accept(visitor);
1275     (void)emitter.Emit("]\t// lazy load static.\n");
1276 }
1277 
EmitArrayClassCacheLoad(Emitter & emitter,const Insn & insn) const1278 void AArch64AsmEmitter::EmitArrayClassCacheLoad(Emitter &emitter, const Insn &insn) const
1279 {
1280     /* adrp xd, :got:__arrayClassCacheTable$$xxx+offset
1281      * ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]
1282      * ldr wzr, [xd]
1283      */
1284     const InsnDesc *md = &AArch64CG::kMd[MOP_arrayclass_cache_ldr];
1285     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1286     Operand *opnd1 = &insn.GetOperand(kInsnSecondOpnd);
1287     const OpndDesc *prop0 = md->GetOpndDes(kInsnFirstOpnd);
1288     A64OpndEmitVisitor visitor(emitter, prop0);
1289     auto *stImmOpnd = static_cast<StImmOperand *>(opnd1);
1290     CHECK_FATAL(stImmOpnd != nullptr, "stImmOpnd is null in AArch64Emitter::EmitLazyLoadStatic");
1291 
1292     /* emit "adrp xd, :got:__arrayClassCacheTable$$xxx+offset" */
1293     (void)emitter.Emit("\t").Emit("adrp").Emit("\t");
1294     opnd0->Accept(visitor);
1295     (void)emitter.Emit(", ");
1296     (void)emitter.Emit(stImmOpnd->GetName());
1297     if (stImmOpnd->GetOffset() != 0) {
1298         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1299     }
1300     (void)emitter.Emit("\t// load array class.\n");
1301 
1302     /* emit "ldr wd, [xd, #:got_lo12:__arrayClassCacheTable$$xxx+offset]" */
1303     (void)emitter.Emit("\tldr\t");
1304     static_cast<RegOperand *>(opnd0)->SetRefField(true);
1305 #ifdef USE_32BIT_REF
1306     const OpndDesc prop2(prop0->GetOperandType(), prop0->GetRegProp(), prop0->GetSize() / 2);
1307     A64OpndEmitVisitor visitor2(emitter, prop2);
1308     opnd0->Accept(visitor2); /* ldr wd, ... for terminal system */
1309 #else
1310     opnd0->Accept(visitor); /* ldr xd, ... for qemu */
1311 #endif /* USE_32BIT_REF */
1312     static_cast<RegOperand *>(opnd0)->SetRefField(false);
1313     (void)emitter.Emit(", ");
1314     (void)emitter.Emit("[");
1315     opnd0->Accept(visitor);
1316     (void)emitter.Emit(",");
1317     (void)emitter.Emit("#");
1318     (void)emitter.Emit(":lo12:").Emit(stImmOpnd->GetName());
1319     if (stImmOpnd->GetOffset() != 0) {
1320         (void)emitter.Emit("+").Emit(stImmOpnd->GetOffset());
1321     }
1322     (void)emitter.Emit("]\t// load array class.\n");
1323 
1324     /* emit "ldr wzr, [xd]" */
1325     (void)emitter.Emit("\t").Emit("ldr\twzr, [");
1326     opnd0->Accept(visitor);
1327     (void)emitter.Emit("]\t// check resolve array class.\n");
1328 }
1329 
1330 /*
1331  * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label
1332  * add    xt, x1, x2
1333  * label:
1334  * ldaxr  w0, [xt]
1335  * add    wt, w0, w3
1336  * stlxr  ws, wt, [xt]
1337  * cbnz   ws, label
1338  */
EmitGetAndAddInt(Emitter & emitter,const Insn & insn) const1339 void AArch64AsmEmitter::EmitGetAndAddInt(Emitter &emitter, const Insn &insn) const
1340 {
1341     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the oprands number");
1342     (void)emitter.Emit("\t//\tstart of Unsafe.getAndAddInt.\n");
1343     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1344     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1345     Operand *tempOpnd2 = &insn.GetOperand(kInsnFourthOpnd);
1346     Operand *objOpnd = &insn.GetOperand(kInsnFifthOpnd);
1347     Operand *offsetOpnd = &insn.GetOperand(kInsnSixthOpnd);
1348     Operand *deltaOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1349     Operand *labelOpnd = &insn.GetOperand(kInsnEighthOpnd);
1350     A64OpndEmitVisitor visitor(emitter, nullptr);
1351     /* emit add. */
1352     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1353     tempOpnd0->Accept(visitor);
1354     (void)emitter.Emit(", ");
1355     objOpnd->Accept(visitor);
1356     (void)emitter.Emit(", ");
1357     offsetOpnd->Accept(visitor);
1358     (void)emitter.Emit("\n");
1359     /* emit label. */
1360     labelOpnd->Accept(visitor);
1361     (void)emitter.Emit(":\n");
1362     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1363     const MOperator mOp = insn.GetMachineOpcode();
1364     const InsnDesc *md = &AArch64CG::kMd[mOp];
1365     const OpndDesc *retProp = md->opndMD[kInsnFirstOpnd];
1366     A64OpndEmitVisitor retVisitor(emitter, retProp);
1367     /* emit ldaxr */
1368     (void)emitter.Emit("\t").Emit("ldaxr").Emit("\t");
1369     retVal->Accept(retVisitor);
1370     (void)emitter.Emit(", [");
1371     tempOpnd0->Accept(visitor);
1372     (void)emitter.Emit("]\n");
1373     /* emit add. */
1374     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1375     tempOpnd1->Accept(retVisitor);
1376     (void)emitter.Emit(", ");
1377     retVal->Accept(retVisitor);
1378     (void)emitter.Emit(", ");
1379     deltaOpnd->Accept(retVisitor);
1380     (void)emitter.Emit("\n");
1381     /* emit stlxr. */
1382     (void)emitter.Emit("\t").Emit("stlxr").Emit("\t");
1383     tempOpnd2->Accept(visitor);
1384     (void)emitter.Emit(", ");
1385     tempOpnd1->Accept(retVisitor);
1386     (void)emitter.Emit(", [");
1387     tempOpnd0->Accept(visitor);
1388     (void)emitter.Emit("]\n");
1389     /* emit cbnz. */
1390     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1391     tempOpnd2->Accept(visitor);
1392     (void)emitter.Emit(", ");
1393     labelOpnd->Accept(visitor);
1394     (void)emitter.Emit("\n");
1395     (void)emitter.Emit("\t//\tend of Unsafe.getAndAddInt.\n");
1396 }
1397 
1398 /*
1399  * intrinsic_get_set_int w0, xt, ws, x1, x2, w3, label
1400  * add    xt, x1, x2
1401  * label:
1402  * ldaxr  w0, [xt]
1403  * stlxr  ws, w3, [xt]
1404  * cbnz   ws, label
1405  */
EmitGetAndSetInt(Emitter & emitter,const Insn & insn) const1406 void AArch64AsmEmitter::EmitGetAndSetInt(Emitter &emitter, const Insn &insn) const
1407 {
1408     /* MOP_get_and_setI and MOP_get_and_setL have 7 operands */
1409     DEBUG_ASSERT(insn.GetOperandSize() > kInsnSeventhOpnd, "ensure the operands number");
1410     Operand *tempOpnd0 = &insn.GetOperand(kInsnSecondOpnd);
1411     Operand *tempOpnd1 = &insn.GetOperand(kInsnThirdOpnd);
1412     Operand *objOpnd = &insn.GetOperand(kInsnFourthOpnd);
1413     Operand *offsetOpnd = &insn.GetOperand(kInsnFifthOpnd);
1414     A64OpndEmitVisitor visitor(emitter, nullptr);
1415     /* add    x1, x1, x2 */
1416     (void)emitter.Emit("\tadd\t");
1417     tempOpnd0->Accept(visitor);
1418     (void)emitter.Emit(", ");
1419     objOpnd->Accept(visitor);
1420     (void)emitter.Emit(", ");
1421     offsetOpnd->Accept(visitor);
1422     (void)emitter.Emit("\n");
1423     Operand *labelOpnd = &insn.GetOperand(kInsnSeventhOpnd);
1424     /* label: */
1425     labelOpnd->Accept(visitor);
1426     (void)emitter.Emit(":\n");
1427     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1428     /* ldaxr  w0, [xt] */
1429     (void)emitter.Emit("\tldaxr\t");
1430     retVal->Accept(visitor);
1431     (void)emitter.Emit(", [");
1432     tempOpnd0->Accept(visitor);
1433     (void)emitter.Emit("]\n");
1434     Operand *newValueOpnd = &insn.GetOperand(kInsnSixthOpnd);
1435     /* stlxr  ws, w3, [xt] */
1436     (void)emitter.Emit("\tstlxr\t");
1437     tempOpnd1->Accept(visitor);
1438     (void)emitter.Emit(", ");
1439     newValueOpnd->Accept(visitor);
1440     (void)emitter.Emit(", [");
1441     tempOpnd0->Accept(visitor);
1442     (void)emitter.Emit("]\n");
1443     /* cbnz   w2, label */
1444     (void)emitter.Emit("\tcbnz\t");
1445     tempOpnd1->Accept(visitor);
1446     (void)emitter.Emit(", ");
1447     labelOpnd->Accept(visitor);
1448     (void)emitter.Emit("\n");
1449 }
1450 
1451 /*
1452  * intrinsic_string_indexof w0, x1, w2, x3, w4, x5, x6, x7, x8, x9, w10,
1453  *                          Label.FIRST_LOOP, Label.STR2_NEXT, Label.STR1_LOOP,
1454  *                          Label.STR1_NEXT, Label.LAST_WORD, Label.NOMATCH, Label.RET
1455  * cmp       w4, w2
1456  * b.gt      .Label.NOMATCH
1457  * sub       w2, w2, w4
1458  * sub       w4, w4, #8
1459  * mov       w10, w2
1460  * uxtw      x4, w4
1461  * uxtw      x2, w2
1462  * add       x3, x3, x4
1463  * add       x1, x1, x2
1464  * neg       x4, x4
1465  * neg       x2, x2
1466  * ldr       x5, [x3,x4]
1467  * .Label.FIRST_LOOP:
1468  * ldr       x7, [x1,x2]
1469  * cmp       x5, x7
1470  * b.eq      .Label.STR1_LOOP
1471  * .Label.STR2_NEXT:
1472  * adds      x2, x2, #1
1473  * b.le      .Label.FIRST_LOOP
1474  * b         .Label.NOMATCH
1475  * .Label.STR1_LOOP:
1476  * adds      x8, x4, #8
1477  * add       x9, x2, #8
1478  * b.ge      .Label.LAST_WORD
1479  * .Label.STR1_NEXT:
1480  * ldr       x6, [x3,x8]
1481  * ldr       x7, [x1,x9]
1482  * cmp       x6, x7
1483  * b.ne      .Label.STR2_NEXT
1484  * adds      x8, x8, #8
1485  * add       x9, x9, #8
1486  * b.lt      .Label.STR1_NEXT
1487  * .Label.LAST_WORD:
1488  * ldr       x6, [x3]
1489  * sub       x9, x1, x4
1490  * ldr       x7, [x9,x2]
1491  * cmp       x6, x7
1492  * b.ne      .Label.STR2_NEXT
1493  * add       w0, w10, w2
1494  * b         .Label.RET
1495  * .Label.NOMATCH:
1496  * mov       w0, #-1
1497  * .Label.RET:
1498  */
EmitStringIndexOf(Emitter & emitter,const Insn & insn) const1499 void AArch64AsmEmitter::EmitStringIndexOf(Emitter &emitter, const Insn &insn) const
1500 {
1501     /* MOP_string_indexof has 18 operands */
1502     DEBUG_ASSERT(insn.GetOperandSize() == 18, "ensure the operands number");
1503     Operand *patternLengthOpnd = &insn.GetOperand(kInsnFifthOpnd);
1504     Operand *srcLengthOpnd = &insn.GetOperand(kInsnThirdOpnd);
1505     const std::string patternLengthReg =
1506         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(patternLengthOpnd)->GetRegisterNumber()];
1507     const std::string srcLengthReg =
1508         AArch64CG::intRegNames[AArch64CG::kR64List][static_cast<RegOperand *>(srcLengthOpnd)->GetRegisterNumber()];
1509     A64OpndEmitVisitor visitor(emitter, nullptr);
1510     /* cmp       w4, w2 */
1511     (void)emitter.Emit("\tcmp\t");
1512     patternLengthOpnd->Accept(visitor);
1513     (void)emitter.Emit(", ");
1514     srcLengthOpnd->Accept(visitor);
1515     (void)emitter.Emit("\n");
1516     /* the 16th operand of MOP_string_indexof is Label.NOMATCH */
1517     Operand *labelNoMatch = &insn.GetOperand(16);
1518     /* b.gt      Label.NOMATCH */
1519     (void)emitter.Emit("\tb.gt\t");
1520     labelNoMatch->Accept(visitor);
1521     (void)emitter.Emit("\n");
1522     /* sub       w2, w2, w4 */
1523     (void)emitter.Emit("\tsub\t");
1524     srcLengthOpnd->Accept(visitor);
1525     (void)emitter.Emit(", ");
1526     srcLengthOpnd->Accept(visitor);
1527     (void)emitter.Emit(", ");
1528     patternLengthOpnd->Accept(visitor);
1529     (void)emitter.Emit("\n");
1530     /* sub       w4, w4, #8 */
1531     (void)emitter.Emit("\tsub\t");
1532     patternLengthOpnd->Accept(visitor);
1533     (void)emitter.Emit(", ");
1534     patternLengthOpnd->Accept(visitor);
1535     (void)emitter.Emit(", #8\n");
1536     /* the 10th operand of MOP_string_indexof is w10 */
1537     Operand *resultTmp = &insn.GetOperand(10);
1538     /* mov       w10, w2 */
1539     (void)emitter.Emit("\tmov\t");
1540     resultTmp->Accept(visitor);
1541     (void)emitter.Emit(", ");
1542     srcLengthOpnd->Accept(visitor);
1543     (void)emitter.Emit("\n");
1544     /* uxtw      x4, w4 */
1545     (void)emitter.Emit("\tuxtw\t").Emit(patternLengthReg);
1546     (void)emitter.Emit(", ");
1547     patternLengthOpnd->Accept(visitor);
1548     (void)emitter.Emit("\n");
1549     /* uxtw      x2, w2 */
1550     (void)emitter.Emit("\tuxtw\t").Emit(srcLengthReg);
1551     (void)emitter.Emit(", ");
1552     srcLengthOpnd->Accept(visitor);
1553     (void)emitter.Emit("\n");
1554     Operand *patternStringBaseOpnd = &insn.GetOperand(kInsnFourthOpnd);
1555     /* add       x3, x3, x4 */
1556     (void)emitter.Emit("\tadd\t");
1557     patternStringBaseOpnd->Accept(visitor);
1558     (void)emitter.Emit(", ");
1559     patternStringBaseOpnd->Accept(visitor);
1560     (void)emitter.Emit(", ").Emit(patternLengthReg);
1561     (void)emitter.Emit("\n");
1562     Operand *srcStringBaseOpnd = &insn.GetOperand(kInsnSecondOpnd);
1563     /* add       x1, x1, x2 */
1564     (void)emitter.Emit("\tadd\t");
1565     srcStringBaseOpnd->Accept(visitor);
1566     (void)emitter.Emit(", ");
1567     srcStringBaseOpnd->Accept(visitor);
1568     (void)emitter.Emit(", ").Emit(srcLengthReg);
1569     (void)emitter.Emit("\n");
1570     /* neg       x4, x4 */
1571     (void)emitter.Emit("\tneg\t").Emit(patternLengthReg);
1572     (void)emitter.Emit(", ").Emit(patternLengthReg);
1573     (void)emitter.Emit("\n");
1574     /* neg       x2, x2 */
1575     (void)emitter.Emit("\tneg\t").Emit(srcLengthReg);
1576     (void)emitter.Emit(", ").Emit(srcLengthReg);
1577     (void)emitter.Emit("\n");
1578     Operand *first = &insn.GetOperand(kInsnSixthOpnd);
1579     /* ldr       x5, [x3,x4] */
1580     (void)emitter.Emit("\tldr\t");
1581     first->Accept(visitor);
1582     (void)emitter.Emit(", [");
1583     patternStringBaseOpnd->Accept(visitor);
1584     (void)emitter.Emit(",").Emit(patternLengthReg);
1585     (void)emitter.Emit("]\n");
1586     /* the 11th operand of MOP_string_indexof is Label.FIRST_LOOP */
1587     Operand *labelFirstLoop = &insn.GetOperand(11);
1588     /* .Label.FIRST_LOOP: */
1589     labelFirstLoop->Accept(visitor);
1590     (void)emitter.Emit(":\n");
1591     /* the 7th operand of MOP_string_indexof is x7 */
1592     Operand *ch2 = &insn.GetOperand(7);
1593     /* ldr       x7, [x1,x2] */
1594     (void)emitter.Emit("\tldr\t");
1595     ch2->Accept(visitor);
1596     (void)emitter.Emit(", [");
1597     srcStringBaseOpnd->Accept(visitor);
1598     (void)emitter.Emit(",").Emit(srcLengthReg);
1599     (void)emitter.Emit("]\n");
1600     /* cmp       x5, x7 */
1601     (void)emitter.Emit("\tcmp\t");
1602     first->Accept(visitor);
1603     (void)emitter.Emit(", ");
1604     ch2->Accept(visitor);
1605     (void)emitter.Emit("\n");
1606     /* the 13th operand of MOP_string_indexof is Label.STR1_LOOP */
1607     Operand *labelStr1Loop = &insn.GetOperand(13);
1608     /* b.eq      .Label.STR1_LOOP */
1609     (void)emitter.Emit("\tb.eq\t");
1610     labelStr1Loop->Accept(visitor);
1611     (void)emitter.Emit("\n");
1612     /* the 12th operand of MOP_string_indexof is Label.STR2_NEXT */
1613     Operand *labelStr2Next = &insn.GetOperand(12);
1614     /* .Label.STR2_NEXT: */
1615     labelStr2Next->Accept(visitor);
1616     (void)emitter.Emit(":\n");
1617     /* adds      x2, x2, #1 */
1618     (void)emitter.Emit("\tadds\t").Emit(srcLengthReg);
1619     (void)emitter.Emit(", ").Emit(srcLengthReg);
1620     (void)emitter.Emit(", #1\n");
1621     /* b.le      .Label.FIRST_LOOP */
1622     (void)emitter.Emit("\tb.le\t");
1623     labelFirstLoop->Accept(visitor);
1624     (void)emitter.Emit("\n");
1625     /* b         .Label.NOMATCH */
1626     (void)emitter.Emit("\tb\t");
1627     labelNoMatch->Accept(visitor);
1628     (void)emitter.Emit("\n");
1629     /* .Label.STR1_LOOP: */
1630     labelStr1Loop->Accept(visitor);
1631     (void)emitter.Emit(":\n");
1632     /* the 8th operand of MOP_string_indexof is x8 */
1633     Operand *tmp1 = &insn.GetOperand(kInsnEighthOpnd);
1634     /* adds      x8, x4, #8 */
1635     (void)emitter.Emit("\tadds\t");
1636     tmp1->Accept(visitor);
1637     (void)emitter.Emit(", ").Emit(patternLengthReg);
1638     (void)emitter.Emit(", #8\n");
1639     /* the 9th operand of MOP_string_indexof is x9 */
1640     Operand *tmp2 = &insn.GetOperand(9);
1641     /* add       x9, x2, #8 */
1642     (void)emitter.Emit("\tadd\t");
1643     tmp2->Accept(visitor);
1644     (void)emitter.Emit(", ").Emit(srcLengthReg);
1645     (void)emitter.Emit(", #8\n");
1646     /* the 15th operand of MOP_string_indexof is Label.LAST_WORD */
1647     Operand *labelLastWord = &insn.GetOperand(15);
1648     /* b.ge      .Label.LAST_WORD */
1649     (void)emitter.Emit("\tb.ge\t");
1650     labelLastWord->Accept(visitor);
1651     (void)emitter.Emit("\n");
1652     /* the 14th operand of MOP_string_indexof is Label.STR1_NEXT */
1653     Operand *labelStr1Next = &insn.GetOperand(14);
1654     /* .Label.STR1_NEXT: */
1655     labelStr1Next->Accept(visitor);
1656     (void)emitter.Emit(":\n");
1657     /* the 6th operand of MOP_string_indexof is x6 */
1658     Operand *ch1 = &insn.GetOperand(6);
1659     /* ldr       x6, [x3,x8] */
1660     (void)emitter.Emit("\tldr\t");
1661     ch1->Accept(visitor);
1662     (void)emitter.Emit(", [");
1663     patternStringBaseOpnd->Accept(visitor);
1664     (void)emitter.Emit(",");
1665     tmp1->Accept(visitor);
1666     (void)emitter.Emit("]\n");
1667     /* ldr       x7, [x1,x9] */
1668     (void)emitter.Emit("\tldr\t");
1669     ch2->Accept(visitor);
1670     (void)emitter.Emit(", [");
1671     srcStringBaseOpnd->Accept(visitor);
1672     (void)emitter.Emit(",");
1673     tmp2->Accept(visitor);
1674     (void)emitter.Emit("]\n");
1675     /* cmp       x6, x7 */
1676     (void)emitter.Emit("\tcmp\t");
1677     ch1->Accept(visitor);
1678     (void)emitter.Emit(", ");
1679     ch2->Accept(visitor);
1680     (void)emitter.Emit("\n");
1681     /* b.ne      .Label.STR2_NEXT */
1682     (void)emitter.Emit("\tb.ne\t");
1683     labelStr2Next->Accept(visitor);
1684     (void)emitter.Emit("\n");
1685     /* adds      x8, x8, #8 */
1686     (void)emitter.Emit("\tadds\t");
1687     tmp1->Accept(visitor);
1688     (void)emitter.Emit(", ");
1689     tmp1->Accept(visitor);
1690     (void)emitter.Emit(", #8\n");
1691     /* add       x9, x9, #8 */
1692     (void)emitter.Emit("\tadd\t");
1693     tmp2->Accept(visitor);
1694     (void)emitter.Emit(", ");
1695     tmp2->Accept(visitor);
1696     (void)emitter.Emit(", #8\n");
1697     /* b.lt      .Label.STR1_NEXT */
1698     (void)emitter.Emit("\tb.lt\t");
1699     labelStr1Next->Accept(visitor);
1700     (void)emitter.Emit("\n");
1701     /* .Label.LAST_WORD: */
1702     labelLastWord->Accept(visitor);
1703     (void)emitter.Emit(":\n");
1704     /* ldr       x6, [x3] */
1705     (void)emitter.Emit("\tldr\t");
1706     ch1->Accept(visitor);
1707     (void)emitter.Emit(", [");
1708     patternStringBaseOpnd->Accept(visitor);
1709     (void)emitter.Emit("]\n");
1710     /* sub       x9, x1, x4 */
1711     (void)emitter.Emit("\tsub\t");
1712     tmp2->Accept(visitor);
1713     (void)emitter.Emit(", ");
1714     srcStringBaseOpnd->Accept(visitor);
1715     (void)emitter.Emit(", ").Emit(patternLengthReg);
1716     (void)emitter.Emit("\n");
1717     /* ldr       x7, [x9,x2] */
1718     (void)emitter.Emit("\tldr\t");
1719     ch2->Accept(visitor);
1720     (void)emitter.Emit(", [");
1721     tmp2->Accept(visitor);
1722     (void)emitter.Emit(", ").Emit(srcLengthReg);
1723     (void)emitter.Emit("]\n");
1724     /* cmp       x6, x7 */
1725     (void)emitter.Emit("\tcmp\t");
1726     ch1->Accept(visitor);
1727     (void)emitter.Emit(", ");
1728     ch2->Accept(visitor);
1729     (void)emitter.Emit("\n");
1730     /* b.ne      .Label.STR2_NEXT */
1731     (void)emitter.Emit("\tb.ne\t");
1732     labelStr2Next->Accept(visitor);
1733     (void)emitter.Emit("\n");
1734     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1735     /* add       w0, w10, w2 */
1736     (void)emitter.Emit("\tadd\t");
1737     retVal->Accept(visitor);
1738     (void)emitter.Emit(", ");
1739     resultTmp->Accept(visitor);
1740     (void)emitter.Emit(", ");
1741     srcLengthOpnd->Accept(visitor);
1742     (void)emitter.Emit("\n");
1743     /* the 17th operand of MOP_string_indexof Label.ret */
1744     Operand *labelRet = &insn.GetOperand(17);
1745     /* b         .Label.ret */
1746     (void)emitter.Emit("\tb\t");
1747     labelRet->Accept(visitor);
1748     (void)emitter.Emit("\n");
1749     /* .Label.NOMATCH: */
1750     labelNoMatch->Accept(visitor);
1751     (void)emitter.Emit(":\n");
1752     /* mov       w0, #-1 */
1753     (void)emitter.Emit("\tmov\t");
1754     retVal->Accept(visitor);
1755     (void)emitter.Emit(", #-1\n");
1756     /* .Label.ret: */
1757     labelRet->Accept(visitor);
1758     (void)emitter.Emit(":\n");
1759 }
1760 
1761 /*
1762  * intrinsic_compare_swap_int x0, xt, xs, x1, x2, w3, w4, lable1, label2
1763  * add       xt, x1, x2
1764  * label1:
1765  * ldaxr     ws, [xt]
1766  * cmp       ws, w3
1767  * b.ne      label2
1768  * stlxr     ws, w4, [xt]
1769  * cbnz      ws, label1
1770  * label2:
1771  * cset      x0, eq
1772  */
EmitCompareAndSwapInt(Emitter & emitter,const Insn & insn) const1773 void AArch64AsmEmitter::EmitCompareAndSwapInt(Emitter &emitter, const Insn &insn) const
1774 {
1775     /* MOP_compare_and_swapI and MOP_compare_and_swapL have 8 operands */
1776     DEBUG_ASSERT(insn.GetOperandSize() > kInsnEighthOpnd, "ensure the operands number");
1777     const MOperator mOp = insn.GetMachineOpcode();
1778     const InsnDesc *md = &AArch64CG::kMd[mOp];
1779     Operand *temp0 = &insn.GetOperand(kInsnSecondOpnd);
1780     Operand *temp1 = &insn.GetOperand(kInsnThirdOpnd);
1781     Operand *obj = &insn.GetOperand(kInsnFourthOpnd);
1782     Operand *offset = &insn.GetOperand(kInsnFifthOpnd);
1783     A64OpndEmitVisitor visitor(emitter, nullptr);
1784     /* add       xt, x1, x2 */
1785     (void)emitter.Emit("\tadd\t");
1786     temp0->Accept(visitor);
1787     (void)emitter.Emit(", ");
1788     obj->Accept(visitor);
1789     (void)emitter.Emit(", ");
1790     offset->Accept(visitor);
1791     (void)emitter.Emit("\n");
1792     Operand *label1 = &insn.GetOperand(kInsnEighthOpnd);
1793     /* label1: */
1794     label1->Accept(visitor);
1795     (void)emitter.Emit(":\n");
1796     /* ldaxr     ws, [xt] */
1797     (void)emitter.Emit("\tldaxr\t");
1798     temp1->Accept(visitor);
1799     (void)emitter.Emit(", [");
1800     temp0->Accept(visitor);
1801     (void)emitter.Emit("]\n");
1802     Operand *expectedValue = &insn.GetOperand(kInsnSixthOpnd);
1803     const OpndDesc *expectedValueProp = md->opndMD[kInsnSixthOpnd];
1804     /* cmp       ws, w3 */
1805     (void)emitter.Emit("\tcmp\t");
1806     temp1->Accept(visitor);
1807     (void)emitter.Emit(", ");
1808     A64OpndEmitVisitor visitorExpect(emitter, expectedValueProp);
1809     expectedValue->Accept(visitorExpect);
1810     (void)emitter.Emit("\n");
1811     constexpr uint32 kInsnNinethOpnd = 8;
1812     Operand *label2 = &insn.GetOperand(kInsnNinethOpnd);
1813     /* b.ne      label2 */
1814     (void)emitter.Emit("\tbne\t");
1815     label2->Accept(visitor);
1816     (void)emitter.Emit("\n");
1817     Operand *newValue = &insn.GetOperand(kInsnSeventhOpnd);
1818     /* stlxr     ws, w4, [xt] */
1819     (void)emitter.Emit("\tstlxr\t");
1820     (void)emitter.Emit(
1821         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1822     (void)emitter.Emit(", ");
1823     newValue->Accept(visitor);
1824     (void)emitter.Emit(", [");
1825     temp0->Accept(visitor);
1826     (void)emitter.Emit("]\n");
1827     /* cbnz      ws, label1 */
1828     (void)emitter.Emit("\tcbnz\t");
1829     (void)emitter.Emit(
1830         AArch64CG::intRegNames[AArch64CG::kR32List][static_cast<RegOperand *>(temp1)->GetRegisterNumber()]);
1831     (void)emitter.Emit(", ");
1832     label1->Accept(visitor);
1833     (void)emitter.Emit("\n");
1834     /* label2: */
1835     label2->Accept(visitor);
1836     (void)emitter.Emit(":\n");
1837     Operand *retVal = &insn.GetOperand(kInsnFirstOpnd);
1838     /* cset      x0, eq */
1839     (void)emitter.Emit("\tcset\t");
1840     retVal->Accept(visitor);
1841     (void)emitter.Emit(", EQ\n");
1842 }
1843 
EmitCTlsDescRel(Emitter & emitter,const Insn & insn) const1844 void AArch64AsmEmitter::EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const
1845 {
1846     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_rel];
1847     Operand *result = &insn.GetOperand(kInsnFirstOpnd);
1848     Operand *src = &insn.GetOperand(kInsnSecondOpnd);
1849     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1850     auto stImmOpnd = static_cast<StImmOperand *>(symbol);
1851     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[0]);
1852     A64OpndEmitVisitor srcVisitor(emitter, md->opndMD[1]);
1853     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1854     result->Accept(resultVisitor);
1855     (void)emitter.Emit(", ");
1856     src->Accept(srcVisitor);
1857     (void)emitter.Emit(", #:tprel_hi12:").Emit(stImmOpnd->GetName()).Emit(", lsl #12\n");
1858     (void)emitter.Emit("\t").Emit("add").Emit("\t");
1859     result->Accept(resultVisitor);
1860     (void)emitter.Emit(", ");
1861     result->Accept(resultVisitor);
1862     (void)emitter.Emit(", #:tprel_lo12_nc:").Emit(stImmOpnd->GetName()).Emit("\n");
1863 }
1864 
EmitCTlsDescCall(Emitter & emitter,const Insn & insn) const1865 void AArch64AsmEmitter::EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const
1866 {
1867     const InsnDesc *md = &AArch64CG::kMd[MOP_tls_desc_call];
1868     Operand *func = &insn.GetOperand(kInsnFirstOpnd);
1869     Operand *symbol = &insn.GetOperand(kInsnThirdOpnd);
1870     const OpndDesc *prop = md->opndMD[0];
1871     auto *stImmOpnd = static_cast<StImmOperand *>(symbol);
1872     const std::string &symName = stImmOpnd->GetName();
1873     A64OpndEmitVisitor funcVisitor(emitter, prop);
1874     /*  adrp    x0, :tlsdesc:symbol */
1875     (void)emitter.Emit("\t").Emit("adrp\tx0, :tlsdesc:").Emit(symName).Emit("\n");
1876     /*  ldr x1, [x0, #tlsdesc_lo12:symbol] */
1877     (void)emitter.Emit("\t").Emit("ldr").Emit("\t");
1878     func->Accept(funcVisitor);
1879     (void)emitter.Emit(", [x0, #:tlsdesc_lo12:").Emit(symName).Emit("]\n");
1880     /*  add x0 ,#tlsdesc_lo12:symbol */
1881     (void)emitter.Emit("\t").Emit("add\tx0, x0, :tlsdesc_lo12:").Emit(symName).Emit("\n");
1882     /* .tlsdesccall <symbolName> */
1883     (void)emitter.Emit("\t").Emit(".tlsdesccall").Emit("\t").Emit(symName).Emit("\n");
1884     /* blr xd */
1885     (void)emitter.Emit("\t").Emit("blr").Emit("\t");
1886     func->Accept(funcVisitor);
1887     (void)emitter.Emit("\n");
1888 }
1889 
EmitSyncLockTestSet(Emitter & emitter,const Insn & insn) const1890 void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const
1891 {
1892     const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()];
1893     auto *result = &insn.GetOperand(kInsnFirstOpnd);
1894     auto *temp = &insn.GetOperand(kInsnSecondOpnd);
1895     auto *addr = &insn.GetOperand(kInsnThirdOpnd);
1896     auto *value = &insn.GetOperand(kInsnFourthOpnd);
1897     auto *label = &insn.GetOperand(kInsnFifthOpnd);
1898     A64OpndEmitVisitor resultVisitor(emitter, md->opndMD[kInsnFirstOpnd]);
1899     A64OpndEmitVisitor tempVisitor(emitter, md->opndMD[kInsnSecondOpnd]);
1900     A64OpndEmitVisitor addrVisitor(emitter, md->opndMD[kInsnThirdOpnd]);
1901     A64OpndEmitVisitor valueVisitor(emitter, md->opndMD[kInsnFourthOpnd]);
1902     A64OpndEmitVisitor labelVisitor(emitter, md->opndMD[kInsnFifthOpnd]);
1903     /* label: */
1904     label->Accept(labelVisitor);
1905     (void)emitter.Emit(":\n");
1906     /* ldxr x0, [x2] */
1907     (void)emitter.Emit("\t").Emit("ldxr").Emit("\t");
1908     result->Accept(resultVisitor);
1909     (void)emitter.Emit(", [");
1910     addr->Accept(addrVisitor);
1911     (void)emitter.Emit("]\n");
1912     /* stxr w1, x3, [x2] */
1913     (void)emitter.Emit("\t").Emit("stxr").Emit("\t");
1914     temp->Accept(tempVisitor);
1915     (void)emitter.Emit(", ");
1916     value->Accept(valueVisitor);
1917     (void)emitter.Emit(", [");
1918     addr->Accept(addrVisitor);
1919     (void)emitter.Emit("]\n");
1920     /* cbnz w1, label */
1921     (void)emitter.Emit("\t").Emit("cbnz").Emit("\t");
1922     temp->Accept(tempVisitor);
1923     (void)emitter.Emit(", ");
1924     label->Accept(labelVisitor);
1925     (void)emitter.Emit("\n");
1926     /* dmb ish */
1927     (void)emitter.Emit("\t").Emit("dmb").Emit("\t").Emit("ish").Emit("\n");
1928 }
1929 
EmitCheckThrowPendingException(Emitter & emitter,Insn & insn) const1930 void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const
1931 {
1932     /*
1933      * mrs x16, TPIDR_EL0
1934      * ldr x16, [x16, #64]
1935      * ldr x16, [x16, #8]
1936      * cbz x16, .lnoexception
1937      * bl MCC_ThrowPendingException
1938      * .lnoexception:
1939      */
1940     (void)emitter.Emit("\t").Emit("mrs").Emit("\tx16, TPIDR_EL0");
1941     (void)emitter.Emit("\n");
1942     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #64]");
1943     (void)emitter.Emit("\n");
1944     (void)emitter.Emit("\t").Emit("ldr").Emit("\tx16, [x16, #8]");
1945     (void)emitter.Emit("\n");
1946     (void)emitter.Emit("\t").Emit("cbz").Emit("\tx16, .lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName());
1947     (void)emitter.Emit("\n");
1948     (void)emitter.Emit("\t").Emit("bl").Emit("\tMCC_ThrowPendingException");
1949     (void)emitter.Emit("\n");
1950     (void)emitter.Emit(".lnoeh.").Emit(maplebe::CG::GetCurCGFunc()->GetName()).Emit(":");
1951     (void)emitter.Emit("\n");
1952 }
1953 
EmitLazyBindingRoutine(Emitter & emitter,const Insn & insn) const1954 void AArch64AsmEmitter::EmitLazyBindingRoutine(Emitter &emitter, const Insn &insn) const
1955 {
1956     /* ldr xzr, [xs] */
1957     const InsnDesc *md = &AArch64CG::kMd[MOP_adrp_ldr];
1958 
1959     Operand *opnd0 = &insn.GetOperand(kInsnFirstOpnd);
1960     const OpndDesc *prop0 = md->opndMD[0];
1961     A64OpndEmitVisitor visitor(emitter, prop0);
1962 
1963     /* emit "ldr  xzr,[xs]" */
1964 #ifdef USE_32BIT_REF
1965     (void)emitter.Emit("\t").Emit("ldr").Emit("\twzr, [");
1966 #else
1967     (void)emitter.Emit("\t").Emit("ldr").Emit("\txzr, [");
1968 #endif /* USE_32BIT_REF */
1969     opnd0->Accept(visitor);
1970     (void)emitter.Emit("]");
1971     (void)emitter.Emit("\t// Lazy binding\n");
1972 }
1973 
PrepareVectorOperand(RegOperand * regOpnd,uint32 & compositeOpnds,Insn & insn) const1974 void AArch64AsmEmitter::PrepareVectorOperand(RegOperand *regOpnd, uint32 &compositeOpnds, Insn &insn) const
1975 {
1976     VectorRegSpec *vecSpec = static_cast<VectorInsn &>(insn).GetAndRemoveRegSpecFromList();
1977     compositeOpnds = vecSpec->compositeOpnds ? vecSpec->compositeOpnds : compositeOpnds;
1978     regOpnd->SetVecLanePosition(vecSpec->vecLane);
1979     switch (insn.GetMachineOpcode()) {
1980         case MOP_vanduuu:
1981         case MOP_vxoruuu:
1982         case MOP_voruuu:
1983         case MOP_vnotuu:
1984         case MOP_vextuuui: {
1985             regOpnd->SetVecLaneSize(k8ByteSize);
1986             regOpnd->SetVecElementSize(k8BitSize);
1987             break;
1988         }
1989         case MOP_vandvvv:
1990         case MOP_vxorvvv:
1991         case MOP_vorvvv:
1992         case MOP_vnotvv:
1993         case MOP_vextvvvi: {
1994             regOpnd->SetVecLaneSize(k16ByteSize);
1995             regOpnd->SetVecElementSize(k8BitSize);
1996             break;
1997         }
1998         default: {
1999             regOpnd->SetVecLaneSize(vecSpec->vecLaneMax);
2000             regOpnd->SetVecElementSize(vecSpec->vecElementSize);
2001             break;
2002         }
2003     }
2004 }
2005 
2006 struct CfiDescr {
2007     const std::string name;
2008     uint32 opndCount;
2009     /* create 3 OperandType array to store cfi instruction's operand type */
2010     std::array<Operand::OperandType, 3> opndTypes;
2011 };
2012 
2013 static CfiDescr cfiDescrTable[cfi::kOpCfiLast + 1] = {
2014 #define CFI_DEFINE(k, sub, n, o0, o1, o2) {".cfi_" #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
2015 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) \
2016     {"." #k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
2017 #include "cfi.def"
2018 #undef CFI_DEFINE
2019 #undef ARM_DIRECTIVES_DEFINE
2020     {".cfi_undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
2021 
EmitAArch64CfiInsn(Emitter & emitter,const Insn & insn) const2022 void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) const
2023 {
2024     MOperator mOp = insn.GetMachineOpcode();
2025     CfiDescr &cfiDescr = cfiDescrTable[mOp];
2026     (void)emitter.Emit("\t").Emit(cfiDescr.name);
2027     for (uint32 i = 0; i < cfiDescr.opndCount; ++i) {
2028         (void)emitter.Emit(" ");
2029         Operand &curOperand = insn.GetOperand(i);
2030         cfi::CFIOpndEmitVisitor cfiOpndEmitVisitor(emitter);
2031         curOperand.Accept(cfiOpndEmitVisitor);
2032         if (i < (cfiDescr.opndCount - 1)) {
2033             (void)emitter.Emit(",");
2034         }
2035     }
2036     (void)emitter.Emit("\n");
2037 }
2038 
2039 struct DbgDescr {
2040     const std::string name;
2041     uint32 opndCount;
2042     /* create 3 OperandType array to store dbg instruction's operand type */
2043     std::array<Operand::OperandType, 3> opndTypes;
2044 };
2045 
2046 static DbgDescr dbgDescrTable[mpldbg::kOpDbgLast + 1] = {
2047 #define DBG_DEFINE(k, sub, n, o0, o1, o2) {#k, n, {Operand::kOpd##o0, Operand::kOpd##o1, Operand::kOpd##o2}},
2048 #include "dbg.def"
2049 #undef DBG_DEFINE
2050     {"undef", 0, {Operand::kOpdUndef, Operand::kOpdUndef, Operand::kOpdUndef}}};
2051 
EmitAArch64DbgInsn(Emitter & emitter,const Insn & insn) const2052 void AArch64AsmEmitter::EmitAArch64DbgInsn(Emitter &emitter, const Insn &insn) const
2053 {
2054     MOperator mOp = insn.GetMachineOpcode();
2055     DbgDescr &dbgDescr = dbgDescrTable[mOp];
2056     (void)emitter.Emit("\t.").Emit(dbgDescr.name);
2057     for (uint32 i = 0; i < dbgDescr.opndCount; ++i) {
2058         (void)emitter.Emit(" ");
2059         Operand &curOperand = insn.GetOperand(i);
2060         mpldbg::DBGOpndEmitVisitor dbgOpndEmitVisitor(emitter);
2061         curOperand.Accept(dbgOpndEmitVisitor);
2062     }
2063     (void)emitter.Emit("\n");
2064 }
2065 
CheckInsnRefField(const Insn & insn,size_t opndIndex) const2066 bool AArch64AsmEmitter::CheckInsnRefField(const Insn &insn, size_t opndIndex) const
2067 {
2068     if (insn.IsAccessRefField() && insn.AccessMem()) {
2069         Operand &opnd0 = insn.GetOperand(opndIndex);
2070         if (opnd0.IsRegister()) {
2071             static_cast<RegOperand &>(opnd0).SetRefField(true);
2072             return true;
2073         }
2074     }
2075     return false;
2076 }
2077 
2078 /* new phase manager */
PhaseRun(maplebe::CGFunc & f)2079 bool CgEmission::PhaseRun(maplebe::CGFunc &f)
2080 {
2081     Emitter *emitter = f.GetCG()->GetEmitter();
2082     CHECK_NULL_FATAL(emitter);
2083     if (CGOptions::GetEmitFileType() == CGOptions::kAsm) {
2084         AsmFuncEmitInfo funcEmitInfo(f);
2085         emitter->EmitLocalVariable(f);
2086         static_cast<AArch64AsmEmitter *>(emitter)->Run(funcEmitInfo);
2087         emitter->EmitHugeSoRoutines();
2088     } else {
2089         FuncEmitInfo &funcEmitInfo = static_cast<AArch64ObjEmitter *>(emitter)->CreateFuncEmitInfo(f);
2090         static_cast<AArch64ObjEmitter *>(emitter)->Run(funcEmitInfo);
2091         f.SetFuncEmitInfo(&funcEmitInfo);
2092     }
2093 
2094     return false;
2095 }
2096 MAPLE_TRANSFORM_PHASE_REGISTER(CgEmission, cgemit)
2097 } /* namespace maplebe */
2098