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