• 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 "emit.h"
17 #if TARGAARCH64
18 #include "aarch64_obj_emitter.h"
19 #include "aarch64_emitter.h"
20 #endif
21 #if TARGX86_64
22 #include "x64_emitter.h"
23 #endif
24 #include <unistd.h>
25 #ifdef _WIN32
26 #include <direct.h>
27 #endif
28 #include "reflection_analysis.h"
29 #include "muid_replacement.h"
30 #include "metadata_layout.h"
31 using namespace namemangler;
32 
33 namespace {
34 using namespace maple;
35 #ifdef ARK_LITECG_DEBUG
36 constexpr uint32 kSizeOfHugesoRoutine = 3;
37 constexpr uint32 kFromDefIndexMask32Mod = 0x40000000;
38 const std::string DEFAULT_PATH = "/data/local/tmp/aot_code_comment.txt";
39 
GetPrimitiveTypeSize(const std::string & name)40 int32 GetPrimitiveTypeSize(const std::string &name)
41 {
42     if (name.length() != 1) {
43         return -1;
44     }
45     char typeName = name[0];
46     switch (typeName) {
47         case 'Z':
48             return static_cast<int32>(GetPrimTypeSize(PTY_u1));
49         case 'B':
50             return static_cast<int32>(GetPrimTypeSize(PTY_i8));
51         case 'S':
52             return static_cast<int32>(GetPrimTypeSize(PTY_i16));
53         case 'C':
54             return static_cast<int32>(GetPrimTypeSize(PTY_u16));
55         case 'I':
56             return static_cast<int32>(GetPrimTypeSize(PTY_i32));
57         case 'J':
58             return static_cast<int32>(GetPrimTypeSize(PTY_i64));
59         case 'F':
60             return static_cast<int32>(GetPrimTypeSize(PTY_f32));
61         case 'D':
62             return static_cast<int32>(GetPrimTypeSize(PTY_f64));
63         case 'V':
64             return static_cast<int32>(GetPrimTypeSize(PTY_void));
65         default:
66             return -1;
67     }
68 }
69 #endif
70 }  // namespace
71 
72 namespace maplebe {
73 using namespace maple;
74 using namespace cfi;
75 
EmitLabelRef(LabelIdx labIdx)76 void Emitter::EmitLabelRef(LabelIdx labIdx)
77 {
78 #ifdef ARK_LITECG_DEBUG
79     CHECK_NULL_FATAL(GetCG()->GetMIRModule()->CurFunction());
80     PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
81     char *idx = strdup(std::to_string(pIdx).c_str());
82     CHECK_FATAL(idx != nullptr, "strdup failed");
83     outStream << ".L." << idx << "__" << labIdx;
84     free(idx);
85     idx = nullptr;
86 #endif
87 }
88 
EmitStmtLabel(LabelIdx labIdx)89 void Emitter::EmitStmtLabel(LabelIdx labIdx)
90 {
91 #ifdef ARK_LITECG_DEBUG
92     EmitLabelRef(labIdx);
93     outStream << ":\n";
94 #endif
95 }
96 
EmitLabelForFunc(const MIRFunction * func,LabelIdx labIdx)97 void Emitter::EmitLabelForFunc(const MIRFunction *func, LabelIdx labIdx)
98 {
99 #ifdef ARK_LITECG_DEBUG
100     DEBUG_ASSERT(func != nullptr, "null ptr check");
101     char *idx = strdup(std::to_string(func->GetPuidx()).c_str());
102     CHECK_FATAL(idx != nullptr, "strdup failed");
103     outStream << ".L." << idx << "__" << labIdx;
104     free(idx);
105     idx = nullptr;
106 #endif
107 }
108 
GetTypeAsmInfoName(PrimType primType) const109 AsmLabel Emitter::GetTypeAsmInfoName(PrimType primType) const
110 {
111 #ifdef ARK_LITECG_DEBUG
112     uint32 size = GetPrimTypeSize(primType);
113     /* case x : x occupies bytes of pty */
114     switch (size) {
115         case k1ByteSize:
116             return kAsmByte;
117         case k2ByteSize:
118             if (GetCG()->GetTargetMachine()->isAArch64() || GetCG()->GetTargetMachine()->isRiscV()) {
119                 return kAsmShort;
120             } else {
121                 return kAsmValue;
122             }
123         case k4ByteSize:
124             return kAsmLong;
125         case k8ByteSize:
126             return kAsmQuad;
127         default:
128             DEBUG_ASSERT(false, "NYI");
129             break;
130     }
131 #endif
132     return kAsmLong;
133 }
134 
EmitFileInfo(const std::string & fileName)135 void Emitter::EmitFileInfo(const std::string &fileName)
136 {
137 #ifdef ARK_LITECG_DEBUG
138 #if defined(_WIN32) || defined(DARWIN) || defined(__APPLE__)
139     char *curDirName = getcwd(nullptr, 0);
140 #else
141     char *curDirName = get_current_dir_name();
142 #endif
143     CHECK_FATAL(curDirName != nullptr, "null ptr check ");
144     Emit(asmInfo->GetCmnt());
145     std::string path(curDirName);
146 #ifdef _WIN32
147     std::string cgFile(path.append("\\mplcg"));
148 #else
149     std::string cgFile(path.append("/mplcg"));
150 #endif
151     Emit(cgFile);
152     Emit("\n");
153 
154     std::string compile("Compiling ");
155     Emit(asmInfo->GetCmnt());
156     Emit(compile);
157     Emit("\n");
158 
159     std::string beOptions("Be options");
160     Emit(asmInfo->GetCmnt());
161     Emit(beOptions);
162     Emit("\n");
163 
164     path = curDirName;
165     path.append("/").append(fileName);
166     /* strip path before out/ */
167     std::string out = "/out/";
168     size_t pos = path.find(out.c_str(), 0, out.length());
169     if (pos != std::string::npos) {
170         path.erase(0, pos + 1);
171     }
172     std::string irFile("\"");
173     irFile.append(path).append("\"");
174     Emit(asmInfo->GetFile());
175     Emit(irFile);
176     Emit("\n");
177 
178     /* save directory path in index 8 */
179     SetFileMapValue(0, path);
180 
181     /* .file #num src_file_name */
182     if (cg->GetCGOptions().WithLoc()) {
183         /* .file 1 mpl_file_name */
184         if (cg->GetCGOptions().WithAsm()) {
185             Emit("\t// ");
186         }
187         Emit(asmInfo->GetFile());
188         Emit("1 ");
189         Emit(irFile);
190         Emit("\n");
191         SetFileMapValue(1, irFile); /* save ir file in 1 */
192         if (cg->GetCGOptions().WithSrc()) {
193             /* insert a list of src files */
194             uint32 i = 2;
195             for (auto it : cg->GetMIRModule()->GetSrcFileInfo()) {
196                 if (cg->GetCGOptions().WithAsm()) {
197                     Emit("\t// ");
198                 }
199                 Emit(asmInfo->GetFile());
200                 Emit(it.second).Emit(" \"");
201                 std::string kStr = GlobalTables::GetStrTable().GetStringFromStrIdx(it.first);
202                 Emit(kStr);
203                 Emit("\"\n");
204                 SetFileMapValue(i++, kStr);
205             }
206         }
207     }
208     free(curDirName);
209 
210     EmitInlineAsmSection();
211 #if TARGARM32
212     Emit("\t.syntax unified\n");
213     /*
214      * "The arm instruction set is a subset of
215      *  the most commonly used 32-bit ARM instructions."
216      * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0210c/CACBCAAE.html
217      */
218     Emit("\t.arm\n");
219     Emit("\t.fpu vfpv4\n");
220     Emit("\t.arch armv7-a\n");
221     Emit("\t.eabi_attribute Tag_ABI_PCS_RW_data, 1\n");
222     Emit("\t.eabi_attribute Tag_ABI_PCS_RO_data, 1\n");
223     Emit("\t.eabi_attribute Tag_ABI_PCS_GOT_use, 2\n");
224     Emit("\t.eabi_attribute Tag_ABI_VFP_args, 1\n");
225     Emit("\t.eabi_attribute Tag_ABI_FP_denormal, 1\n");
226     Emit("\t.eabi_attribute Tag_ABI_FP_exceptions, 1\n");
227     Emit("\t.eabi_attribute Tag_ABI_FP_number_model, 3\n");
228     Emit("\t.eabi_attribute Tag_ABI_align_needed, 1\n");
229     Emit("\t.eabi_attribute Tag_ABI_align_preserved, 1\n");
230     Emit("\t.eabi_attribute Tag_ABI_enum_size, 2\n");
231     Emit("\t.eabi_attribute 30, 6\n");
232     Emit("\t.eabi_attribute Tag_CPU_unaligned_access, 1\n");
233     Emit("\t.eabi_attribute Tag_ABI_PCS_wchar_t, 4\n");
234 #endif /* TARGARM32 */
235 #endif
236 }
237 
EmitInlineAsmSection()238 void Emitter::EmitInlineAsmSection()
239 {
240 #ifdef ARK_LITECG_DEBUG
241     MapleVector<MapleString> &asmSections = cg->GetMIRModule()->GetAsmDecls();
242     if (!asmSections.empty()) {
243         Emit("#APP\n");
244         for (auto &singleSection : asmSections) {
245             Emit("\t");
246             Emit(singleSection);
247             Emit("\n");
248         }
249         Emit("#NO_APP\n");
250     }
251 #endif
252 }
EmitAsmLabel(AsmLabel label)253 void Emitter::EmitAsmLabel(AsmLabel label)
254 {
255 #ifdef ARK_LITECG_DEBUG
256     switch (label) {
257         case kAsmData: {
258             (void)Emit(asmInfo->GetData());
259             (void)Emit("\n");
260             return;
261         }
262         case kAsmText: {
263             (void)Emit(asmInfo->GetText());
264             (void)Emit("\n");
265             return;
266         }
267         case kAsmType: {
268             (void)Emit(asmInfo->GetType());
269             return;
270         }
271         case kAsmByte: {
272             (void)Emit(asmInfo->GetByte());
273             return;
274         }
275         case kAsmShort: {
276             (void)Emit(asmInfo->GetShort());
277             return;
278         }
279         case kAsmValue: {
280             (void)Emit(asmInfo->GetValue());
281             return;
282         }
283         case kAsmLong: {
284             (void)Emit(asmInfo->GetLong());
285             return;
286         }
287         case kAsmQuad: {
288             (void)Emit(asmInfo->GetQuad());
289             return;
290         }
291         case kAsmZero:
292             (void)Emit(asmInfo->GetZero());
293             return;
294         default:
295             DEBUG_ASSERT(false, "should not run here");
296             return;
297     }
298 #endif
299 }
300 
EmitAsmLabel(const MIRSymbol & mirSymbol,AsmLabel label)301 void Emitter::EmitAsmLabel(const MIRSymbol &mirSymbol, AsmLabel label)
302 {
303 #ifdef ARK_LITECG_DEBUG
304     MIRType *mirType = mirSymbol.GetType();
305     std::string symName;
306     if (mirSymbol.GetStorageClass() == kScPstatic && mirSymbol.IsLocal()) {
307         GetCG()->GetMIRModule()->CurFunction();
308         PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
309         symName = mirSymbol.GetName() + std::to_string(pIdx);
310     } else {
311         symName = mirSymbol.GetName();
312     }
313     if (mirSymbol.GetAsmAttr() != UStrIdx(0) &&
314         (mirSymbol.GetStorageClass() == kScPstatic || mirSymbol.GetStorageClass() == kScPstatic)) {
315         std::string asmSection = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol.GetAsmAttr());
316         symName = asmSection;
317     }
318     if (Globals::GetInstance()->GetBECommon()->IsEmptyOfTypeAlignTable()) {
319         DEBUG_ASSERT(false, "container empty check");
320     }
321 
322     switch (label) {
323         case kAsmGlbl: {
324             Emit(asmInfo->GetGlobal());
325             Emit(symName);
326             Emit("\n");
327             return;
328         }
329         case kAsmHidden: {
330             Emit(asmInfo->GetHidden());
331             Emit(symName);
332             Emit("\n");
333             return;
334         }
335         case kAsmLocal: {
336             Emit(asmInfo->GetLocal());
337             Emit(symName);
338             Emit("\n");
339             return;
340         }
341         case kAsmWeak: {
342             Emit(asmInfo->GetWeak());
343             Emit(symName);
344             Emit("\n");
345             return;
346         }
347         case kAsmZero: {
348             uint64 size = Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex());
349             EmitNullConstant(size);
350             return;
351         }
352         case kAsmComm: {
353             std::string size;
354             if (isFlexibleArray) {
355                 size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()) +
356                                       arraySize);
357             } else {
358                 size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()));
359             }
360             (void)Emit(asmInfo->GetComm()).Emit(symName).Emit(", ").Emit(size).Emit(", ");
361 #if PECOFF
362             if (GetCG()->GetTargetMachine()->isAArch64() ||
363                 GetCG()->GetTargetMachine()->isRiscV() || GetCG()->GetTargetMachine()->isArm32() ||
364                 GetCG()->GetTargetMachine()->isArk()) {
365                 std::string align = std::to_string(
366                     static_cast<int>(
367                         log2(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex()))));
368             else {
369                 std::string align =
370                     std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex()));
371             }
372             emit(align.c_str());
373 #else /* ELF */
374             /* output align, symbol name begin with "classInitProtectRegion" align is 4096 */
375             if (symName.find("classInitProtectRegion") == 0) {
376                 Emit(4096);  // symbol name begin with "classInitProtectRegion" align is 4096
377             } else {
378                 (void)Emit(
379                     std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex())));
380             }
381 #endif
382             Emit("\n");
383             return;
384         }
385         case kAsmAlign: {
386             uint8 align = mirSymbol.GetAttrs().GetAlignValue();
387             if (align == 0) {
388                 align = Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirSymbol.GetType()->GetTypeIndex());
389                 if (GetCG()->GetTargetMachine()->isAArch64() || GetCG()->GetTargetMachine()->isRiscV() ||
390                     GetCG()->GetTargetMachine()->isArm32() || GetCG()->GetTargetMachine()->isArk()) {
391                     align = static_cast<uint8>(log2(align));
392                 }
393             }
394             Emit(asmInfo->GetAlign());
395             Emit(std::to_string(align));
396             Emit("\n");
397             return;
398         }
399         case kAsmSyname: {
400             Emit(symName);
401             Emit(":\n");
402             return;
403         }
404         case kAsmSize: {
405             Emit(asmInfo->GetSize());
406             Emit(symName);
407             Emit(", ");
408             if (GetCG()->GetTargetMachine()->isX8664()) {
409                 Emit(".-");
410                 Emit(symName);
411             } else {
412                 std::string size;
413                 if (isFlexibleArray) {
414                     size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()) +
415                                         arraySize);
416                 } else {
417                     size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()));
418                 }
419                 Emit(size);
420             }
421             Emit("\n");
422             return;
423         }
424         case kAsmType: {
425             Emit(asmInfo->GetType());
426             Emit(symName);
427             Emit(",");
428             Emit(asmInfo->GetAtobt());
429             Emit("\n");
430             return;
431         }
432         default:
433             DEBUG_ASSERT(false, "should not run here");
434             return;
435     }
436 #endif
437 }
438 
439 void Emitter::EmitNullConstant(uint64 size)
440 {
441 #ifdef ARK_LITECG_DEBUG
442     EmitAsmLabel(kAsmZero);
443     Emit(std::to_string(size));
444     Emit("\n");
445 #endif
446 }
447 
448 void Emitter::EmitFunctionSymbolTable(FuncEmitInfo &funcEmitInfo)
449 {
450 #ifdef ARK_LITECG_DEBUG
451     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
452     MIRFunction *func = &cgFunc.GetFunction();
453 
454     size_t size =
455         (func == nullptr) ? GlobalTables::GetGsymTable().GetTable().size() : func->GetSymTab()->GetTable().size();
456     for (size_t i = 0; i < size; ++i) {
457         const MIRSymbol *st = nullptr;
458         if (func == nullptr) {
459             auto &symTab = GlobalTables::GetGsymTable();
460             st = symTab.GetSymbol(i);
461         } else {
462             auto &symTab = *func->GetSymTab();
463             st = symTab.GetSymbolAt(i);
464         }
465         if (st == nullptr) {
466             continue;
467         }
468         MIRStorageClass storageClass = st->GetStorageClass();
469         MIRSymKind symKind = st->GetSKind();
470         Emitter *emitter = this;
471         if (storageClass == kScPstatic && symKind == kStConst) {
472             // align
473             emitter->Emit("\t.align 2 \n" + st->GetName() + ":\n");
474             if (st->GetKonst()->GetKind() == kConstStr16Const) {
475                 MIRStr16Const *str16Const = safe_cast<MIRStr16Const>(st->GetKonst());
476                 DEBUG_ASSERT(str16Const != nullptr, "str16Const should not be nullptr");
477                 emitter->EmitStr16Constant(*str16Const);
478                 emitter->Emit("\n");
479                 continue;
480             }
481 
482             if (st->GetKonst()->GetKind() == kConstStrConst) {
483                 MIRStrConst *strConst = safe_cast<MIRStrConst>(st->GetKonst());
484                 DEBUG_ASSERT(strConst != nullptr, "strConst should not be nullptr");
485                 emitter->EmitStrConstant(*strConst);
486                 emitter->Emit("\n");
487                 continue;
488             }
489 
490             switch (st->GetKonst()->GetType().GetPrimType()) {
491                 case PTY_u32: {
492                     MIRIntConst *intConst = safe_cast<MIRIntConst>(st->GetKonst());
493                     DEBUG_ASSERT(intConst != nullptr, "intConst should not be nullptr");
494                     uint32 value = static_cast<uint32>(intConst->GetValue().GetExtValue());
495                     emitter->Emit("\t.long").Emit(value).Emit("\n");
496                     break;
497                 }
498                 case PTY_f32: {
499                     MIRFloatConst *floatConst = safe_cast<MIRFloatConst>(st->GetKonst());
500                     DEBUG_ASSERT(floatConst != nullptr, "floatConst should not be nullptr");
501                     uint32 value = static_cast<uint32>(floatConst->GetIntValue());
502                     emitter->Emit("\t.word").Emit(value).Emit("\n");
503                     break;
504                 }
505                 case PTY_f64: {
506                     MIRDoubleConst *doubleConst = safe_cast<MIRDoubleConst>(st->GetKonst());
507                     DEBUG_ASSERT(doubleConst != nullptr, "doubleConst should not be nullptr");
508                     uint32 value = doubleConst->GetIntLow32();
509                     emitter->Emit("\t.word").Emit(value).Emit("\n");
510                     value = doubleConst->GetIntHigh32();
511                     emitter->Emit("\t.word").Emit(value).Emit("\n");
512                     break;
513                 }
514                 default:
515                     DEBUG_ASSERT(false, "NYI");
516                     break;
517             }
518         }
519     }
520 #endif
521 }
522 
523 void Emitter::EmitStr(const std::string &mplStr, bool emitAscii, bool emitNewline)
524 {
525 #ifdef ARK_LITECG_DEBUG
526     const char *str = mplStr.c_str();
527     size_t len = mplStr.size();
528 
529     if (emitAscii) {
530         Emit("\t.ascii\t\""); /* Do not terminate with \0 */
531     } else {
532         Emit("\t.string\t\"");
533     }
534 
535     /*
536      * don't expand special character in a writeout to .s,
537      * convert all \s to \\s in string for storing in .string
538      */
539     for (size_t i = 0; i < len; i++) {
540         /* Referred to GNU AS: 3.6.1.1 Strings */
541         constexpr int kBufSize = 5;
542         constexpr int kFirstChar = 0;
543         constexpr int kSecondChar = 1;
544         constexpr int kThirdChar = 2;
545         constexpr int kLastChar = 4;
546         char buf[kBufSize];
547         if (isprint(*str)) {
548             buf[kFirstChar] = *str;
549             buf[kSecondChar] = 0;
550             if (*str == '\\' || *str == '\"') {
551                 buf[kFirstChar] = '\\';
552                 buf[kSecondChar] = *str;
553                 buf[kThirdChar] = 0;
554             }
555             Emit(buf);
556         } else if (*str == '\b') {
557             Emit("\\b");
558         } else if (*str == '\n') {
559             Emit("\\n");
560         } else if (*str == '\r') {
561             Emit("\\r");
562         } else if (*str == '\t') {
563             Emit("\\t");
564         } else if (*str == '\0') {
565             buf[kFirstChar] = '\\';
566             buf[kSecondChar] = '0';
567             buf[kThirdChar] = 0;
568             Emit(buf);
569         } else {
570             /* all others, print as number */
571             int ret = snprintf_s(buf, sizeof(buf), k4BitSize, "\\%03o", static_cast<unsigned char>(*str) & 0xFF);
572             if (ret < 0) {
573                 FATAL(kLncFatal, "snprintf_s failed");
574             }
575             buf[kLastChar] = '\0';
576             Emit(buf);
577         }
578         str++;
579     }
580 
581     Emit("\"");
582     if (emitNewline) {
583         Emit("\n");
584     }
585 #endif
586 }
587 
588 void Emitter::EmitStrConstant(const MIRStrConst &mirStrConst, bool isIndirect)
589 {
590 #ifdef ARK_LITECG_DEBUG
591     if (isIndirect) {
592         uint32 strId = mirStrConst.GetValue().GetIdx();
593 
594         if (stringPtr.find(mirStrConst.GetValue()) == stringPtr.end()) {
595             stringPtr.insert(mirStrConst.GetValue());
596         }
597         if (CGOptions::IsArm64ilp32()) {
598             (void)Emit("\t.word\t").Emit(".LSTR__").Emit(std::to_string(strId).c_str());
599         } else {
600             EmitAsmLabel(kAsmQuad);
601             (void)Emit(".LSTR__").Emit(std::to_string(strId).c_str());
602         }
603         return;
604     }
605 
606     const std::string ustr = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirStrConst.GetValue());
607     size_t len = ustr.size();
608     if (isFlexibleArray) {
609         arraySize += static_cast<uint32>(len) + 1;
610     }
611     EmitStr(ustr, false, false);
612 #endif
613 }
614 
615 void Emitter::EmitStr16Constant(const MIRStr16Const &mirStr16Const)
616 {
617 #ifdef ARK_LITECG_DEBUG
618     Emit("\t.byte ");
619     /* note: for now, u16string is emitted 2 bytes without any \u indication */
620     const std::u16string &str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(mirStr16Const.GetValue());
621     constexpr int bufSize = 9;
622     char buf[bufSize];
623     char16_t c = str16[0];
624     /* fetch the type of char16_t c's top 8 bit data */
625     int ret1 = snprintf_s(buf, sizeof(buf), bufSize - 1, "%d,%d", (c >> 8) & 0xFF, c & 0xFF);
626     if (ret1 < 0) {
627         FATAL(kLncFatal, "snprintf_s failed");
628     }
629     buf[bufSize - 1] = '\0';
630     Emit(buf);
631     for (uint32 i = 1; i < str16.length(); ++i) {
632         c = str16[i];
633         /* fetch the type of char16_t c's top 8 bit data */
634         int ret2 = snprintf_s(buf, sizeof(buf), bufSize - 1, ",%d,%d", (c >> 8) & 0xFF, c & 0xFF);
635         if (ret2 < 0) {
636             FATAL(kLncFatal, "snprintf_s failed");
637         }
638         buf[bufSize - 1] = '\0';
639         Emit(buf);
640     }
641     if ((str16.length() & 0x1) == 1) {
642         Emit(",0,0");
643     }
644 #endif
645 }
646 
647 void Emitter::EmitScalarConstant(MIRConst &mirConst, bool newLine, bool flag32, bool isIndirect)
648 {
649 #ifdef ARK_LITECG_DEBUG
650     MIRType &mirType = mirConst.GetType();
651     AsmLabel asmName = GetTypeAsmInfoName(mirType.GetPrimType());
652     switch (mirConst.GetKind()) {
653         case kConstInt: {
654             MIRIntConst &intCt = static_cast<MIRIntConst &>(mirConst);
655             uint32 sizeInBits = GetPrimTypeBitSize(mirType.GetPrimType());
656             if (intCt.GetActualBitWidth() > sizeInBits) {
657                 intCt.Trunc(sizeInBits);
658             }
659             if (flag32) {
660                 EmitAsmLabel(AsmLabel::kAsmLong);
661             } else {
662                 EmitAsmLabel(asmName);
663             }
664             Emit(intCt.GetValue());
665             if (isFlexibleArray) {
666                 arraySize += (sizeInBits / kBitsPerByte);
667             }
668             break;
669         }
670         case kConstFloatConst: {
671             MIRFloatConst &floatCt = static_cast<MIRFloatConst &>(mirConst);
672             EmitAsmLabel(asmName);
673             Emit(std::to_string(floatCt.GetIntValue()));
674             if (isFlexibleArray) {
675                 arraySize += k4ByteFloatSize;
676             }
677             break;
678         }
679         case kConstDoubleConst: {
680             MIRDoubleConst &doubleCt = static_cast<MIRDoubleConst &>(mirConst);
681             EmitAsmLabel(asmName);
682             Emit(std::to_string(doubleCt.GetIntValue()));
683             if (isFlexibleArray) {
684                 arraySize += k8ByteDoubleSize;
685             }
686             break;
687         }
688         case kConstStrConst: {
689             MIRStrConst &strCt = static_cast<MIRStrConst &>(mirConst);
690             EmitStrConstant(strCt);
691             break;
692         }
693         case kConstStr16Const: {
694             MIRStr16Const &str16Ct = static_cast<MIRStr16Const &>(mirConst);
695             EmitStr16Constant(str16Ct);
696             break;
697         }
698         case kConstAddrof: {
699             MIRAddrofConst &symAddr = static_cast<MIRAddrofConst &>(mirConst);
700             StIdx stIdx = symAddr.GetSymbolIndex();
701             CHECK_NULL_FATAL(CG::GetCurCGFunc()->GetMirModule().CurFunction());
702             MIRSymbol *symAddrSym =
703                 stIdx.IsGlobal()
704                     ? GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx())
705                     : CG::GetCurCGFunc()->GetMirModule().CurFunction()->GetSymTab()->GetSymbolFromStIdx(stIdx.Idx());
706             DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
707             std::string str;
708             if (CGOptions::IsArm64ilp32()) {
709                 str = ".word";
710             } else {
711                 str = ".quad";
712             }
713             if (stIdx.IsGlobal() == false && symAddrSym->GetStorageClass() == kScPstatic) {
714                 CHECK_NULL_FATAL(GetCG()->GetMIRModule()->CurFunction());
715                 PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
716                 (void)Emit("\t" + str + "\t" + symAddrSym->GetName() + std::to_string(pIdx));
717             } else {
718                 (void)Emit("\t" + str + "\t" + symAddrSym->GetName());
719             }
720             if (symAddr.GetOffset() != 0) {
721                 (void)Emit(" + ").Emit(symAddr.GetOffset());
722             }
723             break;
724         }
725         case kConstAddrofFunc: {
726             MIRAddroffuncConst &funcAddr = static_cast<MIRAddroffuncConst &>(mirConst);
727             MIRFunction *func = GlobalTables::GetFunctionTable().GetFuncTable().at(funcAddr.GetValue());
728             MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx());
729             std::string str;
730             if (CGOptions::IsArm64ilp32()) {
731                 str = ".word";
732             } else {
733                 str = ".quad";
734             }
735             (void)Emit("\t" + str + "\t" + symAddrSym->GetName());
736             break;
737         }
738         case kConstLblConst: {
739             MIRLblConst &lbl = static_cast<MIRLblConst &>(mirConst);
740             if (CGOptions::IsArm64ilp32()) {
741                 (void)Emit("\t.word\t");
742             } else {
743                 EmitAsmLabel(kAsmQuad);
744             }
745             EmitLabelRef(lbl.GetValue());
746             break;
747         }
748         default:
749             DEBUG_ASSERT(false, "NYI");
750             break;
751     }
752     if (newLine) {
753         Emit("\n");
754     }
755 #endif
756 }
757 
758 void Emitter::EmitAddrofFuncConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx)
759 {
760 #ifdef ARK_LITECG_DEBUG
761     MIRAddroffuncConst &funcAddr = static_cast<MIRAddroffuncConst &>(elemConst);
762     const std::string stName = mirSymbol.GetName();
763     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(funcAddr.GetValue());
764     const std::string &funcName = func->GetName();
765     if ((idx == kFuncDefNameIndex) && mirSymbol.IsMuidFuncInfTab()) {
766         Emit("\t.long\t.Label.name.");
767         Emit(funcName + " - .");
768         Emit("\n");
769         return;
770     }
771     if ((idx == kFuncDefSizeIndex) && mirSymbol.IsMuidFuncInfTab()) {
772         Emit("\t.long\t.Label.end.");
773         Emit(funcName + " - ");
774         Emit(funcName + "\n");
775         return;
776     }
777     if ((idx == static_cast<uint32>(MethodProperty::kPaddrData)) && mirSymbol.IsReflectionMethodsInfo()) {
778 #ifdef USE_32BIT_REF
779         Emit("\t.long\t");
780 #else
781 
782 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
783         EmitAsmLabel(kAsmQuad);
784 #else
785         Emit("\t.word\t");
786 #endif
787 
788 #endif /* USE_32BIT_REF */
789         Emit(funcName + " - .\n");
790         return;
791     }
792     if (((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) ||
793         ((idx == static_cast<uint32>(ClassRO::kClinitAddr)) && mirSymbol.IsReflectionClassInfoRO())) {
794         Emit("\t.long\t");
795         Emit(funcName + " - .\n");
796         return;
797     }
798 
799     if (mirSymbol.IsReflectionMethodAddrData()) {
800 #ifdef USE_32BIT_REF
801         Emit("\t.long\t");
802 #else
803 
804 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
805         EmitAsmLabel(kAsmQuad);
806 #else
807         Emit("\t.word\t");
808 #endif
809 
810 #endif /* USE_32BIT_REF */
811         Emit(funcName + " - .\n");
812         return;
813     }
814 
815     if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncDefTab()) {
816 #if defined(USE_32BIT_REF)
817         Emit("\t.long\t");
818 #else
819 
820 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
821         EmitAsmLabel(kAsmQuad);
822 #else
823         Emit("\t.word\t");
824 #endif
825 
826 #endif /* USE_32BIT_REF */
827         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
828             /*
829              * Check enum BindingState defined in Mpl_Binding.h,
830              * 6 means kBindingStateMethodDef:6 offset away from base __BindingProtectRegion__.
831              */
832 #if defined(USE_32BIT_REF)
833             Emit("0x6\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateMethodDef:6. */
834 #else
835             Emit("__BindingProtectRegion__ + 6\n");
836 #endif /* USE_32BIT_REF */
837         } else {
838 #if defined(USE_32BIT_REF)
839 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
840             Emit(funcName + "\n");
841 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
842             Emit(funcName + "-.\n");
843 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
844 #else  /* USE_32BIT_REF */
845             Emit(funcName + "\n");
846 #endif /* USE_32BIT_REF */
847         }
848         return;
849     }
850 
851     if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncDefOrigTab()) {
852         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
853 #if defined(USE_32BIT_REF)
854             Emit("\t.long\t");
855 #else
856 
857 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
858             EmitAsmLabel(kAsmQuad);
859 #else
860             Emit("\t.word\t");
861 #endif
862 
863 #endif /* USE_32BIT_REF */
864 #if defined(USE_32BIT_REF)
865 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
866             Emit(funcName + "\n");
867 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
868             Emit(funcName + "-.\n");
869 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
870 #else  /* USE_32BIT_REF */
871             Emit(funcName + "\n");
872 #endif /* USE_32BIT_REF */
873         }
874         return;
875     }
876 
877 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
878     EmitAsmLabel(kAsmQuad);
879 #else
880     Emit("\t.word\t");
881 #endif
882     Emit(funcName);
883     if ((stName.find(VTAB_PREFIX_STR) == 0) || (stName.find(ITAB_PREFIX_STR) == 0) ||
884         (stName.find(ITAB_CONFLICT_PREFIX_STR) == 0)) {
885         Emit(" - .\n");
886         return;
887     }
888     Emit("\n");
889 #endif
890 }
891 
892 void Emitter::EmitAddrofSymbolConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx)
893 {
894 #ifdef ARK_LITECG_DEBUG
895     MIRAddrofConst &symAddr = static_cast<MIRAddrofConst &>(elemConst);
896     const std::string stName = mirSymbol.GetName();
897 
898     MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr.GetSymbolIndex().Idx());
899     DEBUG_ASSERT(symAddrSym != nullptr, "symAddrSym should not be nullptr");
900     const std::string &symAddrName = symAddrSym->GetName();
901 
902     if (((idx == static_cast<uint32>(FieldProperty::kPOffset)) && mirSymbol.IsReflectionFieldsInfo()) ||
903         mirSymbol.IsReflectionFieldOffsetData()) {
904 #if USE_32BIT_REF
905         Emit("\t.long\t");
906 #else
907 
908 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
909         EmitAsmLabel(kAsmQuad);
910 #else
911         Emit("\t.word\t");
912 #endif
913 
914 #endif /* USE_32BIT_REF */
915         Emit(symAddrName + " - .\n");
916         return;
917     }
918 
919     if (((idx == static_cast<uint32>(FieldPropertyCompact::kPOffset)) && mirSymbol.IsReflectionFieldsInfoCompact()) ||
920         ((idx == static_cast<uint32>(MethodProperty::kSigName)) && mirSymbol.IsReflectionMethodsInfo()) ||
921         ((idx == static_cast<uint32>(MethodSignatureProperty::kParameterTypes)) &&
922          mirSymbol.IsReflectionMethodSignature())) {
923         Emit("\t.long\t");
924         Emit(symAddrName + " - .\n");
925         return;
926     }
927 
928     if (((idx == static_cast<uint32>(MethodProperty::kDeclarclass)) ||
929          (idx == static_cast<uint32>(MethodProperty::kPaddrData))) &&
930         mirSymbol.IsReflectionMethodsInfo()) {
931 #if USE_32BIT_REF
932         Emit("\t.long\t");
933 #else
934 
935 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
936         EmitAsmLabel(kAsmQuad);
937 #else
938         Emit("\t.word\t");
939 #endif
940 
941 #endif /* USE_32BIT_REF */
942         if (idx == static_cast<uint32>(MethodProperty::kDeclarclass)) {
943             Emit(symAddrName + " - .\n");
944         } else {
945             Emit(symAddrName + " - . + 2\n");
946         }
947         return;
948     }
949 
950     if ((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) {
951         Emit("\t.long\t");
952         Emit(symAddrName + " - . + 2\n");
953         return;
954     }
955 
956     if ((idx == static_cast<uint32>(FieldProperty::kDeclarclass)) && mirSymbol.IsReflectionFieldsInfo()) {
957 #if USE_32BIT_REF
958         Emit("\t.long\t");
959 #else
960 
961 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
962         EmitAsmLabel(kAsmQuad);
963 #else
964         Emit("\t.word\t");
965 #endif
966 
967 #endif /* USE_32BIT_REF */
968         Emit(symAddrName + " - .\n");
969         return;
970     }
971 
972     if ((idx == kDataDefAddrIndex) && (mirSymbol.IsMuidDataUndefTab() || mirSymbol.IsMuidDataDefTab())) {
973         if (symAddrSym->IsReflectionClassInfo()) {
974             Emit(".LDW.ref." + symAddrName + ":\n");
975         }
976         Emit(kPtrPrefixStr + symAddrName + ":\n");
977 #if defined(USE_32BIT_REF)
978         Emit("\t.long\t");
979 #else
980 
981 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
982         EmitAsmLabel(kAsmQuad);
983 #else
984         Emit("\t.word\t");
985 #endif
986 
987 #endif /* USE_32BIT_REF */
988         if (mirSymbol.IsMuidDataUndefTab()) {
989             if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
990                 if (symAddrSym->IsReflectionClassInfo()) {
991                     /*
992                      * Check enum BindingState defined in Mpl_Binding.h,
993                      * 1 means kBindingStateCinfUndef:1 offset away from base __BindingProtectRegion__.
994                      */
995 #if defined(USE_32BIT_REF)
996                     Emit("0x1\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateCinfUndef:1. */
997 #else
998                     Emit("__BindingProtectRegion__ + 1\n");
999 #endif /* USE_32BIT_REF */
1000                 } else {
1001                     /*
1002                      * Check enum BindingState defined in Mpl_Binding.h,
1003                      * 3 means kBindingStateDataUndef:3 offset away from base __BindingProtectRegion__.
1004                      */
1005 #if defined(USE_32BIT_REF)
1006                     Emit("0x3\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateDataUndef:3. */
1007 #else
1008                     Emit("__BindingProtectRegion__ + 3\n");
1009 #endif /* USE_32BIT_REF */
1010                 }
1011             } else {
1012                 Emit("0\n");
1013             }
1014         } else {
1015             if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1016                 if (symAddrSym->IsReflectionClassInfo()) {
1017                     /*
1018                      * Check enum BindingState defined in Mpl_Binding.h,
1019                      * 2 means kBindingStateCinfDef:2 offset away from base __BindingProtectRegion__.
1020                      */
1021 #if defined(USE_32BIT_REF)
1022                     Emit("0x2\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateCinfDef:2. */
1023 #else
1024                     Emit("__BindingProtectRegion__ + 2\n");
1025 #endif /* USE_32BIT_REF */
1026                 } else {
1027                     /*
1028                      * Check enum BindingState defined in Mpl_Binding.h,
1029                      * 4 means kBindingStateDataDef:4 offset away from base __BindingProtectRegion__.
1030                      */
1031 #if defined(USE_32BIT_REF)
1032                     Emit("0x4\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateDataDef:4. */
1033 #else
1034                     Emit("__BindingProtectRegion__ + 4\n");
1035 #endif /* USE_32BIT_REF */
1036                 }
1037             } else {
1038 #if defined(USE_32BIT_REF)
1039 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1040                 Emit(symAddrName + "\n");
1041 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1042                 Emit(symAddrName + "-.\n");
1043 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1044 #else  /* USE_32BIT_REF */
1045                 Emit(symAddrName + "\n");
1046 #endif /* USE_32BIT_REF */
1047             }
1048         }
1049         return;
1050     }
1051 
1052     if (idx == kDataDefAddrIndex && mirSymbol.IsMuidDataDefOrigTab()) {
1053         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1054 #if defined(USE_32BIT_REF)
1055             Emit("\t.long\t");
1056 #else
1057 
1058 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1059             EmitAsmLabel(kAsmQuad);
1060 #else
1061             Emit("\t.word\t");
1062 #endif
1063 
1064 #endif /* USE_32BIT_REF */
1065 
1066 #if defined(USE_32BIT_REF)
1067 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1068             Emit(symAddrName + "\n");
1069 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1070             Emit(symAddrName + "-.\n");
1071 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1072 #else  /* USE_32BIT_REF */
1073             Emit(symAddrName + "\n");
1074 #endif /* USE_32BIT_REF */
1075         }
1076         return;
1077     }
1078 
1079     if (StringUtils::StartsWith(stName, kLocalClassInfoStr)) {
1080 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1081         EmitAsmLabel(kAsmQuad);
1082 #else
1083         Emit("\t.word\t");
1084 #endif
1085         Emit(symAddrName);
1086         Emit(" - . + ").Emit(kDataRefIsOffset);
1087         Emit("\n");
1088         return;
1089     }
1090 #ifdef USE_32BIT_REF
1091     if (mirSymbol.IsReflectionHashTabBucket() || (stName.find(ITAB_PREFIX_STR) == 0) ||
1092         (mirSymbol.IsReflectionClassInfo() && (idx == static_cast<uint32>(ClassProperty::kInfoRo)))) {
1093         Emit("\t.word\t");
1094     } else {
1095 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1096         EmitAsmLabel(kAsmQuad);
1097 #else
1098         Emit("\t.word\t");
1099 #endif
1100     }
1101 #else
1102 
1103 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1104     EmitAsmLabel(kAsmQuad);
1105 #else
1106     Emit("\t.word\t");
1107 #endif
1108 
1109 #endif /* USE_32BIT_REF */
1110 
1111     if ((stName.find(ITAB_CONFLICT_PREFIX_STR) == 0) || (stName.find(ITAB_PREFIX_STR) == 0)) {
1112         Emit(symAddrName + " - .\n");
1113         return;
1114     }
1115     if (mirSymbol.IsMuidRangeTab()) {
1116         if (idx == kRangeBeginIndex) {
1117             Emit(symAddrSym->GetMuidTabName() + "_begin\n");
1118         } else {
1119             Emit(symAddrSym->GetMuidTabName() + "_end\n");
1120         }
1121         return;
1122     }
1123 
1124     if (symAddrName.find(GCTIB_PREFIX_STR) == 0) {
1125         Emit(cg->FindGCTIBPatternName(symAddrName));
1126     } else {
1127         Emit(symAddrName);
1128     }
1129 
1130     if ((((idx == static_cast<uint32>(ClassRO::kIfields)) || (idx == static_cast<uint32>(ClassRO::kMethods))) &&
1131          mirSymbol.IsReflectionClassInfoRO()) ||
1132         mirSymbol.IsReflectionHashTabBucket()) {
1133         Emit(" - .");
1134         if (symAddrSym->IsReflectionFieldsInfoCompact() || symAddrSym->IsReflectionMethodsInfoCompact()) {
1135             /* Mark the least significant bit as 1 for compact fieldinfo */
1136             Emit(" + ").Emit(MethodFieldRef::kMethodFieldRefIsCompact);
1137         }
1138     } else if (mirSymbol.IsReflectionClassInfo()) {
1139         if ((idx == static_cast<uint32>(ClassProperty::kItab)) || (idx == static_cast<uint32>(ClassProperty::kVtab)) ||
1140             (idx == static_cast<uint32>(ClassProperty::kInfoRo))) {
1141             Emit(" - . + ").Emit(kDataRefIsOffset);
1142         } else if (idx == static_cast<uint32>(ClassProperty::kGctib)) {
1143             if (cg->FindGCTIBPatternName(symAddrName).find(REF_PREFIX_STR) == 0) {
1144                 Emit(" - . + ").Emit(kGctibRefIsIndirect);
1145             } else {
1146                 Emit(" - .");
1147             }
1148         }
1149     } else if (mirSymbol.IsReflectionClassInfoRO()) {
1150         if (idx == static_cast<uint32>(ClassRO::kSuperclass)) {
1151             Emit(" - . + ").Emit(kDataRefIsOffset);
1152         }
1153     }
1154 
1155     Emit("\n");
1156 #endif
1157 }
1158 
1159 MIRAddroffuncConst *Emitter::GetAddroffuncConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst)
1160 {
1161     MIRAddroffuncConst *innerFuncAddr = nullptr;
1162 #ifdef ARK_LITECG_DEBUG
1163     size_t addrIndex = mirSymbol.IsReflectionMethodsInfo() ? static_cast<size_t>(MethodProperty::kPaddrData)
1164                                                            : static_cast<size_t>(MethodInfoCompact::kPaddrData);
1165     MIRConst *pAddrConst = aggConst.GetConstVecItem(addrIndex);
1166     if (pAddrConst->GetKind() == kConstAddrof) {
1167         /* point addr data. */
1168         MIRAddrofConst *pAddr = safe_cast<MIRAddrofConst>(pAddrConst);
1169         DEBUG_ASSERT(pAddr != nullptr, "null ptr check");
1170         MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(pAddr->GetSymbolIndex().Idx());
1171         DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
1172         MIRAggConst *methodAddrAggConst = safe_cast<MIRAggConst>(symAddrSym->GetKonst());
1173         DEBUG_ASSERT(methodAddrAggConst != nullptr, "null ptr check");
1174         MIRAggConst *addrAggConst = safe_cast<MIRAggConst>(methodAddrAggConst->GetConstVecItem(0));
1175         DEBUG_ASSERT(addrAggConst != nullptr, "null ptr check");
1176         MIRConst *funcAddrConst = addrAggConst->GetConstVecItem(0);
1177         if (funcAddrConst->GetKind() == kConstAddrofFunc) {
1178             /* func sybmol. */
1179             innerFuncAddr = safe_cast<MIRAddroffuncConst>(funcAddrConst);
1180         } else if (funcAddrConst->GetKind() == kConstInt) {
1181             /* def table index, replaced by def table for lazybinding. */
1182             std::string funcDefTabName =
1183                 namemangler::kMuidFuncDefTabPrefixStr + cg->GetMIRModule()->GetFileNameAsPostfix();
1184             MIRSymbol *funDefTabSy = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
1185                 GlobalTables::GetStrTable().GetStrIdxFromName(funcDefTabName));
1186             DEBUG_ASSERT(funDefTabSy != nullptr, "null ptr check");
1187             MIRAggConst &funDefTabAggConst = static_cast<MIRAggConst &>(*funDefTabSy->GetKonst());
1188             MIRIntConst *funcAddrIndexConst = safe_cast<MIRIntConst>(funcAddrConst);
1189             DEBUG_ASSERT(funcAddrIndexConst != nullptr, "null ptr check");
1190             uint64 indexDefTab = static_cast<uint64>(funcAddrIndexConst->GetExtValue());
1191             MIRAggConst *defTabAggConst = safe_cast<MIRAggConst>(funDefTabAggConst.GetConstVecItem(indexDefTab));
1192             DEBUG_ASSERT(defTabAggConst != nullptr, "null ptr check");
1193             MIRConst *funcConst = defTabAggConst->GetConstVecItem(0);
1194             if (funcConst->GetKind() == kConstAddrofFunc) {
1195                 innerFuncAddr = safe_cast<MIRAddroffuncConst>(funcConst);
1196             }
1197         }
1198     } else if (pAddrConst->GetKind() == kConstAddrofFunc) {
1199         innerFuncAddr = safe_cast<MIRAddroffuncConst>(pAddrConst);
1200     }
1201 #endif
1202     return innerFuncAddr;
1203 }
1204 
1205 int64 Emitter::GetFieldOffsetValue(const std::string &className, const MIRIntConst &intConst,
1206                                    const std::map<GStrIdx, MIRType *> &strIdx2Type)
1207 {
1208 #ifdef ARK_LITECG_DEBUG
1209     uint64 idx = static_cast<uint64>(intConst.GetExtValue());
1210     bool isDefTabIndex = idx & 0x1;
1211     int64 fieldIdx = idx >> 1;
1212     CHECK_FATAL(isDefTabIndex > 0, "isDefTabIndex > 0");
1213     /* it's def table index. */
1214     return fieldIdx;
1215 #else
1216     return 0;
1217 #endif
1218 }
1219 
1220 void Emitter::InitRangeIdx2PerfixStr()
1221 {
1222 #ifdef ARK_LITECG_DEBUG
1223     rangeIdx2PrefixStr[RangeIdx::kVtabAndItab] = kMuidVtabAndItabPrefixStr;
1224     rangeIdx2PrefixStr[RangeIdx::kItabConflict] = kMuidItabConflictPrefixStr;
1225     rangeIdx2PrefixStr[RangeIdx::kVtabOffset] = kMuidVtabOffsetPrefixStr;
1226     rangeIdx2PrefixStr[RangeIdx::kFieldOffset] = kMuidFieldOffsetPrefixStr;
1227     rangeIdx2PrefixStr[RangeIdx::kValueOffset] = kMuidValueOffsetPrefixStr;
1228     rangeIdx2PrefixStr[RangeIdx::kLocalClassInfo] = kMuidLocalClassInfoStr;
1229     rangeIdx2PrefixStr[RangeIdx::kConststr] = kMuidConststrPrefixStr;
1230     rangeIdx2PrefixStr[RangeIdx::kSuperclass] = kMuidSuperclassPrefixStr;
1231     rangeIdx2PrefixStr[RangeIdx::kGlobalRootlist] = kMuidGlobalRootlistPrefixStr;
1232     rangeIdx2PrefixStr[RangeIdx::kClassmetaData] = kMuidClassMetadataPrefixStr;
1233     rangeIdx2PrefixStr[RangeIdx::kClassBucket] = kMuidClassMetadataBucketPrefixStr;
1234     rangeIdx2PrefixStr[RangeIdx::kDataSection] = kMuidDataSectionStr;
1235     rangeIdx2PrefixStr[RangeIdx::kDecoupleStaticKey] = kDecoupleStaticKeyStr;
1236     rangeIdx2PrefixStr[RangeIdx::kDecoupleStaticValue] = kDecoupleStaticValueStr;
1237     rangeIdx2PrefixStr[RangeIdx::kBssStart] = kBssSectionStr;
1238     rangeIdx2PrefixStr[RangeIdx::kLinkerSoHash] = kLinkerHashSoStr;
1239     rangeIdx2PrefixStr[RangeIdx::kArrayClassCache] = kArrayClassCacheTable;
1240     rangeIdx2PrefixStr[RangeIdx::kArrayClassCacheName] = kArrayClassCacheNameTable;
1241 #endif
1242 }
1243 
1244 void Emitter::EmitIntConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst, uint32 itabConflictIndex,
1245                            const std::map<GStrIdx, MIRType *> &strIdx2Type, size_t idx)
1246 {
1247 #ifdef ARK_LITECG_DEBUG
1248     MIRConst *elemConst = aggConst.GetConstVecItem(idx);
1249     DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
1250     const std::string stName = mirSymbol.GetName();
1251 
1252     MIRIntConst *intConst = safe_cast<MIRIntConst>(elemConst);
1253     DEBUG_ASSERT(intConst != nullptr, "Uexpected const type");
1254 
1255     /* ignore abstract function addr */
1256     if ((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) {
1257         return;
1258     }
1259 
1260     if (((idx == static_cast<uint32>(MethodProperty::kVtabIndex)) && (mirSymbol.IsReflectionMethodsInfo())) ||
1261         ((idx == static_cast<uint32>(MethodInfoCompact::kVtabIndex)) && mirSymbol.IsReflectionMethodsInfoCompact())) {
1262         MIRAddroffuncConst *innerFuncAddr = GetAddroffuncConst(mirSymbol, aggConst);
1263         if (innerFuncAddr != nullptr) {
1264             Emit(".Label.name." +
1265                  GlobalTables::GetFunctionTable().GetFunctionFromPuidx(innerFuncAddr->GetValue())->GetName());
1266             Emit(":\n");
1267         }
1268     }
1269     /* refer to DeCouple::GenOffsetTableType */
1270     constexpr int fieldTypeIdx = 2;
1271     constexpr int methodTypeIdx = 2;
1272     bool isClassInfo =
1273         (idx == static_cast<uint32>(ClassRO::kClassName) || idx == static_cast<uint32>(ClassRO::kAnnotation)) &&
1274         mirSymbol.IsReflectionClassInfoRO();
1275     bool isMethodsInfo = (idx == static_cast<uint32>(MethodProperty::kMethodName) ||
1276                           idx == static_cast<uint32>(MethodProperty::kSigName) ||
1277                           idx == static_cast<uint32>(MethodProperty::kAnnotation)) &&
1278                          mirSymbol.IsReflectionMethodsInfo();
1279     bool isFieldsInfo =
1280         (idx == static_cast<uint32>(FieldProperty::kTypeName) || idx == static_cast<uint32>(FieldProperty::kName) ||
1281          idx == static_cast<uint32>(FieldProperty::kAnnotation)) &&
1282         mirSymbol.IsReflectionFieldsInfo();
1283     bool isMethodSignature = (idx == static_cast<uint32>(MethodSignatureProperty::kSignatureOffset)) &&
1284                              mirSymbol.IsReflectionMethodSignature();
1285     /* RegisterTable has been Int Array, visit element instead of field. */
1286     bool isInOffsetTab = (idx == 1 || idx == methodTypeIdx) && (StringUtils::StartsWith(stName, kVtabOffsetTabStr) ||
1287                                                                 StringUtils::StartsWith(stName, kFieldOffsetTabStr));
1288     /* The 1 && 2 of Decouple static struct is the string name */
1289     bool isStaticStr = (idx == 1 || idx == 2) && aggConst.GetConstVec().size() == kSizeOfDecoupleStaticStruct &&
1290                        StringUtils::StartsWith(stName, kDecoupleStaticKeyStr);
1291     /* process conflict table index larger than itabConflictIndex * 2 + 2 element */
1292     bool isConflictPerfix = (idx >= (static_cast<uint64>(itabConflictIndex) * 2 + 2)) && (idx % 2 == 0) &&
1293                             StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR);
1294     bool isArrayClassCacheName = mirSymbol.IsArrayClassCacheName();
1295     if (isClassInfo || isMethodsInfo || isFieldsInfo || mirSymbol.IsRegJNITab() || isInOffsetTab || isStaticStr ||
1296         isConflictPerfix || isArrayClassCacheName || isMethodSignature) {
1297         /* compare with all 1s */
1298         uint32 index = static_cast<uint32>((safe_cast<MIRIntConst>(elemConst))->GetExtValue()) & 0xFFFFFFFF;
1299         bool isHotReflectStr = (index & 0x00000003) != 0; /* use the last two bits of index in this expression */
1300         std::string hotStr;
1301         if (isHotReflectStr) {
1302             uint32 tag = (index & 0x00000003) - kCStringShift; /* use the last two bits of index in this expression */
1303             if (tag == kLayoutBootHot) {
1304                 hotStr = kReflectionStartHotStrtabPrefixStr;
1305             } else if (tag == kLayoutBothHot) {
1306                 hotStr = kReflectionBothHotStrTabPrefixStr;
1307             } else {
1308                 hotStr = kReflectionRunHotStrtabPrefixStr;
1309             }
1310         }
1311         std::string reflectStrTabPrefix = isHotReflectStr ? hotStr : kReflectionStrtabPrefixStr;
1312         std::string strTabName = reflectStrTabPrefix + cg->GetMIRModule()->GetFileNameAsPostfix();
1313         /* left shift 2 bit to get low 30 bit data for MIRIntConst */
1314         ASSERT_NOT_NULL(elemConst);
1315         elemConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(index >> 2, elemConst->GetType());
1316         intConst = safe_cast<MIRIntConst>(elemConst);
1317         aggConst.SetItem(static_cast<uint32>(idx), intConst, aggConst.GetFieldIdItem(idx));
1318 #ifdef USE_32BIT_REF
1319         if (stName.find(ITAB_CONFLICT_PREFIX_STR) == 0) {
1320             EmitScalarConstant(*elemConst, false, true);
1321         } else {
1322             EmitScalarConstant(*elemConst, false);
1323         }
1324 #else
1325         EmitScalarConstant(*elemConst, false);
1326 #endif /* USE_32BIT_REF */
1327         Emit("+" + strTabName);
1328         if (mirSymbol.IsRegJNITab() || mirSymbol.IsReflectionMethodsInfo() || mirSymbol.IsReflectionFieldsInfo() ||
1329             mirSymbol.IsArrayClassCacheName() || mirSymbol.IsReflectionMethodSignature()) {
1330             Emit("-.");
1331         }
1332         if (StringUtils::StartsWith(stName, kDecoupleStaticKeyStr)) {
1333             Emit("-.");
1334         }
1335         if (mirSymbol.IsReflectionClassInfoRO()) {
1336             if (idx == static_cast<uint32>(ClassRO::kAnnotation)) {
1337                 Emit("-.");
1338             } else if (idx == static_cast<uint32>(ClassRO::kClassName)) {
1339                 /* output in hex format to show it is a flag of bits. */
1340                 std::stringstream ss;
1341                 ss << std::hex << "0x" << MByteRef::kPositiveOffsetBias;
1342                 Emit(" - . + " + ss.str());
1343             }
1344         }
1345         if (StringUtils::StartsWith(stName, ITAB_PREFIX_STR)) {
1346             Emit("-.");
1347         }
1348         if (StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR)) {
1349             /* output in hex format to show it is a flag of bits. */
1350             std::stringstream ss;
1351             ss << std::hex << "0x" << MByteRef32::kPositiveOffsetBias;
1352             Emit(" - . + " + ss.str());
1353         }
1354         if ((idx == 1 || idx == methodTypeIdx) && StringUtils::StartsWith(stName, kVtabOffsetTabStr)) {
1355             Emit("-.");
1356         }
1357         if ((idx == 1 || idx == fieldTypeIdx) && StringUtils::StartsWith(stName, kFieldOffsetTabStr)) {
1358             Emit("-.");
1359         }
1360         Emit("\n");
1361     } else if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncUndefTab()) {
1362 #if defined(USE_32BIT_REF)
1363         Emit("\t.long\t");
1364 #else
1365         EmitAsmLabel(kAsmQuad);
1366 #endif /* USE_32BIT_REF */
1367         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1368             /*
1369              * Check enum BindingState defined in Mpl_Binding.h,
1370              * 5 means kBindingStateMethodUndef:5 offset away from base __BindingProtectRegion__.
1371              */
1372 #if defined(USE_32BIT_REF)
1373             Emit("0x5\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateMethodUndef:5. */
1374 #else
1375             Emit("__BindingProtectRegion__ + 5\n");
1376 #endif /* USE_32BIT_REF */
1377         } else {
1378             Emit("0\n");
1379         }
1380     } else if (idx == static_cast<uint32>(FieldProperty::kPClassType) && mirSymbol.IsReflectionFieldsInfo()) {
1381 #ifdef USE_32BIT_REF
1382         Emit("\t.long\t");
1383         const int width = 4;
1384 #else
1385         EmitAsmLabel(kAsmQuad);
1386         const int width = 8;
1387 #endif /* USE_32BIT_REF */
1388         uint32 muidDataTabAddr = static_cast<uint32>((safe_cast<MIRIntConst>(elemConst))->GetExtValue());
1389         if (muidDataTabAddr != 0) {
1390             bool isDefTabIndex = (muidDataTabAddr & kFromDefIndexMask32Mod) == kFromDefIndexMask32Mod;
1391             std::string muidDataTabPrefix = isDefTabIndex ? kMuidDataDefTabPrefixStr : kMuidDataUndefTabPrefixStr;
1392             std::string muidDataTabName = muidDataTabPrefix + cg->GetMIRModule()->GetFileNameAsPostfix();
1393             (void)Emit(muidDataTabName + "+");
1394             uint32 muidDataTabIndex = muidDataTabAddr & 0x3FFFFFFF; /* high 2 bit is the mask of muid tab */
1395             (void)Emit(std::to_string(muidDataTabIndex * width));
1396             (void)Emit("-.\n");
1397         } else {
1398             (void)Emit(muidDataTabAddr);
1399             Emit("\n");
1400         }
1401         return;
1402     } else if (mirSymbol.IsReflectionFieldOffsetData()) {
1403         /* Figure out instance field offset now. */
1404         size_t prefixStrLen = strlen(kFieldOffsetDataPrefixStr);
1405         size_t pos = stName.find("_FieldID_");
1406         std::string typeName = stName.substr(prefixStrLen, pos - prefixStrLen);
1407 #ifdef USE_32BIT_REF
1408         std::string widthFlag = ".long";
1409 #else
1410         std::string widthFlag = ".quad";
1411 #endif /* USE_32BIT_REF */
1412         int64 fieldOffset = GetFieldOffsetValue(typeName, *intConst, strIdx2Type);
1413         uint64 fieldIdx = static_cast<uint64>(intConst->GetExtValue());
1414         bool isDefTabIndex = fieldIdx & 0x1;
1415         if (isDefTabIndex) {
1416             /* it's def table index. */
1417             Emit("\t//  " + typeName + " static field, data def table index " + std::to_string(fieldOffset) + "\n");
1418         } else {
1419             /* really offset. */
1420             fieldIdx >>= 1;
1421             Emit("\t//  " + typeName + "\t field" + std::to_string(fieldIdx) + "\n");
1422         }
1423         Emit("\t" + widthFlag + "\t" + std::to_string(fieldOffset) + "\n");
1424     } else if (((idx == static_cast<uint32>(FieldProperty::kPOffset)) && mirSymbol.IsReflectionFieldsInfo()) ||
1425                ((idx == static_cast<uint32>(FieldPropertyCompact::kPOffset)) &&
1426                 mirSymbol.IsReflectionFieldsInfoCompact())) {
1427         std::string typeName;
1428         std::string widthFlag;
1429 #ifdef USE_32BIT_REF
1430         const int width = 4;
1431 #else
1432         const int width = 8;
1433 #endif /* USE_32BIT_REF */
1434         if (mirSymbol.IsReflectionFieldsInfo()) {
1435             typeName = stName.substr(strlen(kFieldsInfoPrefixStr));
1436 #ifdef USE_32BIT_REF
1437             widthFlag = ".long";
1438 #else
1439             widthFlag = ".quad";
1440 #endif /* USE_32BIT_REF */
1441         } else {
1442             size_t prefixStrLen = strlen(kFieldsInfoCompactPrefixStr);
1443             typeName = stName.substr(prefixStrLen);
1444             widthFlag = ".long";
1445         }
1446         int64 fieldIdx = intConst->GetExtValue();
1447         MIRSymbol *pOffsetData = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
1448             GlobalTables::GetStrTable().GetStrIdxFromName(kFieldOffsetDataPrefixStr + typeName));
1449         if (pOffsetData != nullptr) {
1450             fieldIdx *= width;
1451             std::string fieldOffset = kFieldOffsetDataPrefixStr + typeName;
1452             Emit("\t" + widthFlag + "\t" + std::to_string(fieldIdx) + " + " + fieldOffset + " - .\n");
1453         } else {
1454             /* pOffsetData null, means FieldMeta.offset is really offset */
1455             int64 fieldOffset = GetFieldOffsetValue(typeName, *intConst, strIdx2Type);
1456             Emit("\t//  " + typeName + "\t field" + std::to_string(fieldIdx) + "\n");
1457             Emit("\t" + widthFlag + "\t" + std::to_string(fieldOffset) + "\n");
1458         }
1459     } else if ((idx == static_cast<uint32>(ClassProperty::kObjsize)) && mirSymbol.IsReflectionClassInfo()) {
1460         std::string delimiter = "$$";
1461         std::string typeName =
1462             stName.substr(strlen(CLASSINFO_PREFIX_STR), stName.find(delimiter) - strlen(CLASSINFO_PREFIX_STR));
1463         uint32 objSize = 0;
1464         std::string comments;
1465 
1466         if (typeName.size() > 1 && typeName[0] == '$') {
1467             /* fill element size for array class; */
1468             std::string newTypeName = typeName.substr(1);
1469             /* another $(arraysplitter) */
1470             if (newTypeName.find("$") == std::string::npos) {
1471                 CHECK_FATAL(false, "can not find $ in std::string");
1472             }
1473             typeName = newTypeName.substr(newTypeName.find("$") + 1);
1474             int32 pTypeSize;
1475 
1476             /* we only need to calculate primitive type in arrays. */
1477             if ((pTypeSize = GetPrimitiveTypeSize(typeName)) != -1) {
1478                 objSize = static_cast<uint32>(pTypeSize);
1479             }
1480             comments = "// elemobjsize";
1481         } else {
1482             comments = "// objsize";
1483         }
1484 
1485         if (!objSize) {
1486             GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(typeName);
1487             auto it = strIdx2Type.find(strIdx);
1488             DEBUG_ASSERT(it != strIdx2Type.end(), "Can not find type");
1489             MIRType *mirType = it->second;
1490             ASSERT_NOT_NULL(mirType);
1491             objSize = Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex());
1492         }
1493         /* objSize should not exceed 16 bits */
1494         CHECK_FATAL(objSize <= 0xffff, "Error:the objSize is too large");
1495         Emit("\t.short\t" + std::to_string(objSize) + comments + "\n");
1496     } else if (mirSymbol.IsMuidRangeTab()) {
1497         MIRIntConst *subIntCt = safe_cast<MIRIntConst>(elemConst);
1498         int flag = subIntCt->GetExtValue();
1499         InitRangeIdx2PerfixStr();
1500         if (rangeIdx2PrefixStr.find(flag) == rangeIdx2PrefixStr.end()) {
1501             EmitScalarConstant(*elemConst, false);
1502             Emit("\n");
1503             return;
1504         }
1505         std::string prefix = rangeIdx2PrefixStr[flag];
1506 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1507         EmitAsmLabel(kAsmQuad);
1508 #else
1509         (void)Emit("\t.word\t");
1510 #endif
1511         if (idx == kRangeBeginIndex) {
1512             Emit(prefix + "_begin\n");
1513         } else {
1514             Emit(prefix + "_end\n");
1515         }
1516     } else {
1517 #ifdef USE_32BIT_REF
1518         if (StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR) ||
1519             StringUtils::StartsWith(stName, ITAB_PREFIX_STR) || StringUtils::StartsWith(stName, VTAB_PREFIX_STR)) {
1520             EmitScalarConstant(*elemConst, false, true);
1521         } else {
1522             EmitScalarConstant(*elemConst, false);
1523         }
1524 #else
1525         ASSERT_NOT_NULL(elemConst);
1526         EmitScalarConstant(*elemConst, false);
1527 #endif /* USE_32BIT_REF */
1528         Emit("\n");
1529     }
1530 #endif
1531 }
1532 
1533 void Emitter::EmitConstantTable(const MIRSymbol &mirSymbol, MIRConst &mirConst,
1534                                 const std::map<GStrIdx, MIRType *> &strIdx2Type)
1535 {
1536 #ifdef ARK_LITECG_DEBUG
1537     const std::string stName = mirSymbol.GetName();
1538     MIRAggConst &aggConst = static_cast<MIRAggConst &>(mirConst);
1539     uint32 itabConflictIndex = 0;
1540     for (size_t i = 0; i < aggConst.GetConstVec().size(); ++i) {
1541         MIRConst *elemConst = aggConst.GetConstVecItem(i);
1542         DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
1543         if (i == 0 && StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR)) {
1544 #ifdef USE_32BIT_REF
1545             itabConflictIndex = static_cast<uint64>((safe_cast<MIRIntConst>(elemConst))->GetValue()) & 0xffff;
1546 #else
1547             itabConflictIndex = safe_cast<MIRIntConst>(elemConst)->GetExtValue() & 0xffffffff;
1548 #endif
1549         }
1550         if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) {
1551             if (elemConst->GetKind() == kConstAddrofFunc) { /* addroffunc const */
1552                 EmitAddrofFuncConst(mirSymbol, *elemConst, i);
1553             } else if (elemConst->GetKind() == kConstAddrof) { /* addrof symbol const */
1554                 EmitAddrofSymbolConst(mirSymbol, *elemConst, i);
1555             } else { /* intconst */
1556                 EmitIntConst(mirSymbol, aggConst, itabConflictIndex, strIdx2Type, i);
1557             }
1558         } else if (elemConst->GetType().GetKind() == kTypeArray) {
1559             if (StringUtils::StartsWith(mirSymbol.GetName(), namemangler::kOffsetTabStr) && (i == 0 || i == 1)) {
1560                 /* EmitOffsetValueTable */
1561 #ifdef USE_32BIT_REF
1562                 Emit("\t.long\t");
1563 #else
1564                 EmitAsmLabel(kAsmQuad);
1565 #endif
1566                 if (i == 0) {
1567                     (void)Emit(namemangler::kVtabOffsetTabStr + cg->GetMIRModule()->GetFileNameAsPostfix() + " - .\n");
1568                 } else {
1569                     (void)Emit(namemangler::kFieldOffsetTabStr + cg->GetMIRModule()->GetFileNameAsPostfix() + " - .\n");
1570                 }
1571             } else {
1572                 EmitConstantTable(mirSymbol, *elemConst, strIdx2Type);
1573             }
1574         }
1575     }
1576 #endif
1577 }
1578 
1579 void Emitter::EmitArrayConstant(MIRConst &mirConst)
1580 {
1581 #ifdef ARK_LITECG_DEBUG
1582     MIRType &mirType = mirConst.GetType();
1583     MIRAggConst &arrayCt = static_cast<MIRAggConst &>(mirConst);
1584     MIRArrayType &arrayType = static_cast<MIRArrayType &>(mirType);
1585     size_t uNum = arrayCt.GetConstVec().size();
1586     uint32 dim = arrayType.GetSizeArrayItem(0);
1587     TyIdx scalarIdx = arrayType.GetElemTyIdx();
1588     MIRType *subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx);
1589     if (uNum == 0 && dim) {
1590         while (subTy->GetKind() == kTypeArray) {
1591             MIRArrayType *aSubTy = static_cast<MIRArrayType *>(subTy);
1592             if (aSubTy->GetSizeArrayItem(0) > 0) {
1593                 dim *= (aSubTy->GetSizeArrayItem(0));
1594             }
1595             scalarIdx = aSubTy->GetElemTyIdx();
1596             subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx);
1597         }
1598     }
1599     for (size_t i = 0; i < uNum; ++i) {
1600         MIRConst *elemConst = arrayCt.GetConstVecItem(i);
1601         if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) {
1602             EmitScalarConstant(*elemConst);
1603         } else if (elemConst->GetType().GetKind() == kTypeArray) {
1604             EmitArrayConstant(*elemConst);
1605         } else if (elemConst->GetKind() == kConstAddrofFunc) {
1606             EmitScalarConstant(*elemConst);
1607         } else {
1608             DEBUG_ASSERT(false, "should not run here");
1609         }
1610     }
1611     DEBUG_ASSERT(static_cast<int64>(arrayType.GetSizeArrayItem(0)) > 0, "must not be zero");
1612     int64 iNum = (arrayType.GetSizeArrayItem(0) > 0) ? (static_cast<int64>(arrayType.GetSizeArrayItem(0)) - uNum) : 0;
1613     if (iNum > 0) {
1614         CHECK_FATAL(!Globals::GetInstance()->GetBECommon()->IsEmptyOfTypeSizeTable(), "container empty check");
1615         CHECK_FATAL(!arrayCt.GetConstVec().empty(), "container empty check");
1616         if (uNum > 0) {
1617             uint64 unInSizeInByte =
1618                 static_cast<uint64>(iNum) * static_cast<uint64>(Globals::GetInstance()->GetBECommon()->GetTypeSize(
1619                     arrayCt.GetConstVecItem(0)->GetType().GetTypeIndex()));
1620             if (unInSizeInByte != 0) {
1621                 EmitNullConstant(unInSizeInByte);
1622             }
1623         } else {
1624             uint64 size = Globals::GetInstance()->GetBECommon()->GetTypeSize(scalarIdx.GetIdx()) * dim;
1625             Emit("\t.zero\t").Emit(static_cast<int64>(size)).Emit("\n");
1626         }
1627     }
1628 #endif
1629 }
1630 
1631 /* BlockMarker is for Debugging/Profiling */
1632 void Emitter::EmitBlockMarker(const std::string &markerName, const std::string &sectionName, bool withAddr,
1633                               const std::string &addrName)
1634 {
1635 #ifdef ARK_LITECG_DEBUG
1636     /*
1637      * .type $marker_name$, %object
1638      * .global $marker_name$
1639      * .data
1640      * .align 3
1641      * $marker_name$:
1642      * .quad 0xdeadbeefdeadbeef
1643      * .size $marker_name$, 8
1644      */
1645     Emit(asmInfo->GetType());
1646     Emit(markerName);
1647     Emit(", %object\n");
1648     if (CGOptions::IsEmitBlockMarker()) { /* exposed as global symbol, for profiling */
1649         Emit(asmInfo->GetGlobal());
1650     } else { /* exposed as local symbol, for release. */
1651         Emit(asmInfo->GetLocal());
1652     }
1653     Emit(markerName);
1654     Emit("\n");
1655 
1656     if (!sectionName.empty()) {
1657         Emit("\t.section ." + sectionName);
1658         if (sectionName.find("ro") == 0) {
1659             Emit(",\"a\",%progbits\n");
1660         } else {
1661             Emit(",\"aw\",%progbits\n");
1662         }
1663     } else {
1664         EmitAsmLabel(kAsmData);
1665     }
1666     Emit(asmInfo->GetAlign());
1667     if (GetCG()->GetTargetMachine()->isX8664()) {
1668         Emit("8\n" + markerName + ":\n");
1669     } else {
1670         Emit("3\n" + markerName + ":\n");
1671     }
1672     EmitAsmLabel(kAsmQuad);
1673     if (withAddr) {
1674         Emit(addrName + "\n");
1675     } else {
1676         Emit("0xdeadbeefdeadbeef\n"); /* hexspeak in aarch64 represents crash or dead lock */
1677     }
1678     Emit(asmInfo->GetSize());
1679     Emit(markerName + ", 8\n");
1680 #endif
1681 }
1682 
1683 void Emitter::EmitLiteral(const MIRSymbol &literal, const std::map<GStrIdx, MIRType *> &strIdx2Type)
1684 {
1685 #ifdef ARK_LITECG_DEBUG
1686     /*
1687      * .type _C_STR_xxxx, %object
1688      * .local _C_STR_xxxx
1689      * .data
1690      * .align 3
1691      * _C_STR_xxxx:
1692      * ....
1693      * .size _C_STR_xxxx, 40
1694      */
1695     if (literal.GetStorageClass() == kScUnused) {
1696         return;
1697     }
1698     EmitAsmLabel(literal, kAsmType);
1699     /* literal should always be fstatic and readonly? */
1700     EmitAsmLabel(literal, kAsmLocal); /* alwasy fstatic */
1701     (void)Emit("\t.section\t." + std::string(kMapleLiteralString) + ",\"aw\", %progbits\n");
1702     EmitAsmLabel(literal, kAsmAlign);
1703     EmitAsmLabel(literal, kAsmSyname);
1704     /* literal is an array */
1705     MIRConst *mirConst = literal.GetKonst();
1706     CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitLiteral");
1707     if (literal.HasAddrOfValues()) {
1708         EmitConstantTable(literal, *mirConst, strIdx2Type);
1709     } else {
1710         EmitArrayConstant(*mirConst);
1711     }
1712     EmitAsmLabel(literal, kAsmSize);
1713 #endif
1714 }
1715 
1716 std::string Emitter::GetLayoutTypeString(uint32_t type)
1717 {
1718 #ifdef ARK_LITECG_DEBUG
1719     switch (type) {
1720         case kLayoutBootHot:
1721             return "BootHot";
1722         case kLayoutBothHot:
1723             return "BothHot";
1724         case kLayoutRunHot:
1725             return "RunHot";
1726         case kLayoutStartupOnly:
1727             return "StartupOnly";
1728         case kLayoutUsedOnce:
1729             return "UsedOnce";
1730         case kLayoutExecuted:
1731             return "UsedMaybe";
1732         case kLayoutUnused:
1733             return "Unused";
1734         default:
1735             std::cerr << "no such type" << std::endl;
1736             return "";
1737     }
1738 #else
1739     return "";
1740 #endif
1741 }
1742 
1743 void Emitter::EmitFuncLayoutInfo(const MIRSymbol &layout)
1744 {
1745 #ifdef ARK_LITECG_DEBUG
1746     /*
1747      * .type $marker_name$, %object
1748      * .global $marker_name$
1749      * .data
1750      * .align 3
1751      * $marker_name$:
1752      * .quad funcaddr
1753      * .size $marker_name$, 8
1754      */
1755     MIRConst *mirConst = layout.GetKonst();
1756     MIRAggConst *aggConst = safe_cast<MIRAggConst>(mirConst);
1757     DEBUG_ASSERT(aggConst != nullptr, "null ptr check");
1758     if (aggConst->GetConstVec().size() != static_cast<uint32>(LayoutType::kLayoutTypeCount)) {
1759         maple::LogInfo::MapleLogger(kLlErr) << "something wrong happen in funclayoutsym\t"
1760                                             << "constVec size\t" << aggConst->GetConstVec().size() << "\n";
1761         return;
1762     }
1763     for (size_t i = 0; i < static_cast<size_t>(LayoutType::kLayoutTypeCount); ++i) {
1764         std::string markerName = "__MBlock_" + GetLayoutTypeString(i) + "_func_start";
1765         CHECK_FATAL(aggConst->GetConstVecItem(i)->GetKind() == kConstAddrofFunc, "expect kConstAddrofFunc type");
1766         MIRAddroffuncConst *funcAddr = safe_cast<MIRAddroffuncConst>(aggConst->GetConstVecItem(i));
1767         DEBUG_ASSERT(funcAddr != nullptr, "null ptr check");
1768         Emit(asmInfo->GetType());
1769         Emit(markerName + ", %object\n");
1770         Emit(asmInfo->GetGlobal());
1771         Emit(markerName + "\n");
1772         EmitAsmLabel(kAsmData);
1773         if (GetCG()->GetTargetMachine()->isX8664()) {
1774             EmitAsmLabel(layout, kAsmAlign);
1775             Emit(markerName + ":\n");
1776         } else {
1777             Emit(asmInfo->GetAlign());
1778             Emit("3\n" + markerName + ":\n");
1779         }
1780 
1781 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1782         EmitAsmLabel(kAsmQuad);
1783 #else
1784         Emit("\t.word ");
1785 #endif
1786         Emit(GlobalTables::GetFunctionTable().GetFunctionFromPuidx(funcAddr->GetValue())->GetName());
1787         Emit("\n");
1788         Emit(asmInfo->GetSize());
1789         Emit(markerName + ", 8\n");
1790     }
1791 #endif
1792 }
1793 
1794 void Emitter::EmitStaticFields(const std::vector<MIRSymbol *> &fields)
1795 {
1796 #ifdef ARK_LITECG_DEBUG
1797     for (auto *itSymbol : fields) {
1798         EmitAsmLabel(*itSymbol, kAsmType);
1799         /* literal should always be fstatic and readonly? */
1800         EmitAsmLabel(*itSymbol, kAsmLocal); /* alwasy fstatic */
1801         EmitAsmLabel(kAsmData);
1802         EmitAsmLabel(*itSymbol, kAsmAlign);
1803         EmitAsmLabel(*itSymbol, kAsmSyname);
1804         /* literal is an array */
1805         MIRConst *mirConst = itSymbol->GetKonst();
1806         EmitArrayConstant(*mirConst);
1807     }
1808 #endif
1809 }
1810 
1811 void Emitter::EmitLiterals(std::vector<std::pair<MIRSymbol *, bool>> &literals,
1812                            const std::map<GStrIdx, MIRType *> &strIdx2Type)
1813 {
1814 #ifdef ARK_LITECG_DEBUG
1815     /* emit hot literal start symbol */
1816     EmitBlockMarker("__MBlock_literal_hot_begin", "", false);
1817     /* emit hot literal end symbol */
1818     EmitBlockMarker("__MBlock_literal_hot_end", "", false);
1819 
1820     /* emit cold literal start symbol */
1821     EmitBlockMarker("__MBlock_literal_cold_begin", "", false);
1822     /* emit other literals (not in the profile) next. */
1823     for (const auto &literalPair : literals) {
1824         if (!literalPair.second) {
1825             /* not emit yet */
1826             EmitLiteral(*(literalPair.first), strIdx2Type);
1827         }
1828     }
1829     /* emit cold literal end symbol */
1830     EmitBlockMarker("__MBlock_literal_cold_end", "", false);
1831 #endif
1832 }
1833 
1834 void Emitter::GetHotAndColdMetaSymbolInfo(const std::vector<MIRSymbol *> &mirSymbolVec,
1835                                           std::vector<MIRSymbol *> &hotFieldInfoSymbolVec,
1836                                           std::vector<MIRSymbol *> &coldFieldInfoSymbolVec,
1837                                           const std::string &prefixStr, bool forceCold)
1838 {
1839 #ifdef ARK_LITECG_DEBUG
1840     bool isHot = false;
1841     for (auto mirSymbol : mirSymbolVec) {
1842         CHECK_FATAL(prefixStr.length() < mirSymbol->GetName().length(), "string length check");
1843         std::string name = mirSymbol->GetName().substr(prefixStr.length());
1844         std::string klassJDescriptor;
1845         namemangler::DecodeMapleNameToJDescriptor(name, klassJDescriptor);
1846         if (isHot && !forceCold) {
1847             hotFieldInfoSymbolVec.emplace_back(mirSymbol);
1848         } else {
1849             coldFieldInfoSymbolVec.emplace_back(mirSymbol);
1850         }
1851     }
1852 #endif
1853 }
1854 
1855 void Emitter::EmitMetaDataSymbolWithMarkFlag(const std::vector<MIRSymbol *> &mirSymbolVec,
1856                                              const std::map<GStrIdx, MIRType *> &strIdx2Type,
1857                                              const std::string &prefixStr, const std::string &sectionName,
1858                                              bool isHotFlag)
1859 {
1860 #ifdef ARK_LITECG_DEBUG
1861     if (mirSymbolVec.empty()) {
1862         return;
1863     }
1864     const std::string &markString = "__MBlock" + prefixStr;
1865     const std::string &hotOrCold = isHotFlag ? "hot" : "cold";
1866     EmitBlockMarker((markString + hotOrCold + "_begin"), sectionName, false);
1867     if (prefixStr == kFieldsInfoCompactPrefixStr || prefixStr == kMethodsInfoCompactPrefixStr ||
1868         prefixStr == kFieldOffsetDataPrefixStr || prefixStr == kMethodAddrDataPrefixStr) {
1869         for (auto s : mirSymbolVec) {
1870             EmitMethodFieldSequential(*s, strIdx2Type, sectionName);
1871         }
1872     } else {
1873         for (auto s : mirSymbolVec) {
1874             EmitClassInfoSequential(*s, strIdx2Type, sectionName);
1875         }
1876     }
1877     EmitBlockMarker((markString + hotOrCold + "_end"), sectionName, false);
1878 #endif
1879 }
1880 
1881 void Emitter::MarkVtabOrItabEndFlag(const std::vector<MIRSymbol *> &mirSymbolVec)
1882 {
1883 #ifdef ARK_LITECG_DEBUG
1884     for (auto mirSymbol : mirSymbolVec) {
1885         auto *aggConst = safe_cast<MIRAggConst>(mirSymbol->GetKonst());
1886         if ((aggConst == nullptr) || (aggConst->GetConstVec().empty())) {
1887             continue;
1888         }
1889         size_t size = aggConst->GetConstVec().size();
1890         CHECK_FATAL(size > 0, "must not be zero");
1891         MIRConst *elemConst = aggConst->GetConstVecItem(size - 1);
1892         DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
1893         if (elemConst->GetKind() == kConstAddrofFunc) {
1894             maple::LogInfo::MapleLogger(kLlErr) << "ERROR: the last vtab/itab content should not be funcAddr\n";
1895         } else {
1896             if (elemConst->GetKind() != kConstInt) {
1897                 CHECK_FATAL(elemConst->GetKind() == kConstAddrof, "must be");
1898                 continue;
1899             }
1900             MIRIntConst *tabConst = static_cast<MIRIntConst *>(elemConst);
1901 #ifdef USE_32BIT_REF
1902             /* #define COLD VTAB ITAB END FLAG  0X4000000000000000 */
1903             tabConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
1904                 static_cast<uint32>(tabConst->GetValue()) | 0X40000000, tabConst->GetType());
1905 #else
1906             /* #define COLD VTAB ITAB END FLAG  0X4000000000000000 */
1907             tabConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
1908                 tabConst->GetExtValue() | 0X4000000000000000, tabConst->GetType());
1909 #endif
1910             CHECK_FATAL(size > 0, "must not be zero");
1911             CHECK_FATAL(static_cast<uint32>(size) > 0, "must not be zero");
1912             aggConst->SetItem(static_cast<uint32>(size) - 1, tabConst, aggConst->GetFieldIdItem(size - 1));
1913         }
1914     }
1915 #endif
1916 }
1917 
1918 void Emitter::EmitStringPointers()
1919 {
1920 #ifdef ARK_LITECG_DEBUG
1921     if (CGOptions::OptimizeForSize()) {
1922         (void)Emit(asmInfo->GetSection()).Emit(".rodata,\"aMS\",@progbits,1").Emit("\n");
1923         if (GetCG()->GetTargetMachine()->isX8664()) {
1924             Emit("\t.align 8\n");
1925         } else {
1926             Emit("\t.align 3\n");
1927         }
1928     } else {
1929         (void)Emit(asmInfo->GetSection()).Emit(".rodata").Emit("\n");
1930     }
1931     for (auto idx : localStrPtr) {
1932         if (idx == 0u) {
1933             continue;
1934         }
1935         if (!CGOptions::OptimizeForSize()) {
1936             if (GetCG()->GetTargetMachine()->isX8664()) {
1937                 Emit("\t.align 8\n");
1938             } else {
1939                 Emit("\t.align 3\n");
1940             }
1941         }
1942         uint32 strId = idx.GetIdx();
1943         std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(idx);
1944         (void)Emit(".LUstr_").Emit(strId).Emit(":\n");
1945         std::string mplstr(str);
1946         EmitStr(mplstr, false, true);
1947     }
1948     for (auto idx : stringPtr) {
1949         if (idx == 0u) {
1950             continue;
1951         }
1952         if (!CGOptions::OptimizeForSize()) {
1953             if (GetCG()->GetTargetMachine()->isX8664()) {
1954                 Emit("\t.align 8\n");
1955             } else {
1956                 Emit("\t.align 3\n");
1957             }
1958         }
1959         uint32 strId = idx.GetIdx();
1960         std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(idx);
1961         Emit(asmInfo->GetAlign());
1962         if (GetCG()->GetTargetMachine()->isX8664()) {
1963             Emit("8\n");
1964         } else {
1965             Emit("3\n");
1966         }
1967         Emit(".LSTR__").Emit(strId).Emit(":\n");
1968         std::string mplstr(str);
1969         EmitStr(mplstr, false, true);
1970     }
1971 #endif
1972 }
1973 
1974 void Emitter::EmitLocalVariable(const CGFunc &cgFunc)
1975 {
1976 #ifdef ARK_LITECG_DEBUG
1977     /* function local pstatic initialization */
1978 #endif
1979 }
1980 
1981 void Emitter::EmitGlobalVar(const MIRSymbol &globalVar)
1982 {
1983 #ifdef ARK_LITECG_DEBUG
1984     EmitAsmLabel(globalVar, kAsmType);
1985     if (globalVar.sectionAttr != UStrIdx(0)) { /* check section info if it is from inline asm */
1986         Emit("\t.section\t");
1987         Emit(GlobalTables::GetUStrTable().GetStringFromStrIdx(globalVar.sectionAttr));
1988         Emit(",\"aw\",%progbits\n");
1989     } else {
1990         EmitAsmLabel(globalVar, kAsmLocal);
1991     }
1992     EmitAsmLabel(globalVar, kAsmComm);
1993 #endif
1994 }
1995 
1996 void Emitter::EmitGlobalVars(std::vector<std::pair<MIRSymbol *, bool>> &globalVars)
1997 {
1998 #ifdef ARK_LITECG_DEBUG
1999     if (GetCG()->IsLmbc() && GetCG()->GetGP() != nullptr) {
2000         (void)Emit(asmInfo->GetLocal()).Emit("\t").Emit(GetCG()->GetGP()->GetName()).Emit("\n");
2001         (void)Emit(asmInfo->GetComm()).Emit("\t").Emit(GetCG()->GetGP()->GetName());
2002         (void)Emit(", ").Emit(GetCG()->GetMIRModule()->GetGlobalMemSize()).Emit(", ").Emit("8\n");
2003     }
2004     /* load globalVars profile */
2005     if (globalVars.empty()) {
2006         return;
2007     }
2008     std::unordered_set<std::string> hotVars;
2009     std::ifstream inFile;
2010     if (!CGOptions::IsGlobalVarProFileEmpty()) {
2011         inFile.open(CGOptions::GetGlobalVarProFile());
2012         if (inFile.fail()) {
2013             maple::LogInfo::MapleLogger(kLlErr)
2014                 << "Cannot open globalVar profile file " << CGOptions::GetGlobalVarProFile() << "\n";
2015         }
2016     }
2017     if (CGOptions::IsGlobalVarProFileEmpty() || inFile.fail()) {
2018         for (const auto &globalVarPair : globalVars) {
2019             EmitGlobalVar(*(globalVarPair.first));
2020         }
2021         return;
2022     }
2023     std::string globalVarName;
2024     while (inFile >> globalVarName) {
2025         (void)hotVars.insert(globalVarName);
2026     }
2027     inFile.close();
2028     bool hotBeginSet = false;
2029     bool coldBeginSet = false;
2030     for (auto &globalVarPair : globalVars) {
2031         if (hotVars.find(globalVarPair.first->GetName()) != hotVars.end()) {
2032             if (!hotBeginSet) {
2033                 /* emit hot globalvar start symbol */
2034                 EmitBlockMarker("__MBlock_globalVars_hot_begin", "", true, globalVarPair.first->GetName());
2035                 hotBeginSet = true;
2036             }
2037             EmitGlobalVar(*(globalVarPair.first));
2038             globalVarPair.second = true;
2039         }
2040     }
2041     for (const auto &globalVarPair : globalVars) {
2042         if (!globalVarPair.second) { /* not emit yet */
2043             if (!coldBeginSet) {
2044                 /* emit hot globalvar start symbol */
2045                 EmitBlockMarker("__MBlock_globalVars_cold_begin", "", true, globalVarPair.first->GetName());
2046                 coldBeginSet = true;
2047             }
2048             EmitGlobalVar(*(globalVarPair.first));
2049         }
2050     }
2051     MIRSymbol *endSym = globalVars.back().first;
2052     MIRType *mirType = endSym->GetType();
2053     ASSERT_NOT_NULL(endSym);
2054     ASSERT_NOT_NULL(mirType);
2055     const std::string kStaticVarEndAdd =
2056         std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex())) + "+" +
2057         endSym->GetName();
2058     EmitBlockMarker("__MBlock_globalVars_cold_end", "", true, kStaticVarEndAdd);
2059 #endif
2060 }
2061 
2062 void Emitter::EmitUninitializedSymbolsWithPrefixSection(const MIRSymbol &symbol, const std::string &sectionName)
2063 {
2064 #ifdef ARK_LITECG_DEBUG
2065     EmitAsmLabel(symbol, kAsmType);
2066     Emit(asmInfo->GetSection());
2067     auto sectionConstrains = symbol.IsThreadLocal() ? ",\"awT\"," : ",\"aw\",";
2068     (void)Emit(sectionName).Emit(sectionConstrains);
2069     if (sectionName == ".bss" || StringUtils::StartsWith(sectionName, ".bss.") || sectionName == ".tbss" ||
2070         StringUtils::StartsWith(sectionName, ".tbss.")) {
2071         Emit("%nobits\n");
2072     } else {
2073         Emit("%progbits\n");
2074     }
2075     if (symbol.GetAttr(ATTR_weak)) {
2076         EmitAsmLabel(symbol, kAsmWeak);
2077     } else if (symbol.GetStorageClass() == kScGlobal) {
2078         EmitAsmLabel(symbol, kAsmGlbl);
2079     }
2080     EmitAsmLabel(symbol, kAsmAlign);
2081     EmitAsmLabel(symbol, kAsmSyname);
2082     EmitAsmLabel(symbol, kAsmZero);
2083     EmitAsmLabel(symbol, kAsmSize);
2084 #endif
2085 }
2086 
2087 void Emitter::EmitGlobalVariable()
2088 {
2089 #ifdef ARK_LITECG_DEBUG
2090     std::vector<MIRSymbol *> typeStVec;
2091     std::vector<MIRSymbol *> typeNameStVec;
2092     std::map<GStrIdx, MIRType *> strIdx2Type;
2093 
2094     /* sort symbols; classinfo-->field-->method */
2095     size_t size = GlobalTables::GetGsymTable().GetSymbolTableSize();
2096     std::vector<MIRSymbol *> classInfoVec;
2097     std::vector<MIRSymbol *> vtabVec;
2098     std::vector<MIRSymbol *> staticFieldsVec;
2099     std::vector<std::pair<MIRSymbol *, bool>> globalVarVec;
2100     std::vector<MIRSymbol *> itabVec;
2101     std::vector<MIRSymbol *> itabConflictVec;
2102     std::vector<MIRSymbol *> vtabOffsetVec;
2103     std::vector<MIRSymbol *> fieldOffsetVec;
2104     std::vector<MIRSymbol *> valueOffsetVec;
2105     std::vector<MIRSymbol *> localClassInfoVec;
2106     std::vector<MIRSymbol *> constStrVec;
2107     std::vector<std::pair<MIRSymbol *, bool>> literalVec;
2108     std::vector<MIRSymbol *> muidVec = {nullptr};
2109     std::vector<MIRSymbol *> fieldOffsetDatas;
2110     std::vector<MIRSymbol *> methodAddrDatas;
2111     std::vector<MIRSymbol *> methodSignatureDatas;
2112     std::vector<MIRSymbol *> staticDecoupleKeyVec;
2113     std::vector<MIRSymbol *> staticDecoupleValueVec;
2114     std::vector<MIRSymbol *> superClassStVec;
2115     std::vector<MIRSymbol *> arrayClassCacheVec;
2116     std::vector<MIRSymbol *> arrayClassCacheNameVec;
2117 
2118     for (size_t i = 0; i < size; ++i) {
2119         MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(i);
2120         if (mirSymbol == nullptr || mirSymbol->IsDeleted() || mirSymbol->GetStorageClass() == kScUnused) {
2121             continue;
2122         }
2123         if (mirSymbol->GetSKind() == maple::MIRSymKind::kStFunc) {
2124             EmitAliasAndRef(*mirSymbol);
2125         }
2126 
2127         if (mirSymbol->GetName().find(VTAB_PREFIX_STR) == 0) {
2128             vtabVec.emplace_back(mirSymbol);
2129             continue;
2130         } else if (mirSymbol->GetName().find(ITAB_PREFIX_STR) == 0) {
2131             itabVec.emplace_back(mirSymbol);
2132             continue;
2133         } else if (mirSymbol->GetName().find(ITAB_CONFLICT_PREFIX_STR) == 0) {
2134             itabConflictVec.emplace_back(mirSymbol);
2135             continue;
2136         } else if (mirSymbol->GetName().find(kVtabOffsetTabStr) == 0) {
2137             vtabOffsetVec.emplace_back(mirSymbol);
2138             continue;
2139         } else if (mirSymbol->GetName().find(kFieldOffsetTabStr) == 0) {
2140             fieldOffsetVec.emplace_back(mirSymbol);
2141             continue;
2142         } else if (mirSymbol->GetName().find(kOffsetTabStr) == 0) {
2143             valueOffsetVec.emplace_back(mirSymbol);
2144             continue;
2145         } else if (mirSymbol->IsArrayClassCache()) {
2146             arrayClassCacheVec.emplace_back(mirSymbol);
2147             continue;
2148         } else if (mirSymbol->IsArrayClassCacheName()) {
2149             arrayClassCacheNameVec.emplace_back(mirSymbol);
2150             continue;
2151         } else if (mirSymbol->GetName().find(kLocalClassInfoStr) == 0) {
2152             localClassInfoVec.emplace_back(mirSymbol);
2153             continue;
2154         } else if (StringUtils::StartsWith(mirSymbol->GetName(), namemangler::kDecoupleStaticKeyStr)) {
2155             staticDecoupleKeyVec.emplace_back(mirSymbol);
2156             continue;
2157         } else if (StringUtils::StartsWith(mirSymbol->GetName(), namemangler::kDecoupleStaticValueStr)) {
2158             staticDecoupleValueVec.emplace_back(mirSymbol);
2159             continue;
2160         } else if (mirSymbol->IsLiteral()) {
2161             literalVec.emplace_back(std::make_pair(mirSymbol, false));
2162             continue;
2163         } else if (mirSymbol->IsConstString() || mirSymbol->IsLiteralPtr()) {
2164             MIRConst *mirConst = mirSymbol->GetKonst();
2165             if (mirConst != nullptr && mirConst->GetKind() == kConstAddrof) {
2166                 constStrVec.emplace_back(mirSymbol);
2167                 continue;
2168             }
2169         } else if (mirSymbol->IsReflectionClassInfoPtr()) {
2170             /* _PTR__cinf is emitted in dataDefTab and dataUndefTab */
2171             continue;
2172         } else if (mirSymbol->IsMuidTab()) {
2173             muidVec[0] = mirSymbol;
2174             EmitMuidTable(muidVec, strIdx2Type, mirSymbol->GetMuidTabName());
2175             continue;
2176         } else if (mirSymbol->IsCodeLayoutInfo()) {
2177             EmitFuncLayoutInfo(*mirSymbol);
2178             continue;
2179         } else if (mirSymbol->GetName().find(kStaticFieldNamePrefixStr) == 0) {
2180             staticFieldsVec.emplace_back(mirSymbol);
2181             continue;
2182         } else if (mirSymbol->GetName().find(kGcRootList) == 0) {
2183             EmitGlobalRootList(*mirSymbol);
2184             continue;
2185         } else if (mirSymbol->GetName().find(kFunctionProfileTabPrefixStr) == 0) {
2186             muidVec[0] = mirSymbol;
2187             EmitMuidTable(muidVec, strIdx2Type, kFunctionProfileTabPrefixStr);
2188             continue;
2189         } else if (mirSymbol->IsReflectionFieldOffsetData()) {
2190             fieldOffsetDatas.emplace_back(mirSymbol);
2191             continue;
2192         } else if (mirSymbol->IsReflectionMethodAddrData()) {
2193             methodAddrDatas.emplace_back(mirSymbol);
2194             continue;
2195         } else if (mirSymbol->IsReflectionSuperclassInfo()) {
2196             superClassStVec.emplace_back(mirSymbol);
2197             continue;
2198         } else if (mirSymbol->IsReflectionMethodSignature()) {
2199             methodSignatureDatas.push_back(mirSymbol);
2200             continue;
2201         }
2202 
2203         if (mirSymbol->IsReflectionInfo()) {
2204             if (mirSymbol->IsReflectionClassInfo()) {
2205                 classInfoVec.emplace_back(mirSymbol);
2206             }
2207             continue;
2208         }
2209         /* symbols we do not emit here. */
2210         if (mirSymbol->GetSKind() == maple::MIRSymKind::kStFunc) {
2211             continue;
2212         }
2213         if (mirSymbol->GetStorageClass() == kScTypeInfo) {
2214             typeStVec.emplace_back(mirSymbol);
2215             continue;
2216         }
2217         if (mirSymbol->GetStorageClass() == kScTypeInfoName) {
2218             typeNameStVec.emplace_back(mirSymbol);
2219             continue;
2220         }
2221         if (mirSymbol->GetStorageClass() == kScTypeCxxAbi) {
2222             continue;
2223         }
2224 
2225         MIRType *mirType = mirSymbol->GetType();
2226         if (mirType == nullptr) {
2227             continue;
2228         }
2229         /*
2230          * emit uninitialized global/static variables.
2231          * these variables store in .comm section.
2232          */
2233         if ((mirSymbol->GetStorageClass() == kScGlobal || mirSymbol->GetStorageClass() == kScFstatic) &&
2234             !mirSymbol->IsConst()) {
2235             if (mirSymbol->IsGctibSym()) {
2236                 /* GCTIB symbols are generated in GenerateObjectMaps */
2237                 continue;
2238             }
2239             if (mirSymbol->GetStorageClass() != kScGlobal) {
2240                 globalVarVec.emplace_back(std::make_pair(mirSymbol, false));
2241                 continue;
2242             }
2243             if (mirSymbol->sectionAttr != UStrIdx(0)) {
2244                 auto &sectionName = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol->sectionAttr);
2245                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, sectionName);
2246                 continue;
2247             } else if (mirSymbol->IsThreadLocal()) {
2248                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, ".tbss");
2249                 continue;
2250             } else if (mirSymbol->GetAttr(ATTR_static_init_zero)) {
2251                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, ".bss");
2252                 continue;
2253             }
2254             EmitAsmLabel(*mirSymbol, kAsmType);
2255             EmitAsmLabel(*mirSymbol, kAsmComm);
2256             continue;
2257         }
2258 
2259         /* emit initialized global/static variables. */
2260         if (mirSymbol->GetStorageClass() == kScGlobal ||
2261             (mirSymbol->GetStorageClass() == kScFstatic && !mirSymbol->IsReadOnly())) {
2262             /* Emit section */
2263             EmitAsmLabel(*mirSymbol, kAsmType);
2264             if (mirSymbol->IsReflectionStrTab()) {
2265                 std::string sectionName = ".reflection_strtab";
2266                 if (mirSymbol->GetName().find(kReflectionStartHotStrtabPrefixStr) == 0) {
2267                     sectionName = ".reflection_start_hot_strtab";
2268                 } else if (mirSymbol->GetName().find(kReflectionBothHotStrTabPrefixStr) == 0) {
2269                     sectionName = ".reflection_both_hot_strtab";
2270                 } else if (mirSymbol->GetName().find(kReflectionRunHotStrtabPrefixStr) == 0) {
2271                     sectionName = ".reflection_run_hot_strtab";
2272                 }
2273                 Emit("\t.section\t" + sectionName + ",\"a\",%progbits\n");
2274             } else if (mirSymbol->GetName().find(kDecoupleOption) == 0) {
2275                 Emit("\t.section\t." + std::string(kDecoupleStr) + ",\"a\",%progbits\n");
2276             } else if (mirSymbol->IsRegJNITab()) {
2277                 Emit("\t.section\t.reg_jni_tab,\"a\", %progbits\n");
2278             } else if (mirSymbol->GetName().find(kCompilerVersionNum) == 0) {
2279                 Emit("\t.section\t." + std::string(kCompilerVersionNumStr) + ",\"a\", %progbits\n");
2280             } else if (mirSymbol->GetName().find(kSourceMuid) == 0) {
2281                 Emit("\t.section\t." + std::string(kSourceMuidSectionStr) + ",\"a\", %progbits\n");
2282             } else if (mirSymbol->GetName().find(kCompilerMfileStatus) == 0) {
2283                 Emit("\t.section\t." + std::string(kCompilerMfileStatus) + ",\"a\", %progbits\n");
2284             } else if (mirSymbol->IsRegJNIFuncTab()) {
2285                 Emit("\t.section\t.reg_jni_func_tab,\"aw\", %progbits\n");
2286             } else if (mirSymbol->IsReflectionPrimitiveClassInfo()) {
2287                 Emit("\t.section\t.primitive_classinfo,\"awG\", %progbits,__primitive_classinfo__,comdat\n");
2288             } else if (mirSymbol->IsReflectionHashTabBucket()) {
2289                 std::string stName = mirSymbol->GetName();
2290                 const std::string delimiter = "$$";
2291                 if (stName.find(delimiter) == std::string::npos) {
2292                     FATAL(kLncFatal, "Can not find delimiter in target ");
2293                 }
2294                 std::string secName = stName.substr(0, stName.find(delimiter));
2295                 /* remove leading "__" in sec name. */
2296                 secName.erase(0, 2);  // remove 2 chars "__"
2297                 Emit("\t.section\t." + secName + ",\"a\",%progbits\n");
2298             } else {
2299                 bool isThreadLocal = mirSymbol->IsThreadLocal();
2300                 if (mirSymbol->sectionAttr != UStrIdx(0)) {
2301                     auto &sectionName = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol->sectionAttr);
2302                     auto sectionConstrains = isThreadLocal ? ",\"awT\"," : ",\"aw\",";
2303                     (void)Emit("\t.section\t" + sectionName + sectionConstrains + "@progbits\n");
2304                 } else if (isThreadLocal) {
2305                     (void)Emit("\t.section\t.tdata,\"awT\",@progbits\n");
2306                 } else {
2307                     (void)Emit("\t.data\n");
2308                 }
2309             }
2310             /* Emit size and align by type */
2311             if (mirSymbol->GetStorageClass() == kScGlobal) {
2312                 if (mirSymbol->GetAttr(ATTR_weak) || mirSymbol->IsReflectionPrimitiveClassInfo()) {
2313                     EmitAsmLabel(*mirSymbol, kAsmWeak);
2314                 } else {
2315                     EmitAsmLabel(*mirSymbol, kAsmGlbl);
2316                 }
2317             } else if (mirSymbol->GetStorageClass() == kScFstatic) {
2318                 if (mirSymbol->sectionAttr == UStrIdx(0)) {
2319                     EmitAsmLabel(*mirSymbol, kAsmLocal);
2320                 }
2321             }
2322             if (mirSymbol->IsReflectionStrTab()) { /* reflection-string-tab also aligned to 8B boundaries. */
2323                 Emit(asmInfo->GetAlign());
2324                 if (GetCG()->GetTargetMachine()->isX8664()) {
2325                     Emit("8\n");
2326                 } else {
2327                     Emit("3\n");
2328                 }
2329             } else {
2330                 EmitAsmLabel(*mirSymbol, kAsmAlign);
2331             }
2332             EmitAsmLabel(*mirSymbol, kAsmSyname);
2333             MIRConst *mirConst = mirSymbol->GetKonst();
2334             if (IsPrimitiveScalar(mirType->GetPrimType())) {
2335                 if (!CGOptions::IsArm64ilp32()) {
2336                     if (IsAddress(mirType->GetPrimType())) {
2337                         uint32 sizeinbits = GetPrimTypeBitSize(mirConst->GetType().GetPrimType());
2338                         CHECK_FATAL(sizeinbits == k64BitSize, "EmitGlobalVariable: pointer must be of size 8");
2339                     }
2340                 }
2341                 EmitScalarConstant(*mirConst);
2342             } else if (mirType->GetKind() == kTypeArray) {
2343                 if (mirSymbol->HasAddrOfValues()) {
2344                     EmitConstantTable(*mirSymbol, *mirConst, strIdx2Type);
2345                 } else {
2346                     EmitArrayConstant(*mirConst);
2347                 }
2348             } else {
2349                 DEBUG_ASSERT(false, "NYI");
2350             }
2351             EmitAsmLabel(*mirSymbol, kAsmSize);
2352             /* emit constant float/double */
2353         } else if (mirSymbol->IsReadOnly()) {
2354             MIRConst *mirConst = mirSymbol->GetKonst();
2355             if (mirConst->GetKind() == maple::kConstStrConst) {
2356                 auto strCt = static_cast<MIRStrConst *>(mirConst);
2357                 localStrPtr.push_back(strCt->GetValue());
2358             } else {
2359                 EmitAsmLabel(*mirSymbol, kAsmType);
2360                 (void)Emit(asmInfo->GetSection()).Emit(asmInfo->GetRodata()).Emit("\n");
2361                 if (!CGOptions::OptimizeForSize()) {
2362                     EmitAsmLabel(*mirSymbol, kAsmAlign);
2363                 }
2364                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2365                 EmitScalarConstant(*mirConst);
2366             }
2367         } else if (mirSymbol->GetStorageClass() == kScPstatic) {
2368             EmitAsmLabel(*mirSymbol, kAsmType);
2369             Emit(asmInfo->GetSection());
2370             Emit(asmInfo->GetData());
2371             Emit("\n");
2372             EmitAsmLabel(*mirSymbol, kAsmAlign);
2373             EmitAsmLabel(*mirSymbol, kAsmLocal);
2374             MIRConst *ct = mirSymbol->GetKonst();
2375             if (ct == nullptr) {
2376                 EmitAsmLabel(*mirSymbol, kAsmComm);
2377             } else if (IsPrimitiveScalar(mirType->GetPrimType())) {
2378                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2379                 EmitScalarConstant(*ct, true, false, true);
2380             } else if (kTypeArray == mirType->GetKind()) {
2381                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2382                 EmitArrayConstant(*ct);
2383             } else {
2384                 CHECK_FATAL(0, "Unknown type in Global pstatic");
2385             }
2386         }
2387     } /* end proccess all mirSymbols. */
2388     EmitStringPointers();
2389     /* emit global var */
2390     EmitGlobalVars(globalVarVec);
2391     /* emit literal std::strings */
2392     EmitLiterals(literalVec, strIdx2Type);
2393     /* emit static field std::strings */
2394     EmitStaticFields(staticFieldsVec);
2395 
2396     EmitMuidTable(constStrVec, strIdx2Type, kMuidConststrPrefixStr);
2397 
2398     /* emit classinfo, field, method */
2399     std::vector<MIRSymbol *> fieldInfoStVec;
2400     std::vector<MIRSymbol *> fieldInfoStCompactVec;
2401     std::vector<MIRSymbol *> methodInfoStVec;
2402     std::vector<MIRSymbol *> methodInfoStCompactVec;
2403 
2404     std::string sectionName = kMuidClassMetadataPrefixStr;
2405     Emit("\t.section ." + sectionName + ",\"aw\",%progbits\n");
2406     Emit(sectionName + "_begin:\n");
2407 
2408     for (size_t i = 0; i < classInfoVec.size(); ++i) {
2409         MIRSymbol *mirSymbol = classInfoVec[i];
2410         if (mirSymbol != nullptr && mirSymbol->GetKonst() != nullptr && mirSymbol->IsReflectionClassInfo()) {
2411             /* Emit classinfo */
2412             EmitClassInfoSequential(*mirSymbol, strIdx2Type, sectionName);
2413             std::string stName = mirSymbol->GetName();
2414             std::string className = stName.substr(strlen(CLASSINFO_PREFIX_STR));
2415             /* Get classinfo ro symbol */
2416             MIRSymbol *classInfoROSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2417                 GlobalTables::GetStrTable().GetStrIdxFromName(CLASSINFO_RO_PREFIX_STR + className));
2418             EmitClassInfoSequential(*classInfoROSt, strIdx2Type, sectionName);
2419             /* Get fields */
2420             MIRSymbol *fieldSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2421                 GlobalTables::GetStrTable().GetStrIdxFromName(kFieldsInfoPrefixStr + className));
2422             MIRSymbol *fieldStCompact = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2423                 GlobalTables::GetStrTable().GetStrIdxFromName(kFieldsInfoCompactPrefixStr + className));
2424             /* Get methods */
2425             MIRSymbol *methodSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2426                 GlobalTables::GetStrTable().GetStrIdxFromName(kMethodsInfoPrefixStr + className));
2427             MIRSymbol *methodStCompact = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2428                 GlobalTables::GetStrTable().GetStrIdxFromName(kMethodsInfoCompactPrefixStr + className));
2429 
2430             if (fieldSt != nullptr) {
2431                 fieldInfoStVec.emplace_back(fieldSt);
2432             }
2433             if (fieldStCompact != nullptr) {
2434                 fieldInfoStCompactVec.emplace_back(fieldStCompact);
2435             }
2436             if (methodSt != nullptr) {
2437                 methodInfoStVec.emplace_back(methodSt);
2438             }
2439             if (methodStCompact != nullptr) {
2440                 methodInfoStCompactVec.emplace_back(methodStCompact);
2441             }
2442         }
2443     }
2444     Emit(sectionName + "_end:\n");
2445 
2446     std::vector<MIRSymbol *> hotVtabStVec;
2447     std::vector<MIRSymbol *> coldVtabStVec;
2448     std::vector<MIRSymbol *> hotItabStVec;
2449     std::vector<MIRSymbol *> coldItabStVec;
2450     std::vector<MIRSymbol *> hotItabCStVec;
2451     std::vector<MIRSymbol *> coldItabCStVec;
2452     std::vector<MIRSymbol *> hotMethodsInfoCStVec;
2453     std::vector<MIRSymbol *> coldMethodsInfoCStVec;
2454     std::vector<MIRSymbol *> hotFieldsInfoCStVec;
2455     std::vector<MIRSymbol *> coldFieldsInfoCStVec;
2456     GetHotAndColdMetaSymbolInfo(vtabVec, hotVtabStVec, coldVtabStVec, VTAB_PREFIX_STR,
2457                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2458     GetHotAndColdMetaSymbolInfo(itabVec, hotItabStVec, coldItabStVec, ITAB_PREFIX_STR,
2459                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2460     GetHotAndColdMetaSymbolInfo(itabConflictVec, hotItabCStVec, coldItabCStVec, ITAB_CONFLICT_PREFIX_STR,
2461                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2462     GetHotAndColdMetaSymbolInfo(fieldInfoStVec, hotFieldsInfoCStVec, coldFieldsInfoCStVec, kFieldsInfoPrefixStr);
2463     GetHotAndColdMetaSymbolInfo(methodInfoStVec, hotMethodsInfoCStVec, coldMethodsInfoCStVec, kMethodsInfoPrefixStr);
2464 
2465     std::string sectionNameIsEmpty;
2466     std::string fieldSectionName("rometadata.field");
2467     std::string methodSectionName("rometadata.method");
2468 
2469     /* fieldinfo */
2470     EmitMetaDataSymbolWithMarkFlag(hotFieldsInfoCStVec, strIdx2Type, kFieldsInfoPrefixStr, fieldSectionName, true);
2471     EmitMetaDataSymbolWithMarkFlag(coldFieldsInfoCStVec, strIdx2Type, kFieldsInfoPrefixStr, fieldSectionName, false);
2472     EmitMetaDataSymbolWithMarkFlag(fieldInfoStCompactVec, strIdx2Type, kFieldsInfoCompactPrefixStr, fieldSectionName,
2473                                    false);
2474     /* methodinfo */
2475     EmitMetaDataSymbolWithMarkFlag(hotMethodsInfoCStVec, strIdx2Type, kMethodsInfoPrefixStr, methodSectionName, true);
2476     EmitMetaDataSymbolWithMarkFlag(coldMethodsInfoCStVec, strIdx2Type, kMethodsInfoPrefixStr, methodSectionName, false);
2477     EmitMetaDataSymbolWithMarkFlag(methodInfoStCompactVec, strIdx2Type, kMethodsInfoCompactPrefixStr, methodSectionName,
2478                                    false);
2479 
2480     /* itabConflict */
2481     MarkVtabOrItabEndFlag(coldItabCStVec);
2482     EmitMuidTable(hotItabCStVec, strIdx2Type, kMuidItabConflictPrefixStr);
2483     EmitMetaDataSymbolWithMarkFlag(coldItabCStVec, strIdx2Type, ITAB_CONFLICT_PREFIX_STR,
2484                                    kMuidColdItabConflictPrefixStr, false);
2485 
2486     /*
2487      * vtab
2488      * And itab to vtab section
2489      */
2490     for (auto sym : hotItabStVec) {
2491         hotVtabStVec.emplace_back(sym);
2492     }
2493     for (auto sym : coldItabStVec) {
2494         coldVtabStVec.emplace_back(sym);
2495     }
2496     MarkVtabOrItabEndFlag(coldVtabStVec);
2497     EmitMuidTable(hotVtabStVec, strIdx2Type, kMuidVtabAndItabPrefixStr);
2498     EmitMetaDataSymbolWithMarkFlag(coldVtabStVec, strIdx2Type, VTAB_AND_ITAB_PREFIX_STR, kMuidColdVtabAndItabPrefixStr,
2499                                    false);
2500 
2501     /* vtab_offset */
2502     EmitMuidTable(vtabOffsetVec, strIdx2Type, kMuidVtabOffsetPrefixStr);
2503     /* field_offset */
2504     EmitMuidTable(fieldOffsetVec, strIdx2Type, kMuidFieldOffsetPrefixStr);
2505     /* value_offset */
2506     EmitMuidTable(valueOffsetVec, strIdx2Type, kMuidValueOffsetPrefixStr);
2507     /* local clasinfo */
2508     EmitMuidTable(localClassInfoVec, strIdx2Type, kMuidLocalClassInfoStr);
2509     /* Emit decouple static */
2510     EmitMuidTable(staticDecoupleKeyVec, strIdx2Type, kDecoupleStaticKeyStr);
2511     EmitMuidTable(staticDecoupleValueVec, strIdx2Type, kDecoupleStaticValueStr);
2512 
2513     /* super class */
2514     EmitMuidTable(superClassStVec, strIdx2Type, kMuidSuperclassPrefixStr);
2515 
2516     /* field offset rw */
2517     EmitMetaDataSymbolWithMarkFlag(fieldOffsetDatas, strIdx2Type, kFieldOffsetDataPrefixStr, sectionNameIsEmpty, false);
2518     /* method address rw */
2519     EmitMetaDataSymbolWithMarkFlag(methodAddrDatas, strIdx2Type, kMethodAddrDataPrefixStr, sectionNameIsEmpty, false);
2520     /* method address ro */
2521     std::string methodSignatureSectionName("romethodsignature");
2522     EmitMetaDataSymbolWithMarkFlag(methodSignatureDatas, strIdx2Type, kMethodSignaturePrefixStr,
2523                                    methodSignatureSectionName, false);
2524 
2525     /* array class cache table */
2526     EmitMuidTable(arrayClassCacheVec, strIdx2Type, kArrayClassCacheTable);
2527     /* array class cache name table */
2528     EmitMuidTable(arrayClassCacheNameVec, strIdx2Type, kArrayClassCacheNameTable);
2529 
2530 #if !defined(TARGARM32)
2531     /* finally emit __gxx_personality_v0 DW.ref */
2532     EmitDWRef("__mpl_personality_v0");
2533 #endif
2534 #endif
2535 }
2536 void Emitter::EmitAddressString(const std::string &address)
2537 {
2538 #ifdef ARK_LITECG_DEBUG
2539 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
2540     EmitAsmLabel(kAsmQuad);
2541     Emit(address);
2542 #else
2543     Emit("\t.word\t" + address);
2544 #endif
2545 #endif
2546 }
2547 void Emitter::EmitGlobalRootList(const MIRSymbol &mirSymbol)
2548 {
2549 #ifdef ARK_LITECG_DEBUG
2550     Emit("\t.section .maple.gcrootsmap").Emit(",\"aw\",%progbits\n");
2551     std::vector<std::string> nameVec;
2552     std::string name = mirSymbol.GetName();
2553     nameVec.emplace_back(name);
2554     nameVec.emplace_back(name + "Size");
2555     bool gcrootsFlag = true;
2556     uint64 vecSize = 0;
2557     for (const auto &gcrootsName : nameVec) {
2558 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
2559         Emit("\t.type\t" + gcrootsName + ", @object\n" + "\t.p2align 3\n");
2560 #else
2561         Emit("\t.type\t" + gcrootsName + ", %object\n" + "\t.p2align 3\n");
2562 #endif
2563         Emit("\t.global\t" + gcrootsName + "\n");
2564         if (gcrootsFlag) {
2565             Emit(kMuidGlobalRootlistPrefixStr).Emit("_begin:\n");
2566         }
2567         Emit(gcrootsName + ":\n");
2568         if (gcrootsFlag) {
2569             MIRAggConst *aggConst = safe_cast<MIRAggConst>(mirSymbol.GetKonst());
2570             if (aggConst == nullptr) {
2571                 continue;
2572             }
2573             size_t i = 0;
2574             while (i < aggConst->GetConstVec().size()) {
2575                 MIRConst *elemConst = aggConst->GetConstVecItem(i);
2576                 if (elemConst->GetKind() == kConstAddrof) {
2577                     MIRAddrofConst *symAddr = safe_cast<MIRAddrofConst>(elemConst);
2578                     CHECK_FATAL(symAddr != nullptr, "nullptr of symAddr");
2579                     MIRSymbol *symAddrSym =
2580                         GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr->GetSymbolIndex().Idx());
2581                     const std::string &symAddrName = symAddrSym->GetName();
2582                     EmitAddressString(symAddrName + "\n");
2583                 } else {
2584                     EmitScalarConstant(*elemConst);
2585                 }
2586                 i++;
2587             }
2588             vecSize = i;
2589         } else {
2590             EmitAddressString(std::to_string(vecSize) + "\n");
2591         }
2592         Emit("\t.size\t" + gcrootsName + ",.-").Emit(gcrootsName + "\n");
2593         if (gcrootsFlag) {
2594             Emit(kMuidGlobalRootlistPrefixStr).Emit("_end:\n");
2595         }
2596         gcrootsFlag = false;
2597     }
2598 #endif
2599 }
2600 
2601 void Emitter::EmitMuidTable(const std::vector<MIRSymbol *> &vec, const std::map<GStrIdx, MIRType *> &strIdx2Type,
2602                             const std::string &sectionName)
2603 {
2604 #ifdef ARK_LITECG_DEBUG
2605     MIRSymbol *st = nullptr;
2606     if (!vec.empty()) {
2607         st = vec[0];
2608     }
2609     if (st != nullptr && st->IsMuidRoTab()) {
2610         Emit("\t.section  ." + sectionName + ",\"a\",%progbits\n");
2611     } else {
2612         Emit("\t.section  ." + sectionName + ",\"aw\",%progbits\n");
2613     }
2614     Emit(sectionName + "_begin:\n");
2615     bool isConstString = sectionName == kMuidConststrPrefixStr;
2616     for (size_t i = 0; i < vec.size(); i++) {
2617         MIRSymbol *st1 = vec[i];
2618         DEBUG_ASSERT(st1 != nullptr, "null ptr check");
2619         if (st1->GetStorageClass() == kScUnused) {
2620             continue;
2621         }
2622         EmitAsmLabel(*st1, kAsmType);
2623         if (st1->GetStorageClass() == kScFstatic) {
2624             EmitAsmLabel(*st1, kAsmLocal);
2625         } else {
2626             EmitAsmLabel(*st1, kAsmGlbl);
2627             EmitAsmLabel(*st1, kAsmHidden);
2628         }
2629         EmitAsmLabel(*st1, kAsmAlign);
2630         EmitAsmLabel(*st1, kAsmSyname);
2631         MIRConst *mirConst = st1->GetKonst();
2632         CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitMuidTable");
2633         if (mirConst->GetKind() == kConstAddrof) {
2634             MIRAddrofConst *symAddr = safe_cast<MIRAddrofConst>(mirConst);
2635             CHECK_FATAL(symAddr != nullptr, "call static_cast failed in EmitMuidTable");
2636             MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr->GetSymbolIndex().Idx());
2637             DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
2638             if (isConstString) {
2639                 EmitAddressString(symAddrSym->GetName() + " - . + ");
2640                 Emit(kDataRefIsOffset);
2641                 Emit("\n");
2642             } else {
2643                 EmitAddressString(symAddrSym->GetName() + "\n");
2644             }
2645         } else if (mirConst->GetKind() == kConstInt) {
2646             EmitScalarConstant(*mirConst, true);
2647         } else {
2648             EmitConstantTable(*st1, *mirConst, strIdx2Type);
2649         }
2650         EmitAsmLabel(*st1, kAsmSize);
2651     }
2652     Emit(sectionName + "_end:\n");
2653 #endif
2654 }
2655 
2656 void Emitter::EmitClassInfoSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
2657                                       const std::string &sectionName)
2658 {
2659 #ifdef ARK_LITECG_DEBUG
2660     EmitAsmLabel(mirSymbol, kAsmType);
2661     if (!sectionName.empty()) {
2662         Emit("\t.section ." + sectionName);
2663         if (StringUtils::StartsWith(sectionName, "ro")) {
2664             Emit(",\"a\",%progbits\n");
2665         } else {
2666             Emit(",\"aw\",%progbits\n");
2667         }
2668     } else {
2669         EmitAsmLabel(kAsmData);
2670     }
2671     EmitAsmLabel(mirSymbol, kAsmGlbl);
2672     EmitAsmLabel(mirSymbol, kAsmHidden);
2673     EmitAsmLabel(mirSymbol, kAsmAlign);
2674     EmitAsmLabel(mirSymbol, kAsmSyname);
2675     MIRConst *mirConst = mirSymbol.GetKonst();
2676     CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitClassInfoSequential");
2677     EmitConstantTable(mirSymbol, *mirConst, strIdx2Type);
2678     EmitAsmLabel(mirSymbol, kAsmSize);
2679 #endif
2680 }
2681 
2682 void Emitter::EmitMethodDeclaringClass(const MIRSymbol &mirSymbol, const std::string &sectionName)
2683 {
2684 #ifdef ARK_LITECG_DEBUG
2685     std::string symName = mirSymbol.GetName();
2686     std::string emitSyName = symName + "_DeclaringClass";
2687     std::string declaringClassName = symName.substr(strlen(kFieldsInfoCompactPrefixStr) + 1);
2688     Emit(asmInfo->GetType());
2689     Emit(emitSyName + ", %object\n");
2690     if (!sectionName.empty()) {
2691         Emit("\t.section  ." + sectionName + "\n");
2692     } else {
2693         EmitAsmLabel(kAsmData);
2694     }
2695     Emit(asmInfo->GetLocal());
2696     Emit(emitSyName + "\n");
2697     Emit(asmInfo->GetAlign());
2698     Emit("  2\n" + emitSyName + ":\n");
2699     Emit("\t.long\t");
2700     Emit(CLASSINFO_PREFIX_STR + declaringClassName + " - .\n");
2701     Emit(asmInfo->GetSize());
2702     Emit(emitSyName + ", 4\n");
2703 #endif
2704 }
2705 
2706 void Emitter::EmitMethodFieldSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
2707                                         const std::string &sectionName)
2708 {
2709 #ifdef ARK_LITECG_DEBUG
2710     std::string symName = mirSymbol.GetName();
2711     if (symName.find(kMethodsInfoCompactPrefixStr) != std::string::npos) {
2712         EmitMethodDeclaringClass(mirSymbol, sectionName);
2713     }
2714     EmitAsmLabel(mirSymbol, kAsmType);
2715     if (!sectionName.empty()) {
2716         Emit("\t.section  ." + sectionName + "\n");
2717     } else {
2718         EmitAsmLabel(kAsmData);
2719     }
2720     EmitAsmLabel(mirSymbol, kAsmLocal);
2721 
2722     /* Emit(2) is 4 bit align */
2723     Emit(asmInfo->GetAlign()).Emit(2).Emit("\n");
2724     EmitAsmLabel(mirSymbol, kAsmSyname);
2725     MIRConst *ct = mirSymbol.GetKonst();
2726     EmitConstantTable(mirSymbol, *ct, strIdx2Type);
2727     std::string symbolName = mirSymbol.GetName();
2728     Emit("\t.size\t" + symbolName + ", .-");
2729     Emit(symbolName + "\n");
2730 #endif
2731 }
2732 
2733 void Emitter::EmitDWRef(const std::string &name)
2734 {
2735 #ifdef ARK_LITECG_DEBUG
2736     /*
2737      *   .hidden DW.ref._ZTI3xxx
2738      *   .weak DW.ref._ZTI3xxx
2739      *   .section  .data.DW.ref._ZTI3xxx,"awG",@progbits,DW.ref._ZTI3xxx,comdat
2740      *   .align  3
2741      *   .type DW.ref._ZTI3xxx, %object
2742      *   .size DW.ref._ZTI3xxx, 8
2743      * DW.ref._ZTI3xxx:
2744      *   .xword  _ZTI3xxx
2745      */
2746     Emit("\t.hidden DW.ref." + name + "\n");
2747     Emit("\t.weak DW.ref." + name + "\n");
2748     Emit("\t.section .data.DW.ref." + name + ",\"awG\",%progbits,DW.ref.");
2749     Emit(name + ",comdat\n");
2750     Emit(asmInfo->GetAlign());
2751     if (GetCG()->GetTargetMachine()->isX8664()) {
2752         Emit("8\n");
2753     } else {
2754         Emit("3\n");
2755     }
2756     Emit("\t.type DW.ref." + name + ", \%object\n");
2757     Emit("\t.size DW.ref." + name + ",8\n");
2758     Emit("DW.ref." + name + ":\n");
2759     if (GetCG()->GetTargetMachine()->isAArch64()) {
2760         Emit("\t.xword " + name + "\n");
2761     } else {
2762         Emit("\t.word " + name + "\n");
2763     }
2764 #endif
2765 }
2766 
2767 void Emitter::EmitDecSigned(int64 num)
2768 {
2769 #ifdef ARK_LITECG_DEBUG
2770     std::ios::fmtflags flag(outStream.flags());
2771     outStream << std::dec << num;
2772     outStream.flags(flag);
2773 #endif
2774 }
2775 
2776 void Emitter::EmitDecUnsigned(uint64 num)
2777 {
2778 #ifdef ARK_LITECG_DEBUG
2779     std::ios::fmtflags flag(outStream.flags());
2780     outStream << std::dec << num;
2781     outStream.flags(flag);
2782 #endif
2783 }
2784 
2785 void Emitter::EmitHexUnsigned(uint64 num)
2786 {
2787 #ifdef ARK_LITECG_DEBUG
2788     std::ios::fmtflags flag(outStream.flags());
2789     outStream << "0x" << std::hex << num;
2790     outStream.flags(flag);
2791 #endif
2792 }
2793 
2794 void Emitter::WriteDebugCommentToFile()
2795 {
2796 #ifdef ARK_LITECG_DEBUG
2797     struct stat buffer;
2798     std::string filePath = cg->GetCGOptions().GetEmitAotCodeCommentFile();
2799     std::string outputFile = stat(filePath.c_str(), &buffer) == 0 ? filePath : DEFAULT_PATH;
2800     std::ofstream file(outputFile.c_str(), std::ios::app);
2801     if (!file.is_open()) {
2802         std::cerr << outputFile << " Unable to open file for writing." << std::endl;
2803         return;
2804     }
2805 
2806     file << outStream.str();
2807     file.flush();
2808     file.close();
2809 #endif
2810 }
2811 
2812 #ifndef TARGX86_64
2813 #define XSTR(s) str(s)
2814 #endif
2815 #define str(s) #s
2816 
2817 void Emitter::EmitAliasAndRef(const MIRSymbol &sym)
2818 {
2819 #ifdef ARK_LITECG_DEBUG
2820     MIRFunction *mFunc = sym.GetFunction();
2821     if (mFunc == nullptr || !mFunc->GetAttr(FUNCATTR_alias)) {
2822         return;
2823     }
2824     if (mFunc->GetAttr(FUNCATTR_extern)) {
2825         Emit(asmInfo->GetGlobal()).Emit(mFunc->GetName()).Emit("\n");
2826     }
2827     auto &aliasPrefix = mFunc->GetAttr(FUNCATTR_weakref) ? asmInfo->GetWeakref() : asmInfo->GetSet();
2828     Emit(aliasPrefix);
2829     Emit(sym.GetName()).Emit(",").Emit(mFunc->GetAttrs().GetAliasFuncName()).Emit("\n");
2830 #endif
2831 }
2832 
2833 void Emitter::EmitHugeSoRoutines(bool lastRoutine)
2834 {
2835 #ifdef ARK_LITECG_DEBUG
2836     if (!lastRoutine &&
2837         (soInsnCount < (static_cast<uint64>(hugeSoSeqence) * static_cast<uint64>(kHugeSoInsnCountThreshold)))) {
2838         return;
2839     }
2840     for (auto &target : hugeSoTargets) {
2841         if (GetCG()->GetTargetMachine()->isX8664()) {
2842                 Emit("\t.align\t8\n");
2843         } else {
2844                 Emit("\t.align 3\n");
2845         }
2846         std::string routineName = target + HugeSoPostFix();
2847         Emit("\t.type\t" + routineName + ", %function\n");
2848         Emit(routineName + ":\n");
2849         Emit("\tadrp\tx17, :got:" + target + "\n");
2850         Emit("\tldr\tx17, [x17, :got_lo12:" + target + "]\n");
2851         Emit("\tbr\tx17\n");
2852         soInsnCount += kSizeOfHugesoRoutine;
2853     }
2854     hugeSoTargets.clear();
2855     ++hugeSoSeqence;
2856 #endif
2857 }
2858 
2859 void ImmOperand::Dump() const
2860 {
2861 #ifdef ARK_LITECG_DEBUG
2862     LogInfo::MapleLogger() << "imm:" << value;
2863 #endif
2864 }
2865 
2866 void LabelOperand::Dump() const
2867 {
2868 #ifdef ARK_LITECG_DEBUG
2869     LogInfo::MapleLogger() << "label:" << labelIndex;
2870 #endif
2871 }
2872 
2873 /* new phase manager */
2874 bool CgEmission::PhaseRun(maplebe::CGFunc &f)
2875 {
2876     if (Triple::GetTriple().IsAarch64BeOrLe()) {
2877         f.GetCG()->template Emit<CG::EmitterType::AsmEmitter>([&f](Emitter *emitter) {
2878             AsmFuncEmitInfo funcEmitInfo(f);
2879             emitter->EmitLocalVariable(f);
2880             static_cast<AArch64AsmEmitter *>(emitter)->Run(funcEmitInfo);
2881             emitter->EmitHugeSoRoutines();
2882         });
2883         f.GetCG()->template Emit<CG::EmitterType::ObjEmiter>([&f](Emitter *emitter) {
2884             auto objEmitter = static_cast<AArch64ObjEmitter *>(emitter);
2885             FuncEmitInfo &funcEmitInfo = objEmitter->CreateFuncEmitInfo(f);
2886             objEmitter->Run(funcEmitInfo);
2887             f.SetFuncEmitInfo(&funcEmitInfo);
2888         });
2889     } else if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
2890         f.GetCG()->Emit([&f](Emitter *emitter) {
2891             CHECK_NULL_FATAL(emitter);
2892             static_cast<X64Emitter *>(emitter)->Run(f);
2893         });
2894     } else {
2895         CHECK_FATAL(false, "unsupportted");
2896     }
2897     return false;
2898 }
2899 MAPLE_TRANSFORM_PHASE_REGISTER(CgEmission, cgemit)
2900 } /* namespace maplebe */
2901