• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "emit.h"
17 #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 constexpr uint32 kSizeOfHugesoRoutine = 3;
38 constexpr uint32 kFromDefIndexMask32Mod = 0x40000000;
39 
GetPrimitiveTypeSize(const std::string & name)40 int32 GetPrimitiveTypeSize(const std::string &name)
41 {
42     if (name.length() != 1) {
43         return -1;
44     }
45     char typeName = name[0];
46     switch (typeName) {
47         case 'Z':
48             return static_cast<int32>(GetPrimTypeSize(PTY_u1));
49         case 'B':
50             return static_cast<int32>(GetPrimTypeSize(PTY_i8));
51         case 'S':
52             return static_cast<int32>(GetPrimTypeSize(PTY_i16));
53         case 'C':
54             return static_cast<int32>(GetPrimTypeSize(PTY_u16));
55         case 'I':
56             return static_cast<int32>(GetPrimTypeSize(PTY_i32));
57         case 'J':
58             return static_cast<int32>(GetPrimTypeSize(PTY_i64));
59         case 'F':
60             return static_cast<int32>(GetPrimTypeSize(PTY_f32));
61         case 'D':
62             return static_cast<int32>(GetPrimTypeSize(PTY_f64));
63         case 'V':
64             return static_cast<int32>(GetPrimTypeSize(PTY_void));
65         default:
66             return -1;
67     }
68 }
LFindAttribute(MapleVector<DBGDieAttr * > & vec,DwAt key)69 DBGDieAttr *LFindAttribute(MapleVector<DBGDieAttr *> &vec, DwAt key)
70 {
71     for (DBGDieAttr *at : vec)
72         if (at->GetDwAt() == key) {
73             return at;
74         }
75     return nullptr;
76 }
77 
LFindAbbrevEntry(MapleVector<DBGAbbrevEntry * > & abbvec,unsigned int key)78 DBGAbbrevEntry *LFindAbbrevEntry(MapleVector<DBGAbbrevEntry *> &abbvec, unsigned int key)
79 {
80     for (DBGAbbrevEntry *daie : abbvec) {
81         if (!daie) {
82             continue;
83         }
84         if (daie->GetAbbrevId() == key) {
85             return daie;
86         }
87     }
88     DEBUG_ASSERT(0, "");
89     return nullptr;
90 }
91 
LShouldEmit(unsigned int dwform)92 bool LShouldEmit(unsigned int dwform)
93 {
94     return dwform != DW_FORM_flag_present;
95 }
96 
LFindChildDieWithName(DBGDie * die,DwTag tag,const GStrIdx key)97 DBGDie *LFindChildDieWithName(DBGDie *die, DwTag tag, const GStrIdx key)
98 {
99     for (DBGDie *c : die->GetSubDieVec()) {
100         if (c->GetTag() == tag) {
101             for (DBGDieAttr *a : c->GetAttrVec()) {
102                 if (a->GetDwAt() == DW_AT_name) {
103                     if ((a->GetDwForm() == DW_FORM_string || a->GetDwForm() == DW_FORM_strp) &&
104                         a->GetId() == key.GetIdx()) {
105                         return c;
106                     } else {
107                         break;
108                     }
109                 }
110             }
111         }
112     }
113     return nullptr;
114 }
115 
LFindDieAttr(DBGDie * die,DwAt attrname)116 DBGDieAttr *LFindDieAttr(DBGDie *die, DwAt attrname)
117 {
118     for (DBGDieAttr *attr : die->GetAttrVec()) {
119         if (attr->GetDwAt() == attrname) {
120             return attr;
121         }
122     }
123     return nullptr;
124 }
125 
LUpdateAttrValue(DBGDieAttr * attr,int64_t newval)126 static void LUpdateAttrValue(DBGDieAttr *attr, int64_t newval)
127 {
128     attr->SetI(int32_t(newval));
129 }
130 }  // namespace
131 
132 namespace maplebe {
133 using namespace maple;
134 using namespace cfi;
135 
EmitLabelRef(LabelIdx labIdx)136 void Emitter::EmitLabelRef(LabelIdx labIdx)
137 {
138     CHECK_NULL_FATAL(GetCG()->GetMIRModule()->CurFunction());
139     PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
140     char *idx = strdup(std::to_string(pIdx).c_str());
141     CHECK_FATAL(idx != nullptr, "strdup failed");
142     outStream << ".L." << idx << "__" << labIdx;
143     free(idx);
144     idx = nullptr;
145 }
146 
EmitStmtLabel(LabelIdx labIdx)147 void Emitter::EmitStmtLabel(LabelIdx labIdx)
148 {
149     EmitLabelRef(labIdx);
150     outStream << ":\n";
151 }
152 
EmitLabelPair(const LabelPair & pairLabel)153 void Emitter::EmitLabelPair(const LabelPair &pairLabel)
154 {
155     DEBUG_ASSERT(pairLabel.GetEndOffset() || pairLabel.GetStartOffset(), "NYI");
156     EmitLabelRef(pairLabel.GetEndOffset()->GetLabelIdx());
157     outStream << " - ";
158     EmitLabelRef(pairLabel.GetStartOffset()->GetLabelIdx());
159     outStream << "\n";
160 }
161 
EmitLabelForFunc(const MIRFunction * func,LabelIdx labIdx)162 void Emitter::EmitLabelForFunc(const MIRFunction *func, LabelIdx labIdx)
163 {
164     DEBUG_ASSERT(func != nullptr, "null ptr check");
165     char *idx = strdup(std::to_string(func->GetPuidx()).c_str());
166     CHECK_FATAL(idx != nullptr, "strdup failed");
167     outStream << ".L." << idx << "__" << labIdx;
168     free(idx);
169     idx = nullptr;
170 }
171 
GetTypeAsmInfoName(PrimType primType) const172 AsmLabel Emitter::GetTypeAsmInfoName(PrimType primType) const
173 {
174     uint32 size = GetPrimTypeSize(primType);
175     /* case x : x occupies bytes of pty */
176     switch (size) {
177         case k1ByteSize:
178             return kAsmByte;
179         case k2ByteSize:
180             if (GetCG()->GetTargetMachine()->isAArch64() || GetCG()->GetTargetMachine()->isRiscV()) {
181                 return kAsmShort;
182             } else {
183                 return kAsmValue;
184             }
185         case k4ByteSize:
186             return kAsmLong;
187         case k8ByteSize:
188             return kAsmQuad;
189         default:
190             DEBUG_ASSERT(false, "NYI");
191             break;
192     }
193     return kAsmLong;
194 }
195 
EmitFileInfo(const std::string & fileName)196 void Emitter::EmitFileInfo(const std::string &fileName)
197 {
198 #if defined(_WIN32) || defined(DARWIN) || defined(__APPLE__)
199     char *curDirName = getcwd(nullptr, 0);
200 #else
201     char *curDirName = get_current_dir_name();
202 #endif
203     CHECK_FATAL(curDirName != nullptr, "null ptr check ");
204     Emit(asmInfo->GetCmnt());
205     std::string path(curDirName);
206 #ifdef _WIN32
207     std::string cgFile(path.append("\\mplcg"));
208 #else
209     std::string cgFile(path.append("/mplcg"));
210 #endif
211     Emit(cgFile);
212     Emit("\n");
213 
214     std::string compile("Compiling ");
215     Emit(asmInfo->GetCmnt());
216     Emit(compile);
217     Emit("\n");
218 
219     std::string beOptions("Be options");
220     Emit(asmInfo->GetCmnt());
221     Emit(beOptions);
222     Emit("\n");
223 
224     path = curDirName;
225     path.append("/").append(fileName);
226     /* strip path before out/ */
227     std::string out = "/out/";
228     size_t pos = path.find(out.c_str(), 0, out.length());
229     if (pos != std::string::npos) {
230         path.erase(0, pos + 1);
231     }
232     std::string irFile("\"");
233     irFile.append(path).append("\"");
234     Emit(asmInfo->GetFile());
235     Emit(irFile);
236     Emit("\n");
237 
238     /* save directory path in index 8 */
239     SetFileMapValue(0, path);
240 
241     /* .file #num src_file_name */
242     if (cg->GetCGOptions().WithLoc()) {
243         /* .file 1 mpl_file_name */
244         if (cg->GetCGOptions().WithAsm()) {
245             Emit("\t// ");
246         }
247         Emit(asmInfo->GetFile());
248         Emit("1 ");
249         Emit(irFile);
250         Emit("\n");
251         SetFileMapValue(1, irFile); /* save ir file in 1 */
252         if (cg->GetCGOptions().WithSrc()) {
253             /* insert a list of src files */
254             uint32 i = 2;
255             for (auto it : cg->GetMIRModule()->GetSrcFileInfo()) {
256                 if (cg->GetCGOptions().WithAsm()) {
257                     Emit("\t// ");
258                 }
259                 Emit(asmInfo->GetFile());
260                 Emit(it.second).Emit(" \"");
261                 std::string kStr = GlobalTables::GetStrTable().GetStringFromStrIdx(it.first);
262                 Emit(kStr);
263                 Emit("\"\n");
264                 SetFileMapValue(i++, kStr);
265             }
266         }
267     }
268     free(curDirName);
269 
270     EmitInlineAsmSection();
271 #if TARGARM32
272     Emit("\t.syntax unified\n");
273     /*
274      * "The arm instruction set is a subset of
275      *  the most commonly used 32-bit ARM instructions."
276      * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0210c/CACBCAAE.html
277      */
278     Emit("\t.arm\n");
279     Emit("\t.fpu vfpv4\n");
280     Emit("\t.arch armv7-a\n");
281     Emit("\t.eabi_attribute Tag_ABI_PCS_RW_data, 1\n");
282     Emit("\t.eabi_attribute Tag_ABI_PCS_RO_data, 1\n");
283     Emit("\t.eabi_attribute Tag_ABI_PCS_GOT_use, 2\n");
284     if (CGOptions::GetABIType() == CGOptions::kABIHard) {
285         Emit("\t.eabi_attribute Tag_ABI_VFP_args, 1\n");
286     }
287     Emit("\t.eabi_attribute Tag_ABI_FP_denormal, 1\n");
288     Emit("\t.eabi_attribute Tag_ABI_FP_exceptions, 1\n");
289     Emit("\t.eabi_attribute Tag_ABI_FP_number_model, 3\n");
290     Emit("\t.eabi_attribute Tag_ABI_align_needed, 1\n");
291     Emit("\t.eabi_attribute Tag_ABI_align_preserved, 1\n");
292     Emit("\t.eabi_attribute Tag_ABI_enum_size, 2\n");
293     Emit("\t.eabi_attribute 30, 6\n");
294     Emit("\t.eabi_attribute Tag_CPU_unaligned_access, 1\n");
295     Emit("\t.eabi_attribute Tag_ABI_PCS_wchar_t, 4\n");
296 #endif /* TARGARM32 */
297 }
298 
EmitInlineAsmSection()299 void Emitter::EmitInlineAsmSection()
300 {
301     MapleVector<MapleString> &asmSections = cg->GetMIRModule()->GetAsmDecls();
302     if (!asmSections.empty()) {
303         Emit("#APP\n");
304         for (auto &singleSection : asmSections) {
305             Emit("\t");
306             Emit(singleSection);
307             Emit("\n");
308         }
309         Emit("#NO_APP\n");
310     }
311 }
EmitAsmLabel(AsmLabel label)312 void Emitter::EmitAsmLabel(AsmLabel label)
313 {
314     switch (label) {
315         case kAsmData: {
316             (void)Emit(asmInfo->GetData());
317             (void)Emit("\n");
318             return;
319         }
320         case kAsmText: {
321             (void)Emit(asmInfo->GetText());
322             (void)Emit("\n");
323             return;
324         }
325         case kAsmType: {
326             (void)Emit(asmInfo->GetType());
327             return;
328         }
329         case kAsmByte: {
330             (void)Emit(asmInfo->GetByte());
331             return;
332         }
333         case kAsmShort: {
334             (void)Emit(asmInfo->GetShort());
335             return;
336         }
337         case kAsmValue: {
338             (void)Emit(asmInfo->GetValue());
339             return;
340         }
341         case kAsmLong: {
342             (void)Emit(asmInfo->GetLong());
343             return;
344         }
345         case kAsmQuad: {
346             (void)Emit(asmInfo->GetQuad());
347             return;
348         }
349         case kAsmZero:
350             (void)Emit(asmInfo->GetZero());
351             return;
352         default:
353             DEBUG_ASSERT(false, "should not run here");
354             return;
355     }
356 }
357 
EmitAsmLabel(const MIRSymbol & mirSymbol,AsmLabel label)358 void Emitter::EmitAsmLabel(const MIRSymbol &mirSymbol, AsmLabel label)
359 {
360     MIRType *mirType = mirSymbol.GetType();
361     std::string symName;
362     if (mirSymbol.GetStorageClass() == kScPstatic && mirSymbol.IsLocal()) {
363         GetCG()->GetMIRModule()->CurFunction();
364         PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
365         symName = mirSymbol.GetName() + std::to_string(pIdx);
366     } else {
367         symName = mirSymbol.GetName();
368     }
369     if (mirSymbol.GetAsmAttr() != UStrIdx(0) &&
370         (mirSymbol.GetStorageClass() == kScPstatic || mirSymbol.GetStorageClass() == kScPstatic)) {
371         std::string asmSection = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol.GetAsmAttr());
372         symName = asmSection;
373     }
374     if (Globals::GetInstance()->GetBECommon()->IsEmptyOfTypeAlignTable()) {
375         DEBUG_ASSERT(false, "container empty check");
376     }
377 
378     switch (label) {
379         case kAsmGlbl: {
380             Emit(asmInfo->GetGlobal());
381             Emit(symName);
382             Emit("\n");
383             return;
384         }
385         case kAsmHidden: {
386             Emit(asmInfo->GetHidden());
387             Emit(symName);
388             Emit("\n");
389             return;
390         }
391         case kAsmLocal: {
392             Emit(asmInfo->GetLocal());
393             Emit(symName);
394             Emit("\n");
395             return;
396         }
397         case kAsmWeak: {
398             Emit(asmInfo->GetWeak());
399             Emit(symName);
400             Emit("\n");
401             return;
402         }
403         case kAsmZero: {
404             uint64 size = Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex());
405             EmitNullConstant(size);
406             return;
407         }
408         case kAsmComm: {
409             std::string size;
410             if (isFlexibleArray) {
411                 size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()) +
412                                       arraySize);
413             } else {
414                 size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()));
415             }
416             (void)Emit(asmInfo->GetComm()).Emit(symName).Emit(", ").Emit(size).Emit(", ");
417 #if PECOFF
418             if (GetCG()->GetTargetMachine()->isAArch64() ||
419                 GetCG()->GetTargetMachine()->isRiscV() || GetCG()->GetTargetMachine()->isArm32() ||
420                 GetCG()->GetTargetMachine()->isArk()) {
421                 std::string align = std::to_string(
422                     static_cast<int>(
423                         log2(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex()))));
424             } else {
425                 std::string align =
426                     std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex()));
427             }
428             emit(align.c_str());
429 #else /* ELF */
430             /* output align, symbol name begin with "classInitProtectRegion" align is 4096 */
431             MIRTypeKind kind = mirSymbol.GetType()->GetKind();
432             MIRStorageClass storage = mirSymbol.GetStorageClass();
433             if (symName.find("classInitProtectRegion") == 0) {
434                 Emit(4096);  // symbol name begin with "classInitProtectRegion" align is 4096
435             } else if (((kind == kTypeStruct) || (kind == kTypeClass) || (kind == kTypeArray) ||
436                         (kind == kTypeUnion)) &&
437                        ((storage == kScGlobal) || (storage == kScPstatic) || (storage == kScFstatic))) {
438                 int32 align = Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex());
439                 if (GetPointerSize() < align) {
440                     (void)Emit(std::to_string(align));
441                 } else {
442                     (void)Emit(std::to_string(k8ByteSize));
443                 }
444             } else {
445                 (void)Emit(
446                     std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirType->GetTypeIndex())));
447             }
448 #endif
449             Emit("\n");
450             return;
451         }
452         case kAsmAlign: {
453             uint8 align = mirSymbol.GetAttrs().GetAlignValue();
454             if (align == 0) {
455                 if (mirSymbol.GetType()->GetKind() == kTypeStruct || mirSymbol.GetType()->GetKind() == kTypeClass ||
456                     mirSymbol.GetType()->GetKind() == kTypeArray || mirSymbol.GetType()->GetKind() == kTypeUnion) {
457                     if (GetCG()->GetTargetMachine()->isX8664()) {
458                         return;
459                     } else {
460                         align = kAlignOfU8;
461                     }
462                 } else {
463                     align = Globals::GetInstance()->GetBECommon()->GetTypeAlign(mirSymbol.GetType()->GetTypeIndex());
464                     if (GetCG()->GetTargetMachine()->isAArch64() || GetCG()->GetTargetMachine()->isRiscV() ||
465                         GetCG()->GetTargetMachine()->isArm32() || GetCG()->GetTargetMachine()->isArk()) {
466                         if (CGOptions::IsArm64ilp32() && mirSymbol.GetType()->GetPrimType() == PTY_a32) {
467                             align = kAlignOfU8;
468                         } else {
469                             align = static_cast<uint8>(log2(align));
470                         }
471                     }
472                 }
473             }
474             Emit(asmInfo->GetAlign());
475             Emit(std::to_string(align));
476             Emit("\n");
477             return;
478         }
479         case kAsmSyname: {
480             Emit(symName);
481             Emit(":\n");
482             return;
483         }
484         case kAsmSize: {
485             Emit(asmInfo->GetSize());
486             Emit(symName);
487             Emit(", ");
488             if (GetCG()->GetTargetMachine()->isX8664()) {
489                 Emit(".-");
490                 Emit(symName);
491             } else {
492                 std::string size;
493                 if (isFlexibleArray) {
494                     size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()) +
495                                         arraySize);
496                 } else {
497                     size = std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex()));
498                 }
499                 Emit(size);
500             }
501             Emit("\n");
502             return;
503         }
504         case kAsmType: {
505             Emit(asmInfo->GetType());
506             if (GetCG()->GetMIRModule()->IsCModule() && (symName == "sys_nerr" || symName == "sys_errlist")) {
507                 /* eliminate warning from deprecated C name */
508                 Emit("strerror");
509             } else {
510                 Emit(symName);
511             }
512             Emit(",");
513             Emit(asmInfo->GetAtobt());
514             Emit("\n");
515             return;
516         }
517         default:
518             DEBUG_ASSERT(false, "should not run here");
519             return;
520     }
521 }
522 
EmitNullConstant(uint64 size)523 void Emitter::EmitNullConstant(uint64 size)
524 {
525     EmitAsmLabel(kAsmZero);
526     Emit(std::to_string(size));
527     Emit("\n");
528 }
529 
EmitCombineBfldValue(StructEmitInfo & structEmitInfo)530 void Emitter::EmitCombineBfldValue(StructEmitInfo &structEmitInfo)
531 {
532     uint8 charBitWidth = GetPrimTypeSize(PTY_i8) * kBitsPerByte;
533     auto emitBfldValue = [&structEmitInfo, charBitWidth, this](bool flag) {
534         while (structEmitInfo.GetCombineBitFieldWidth() > charBitWidth) {
535             uint8 shift = flag ? (structEmitInfo.GetCombineBitFieldWidth() - charBitWidth) : 0U;
536             uint64 tmp = (structEmitInfo.GetCombineBitFieldValue() >> shift) & 0x00000000000000ffUL;
537             EmitAsmLabel(kAsmByte);
538             Emit(std::to_string(tmp));
539             Emit("\n");
540             structEmitInfo.DecreaseCombineBitFieldWidth(charBitWidth);
541             uint64 value =
542                 flag ? structEmitInfo.GetCombineBitFieldValue() - (tmp << structEmitInfo.GetCombineBitFieldWidth())
543                      : structEmitInfo.GetCombineBitFieldValue() >> charBitWidth;
544             structEmitInfo.SetCombineBitFieldValue(value);
545         }
546     };
547     if (CGOptions::IsBigEndian()) {
548         /*
549          * If the total number of bits in the bit field is not a multiple of 8,
550          * the bits must be aligned to 8 bits to prevent errors in the emit.
551          */
552         auto width = static_cast<uint8>(RoundUp(structEmitInfo.GetCombineBitFieldWidth(), charBitWidth));
553         if (structEmitInfo.GetCombineBitFieldWidth() < width) {
554             structEmitInfo.SetCombineBitFieldValue(structEmitInfo.GetCombineBitFieldValue()
555                                                    << (width - structEmitInfo.GetCombineBitFieldWidth()));
556             structEmitInfo.IncreaseCombineBitFieldWidth(
557                 static_cast<uint8>(width - structEmitInfo.GetCombineBitFieldWidth()));
558         }
559         emitBfldValue(true);
560     } else {
561         emitBfldValue(false);
562     }
563     if (structEmitInfo.GetCombineBitFieldWidth() != 0) {
564         EmitAsmLabel(kAsmByte);
565         uint64 value = structEmitInfo.GetCombineBitFieldValue() & 0x00000000000000ffUL;
566         Emit(std::to_string(value));
567         Emit("\n");
568     }
569     CHECK_FATAL(charBitWidth != 0, "divide by zero");
570     if ((structEmitInfo.GetNextFieldOffset() % charBitWidth) != 0) {
571         uint8 value = charBitWidth - (structEmitInfo.GetNextFieldOffset() % charBitWidth);
572         structEmitInfo.IncreaseNextFieldOffset(value);
573     }
574     structEmitInfo.SetTotalSize(structEmitInfo.GetNextFieldOffset() / charBitWidth);
575     structEmitInfo.SetCombineBitFieldValue(0);
576     structEmitInfo.SetCombineBitFieldWidth(0);
577 }
578 
EmitBitFieldConstant(StructEmitInfo & structEmitInfo,MIRConst & mirConst,const MIRType * nextType,uint64 fieldOffset)579 void Emitter::EmitBitFieldConstant(StructEmitInfo &structEmitInfo, MIRConst &mirConst, const MIRType *nextType,
580                                    uint64 fieldOffset)
581 {
582     MIRType &mirType = mirConst.GetType();
583     if (fieldOffset > structEmitInfo.GetNextFieldOffset()) {
584         uint16 curFieldOffset = structEmitInfo.GetNextFieldOffset() - structEmitInfo.GetCombineBitFieldWidth();
585         structEmitInfo.SetCombineBitFieldWidth(fieldOffset - curFieldOffset);
586         EmitCombineBfldValue(structEmitInfo);
587         DEBUG_ASSERT(structEmitInfo.GetNextFieldOffset() <= fieldOffset,
588                      "structEmitInfo's nextFieldOffset should be <= fieldOffset");
589         structEmitInfo.SetNextFieldOffset(fieldOffset);
590     }
591     uint32 fieldSize = static_cast<MIRBitFieldType &>(mirType).GetFieldSize();
592     MIRIntConst &fieldValue = static_cast<MIRIntConst &>(mirConst);
593     /* Truncate the size of FieldValue to the bit field size. */
594     if (fieldSize < fieldValue.GetActualBitWidth()) {
595         fieldValue.Trunc(fieldSize);
596     }
597     /* Clear higher Bits for signed value  */
598     if (structEmitInfo.GetCombineBitFieldValue() != 0) {
599         structEmitInfo.SetCombineBitFieldValue((~(~0ULL << structEmitInfo.GetCombineBitFieldWidth())) &
600                                                structEmitInfo.GetCombineBitFieldValue());
601     }
602     if (CGOptions::IsBigEndian()) {
603         uint64 beValue = static_cast<uint64>(fieldValue.GetExtValue());
604         if (fieldValue.IsNegative()) {
605             beValue = beValue - ((beValue >> fieldSize) << fieldSize);
606         }
607         structEmitInfo.SetCombineBitFieldValue((structEmitInfo.GetCombineBitFieldValue() << fieldSize) + beValue);
608     } else {
609         structEmitInfo.SetCombineBitFieldValue((fieldValue.GetExtValue() << structEmitInfo.GetCombineBitFieldWidth()) +
610                                                structEmitInfo.GetCombineBitFieldValue());
611     }
612     structEmitInfo.IncreaseCombineBitFieldWidth(fieldSize);
613     structEmitInfo.IncreaseNextFieldOffset(fieldSize);
614     if ((nextType == nullptr) || (kTypeBitField != nextType->GetKind())) {
615         /* emit structEmitInfo->combineBitFieldValue */
616         EmitCombineBfldValue(structEmitInfo);
617     }
618 }
619 
EmitFunctionSymbolTable(FuncEmitInfo & funcEmitInfo)620 void Emitter::EmitFunctionSymbolTable(FuncEmitInfo &funcEmitInfo)
621 {
622     CGFunc &cgFunc = funcEmitInfo.GetCGFunc();
623     MIRFunction *func = &cgFunc.GetFunction();
624 
625     size_t size =
626         (func == nullptr) ? GlobalTables::GetGsymTable().GetTable().size() : func->GetSymTab()->GetTable().size();
627     for (size_t i = 0; i < size; ++i) {
628         const MIRSymbol *st = nullptr;
629         if (func == nullptr) {
630             auto &symTab = GlobalTables::GetGsymTable();
631             st = symTab.GetSymbol(i);
632         } else {
633             auto &symTab = *func->GetSymTab();
634             st = symTab.GetSymbolAt(i);
635         }
636         if (st == nullptr) {
637             continue;
638         }
639         MIRStorageClass storageClass = st->GetStorageClass();
640         MIRSymKind symKind = st->GetSKind();
641         Emitter *emitter = this;
642         if (storageClass == kScPstatic && symKind == kStConst) {
643             // align
644             emitter->Emit("\t.align 2 \n" + st->GetName() + ":\n");
645             if (st->GetKonst()->GetKind() == kConstStr16Const) {
646                 MIRStr16Const *str16Const = safe_cast<MIRStr16Const>(st->GetKonst());
647                 DEBUG_ASSERT(str16Const != nullptr, "str16Const should not be nullptr");
648                 emitter->EmitStr16Constant(*str16Const);
649                 emitter->Emit("\n");
650                 continue;
651             }
652 
653             if (st->GetKonst()->GetKind() == kConstStrConst) {
654                 MIRStrConst *strConst = safe_cast<MIRStrConst>(st->GetKonst());
655                 DEBUG_ASSERT(strConst != nullptr, "strConst should not be nullptr");
656                 emitter->EmitStrConstant(*strConst);
657                 emitter->Emit("\n");
658                 continue;
659             }
660 
661             switch (st->GetKonst()->GetType().GetPrimType()) {
662                 case PTY_u32: {
663                     MIRIntConst *intConst = safe_cast<MIRIntConst>(st->GetKonst());
664                     DEBUG_ASSERT(intConst != nullptr, "intConst should not be nullptr");
665                     uint32 value = static_cast<uint32>(intConst->GetValue().GetExtValue());
666                     emitter->Emit("\t.long").Emit(value).Emit("\n");
667                     break;
668                 }
669                 case PTY_f32: {
670                     MIRFloatConst *floatConst = safe_cast<MIRFloatConst>(st->GetKonst());
671                     DEBUG_ASSERT(floatConst != nullptr, "floatConst should not be nullptr");
672                     uint32 value = static_cast<uint32>(floatConst->GetIntValue());
673                     emitter->Emit("\t.word").Emit(value).Emit("\n");
674                     break;
675                 }
676                 case PTY_f64: {
677                     MIRDoubleConst *doubleConst = safe_cast<MIRDoubleConst>(st->GetKonst());
678                     DEBUG_ASSERT(doubleConst != nullptr, "doubleConst should not be nullptr");
679                     uint32 value = doubleConst->GetIntLow32();
680                     emitter->Emit("\t.word").Emit(value).Emit("\n");
681                     value = doubleConst->GetIntHigh32();
682                     emitter->Emit("\t.word").Emit(value).Emit("\n");
683                     break;
684                 }
685                 default:
686                     DEBUG_ASSERT(false, "NYI");
687                     break;
688             }
689         }
690     }
691 }
692 
EmitStr(const std::string & mplStr,bool emitAscii,bool emitNewline)693 void Emitter::EmitStr(const std::string &mplStr, bool emitAscii, bool emitNewline)
694 {
695     const char *str = mplStr.c_str();
696     size_t len = mplStr.size();
697 
698     if (emitAscii) {
699         Emit("\t.ascii\t\""); /* Do not terminate with \0 */
700     } else {
701         Emit("\t.string\t\"");
702     }
703 
704     /*
705      * don't expand special character in a writeout to .s,
706      * convert all \s to \\s in string for storing in .string
707      */
708     for (size_t i = 0; i < len; i++) {
709         /* Referred to GNU AS: 3.6.1.1 Strings */
710         constexpr int kBufSize = 5;
711         constexpr int kFirstChar = 0;
712         constexpr int kSecondChar = 1;
713         constexpr int kThirdChar = 2;
714         constexpr int kLastChar = 4;
715         char buf[kBufSize];
716         if (isprint(*str)) {
717             buf[kFirstChar] = *str;
718             buf[kSecondChar] = 0;
719             if (*str == '\\' || *str == '\"') {
720                 buf[kFirstChar] = '\\';
721                 buf[kSecondChar] = *str;
722                 buf[kThirdChar] = 0;
723             }
724             Emit(buf);
725         } else if (*str == '\b') {
726             Emit("\\b");
727         } else if (*str == '\n') {
728             Emit("\\n");
729         } else if (*str == '\r') {
730             Emit("\\r");
731         } else if (*str == '\t') {
732             Emit("\\t");
733         } else if (*str == '\0') {
734             buf[kFirstChar] = '\\';
735             buf[kSecondChar] = '0';
736             buf[kThirdChar] = 0;
737             Emit(buf);
738         } else {
739             /* all others, print as number */
740             int ret = snprintf_s(buf, sizeof(buf), k4BitSize, "\\%03o", static_cast<unsigned char>(*str) & 0xFF);
741             if (ret < 0) {
742                 FATAL(kLncFatal, "snprintf_s failed");
743             }
744             buf[kLastChar] = '\0';
745             Emit(buf);
746         }
747         str++;
748     }
749 
750     Emit("\"");
751     if (emitNewline) {
752         Emit("\n");
753     }
754 }
755 
EmitStrConstant(const MIRStrConst & mirStrConst,bool isIndirect)756 void Emitter::EmitStrConstant(const MIRStrConst &mirStrConst, bool isIndirect)
757 {
758     if (isIndirect) {
759         uint32 strId = mirStrConst.GetValue().GetIdx();
760 
761         if (stringPtr.find(mirStrConst.GetValue()) == stringPtr.end()) {
762             stringPtr.insert(mirStrConst.GetValue());
763         }
764         if (CGOptions::IsArm64ilp32()) {
765             (void)Emit("\t.word\t").Emit(".LSTR__").Emit(std::to_string(strId).c_str());
766         } else {
767             EmitAsmLabel(kAsmQuad);
768             (void)Emit(".LSTR__").Emit(std::to_string(strId).c_str());
769         }
770         return;
771     }
772 
773     const std::string ustr = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirStrConst.GetValue());
774     size_t len = ustr.size();
775     if (isFlexibleArray) {
776         arraySize += static_cast<uint32>(len) + 1;
777     }
778     EmitStr(ustr, false, false);
779 }
780 
EmitStr16Constant(const MIRStr16Const & mirStr16Const)781 void Emitter::EmitStr16Constant(const MIRStr16Const &mirStr16Const)
782 {
783     Emit("\t.byte ");
784     /* note: for now, u16string is emitted 2 bytes without any \u indication */
785     const std::u16string &str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(mirStr16Const.GetValue());
786     constexpr int bufSize = 9;
787     char buf[bufSize];
788     char16_t c = str16[0];
789     /* fetch the type of char16_t c's top 8 bit data */
790     int ret1 = snprintf_s(buf, sizeof(buf), bufSize - 1, "%d,%d", (c >> 8) & 0xFF, c & 0xFF);
791     if (ret1 < 0) {
792         FATAL(kLncFatal, "snprintf_s failed");
793     }
794     buf[bufSize - 1] = '\0';
795     Emit(buf);
796     for (uint32 i = 1; i < str16.length(); ++i) {
797         c = str16[i];
798         /* fetch the type of char16_t c's top 8 bit data */
799         int ret2 = snprintf_s(buf, sizeof(buf), bufSize - 1, ",%d,%d", (c >> 8) & 0xFF, c & 0xFF);
800         if (ret2 < 0) {
801             FATAL(kLncFatal, "snprintf_s failed");
802         }
803         buf[bufSize - 1] = '\0';
804         Emit(buf);
805     }
806     if ((str16.length() & 0x1) == 1) {
807         Emit(",0,0");
808     }
809 }
810 
EmitScalarConstant(MIRConst & mirConst,bool newLine,bool flag32,bool isIndirect)811 void Emitter::EmitScalarConstant(MIRConst &mirConst, bool newLine, bool flag32, bool isIndirect)
812 {
813     MIRType &mirType = mirConst.GetType();
814     AsmLabel asmName = GetTypeAsmInfoName(mirType.GetPrimType());
815     switch (mirConst.GetKind()) {
816         case kConstInt: {
817             MIRIntConst &intCt = static_cast<MIRIntConst &>(mirConst);
818             uint32 sizeInBits = GetPrimTypeBitSize(mirType.GetPrimType());
819             if (intCt.GetActualBitWidth() > sizeInBits) {
820                 intCt.Trunc(sizeInBits);
821             }
822             if (flag32) {
823                 EmitAsmLabel(AsmLabel::kAsmLong);
824             } else {
825                 EmitAsmLabel(asmName);
826             }
827             Emit(intCt.GetValue());
828             if (isFlexibleArray) {
829                 arraySize += (sizeInBits / kBitsPerByte);
830             }
831             break;
832         }
833         case kConstFloatConst: {
834             MIRFloatConst &floatCt = static_cast<MIRFloatConst &>(mirConst);
835             EmitAsmLabel(asmName);
836             Emit(std::to_string(floatCt.GetIntValue()));
837             if (isFlexibleArray) {
838                 arraySize += k4ByteFloatSize;
839             }
840             break;
841         }
842         case kConstDoubleConst: {
843             MIRDoubleConst &doubleCt = static_cast<MIRDoubleConst &>(mirConst);
844             EmitAsmLabel(asmName);
845             Emit(std::to_string(doubleCt.GetIntValue()));
846             if (isFlexibleArray) {
847                 arraySize += k8ByteDoubleSize;
848             }
849             break;
850         }
851         case kConstStrConst: {
852             MIRStrConst &strCt = static_cast<MIRStrConst &>(mirConst);
853             if (cg->GetMIRModule()->IsCModule()) {
854                 EmitStrConstant(strCt, isIndirect);
855             } else {
856                 EmitStrConstant(strCt);
857             }
858             break;
859         }
860         case kConstStr16Const: {
861             MIRStr16Const &str16Ct = static_cast<MIRStr16Const &>(mirConst);
862             EmitStr16Constant(str16Ct);
863             break;
864         }
865         case kConstAddrof: {
866             MIRAddrofConst &symAddr = static_cast<MIRAddrofConst &>(mirConst);
867             StIdx stIdx = symAddr.GetSymbolIndex();
868             CHECK_NULL_FATAL(CG::GetCurCGFunc()->GetMirModule().CurFunction());
869             MIRSymbol *symAddrSym =
870                 stIdx.IsGlobal()
871                     ? GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx())
872                     : CG::GetCurCGFunc()->GetMirModule().CurFunction()->GetSymTab()->GetSymbolFromStIdx(stIdx.Idx());
873             DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
874             std::string str;
875             if (CGOptions::IsArm64ilp32()) {
876                 str = ".word";
877             } else {
878                 str = ".quad";
879             }
880             if (stIdx.IsGlobal() == false && symAddrSym->GetStorageClass() == kScPstatic) {
881                 CHECK_NULL_FATAL(GetCG()->GetMIRModule()->CurFunction());
882                 PUIdx pIdx = GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
883                 (void)Emit("\t" + str + "\t" + symAddrSym->GetName() + std::to_string(pIdx));
884             } else {
885                 (void)Emit("\t" + str + "\t" + symAddrSym->GetName());
886             }
887             if (symAddr.GetOffset() != 0) {
888                 (void)Emit(" + ").Emit(symAddr.GetOffset());
889             }
890             if (symAddr.GetFieldID() > 1) {
891                 MIRStructType *structType = static_cast<MIRStructType *>(symAddrSym->GetType());
892                 DEBUG_ASSERT(structType != nullptr, "EmitScalarConstant: non-zero fieldID for non-structure");
893                 (void)Emit(" + ").Emit(
894                     Globals::GetInstance()->GetBECommon()->GetFieldOffset(*structType, symAddr.GetFieldID()).first);
895             }
896             break;
897         }
898         case kConstAddrofFunc: {
899             MIRAddroffuncConst &funcAddr = static_cast<MIRAddroffuncConst &>(mirConst);
900             MIRFunction *func = GlobalTables::GetFunctionTable().GetFuncTable().at(funcAddr.GetValue());
901             MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx());
902             std::string str;
903             if (CGOptions::IsArm64ilp32()) {
904                 str = ".word";
905             } else {
906                 str = ".quad";
907             }
908             (void)Emit("\t" + str + "\t" + symAddrSym->GetName());
909             break;
910         }
911         case kConstLblConst: {
912             MIRLblConst &lbl = static_cast<MIRLblConst &>(mirConst);
913             if (CGOptions::IsArm64ilp32()) {
914                 (void)Emit("\t.word\t");
915             } else {
916                 EmitAsmLabel(kAsmQuad);
917             }
918             EmitLabelRef(lbl.GetValue());
919             break;
920         }
921         default:
922             DEBUG_ASSERT(false, "NYI");
923             break;
924     }
925     if (newLine) {
926         Emit("\n");
927     }
928 }
929 
EmitAddrofFuncConst(const MIRSymbol & mirSymbol,MIRConst & elemConst,size_t idx)930 void Emitter::EmitAddrofFuncConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx)
931 {
932     MIRAddroffuncConst &funcAddr = static_cast<MIRAddroffuncConst &>(elemConst);
933     const std::string stName = mirSymbol.GetName();
934     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(funcAddr.GetValue());
935     const std::string &funcName = func->GetName();
936     if ((idx == kFuncDefNameIndex) && mirSymbol.IsMuidFuncInfTab()) {
937         Emit("\t.long\t.Label.name.");
938         Emit(funcName + " - .");
939         Emit("\n");
940         return;
941     }
942     if ((idx == kFuncDefSizeIndex) && mirSymbol.IsMuidFuncInfTab()) {
943         Emit("\t.long\t.Label.end.");
944         Emit(funcName + " - ");
945         Emit(funcName + "\n");
946         return;
947     }
948     if ((idx == static_cast<uint32>(MethodProperty::kPaddrData)) && mirSymbol.IsReflectionMethodsInfo()) {
949 #ifdef USE_32BIT_REF
950         Emit("\t.long\t");
951 #else
952 
953 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
954         EmitAsmLabel(kAsmQuad);
955 #else
956         Emit("\t.word\t");
957 #endif
958 
959 #endif /* USE_32BIT_REF */
960         Emit(funcName + " - .\n");
961         return;
962     }
963     if (((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) ||
964         ((idx == static_cast<uint32>(ClassRO::kClinitAddr)) && mirSymbol.IsReflectionClassInfoRO())) {
965         Emit("\t.long\t");
966         Emit(funcName + " - .\n");
967         return;
968     }
969 
970     if (mirSymbol.IsReflectionMethodAddrData()) {
971 #ifdef USE_32BIT_REF
972         Emit("\t.long\t");
973 #else
974 
975 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
976         EmitAsmLabel(kAsmQuad);
977 #else
978         Emit("\t.word\t");
979 #endif
980 
981 #endif /* USE_32BIT_REF */
982         Emit(funcName + " - .\n");
983         return;
984     }
985 
986     if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncDefTab()) {
987 #if defined(USE_32BIT_REF)
988         Emit("\t.long\t");
989 #else
990 
991 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
992         EmitAsmLabel(kAsmQuad);
993 #else
994         Emit("\t.word\t");
995 #endif
996 
997 #endif /* USE_32BIT_REF */
998         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
999             /*
1000              * Check enum BindingState defined in Mpl_Binding.h,
1001              * 6 means kBindingStateMethodDef:6 offset away from base __BindingProtectRegion__.
1002              */
1003 #if defined(USE_32BIT_REF)
1004             Emit("0x6\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateMethodDef:6. */
1005 #else
1006             Emit("__BindingProtectRegion__ + 6\n");
1007 #endif /* USE_32BIT_REF */
1008         } else {
1009 #if defined(USE_32BIT_REF)
1010 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1011             Emit(funcName + "\n");
1012 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1013             Emit(funcName + "-.\n");
1014 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1015 #else  /* USE_32BIT_REF */
1016             Emit(funcName + "\n");
1017 #endif /* USE_32BIT_REF */
1018         }
1019         return;
1020     }
1021 
1022     if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncDefOrigTab()) {
1023         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1024 #if defined(USE_32BIT_REF)
1025             Emit("\t.long\t");
1026 #else
1027 
1028 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1029             EmitAsmLabel(kAsmQuad);
1030 #else
1031             Emit("\t.word\t");
1032 #endif
1033 
1034 #endif /* USE_32BIT_REF */
1035 #if defined(USE_32BIT_REF)
1036 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1037             Emit(funcName + "\n");
1038 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1039             Emit(funcName + "-.\n");
1040 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1041 #else  /* USE_32BIT_REF */
1042             Emit(funcName + "\n");
1043 #endif /* USE_32BIT_REF */
1044         }
1045         return;
1046     }
1047 
1048 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1049     EmitAsmLabel(kAsmQuad);
1050 #else
1051     Emit("\t.word\t");
1052 #endif
1053     Emit(funcName);
1054     if ((stName.find(VTAB_PREFIX_STR) == 0) || (stName.find(ITAB_PREFIX_STR) == 0) ||
1055         (stName.find(ITAB_CONFLICT_PREFIX_STR) == 0)) {
1056         Emit(" - .\n");
1057         return;
1058     }
1059     if (cg->GetCGOptions().GeneratePositionIndependentExecutable()) {
1060         Emit(" - ");
1061         Emit(stName);
1062     }
1063     Emit("\n");
1064 }
1065 
EmitAddrofSymbolConst(const MIRSymbol & mirSymbol,MIRConst & elemConst,size_t idx)1066 void Emitter::EmitAddrofSymbolConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx)
1067 {
1068     MIRAddrofConst &symAddr = static_cast<MIRAddrofConst &>(elemConst);
1069     const std::string stName = mirSymbol.GetName();
1070 
1071     MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr.GetSymbolIndex().Idx());
1072     DEBUG_ASSERT(symAddrSym != nullptr, "symAddrSym should not be nullptr");
1073     const std::string &symAddrName = symAddrSym->GetName();
1074 
1075     if (((idx == static_cast<uint32>(FieldProperty::kPOffset)) && mirSymbol.IsReflectionFieldsInfo()) ||
1076         mirSymbol.IsReflectionFieldOffsetData()) {
1077 #if USE_32BIT_REF
1078         Emit("\t.long\t");
1079 #else
1080 
1081 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1082         EmitAsmLabel(kAsmQuad);
1083 #else
1084         Emit("\t.word\t");
1085 #endif
1086 
1087 #endif /* USE_32BIT_REF */
1088         Emit(symAddrName + " - .\n");
1089         return;
1090     }
1091 
1092     if (((idx == static_cast<uint32>(FieldPropertyCompact::kPOffset)) && mirSymbol.IsReflectionFieldsInfoCompact()) ||
1093         ((idx == static_cast<uint32>(MethodProperty::kSigName)) && mirSymbol.IsReflectionMethodsInfo()) ||
1094         ((idx == static_cast<uint32>(MethodSignatureProperty::kParameterTypes)) &&
1095          mirSymbol.IsReflectionMethodSignature())) {
1096         Emit("\t.long\t");
1097         Emit(symAddrName + " - .\n");
1098         return;
1099     }
1100 
1101     if (((idx == static_cast<uint32>(MethodProperty::kDeclarclass)) ||
1102          (idx == static_cast<uint32>(MethodProperty::kPaddrData))) &&
1103         mirSymbol.IsReflectionMethodsInfo()) {
1104 #if USE_32BIT_REF
1105         Emit("\t.long\t");
1106 #else
1107 
1108 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1109         EmitAsmLabel(kAsmQuad);
1110 #else
1111         Emit("\t.word\t");
1112 #endif
1113 
1114 #endif /* USE_32BIT_REF */
1115         if (idx == static_cast<uint32>(MethodProperty::kDeclarclass)) {
1116             Emit(symAddrName + " - .\n");
1117         } else {
1118             Emit(symAddrName + " - . + 2\n");
1119         }
1120         return;
1121     }
1122 
1123     if ((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) {
1124         Emit("\t.long\t");
1125         Emit(symAddrName + " - . + 2\n");
1126         return;
1127     }
1128 
1129     if ((idx == static_cast<uint32>(FieldProperty::kDeclarclass)) && mirSymbol.IsReflectionFieldsInfo()) {
1130 #if USE_32BIT_REF
1131         Emit("\t.long\t");
1132 #else
1133 
1134 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1135         EmitAsmLabel(kAsmQuad);
1136 #else
1137         Emit("\t.word\t");
1138 #endif
1139 
1140 #endif /* USE_32BIT_REF */
1141         Emit(symAddrName + " - .\n");
1142         return;
1143     }
1144 
1145     if ((idx == kDataDefAddrIndex) && (mirSymbol.IsMuidDataUndefTab() || mirSymbol.IsMuidDataDefTab())) {
1146         if (symAddrSym->IsReflectionClassInfo()) {
1147             Emit(".LDW.ref." + symAddrName + ":\n");
1148         }
1149         Emit(kPtrPrefixStr + symAddrName + ":\n");
1150 #if defined(USE_32BIT_REF)
1151         Emit("\t.long\t");
1152 #else
1153 
1154 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1155         EmitAsmLabel(kAsmQuad);
1156 #else
1157         Emit("\t.word\t");
1158 #endif
1159 
1160 #endif /* USE_32BIT_REF */
1161         if (mirSymbol.IsMuidDataUndefTab()) {
1162             if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1163                 if (symAddrSym->IsReflectionClassInfo()) {
1164                     /*
1165                      * Check enum BindingState defined in Mpl_Binding.h,
1166                      * 1 means kBindingStateCinfUndef:1 offset away from base __BindingProtectRegion__.
1167                      */
1168 #if defined(USE_32BIT_REF)
1169                     Emit("0x1\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateCinfUndef:1. */
1170 #else
1171                     Emit("__BindingProtectRegion__ + 1\n");
1172 #endif /* USE_32BIT_REF */
1173                 } else {
1174                     /*
1175                      * Check enum BindingState defined in Mpl_Binding.h,
1176                      * 3 means kBindingStateDataUndef:3 offset away from base __BindingProtectRegion__.
1177                      */
1178 #if defined(USE_32BIT_REF)
1179                     Emit("0x3\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateDataUndef:3. */
1180 #else
1181                     Emit("__BindingProtectRegion__ + 3\n");
1182 #endif /* USE_32BIT_REF */
1183                 }
1184             } else {
1185                 Emit("0\n");
1186             }
1187         } else {
1188             if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1189                 if (symAddrSym->IsReflectionClassInfo()) {
1190                     /*
1191                      * Check enum BindingState defined in Mpl_Binding.h,
1192                      * 2 means kBindingStateCinfDef:2 offset away from base __BindingProtectRegion__.
1193                      */
1194 #if defined(USE_32BIT_REF)
1195                     Emit("0x2\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateCinfDef:2. */
1196 #else
1197                     Emit("__BindingProtectRegion__ + 2\n");
1198 #endif /* USE_32BIT_REF */
1199                 } else {
1200                     /*
1201                      * Check enum BindingState defined in Mpl_Binding.h,
1202                      * 4 means kBindingStateDataDef:4 offset away from base __BindingProtectRegion__.
1203                      */
1204 #if defined(USE_32BIT_REF)
1205                     Emit("0x4\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateDataDef:4. */
1206 #else
1207                     Emit("__BindingProtectRegion__ + 4\n");
1208 #endif /* USE_32BIT_REF */
1209                 }
1210             } else {
1211 #if defined(USE_32BIT_REF)
1212 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1213                 Emit(symAddrName + "\n");
1214 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1215                 Emit(symAddrName + "-.\n");
1216 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1217 #else  /* USE_32BIT_REF */
1218                 Emit(symAddrName + "\n");
1219 #endif /* USE_32BIT_REF */
1220             }
1221         }
1222         return;
1223     }
1224 
1225     if (idx == kDataDefAddrIndex && mirSymbol.IsMuidDataDefOrigTab()) {
1226         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1227 #if defined(USE_32BIT_REF)
1228             Emit("\t.long\t");
1229 #else
1230 
1231 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1232             EmitAsmLabel(kAsmQuad);
1233 #else
1234             Emit("\t.word\t");
1235 #endif
1236 
1237 #endif /* USE_32BIT_REF */
1238 
1239 #if defined(USE_32BIT_REF)
1240 #if defined(MPL_LNK_ADDRESS_VIA_BASE)
1241             Emit(symAddrName + "\n");
1242 #else  /* MPL_LNK_ADDRESS_VIA_BASE */
1243             Emit(symAddrName + "-.\n");
1244 #endif /* MPL_LNK_ADDRESS_VIA_BASE */
1245 #else  /* USE_32BIT_REF */
1246             Emit(symAddrName + "\n");
1247 #endif /* USE_32BIT_REF */
1248         }
1249         return;
1250     }
1251 
1252     if (StringUtils::StartsWith(stName, kLocalClassInfoStr)) {
1253 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1254         EmitAsmLabel(kAsmQuad);
1255 #else
1256         Emit("\t.word\t");
1257 #endif
1258         Emit(symAddrName);
1259         Emit(" - . + ").Emit(kDataRefIsOffset);
1260         Emit("\n");
1261         return;
1262     }
1263 #ifdef USE_32BIT_REF
1264     if (mirSymbol.IsReflectionHashTabBucket() || (stName.find(ITAB_PREFIX_STR) == 0) ||
1265         (mirSymbol.IsReflectionClassInfo() && (idx == static_cast<uint32>(ClassProperty::kInfoRo)))) {
1266         Emit("\t.word\t");
1267     } else {
1268 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1269         EmitAsmLabel(kAsmQuad);
1270 #else
1271         Emit("\t.word\t");
1272 #endif
1273     }
1274 #else
1275 
1276 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1277     EmitAsmLabel(kAsmQuad);
1278 #else
1279     Emit("\t.word\t");
1280 #endif
1281 
1282 #endif /* USE_32BIT_REF */
1283 
1284     if ((stName.find(ITAB_CONFLICT_PREFIX_STR) == 0) || (stName.find(ITAB_PREFIX_STR) == 0)) {
1285         Emit(symAddrName + " - .\n");
1286         return;
1287     }
1288     if (mirSymbol.IsMuidRangeTab()) {
1289         if (idx == kRangeBeginIndex) {
1290             Emit(symAddrSym->GetMuidTabName() + "_begin\n");
1291         } else {
1292             Emit(symAddrSym->GetMuidTabName() + "_end\n");
1293         }
1294         return;
1295     }
1296 
1297     if (symAddrName.find(GCTIB_PREFIX_STR) == 0) {
1298         Emit(cg->FindGCTIBPatternName(symAddrName));
1299     } else {
1300         Emit(symAddrName);
1301     }
1302 
1303     if ((((idx == static_cast<uint32>(ClassRO::kIfields)) || (idx == static_cast<uint32>(ClassRO::kMethods))) &&
1304          mirSymbol.IsReflectionClassInfoRO()) ||
1305         mirSymbol.IsReflectionHashTabBucket()) {
1306         Emit(" - .");
1307         if (symAddrSym->IsReflectionFieldsInfoCompact() || symAddrSym->IsReflectionMethodsInfoCompact()) {
1308             /* Mark the least significant bit as 1 for compact fieldinfo */
1309             Emit(" + ").Emit(MethodFieldRef::kMethodFieldRefIsCompact);
1310         }
1311     } else if (mirSymbol.IsReflectionClassInfo()) {
1312         if ((idx == static_cast<uint32>(ClassProperty::kItab)) || (idx == static_cast<uint32>(ClassProperty::kVtab)) ||
1313             (idx == static_cast<uint32>(ClassProperty::kInfoRo))) {
1314             Emit(" - . + ").Emit(kDataRefIsOffset);
1315         } else if (idx == static_cast<uint32>(ClassProperty::kGctib)) {
1316             if (cg->FindGCTIBPatternName(symAddrName).find(REF_PREFIX_STR) == 0) {
1317                 Emit(" - . + ").Emit(kGctibRefIsIndirect);
1318             } else {
1319                 Emit(" - .");
1320             }
1321         }
1322     } else if (mirSymbol.IsReflectionClassInfoRO()) {
1323         if (idx == static_cast<uint32>(ClassRO::kSuperclass)) {
1324             Emit(" - . + ").Emit(kDataRefIsOffset);
1325         }
1326     }
1327 
1328     if (cg->GetCGOptions().GeneratePositionIndependentExecutable()) {
1329         Emit(" - ");
1330         Emit(stName);
1331     }
1332     Emit("\n");
1333 }
1334 
GetAddroffuncConst(const MIRSymbol & mirSymbol,MIRAggConst & aggConst)1335 MIRAddroffuncConst *Emitter::GetAddroffuncConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst)
1336 {
1337     MIRAddroffuncConst *innerFuncAddr = nullptr;
1338     size_t addrIndex = mirSymbol.IsReflectionMethodsInfo() ? static_cast<size_t>(MethodProperty::kPaddrData)
1339                                                            : static_cast<size_t>(MethodInfoCompact::kPaddrData);
1340     MIRConst *pAddrConst = aggConst.GetConstVecItem(addrIndex);
1341     if (pAddrConst->GetKind() == kConstAddrof) {
1342         /* point addr data. */
1343         MIRAddrofConst *pAddr = safe_cast<MIRAddrofConst>(pAddrConst);
1344         DEBUG_ASSERT(pAddr != nullptr, "null ptr check");
1345         MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(pAddr->GetSymbolIndex().Idx());
1346         DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
1347         MIRAggConst *methodAddrAggConst = safe_cast<MIRAggConst>(symAddrSym->GetKonst());
1348         DEBUG_ASSERT(methodAddrAggConst != nullptr, "null ptr check");
1349         MIRAggConst *addrAggConst = safe_cast<MIRAggConst>(methodAddrAggConst->GetConstVecItem(0));
1350         DEBUG_ASSERT(addrAggConst != nullptr, "null ptr check");
1351         MIRConst *funcAddrConst = addrAggConst->GetConstVecItem(0);
1352         if (funcAddrConst->GetKind() == kConstAddrofFunc) {
1353             /* func sybmol. */
1354             innerFuncAddr = safe_cast<MIRAddroffuncConst>(funcAddrConst);
1355         } else if (funcAddrConst->GetKind() == kConstInt) {
1356             /* def table index, replaced by def table for lazybinding. */
1357             std::string funcDefTabName =
1358                 namemangler::kMuidFuncDefTabPrefixStr + cg->GetMIRModule()->GetFileNameAsPostfix();
1359             MIRSymbol *funDefTabSy = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
1360                 GlobalTables::GetStrTable().GetStrIdxFromName(funcDefTabName));
1361             DEBUG_ASSERT(funDefTabSy != nullptr, "null ptr check");
1362             MIRAggConst &funDefTabAggConst = static_cast<MIRAggConst &>(*funDefTabSy->GetKonst());
1363             MIRIntConst *funcAddrIndexConst = safe_cast<MIRIntConst>(funcAddrConst);
1364             DEBUG_ASSERT(funcAddrIndexConst != nullptr, "null ptr check");
1365             uint64 indexDefTab = static_cast<uint64>(funcAddrIndexConst->GetExtValue());
1366             MIRAggConst *defTabAggConst = safe_cast<MIRAggConst>(funDefTabAggConst.GetConstVecItem(indexDefTab));
1367             DEBUG_ASSERT(defTabAggConst != nullptr, "null ptr check");
1368             MIRConst *funcConst = defTabAggConst->GetConstVecItem(0);
1369             if (funcConst->GetKind() == kConstAddrofFunc) {
1370                 innerFuncAddr = safe_cast<MIRAddroffuncConst>(funcConst);
1371             }
1372         }
1373     } else if (pAddrConst->GetKind() == kConstAddrofFunc) {
1374         innerFuncAddr = safe_cast<MIRAddroffuncConst>(pAddrConst);
1375     }
1376     return innerFuncAddr;
1377 }
1378 
GetFieldOffsetValue(const std::string & className,const MIRIntConst & intConst,const std::map<GStrIdx,MIRType * > & strIdx2Type)1379 int64 Emitter::GetFieldOffsetValue(const std::string &className, const MIRIntConst &intConst,
1380                                    const std::map<GStrIdx, MIRType *> &strIdx2Type)
1381 {
1382     uint64 idx = static_cast<uint64>(intConst.GetExtValue());
1383     bool isDefTabIndex = idx & 0x1;
1384     int64 fieldIdx = idx >> 1;
1385     if (isDefTabIndex) {
1386         /* it's def table index. */
1387         return fieldIdx;
1388     } else {
1389         /* really offset. */
1390         uint8 charBitWidth = GetPrimTypeSize(PTY_i8) * kBitsPerByte;
1391         GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(className);
1392         auto it = strIdx2Type.find(strIdx);
1393         CHECK_FATAL(it->second != nullptr, "valid iterator check");
1394         DEBUG_ASSERT(it != strIdx2Type.end(), "Can not find type");
1395         MIRType &ty = *it->second;
1396         MIRStructType &structType = static_cast<MIRStructType &>(ty);
1397         std::pair<int32, int32> fieldOffsetPair =
1398             Globals::GetInstance()->GetBECommon()->GetFieldOffset(structType, fieldIdx);
1399         int64 fieldOffset = fieldOffsetPair.first * static_cast<int64>(charBitWidth) + fieldOffsetPair.second;
1400         return fieldOffset;
1401     }
1402 }
1403 
InitRangeIdx2PerfixStr()1404 void Emitter::InitRangeIdx2PerfixStr()
1405 {
1406     rangeIdx2PrefixStr[RangeIdx::kVtabAndItab] = kMuidVtabAndItabPrefixStr;
1407     rangeIdx2PrefixStr[RangeIdx::kItabConflict] = kMuidItabConflictPrefixStr;
1408     rangeIdx2PrefixStr[RangeIdx::kVtabOffset] = kMuidVtabOffsetPrefixStr;
1409     rangeIdx2PrefixStr[RangeIdx::kFieldOffset] = kMuidFieldOffsetPrefixStr;
1410     rangeIdx2PrefixStr[RangeIdx::kValueOffset] = kMuidValueOffsetPrefixStr;
1411     rangeIdx2PrefixStr[RangeIdx::kLocalClassInfo] = kMuidLocalClassInfoStr;
1412     rangeIdx2PrefixStr[RangeIdx::kConststr] = kMuidConststrPrefixStr;
1413     rangeIdx2PrefixStr[RangeIdx::kSuperclass] = kMuidSuperclassPrefixStr;
1414     rangeIdx2PrefixStr[RangeIdx::kGlobalRootlist] = kMuidGlobalRootlistPrefixStr;
1415     rangeIdx2PrefixStr[RangeIdx::kClassmetaData] = kMuidClassMetadataPrefixStr;
1416     rangeIdx2PrefixStr[RangeIdx::kClassBucket] = kMuidClassMetadataBucketPrefixStr;
1417     rangeIdx2PrefixStr[RangeIdx::kDataSection] = kMuidDataSectionStr;
1418     rangeIdx2PrefixStr[RangeIdx::kDecoupleStaticKey] = kDecoupleStaticKeyStr;
1419     rangeIdx2PrefixStr[RangeIdx::kDecoupleStaticValue] = kDecoupleStaticValueStr;
1420     rangeIdx2PrefixStr[RangeIdx::kBssStart] = kBssSectionStr;
1421     rangeIdx2PrefixStr[RangeIdx::kLinkerSoHash] = kLinkerHashSoStr;
1422     rangeIdx2PrefixStr[RangeIdx::kArrayClassCache] = kArrayClassCacheTable;
1423     rangeIdx2PrefixStr[RangeIdx::kArrayClassCacheName] = kArrayClassCacheNameTable;
1424 }
1425 
EmitIntConst(const MIRSymbol & mirSymbol,MIRAggConst & aggConst,uint32 itabConflictIndex,const std::map<GStrIdx,MIRType * > & strIdx2Type,size_t idx)1426 void Emitter::EmitIntConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst, uint32 itabConflictIndex,
1427                            const std::map<GStrIdx, MIRType *> &strIdx2Type, size_t idx)
1428 {
1429     MIRConst *elemConst = aggConst.GetConstVecItem(idx);
1430     DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
1431     const std::string stName = mirSymbol.GetName();
1432 
1433     MIRIntConst *intConst = safe_cast<MIRIntConst>(elemConst);
1434     DEBUG_ASSERT(intConst != nullptr, "Uexpected const type");
1435 
1436     /* ignore abstract function addr */
1437     if ((idx == static_cast<uint32>(MethodInfoCompact::kPaddrData)) && mirSymbol.IsReflectionMethodsInfoCompact()) {
1438         return;
1439     }
1440 
1441     if (((idx == static_cast<uint32>(MethodProperty::kVtabIndex)) && (mirSymbol.IsReflectionMethodsInfo())) ||
1442         ((idx == static_cast<uint32>(MethodInfoCompact::kVtabIndex)) && mirSymbol.IsReflectionMethodsInfoCompact())) {
1443         MIRAddroffuncConst *innerFuncAddr = GetAddroffuncConst(mirSymbol, aggConst);
1444         if (innerFuncAddr != nullptr) {
1445             Emit(".Label.name." +
1446                  GlobalTables::GetFunctionTable().GetFunctionFromPuidx(innerFuncAddr->GetValue())->GetName());
1447             Emit(":\n");
1448         }
1449     }
1450     /* refer to DeCouple::GenOffsetTableType */
1451     constexpr int fieldTypeIdx = 2;
1452     constexpr int methodTypeIdx = 2;
1453     bool isClassInfo =
1454         (idx == static_cast<uint32>(ClassRO::kClassName) || idx == static_cast<uint32>(ClassRO::kAnnotation)) &&
1455         mirSymbol.IsReflectionClassInfoRO();
1456     bool isMethodsInfo = (idx == static_cast<uint32>(MethodProperty::kMethodName) ||
1457                           idx == static_cast<uint32>(MethodProperty::kSigName) ||
1458                           idx == static_cast<uint32>(MethodProperty::kAnnotation)) &&
1459                          mirSymbol.IsReflectionMethodsInfo();
1460     bool isFieldsInfo =
1461         (idx == static_cast<uint32>(FieldProperty::kTypeName) || idx == static_cast<uint32>(FieldProperty::kName) ||
1462          idx == static_cast<uint32>(FieldProperty::kAnnotation)) &&
1463         mirSymbol.IsReflectionFieldsInfo();
1464     bool isMethodSignature = (idx == static_cast<uint32>(MethodSignatureProperty::kSignatureOffset)) &&
1465                              mirSymbol.IsReflectionMethodSignature();
1466     /* RegisterTable has been Int Array, visit element instead of field. */
1467     bool isInOffsetTab = (idx == 1 || idx == methodTypeIdx) && (StringUtils::StartsWith(stName, kVtabOffsetTabStr) ||
1468                                                                 StringUtils::StartsWith(stName, kFieldOffsetTabStr));
1469     /* The 1 && 2 of Decouple static struct is the string name */
1470     bool isStaticStr = (idx == 1 || idx == 2) && aggConst.GetConstVec().size() == kSizeOfDecoupleStaticStruct &&
1471                        StringUtils::StartsWith(stName, kDecoupleStaticKeyStr);
1472     /* process conflict table index larger than itabConflictIndex * 2 + 2 element */
1473     bool isConflictPerfix = (idx >= (static_cast<uint64>(itabConflictIndex) * 2 + 2)) && (idx % 2 == 0) &&
1474                             StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR);
1475     bool isArrayClassCacheName = mirSymbol.IsArrayClassCacheName();
1476     if (isClassInfo || isMethodsInfo || isFieldsInfo || mirSymbol.IsRegJNITab() || isInOffsetTab || isStaticStr ||
1477         isConflictPerfix || isArrayClassCacheName || isMethodSignature) {
1478         /* compare with all 1s */
1479         uint32 index = static_cast<uint32>((safe_cast<MIRIntConst>(elemConst))->GetExtValue()) & 0xFFFFFFFF;
1480         bool isHotReflectStr = (index & 0x00000003) != 0; /* use the last two bits of index in this expression */
1481         std::string hotStr;
1482         if (isHotReflectStr) {
1483             uint32 tag = (index & 0x00000003) - kCStringShift; /* use the last two bits of index in this expression */
1484             if (tag == kLayoutBootHot) {
1485                 hotStr = kReflectionStartHotStrtabPrefixStr;
1486             } else if (tag == kLayoutBothHot) {
1487                 hotStr = kReflectionBothHotStrTabPrefixStr;
1488             } else {
1489                 hotStr = kReflectionRunHotStrtabPrefixStr;
1490             }
1491         }
1492         std::string reflectStrTabPrefix = isHotReflectStr ? hotStr : kReflectionStrtabPrefixStr;
1493         std::string strTabName = reflectStrTabPrefix + cg->GetMIRModule()->GetFileNameAsPostfix();
1494         /* left shift 2 bit to get low 30 bit data for MIRIntConst */
1495         ASSERT_NOT_NULL(elemConst);
1496         elemConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(index >> 2, elemConst->GetType());
1497         intConst = safe_cast<MIRIntConst>(elemConst);
1498         aggConst.SetItem(static_cast<uint32>(idx), intConst, aggConst.GetFieldIdItem(idx));
1499 #ifdef USE_32BIT_REF
1500         if (stName.find(ITAB_CONFLICT_PREFIX_STR) == 0) {
1501             EmitScalarConstant(*elemConst, false, true);
1502         } else {
1503             EmitScalarConstant(*elemConst, false);
1504         }
1505 #else
1506         EmitScalarConstant(*elemConst, false);
1507 #endif /* USE_32BIT_REF */
1508         Emit("+" + strTabName);
1509         if (mirSymbol.IsRegJNITab() || mirSymbol.IsReflectionMethodsInfo() || mirSymbol.IsReflectionFieldsInfo() ||
1510             mirSymbol.IsArrayClassCacheName() || mirSymbol.IsReflectionMethodSignature()) {
1511             Emit("-.");
1512         }
1513         if (StringUtils::StartsWith(stName, kDecoupleStaticKeyStr)) {
1514             Emit("-.");
1515         }
1516         if (mirSymbol.IsReflectionClassInfoRO()) {
1517             if (idx == static_cast<uint32>(ClassRO::kAnnotation)) {
1518                 Emit("-.");
1519             } else if (idx == static_cast<uint32>(ClassRO::kClassName)) {
1520                 /* output in hex format to show it is a flag of bits. */
1521                 std::stringstream ss;
1522                 ss << std::hex << "0x" << MByteRef::kPositiveOffsetBias;
1523                 Emit(" - . + " + ss.str());
1524             }
1525         }
1526         if (StringUtils::StartsWith(stName, ITAB_PREFIX_STR)) {
1527             Emit("-.");
1528         }
1529         if (StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR)) {
1530             /* output in hex format to show it is a flag of bits. */
1531             std::stringstream ss;
1532             ss << std::hex << "0x" << MByteRef32::kPositiveOffsetBias;
1533             Emit(" - . + " + ss.str());
1534         }
1535         if ((idx == 1 || idx == methodTypeIdx) && StringUtils::StartsWith(stName, kVtabOffsetTabStr)) {
1536             Emit("-.");
1537         }
1538         if ((idx == 1 || idx == fieldTypeIdx) && StringUtils::StartsWith(stName, kFieldOffsetTabStr)) {
1539             Emit("-.");
1540         }
1541         Emit("\n");
1542     } else if (idx == kFuncDefAddrIndex && mirSymbol.IsMuidFuncUndefTab()) {
1543 #if defined(USE_32BIT_REF)
1544         Emit("\t.long\t");
1545 #else
1546         EmitAsmLabel(kAsmQuad);
1547 #endif /* USE_32BIT_REF */
1548         if (CGOptions::IsLazyBinding() && !cg->IsLibcore()) {
1549             /*
1550              * Check enum BindingState defined in Mpl_Binding.h,
1551              * 5 means kBindingStateMethodUndef:5 offset away from base __BindingProtectRegion__.
1552              */
1553 #if defined(USE_32BIT_REF)
1554             Emit("0x5\n"); /* Fix it in runtime, __BindingProtectRegion__ + kBindingStateMethodUndef:5. */
1555 #else
1556             Emit("__BindingProtectRegion__ + 5\n");
1557 #endif /* USE_32BIT_REF */
1558         } else {
1559             Emit("0\n");
1560         }
1561     } else if (idx == static_cast<uint32>(FieldProperty::kPClassType) && mirSymbol.IsReflectionFieldsInfo()) {
1562 #ifdef USE_32BIT_REF
1563         Emit("\t.long\t");
1564         const int width = 4;
1565 #else
1566         EmitAsmLabel(kAsmQuad);
1567         const int width = 8;
1568 #endif /* USE_32BIT_REF */
1569         uint32 muidDataTabAddr = static_cast<uint32>((safe_cast<MIRIntConst>(elemConst))->GetExtValue());
1570         if (muidDataTabAddr != 0) {
1571             bool isDefTabIndex = (muidDataTabAddr & kFromDefIndexMask32Mod) == kFromDefIndexMask32Mod;
1572             std::string muidDataTabPrefix = isDefTabIndex ? kMuidDataDefTabPrefixStr : kMuidDataUndefTabPrefixStr;
1573             std::string muidDataTabName = muidDataTabPrefix + cg->GetMIRModule()->GetFileNameAsPostfix();
1574             (void)Emit(muidDataTabName + "+");
1575             uint32 muidDataTabIndex = muidDataTabAddr & 0x3FFFFFFF; /* high 2 bit is the mask of muid tab */
1576             (void)Emit(std::to_string(muidDataTabIndex * width));
1577             (void)Emit("-.\n");
1578         } else {
1579             (void)Emit(muidDataTabAddr);
1580             Emit("\n");
1581         }
1582         return;
1583     } else if (mirSymbol.IsReflectionFieldOffsetData()) {
1584         /* Figure out instance field offset now. */
1585         size_t prefixStrLen = strlen(kFieldOffsetDataPrefixStr);
1586         size_t pos = stName.find("_FieldID_");
1587         std::string typeName = stName.substr(prefixStrLen, pos - prefixStrLen);
1588 #ifdef USE_32BIT_REF
1589         std::string widthFlag = ".long";
1590 #else
1591         std::string widthFlag = ".quad";
1592 #endif /* USE_32BIT_REF */
1593         int64 fieldOffset = GetFieldOffsetValue(typeName, *intConst, strIdx2Type);
1594         uint64 fieldIdx = static_cast<uint64>(intConst->GetExtValue());
1595         bool isDefTabIndex = fieldIdx & 0x1;
1596         if (isDefTabIndex) {
1597             /* it's def table index. */
1598             Emit("\t//  " + typeName + " static field, data def table index " + std::to_string(fieldOffset) + "\n");
1599         } else {
1600             /* really offset. */
1601             fieldIdx >>= 1;
1602             Emit("\t//  " + typeName + "\t field" + std::to_string(fieldIdx) + "\n");
1603         }
1604         Emit("\t" + widthFlag + "\t" + std::to_string(fieldOffset) + "\n");
1605     } else if (((idx == static_cast<uint32>(FieldProperty::kPOffset)) && mirSymbol.IsReflectionFieldsInfo()) ||
1606                ((idx == static_cast<uint32>(FieldPropertyCompact::kPOffset)) &&
1607                 mirSymbol.IsReflectionFieldsInfoCompact())) {
1608         std::string typeName;
1609         std::string widthFlag;
1610 #ifdef USE_32BIT_REF
1611         const int width = 4;
1612 #else
1613         const int width = 8;
1614 #endif /* USE_32BIT_REF */
1615         if (mirSymbol.IsReflectionFieldsInfo()) {
1616             typeName = stName.substr(strlen(kFieldsInfoPrefixStr));
1617 #ifdef USE_32BIT_REF
1618             widthFlag = ".long";
1619 #else
1620             widthFlag = ".quad";
1621 #endif /* USE_32BIT_REF */
1622         } else {
1623             size_t prefixStrLen = strlen(kFieldsInfoCompactPrefixStr);
1624             typeName = stName.substr(prefixStrLen);
1625             widthFlag = ".long";
1626         }
1627         int64 fieldIdx = intConst->GetExtValue();
1628         MIRSymbol *pOffsetData = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
1629             GlobalTables::GetStrTable().GetStrIdxFromName(kFieldOffsetDataPrefixStr + typeName));
1630         if (pOffsetData != nullptr) {
1631             fieldIdx *= width;
1632             std::string fieldOffset = kFieldOffsetDataPrefixStr + typeName;
1633             Emit("\t" + widthFlag + "\t" + std::to_string(fieldIdx) + " + " + fieldOffset + " - .\n");
1634         } else {
1635             /* pOffsetData null, means FieldMeta.offset is really offset */
1636             int64 fieldOffset = GetFieldOffsetValue(typeName, *intConst, strIdx2Type);
1637             Emit("\t//  " + typeName + "\t field" + std::to_string(fieldIdx) + "\n");
1638             Emit("\t" + widthFlag + "\t" + std::to_string(fieldOffset) + "\n");
1639         }
1640     } else if ((idx == static_cast<uint32>(ClassProperty::kObjsize)) && mirSymbol.IsReflectionClassInfo()) {
1641         std::string delimiter = "$$";
1642         std::string typeName =
1643             stName.substr(strlen(CLASSINFO_PREFIX_STR), stName.find(delimiter) - strlen(CLASSINFO_PREFIX_STR));
1644         uint32 objSize = 0;
1645         std::string comments;
1646 
1647         if (typeName.size() > 1 && typeName[0] == '$') {
1648             /* fill element size for array class; */
1649             std::string newTypeName = typeName.substr(1);
1650             /* another $(arraysplitter) */
1651             if (newTypeName.find("$") == std::string::npos) {
1652                 CHECK_FATAL(false, "can not find $ in std::string");
1653             }
1654             typeName = newTypeName.substr(newTypeName.find("$") + 1);
1655             int32 pTypeSize;
1656 
1657             /* we only need to calculate primitive type in arrays. */
1658             if ((pTypeSize = GetPrimitiveTypeSize(typeName)) != -1) {
1659                 objSize = static_cast<uint32>(pTypeSize);
1660             }
1661             comments = "// elemobjsize";
1662         } else {
1663             comments = "// objsize";
1664         }
1665 
1666         if (!objSize) {
1667             GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(typeName);
1668             auto it = strIdx2Type.find(strIdx);
1669             DEBUG_ASSERT(it != strIdx2Type.end(), "Can not find type");
1670             MIRType *mirType = it->second;
1671             ASSERT_NOT_NULL(mirType);
1672             objSize = Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex());
1673         }
1674         /* objSize should not exceed 16 bits */
1675         CHECK_FATAL(objSize <= 0xffff, "Error:the objSize is too large");
1676         Emit("\t.short\t" + std::to_string(objSize) + comments + "\n");
1677     } else if (mirSymbol.IsMuidRangeTab()) {
1678         MIRIntConst *subIntCt = safe_cast<MIRIntConst>(elemConst);
1679         int flag = subIntCt->GetExtValue();
1680         InitRangeIdx2PerfixStr();
1681         if (rangeIdx2PrefixStr.find(flag) == rangeIdx2PrefixStr.end()) {
1682             EmitScalarConstant(*elemConst, false);
1683             Emit("\n");
1684             return;
1685         }
1686         std::string prefix = rangeIdx2PrefixStr[flag];
1687 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
1688         EmitAsmLabel(kAsmQuad);
1689 #else
1690         (void)Emit("\t.word\t");
1691 #endif
1692         if (idx == kRangeBeginIndex) {
1693             Emit(prefix + "_begin\n");
1694         } else {
1695             Emit(prefix + "_end\n");
1696         }
1697     } else {
1698 #ifdef USE_32BIT_REF
1699         if (StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR) ||
1700             StringUtils::StartsWith(stName, ITAB_PREFIX_STR) || StringUtils::StartsWith(stName, VTAB_PREFIX_STR)) {
1701             EmitScalarConstant(*elemConst, false, true);
1702         } else {
1703             EmitScalarConstant(*elemConst, false);
1704         }
1705 #else
1706         ASSERT_NOT_NULL(elemConst);
1707         EmitScalarConstant(*elemConst, false);
1708 #endif /* USE_32BIT_REF */
1709         Emit("\n");
1710     }
1711 }
1712 
EmitConstantTable(const MIRSymbol & mirSymbol,MIRConst & mirConst,const std::map<GStrIdx,MIRType * > & strIdx2Type)1713 void Emitter::EmitConstantTable(const MIRSymbol &mirSymbol, MIRConst &mirConst,
1714                                 const std::map<GStrIdx, MIRType *> &strIdx2Type)
1715 {
1716     const std::string stName = mirSymbol.GetName();
1717     MIRAggConst &aggConst = static_cast<MIRAggConst &>(mirConst);
1718     uint32 itabConflictIndex = 0;
1719     for (size_t i = 0; i < aggConst.GetConstVec().size(); ++i) {
1720         MIRConst *elemConst = aggConst.GetConstVecItem(i);
1721         DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
1722         if (i == 0 && StringUtils::StartsWith(stName, ITAB_CONFLICT_PREFIX_STR)) {
1723 #ifdef USE_32BIT_REF
1724             itabConflictIndex = static_cast<uint64>((safe_cast<MIRIntConst>(elemConst))->GetValue()) & 0xffff;
1725 #else
1726             itabConflictIndex = safe_cast<MIRIntConst>(elemConst)->GetExtValue() & 0xffffffff;
1727 #endif
1728         }
1729         if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) {
1730             if (elemConst->GetKind() == kConstAddrofFunc) { /* addroffunc const */
1731                 EmitAddrofFuncConst(mirSymbol, *elemConst, i);
1732             } else if (elemConst->GetKind() == kConstAddrof) { /* addrof symbol const */
1733                 EmitAddrofSymbolConst(mirSymbol, *elemConst, i);
1734             } else { /* intconst */
1735                 EmitIntConst(mirSymbol, aggConst, itabConflictIndex, strIdx2Type, i);
1736             }
1737         } else if (elemConst->GetType().GetKind() == kTypeArray || elemConst->GetType().GetKind() == kTypeStruct) {
1738             if (StringUtils::StartsWith(mirSymbol.GetName(), namemangler::kOffsetTabStr) && (i == 0 || i == 1)) {
1739                 /* EmitOffsetValueTable */
1740 #ifdef USE_32BIT_REF
1741                 Emit("\t.long\t");
1742 #else
1743                 EmitAsmLabel(kAsmQuad);
1744 #endif
1745                 if (i == 0) {
1746                     (void)Emit(namemangler::kVtabOffsetTabStr + cg->GetMIRModule()->GetFileNameAsPostfix() + " - .\n");
1747                 } else {
1748                     (void)Emit(namemangler::kFieldOffsetTabStr + cg->GetMIRModule()->GetFileNameAsPostfix() + " - .\n");
1749                 }
1750             } else {
1751                 EmitConstantTable(mirSymbol, *elemConst, strIdx2Type);
1752             }
1753         }
1754     }
1755 }
1756 
EmitArrayConstant(MIRConst & mirConst)1757 void Emitter::EmitArrayConstant(MIRConst &mirConst)
1758 {
1759     MIRType &mirType = mirConst.GetType();
1760     MIRAggConst &arrayCt = static_cast<MIRAggConst &>(mirConst);
1761     MIRArrayType &arrayType = static_cast<MIRArrayType &>(mirType);
1762     size_t uNum = arrayCt.GetConstVec().size();
1763     uint32 dim = arrayType.GetSizeArrayItem(0);
1764     TyIdx scalarIdx = arrayType.GetElemTyIdx();
1765     MIRType *subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx);
1766     if (uNum == 0 && dim) {
1767         while (subTy->GetKind() == kTypeArray) {
1768             MIRArrayType *aSubTy = static_cast<MIRArrayType *>(subTy);
1769             if (aSubTy->GetSizeArrayItem(0) > 0) {
1770                 dim *= (aSubTy->GetSizeArrayItem(0));
1771             }
1772             scalarIdx = aSubTy->GetElemTyIdx();
1773             subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx);
1774         }
1775     }
1776     for (size_t i = 0; i < uNum; ++i) {
1777         MIRConst *elemConst = arrayCt.GetConstVecItem(i);
1778         if (IsPrimitiveVector(subTy->GetPrimType())) {
1779             EmitVectorConstant(*elemConst);
1780         } else if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) {
1781             if (cg->GetMIRModule()->IsCModule()) {
1782                 bool strLiteral = false;
1783                 if (arrayType.GetDim() == 1) {
1784                     MIRType *ety = arrayType.GetElemType();
1785                     if (ety->GetPrimType() == PTY_i8 || ety->GetPrimType() == PTY_u8) {
1786                         strLiteral = true;
1787                     }
1788                 }
1789                 EmitScalarConstant(*elemConst, true, false, strLiteral == false);
1790             } else {
1791                 EmitScalarConstant(*elemConst);
1792             }
1793         } else if (elemConst->GetType().GetKind() == kTypeArray) {
1794             EmitArrayConstant(*elemConst);
1795         } else if (elemConst->GetType().GetKind() == kTypeStruct || elemConst->GetType().GetKind() == kTypeClass ||
1796                    elemConst->GetType().GetKind() == kTypeUnion) {
1797             EmitStructConstant(*elemConst);
1798         } else if (elemConst->GetKind() == kConstAddrofFunc) {
1799             EmitScalarConstant(*elemConst);
1800         } else {
1801             DEBUG_ASSERT(false, "should not run here");
1802         }
1803     }
1804     DEBUG_ASSERT(static_cast<int64>(arrayType.GetSizeArrayItem(0)) > 0, "must not be zero");
1805     int64 iNum = (arrayType.GetSizeArrayItem(0) > 0) ? (static_cast<int64>(arrayType.GetSizeArrayItem(0)) - uNum) : 0;
1806     if (iNum > 0) {
1807         if (!cg->GetMIRModule()->IsCModule()) {
1808             CHECK_FATAL(!Globals::GetInstance()->GetBECommon()->IsEmptyOfTypeSizeTable(), "container empty check");
1809             CHECK_FATAL(!arrayCt.GetConstVec().empty(), "container empty check");
1810         }
1811         if (uNum > 0) {
1812             uint64 unInSizeInByte =
1813                 static_cast<uint64>(iNum) * static_cast<uint64>(Globals::GetInstance()->GetBECommon()->GetTypeSize(
1814                     arrayCt.GetConstVecItem(0)->GetType().GetTypeIndex()));
1815             if (unInSizeInByte != 0) {
1816                 EmitNullConstant(unInSizeInByte);
1817             }
1818         } else {
1819             uint64 size = Globals::GetInstance()->GetBECommon()->GetTypeSize(scalarIdx.GetIdx()) * dim;
1820             Emit("\t.zero\t").Emit(static_cast<int64>(size)).Emit("\n");
1821         }
1822     }
1823 }
1824 
EmitVectorConstant(MIRConst & mirConst)1825 void Emitter::EmitVectorConstant(MIRConst &mirConst)
1826 {
1827     MIRType &mirType = mirConst.GetType();
1828     MIRAggConst &vecCt = static_cast<MIRAggConst &>(mirConst);
1829     size_t uNum = vecCt.GetConstVec().size();
1830     for (size_t i = 0; i < uNum; ++i) {
1831         MIRConst *elemConst = vecCt.GetConstVecItem(i);
1832         if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) {
1833             bool strLiteral = false;
1834             EmitScalarConstant(*elemConst, true, false, strLiteral == false);
1835         } else {
1836             DEBUG_ASSERT(false, "should not run here");
1837         }
1838     }
1839     size_t lanes = GetVecLanes(mirType.GetPrimType());
1840     if (lanes > uNum) {
1841         MIRIntConst zConst(0, vecCt.GetConstVecItem(0)->GetType());
1842         for (size_t i = uNum; i < lanes; i++) {
1843             EmitScalarConstant(zConst, true, false, false);
1844         }
1845     }
1846 }
1847 
EmitStructConstant(MIRConst & mirConst)1848 void Emitter::EmitStructConstant(MIRConst &mirConst)
1849 {
1850     uint32_t subStructFieldCounts = 0;
1851     EmitStructConstant(mirConst, subStructFieldCounts);
1852 }
1853 
EmitStructConstant(MIRConst & mirConst,uint32 & subStructFieldCounts)1854 void Emitter::EmitStructConstant(MIRConst &mirConst, uint32 &subStructFieldCounts)
1855 {
1856     StructEmitInfo *sEmitInfo = cg->GetMIRModule()->GetMemPool()->New<StructEmitInfo>();
1857     CHECK_FATAL(sEmitInfo != nullptr, "create a new struct emit info failed in Emitter::EmitStructConstant");
1858     MIRType &mirType = mirConst.GetType();
1859     MIRAggConst &structCt = static_cast<MIRAggConst &>(mirConst);
1860     MIRStructType &structType = static_cast<MIRStructType &>(mirType);
1861     auto structPack = static_cast<uint8>(structType.GetTypeAttrs().GetPack());
1862     /* all elements of struct. */
1863     uint8 num;
1864     if (structType.GetKind() == kTypeUnion) {
1865         num = 1;
1866     } else {
1867         num = static_cast<uint8>(structType.GetFieldsSize());
1868     }
1869     BECommon *beCommon = Globals::GetInstance()->GetBECommon();
1870     /* total size of emitted elements size. */
1871     uint32 size = beCommon->GetTypeSize(structType.GetTypeIndex());
1872     uint32 fieldIdx = 1;
1873     if (structType.GetKind() == kTypeUnion) {
1874         fieldIdx = structCt.GetFieldIdItem(0);
1875     }
1876     for (uint32 i = 0; i < num; ++i) {
1877         if (((i + 1) == num) && cg->GetMIRModule()->GetSrcLang() == kSrcLangC) {
1878             isFlexibleArray = beCommon->GetHasFlexibleArray(mirType.GetTypeIndex().GetIdx());
1879             arraySize = 0;
1880         }
1881         MIRConst *elemConst;
1882         if (structType.GetKind() == kTypeStruct) {
1883             elemConst = structCt.GetAggConstElement(i + 1);
1884         } else {
1885             elemConst = structCt.GetAggConstElement(fieldIdx);
1886         }
1887         MIRType *elemType = structType.GetElemType(i);
1888         if (structType.GetKind() == kTypeUnion) {
1889             CHECK_NULL_FATAL(elemConst);
1890             elemType = &(elemConst->GetType());
1891         }
1892         MIRType *nextElemType = nullptr;
1893         if (i != static_cast<uint32>(num - 1)) {
1894             nextElemType = structType.GetElemType(i + 1);
1895         }
1896         uint64 elemSize = beCommon->GetTypeSize(elemType->GetTypeIndex());
1897         uint8 charBitWidth = GetPrimTypeSize(PTY_i8) * kBitsPerByte;
1898         if (elemType->GetKind() == kTypeBitField) {
1899             if (elemConst == nullptr) {
1900                 MIRIntConst *zeroFill = GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, *elemType);
1901                 elemConst = zeroFill;
1902             }
1903             std::pair<int32_t, int32_t> fieldOffsetPair = beCommon->GetFieldOffset(structType, fieldIdx);
1904             uint64_t fieldOffset = static_cast<uint64_t>(static_cast<int64_t>(fieldOffsetPair.first)) *
1905                                        static_cast<uint64_t>(charBitWidth) +
1906                                    static_cast<uint64_t>(static_cast<int64_t>(fieldOffsetPair.second));
1907             EmitBitFieldConstant(*sEmitInfo, *elemConst, nextElemType, fieldOffset);
1908         } else {
1909             if (elemConst != nullptr) {
1910                 if (IsPrimitiveVector(elemType->GetPrimType())) {
1911                     EmitVectorConstant(*elemConst);
1912                 } else if (IsPrimitiveScalar(elemType->GetPrimType())) {
1913                     EmitScalarConstant(*elemConst, true, false, true);
1914                 } else if (elemType->GetKind() == kTypeArray) {
1915                     if (elemType->GetSize() != 0) {
1916                         EmitArrayConstant(*elemConst);
1917                     }
1918                 } else if ((elemType->GetKind() == kTypeStruct) || (elemType->GetKind() == kTypeClass) ||
1919                            (elemType->GetKind() == kTypeUnion)) {
1920                     EmitStructConstant(*elemConst, subStructFieldCounts);
1921                     fieldIdx += subStructFieldCounts;
1922                 } else {
1923                     DEBUG_ASSERT(false, "should not run here");
1924                 }
1925             } else {
1926                 EmitNullConstant(elemSize);
1927             }
1928             sEmitInfo->IncreaseTotalSize(elemSize);
1929             sEmitInfo->SetNextFieldOffset(sEmitInfo->GetTotalSize() * charBitWidth);
1930         }
1931 
1932         if (nextElemType != nullptr && kTypeBitField != nextElemType->GetKind()) {
1933             DEBUG_ASSERT(i < static_cast<uint32>(num - 1), "NYI");
1934             uint8 nextAlign = Globals::GetInstance()->GetBECommon()->GetTypeAlign(nextElemType->GetTypeIndex());
1935             auto fieldAttr = structType.GetFields()[i + 1].second.second;
1936             nextAlign = fieldAttr.IsPacked() ? 1 : std::min(nextAlign, structPack);
1937             DEBUG_ASSERT(nextAlign != 0, "expect non-zero");
1938             /* append size, append 0 when align need. */
1939             uint64 totalSize = sEmitInfo->GetTotalSize();
1940             uint64 psize = (totalSize % nextAlign == 0) ? 0 : (nextAlign - (totalSize % nextAlign));
1941             if (psize != 0) {
1942                 EmitNullConstant(psize);
1943                 sEmitInfo->IncreaseTotalSize(psize);
1944                 sEmitInfo->SetNextFieldOffset(sEmitInfo->GetTotalSize() * charBitWidth);
1945             }
1946             /* element is uninitialized, emit null constant. */
1947         }
1948         fieldIdx++;
1949     }
1950     if (structType.GetKind() == kTypeStruct) {
1951         /* The reason of subtracting one is that fieldIdx adds one at the end of the cycle. */
1952         CHECK_FATAL(fieldIdx > 0, "must not be zero");
1953         subStructFieldCounts = fieldIdx - 1;
1954     } else if (structType.GetKind() == kTypeUnion) {
1955         subStructFieldCounts = static_cast<uint32>(beCommon->GetStructFieldCount(structType.GetTypeIndex()));
1956     }
1957 
1958     isFlexibleArray = false;
1959     uint64 opSize = size - sEmitInfo->GetTotalSize();
1960     if (opSize != 0) {
1961         EmitNullConstant(opSize);
1962     }
1963 }
1964 
1965 /* BlockMarker is for Debugging/Profiling */
EmitBlockMarker(const std::string & markerName,const std::string & sectionName,bool withAddr,const std::string & addrName)1966 void Emitter::EmitBlockMarker(const std::string &markerName, const std::string &sectionName, bool withAddr,
1967                               const std::string &addrName)
1968 {
1969     /*
1970      * .type $marker_name$, %object
1971      * .global $marker_name$
1972      * .data
1973      * .align 3
1974      * $marker_name$:
1975      * .quad 0xdeadbeefdeadbeef
1976      * .size $marker_name$, 8
1977      */
1978     Emit(asmInfo->GetType());
1979     Emit(markerName);
1980     Emit(", %object\n");
1981     if (CGOptions::IsEmitBlockMarker()) { /* exposed as global symbol, for profiling */
1982         Emit(asmInfo->GetGlobal());
1983     } else { /* exposed as local symbol, for release. */
1984         Emit(asmInfo->GetLocal());
1985     }
1986     Emit(markerName);
1987     Emit("\n");
1988 
1989     if (!sectionName.empty()) {
1990         Emit("\t.section ." + sectionName);
1991         if (sectionName.find("ro") == 0) {
1992             Emit(",\"a\",%progbits\n");
1993         } else {
1994             Emit(",\"aw\",%progbits\n");
1995         }
1996     } else {
1997         EmitAsmLabel(kAsmData);
1998     }
1999     Emit(asmInfo->GetAlign());
2000     if (GetCG()->GetTargetMachine()->isX8664()) {
2001         Emit("8\n" + markerName + ":\n");
2002     } else {
2003         Emit("3\n" + markerName + ":\n");
2004     }
2005     EmitAsmLabel(kAsmQuad);
2006     if (withAddr) {
2007         Emit(addrName + "\n");
2008     } else {
2009         Emit("0xdeadbeefdeadbeef\n"); /* hexspeak in aarch64 represents crash or dead lock */
2010     }
2011     Emit(asmInfo->GetSize());
2012     Emit(markerName + ", 8\n");
2013 }
2014 
EmitLiteral(const MIRSymbol & literal,const std::map<GStrIdx,MIRType * > & strIdx2Type)2015 void Emitter::EmitLiteral(const MIRSymbol &literal, const std::map<GStrIdx, MIRType *> &strIdx2Type)
2016 {
2017     /*
2018      * .type _C_STR_xxxx, %object
2019      * .local _C_STR_xxxx
2020      * .data
2021      * .align 3
2022      * _C_STR_xxxx:
2023      * ....
2024      * .size _C_STR_xxxx, 40
2025      */
2026     if (literal.GetStorageClass() == kScUnused) {
2027         return;
2028     }
2029     EmitAsmLabel(literal, kAsmType);
2030     /* literal should always be fstatic and readonly? */
2031     EmitAsmLabel(literal, kAsmLocal); /* alwasy fstatic */
2032     (void)Emit("\t.section\t." + std::string(kMapleLiteralString) + ",\"aw\", %progbits\n");
2033     EmitAsmLabel(literal, kAsmAlign);
2034     EmitAsmLabel(literal, kAsmSyname);
2035     /* literal is an array */
2036     MIRConst *mirConst = literal.GetKonst();
2037     CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitLiteral");
2038     if (literal.HasAddrOfValues()) {
2039         EmitConstantTable(literal, *mirConst, strIdx2Type);
2040     } else {
2041         EmitArrayConstant(*mirConst);
2042     }
2043     EmitAsmLabel(literal, kAsmSize);
2044 }
2045 
EmitFuncLayoutInfo(const MIRSymbol & layout)2046 void Emitter::EmitFuncLayoutInfo(const MIRSymbol &layout)
2047 {
2048     /*
2049      * .type $marker_name$, %object
2050      * .global $marker_name$
2051      * .data
2052      * .align 3
2053      * $marker_name$:
2054      * .quad funcaddr
2055      * .size $marker_name$, 8
2056      */
2057     MIRConst *mirConst = layout.GetKonst();
2058     MIRAggConst *aggConst = safe_cast<MIRAggConst>(mirConst);
2059     DEBUG_ASSERT(aggConst != nullptr, "null ptr check");
2060     if (aggConst->GetConstVec().size() != static_cast<uint32>(LayoutType::kLayoutTypeCount)) {
2061         maple::LogInfo::MapleLogger(kLlErr) << "something wrong happen in funclayoutsym\t"
2062                                             << "constVec size\t" << aggConst->GetConstVec().size() << "\n";
2063         return;
2064     }
2065     for (size_t i = 0; i < static_cast<size_t>(LayoutType::kLayoutTypeCount); ++i) {
2066         std::string markerName = "__MBlock_" + GetLayoutTypeString(i) + "_func_start";
2067         CHECK_FATAL(aggConst->GetConstVecItem(i)->GetKind() == kConstAddrofFunc, "expect kConstAddrofFunc type");
2068         MIRAddroffuncConst *funcAddr = safe_cast<MIRAddroffuncConst>(aggConst->GetConstVecItem(i));
2069         DEBUG_ASSERT(funcAddr != nullptr, "null ptr check");
2070         Emit(asmInfo->GetType());
2071         Emit(markerName + ", %object\n");
2072         Emit(asmInfo->GetGlobal());
2073         Emit(markerName + "\n");
2074         EmitAsmLabel(kAsmData);
2075         if (GetCG()->GetTargetMachine()->isX8664()) {
2076             EmitAsmLabel(layout, kAsmAlign);
2077             Emit(markerName + ":\n");
2078         } else {
2079             Emit(asmInfo->GetAlign());
2080             Emit("3\n" + markerName + ":\n");
2081         }
2082 
2083 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
2084         EmitAsmLabel(kAsmQuad);
2085 #else
2086         Emit("\t.word ");
2087 #endif
2088         Emit(GlobalTables::GetFunctionTable().GetFunctionFromPuidx(funcAddr->GetValue())->GetName());
2089         Emit("\n");
2090         Emit(asmInfo->GetSize());
2091         Emit(markerName + ", 8\n");
2092     }
2093 }
2094 
EmitStaticFields(const std::vector<MIRSymbol * > & fields)2095 void Emitter::EmitStaticFields(const std::vector<MIRSymbol *> &fields)
2096 {
2097     for (auto *itSymbol : fields) {
2098         EmitAsmLabel(*itSymbol, kAsmType);
2099         /* literal should always be fstatic and readonly? */
2100         EmitAsmLabel(*itSymbol, kAsmLocal); /* alwasy fstatic */
2101         EmitAsmLabel(kAsmData);
2102         EmitAsmLabel(*itSymbol, kAsmAlign);
2103         EmitAsmLabel(*itSymbol, kAsmSyname);
2104         /* literal is an array */
2105         MIRConst *mirConst = itSymbol->GetKonst();
2106         EmitArrayConstant(*mirConst);
2107     }
2108 }
2109 
EmitLiterals(std::vector<std::pair<MIRSymbol *,bool>> & literals,const std::map<GStrIdx,MIRType * > & strIdx2Type)2110 void Emitter::EmitLiterals(std::vector<std::pair<MIRSymbol *, bool>> &literals,
2111                            const std::map<GStrIdx, MIRType *> &strIdx2Type)
2112 {
2113     /*
2114      * load literals profile
2115      * currently only used here, so declare it as local
2116      */
2117     if (!cg->GetMIRModule()->GetProfile().GetLiteralProfileSize()) {
2118         for (const auto &literalPair : literals) {
2119             EmitLiteral(*(literalPair.first), strIdx2Type);
2120         }
2121         return;
2122     }
2123     /* emit hot literal start symbol */
2124     EmitBlockMarker("__MBlock_literal_hot_begin", "", false);
2125     /*
2126      * emit literals into .data section
2127      * emit literals in the profile first
2128      */
2129     for (auto &literalPair : literals) {
2130         if (cg->GetMIRModule()->GetProfile().CheckLiteralHot(literalPair.first->GetName())) {
2131             /* it's in the literal profiling data, means it's "hot" */
2132             EmitLiteral(*(literalPair.first), strIdx2Type);
2133             literalPair.second = true;
2134         }
2135     }
2136     /* emit hot literal end symbol */
2137     EmitBlockMarker("__MBlock_literal_hot_end", "", false);
2138 
2139     /* emit cold literal start symbol */
2140     EmitBlockMarker("__MBlock_literal_cold_begin", "", false);
2141     /* emit other literals (not in the profile) next. */
2142     for (const auto &literalPair : literals) {
2143         if (!literalPair.second) {
2144             /* not emit yet */
2145             EmitLiteral(*(literalPair.first), strIdx2Type);
2146         }
2147     }
2148     /* emit cold literal end symbol */
2149     EmitBlockMarker("__MBlock_literal_cold_end", "", false);
2150 }
2151 
GetHotAndColdMetaSymbolInfo(const std::vector<MIRSymbol * > & mirSymbolVec,std::vector<MIRSymbol * > & hotFieldInfoSymbolVec,std::vector<MIRSymbol * > & coldFieldInfoSymbolVec,const std::string & prefixStr,bool forceCold)2152 void Emitter::GetHotAndColdMetaSymbolInfo(const std::vector<MIRSymbol *> &mirSymbolVec,
2153                                           std::vector<MIRSymbol *> &hotFieldInfoSymbolVec,
2154                                           std::vector<MIRSymbol *> &coldFieldInfoSymbolVec,
2155                                           const std::string &prefixStr, bool forceCold)
2156 {
2157     bool isHot = false;
2158     for (auto mirSymbol : mirSymbolVec) {
2159         CHECK_FATAL(prefixStr.length() < mirSymbol->GetName().length(), "string length check");
2160         std::string name = mirSymbol->GetName().substr(prefixStr.length());
2161         std::string klassJDescriptor;
2162         namemangler::DecodeMapleNameToJDescriptor(name, klassJDescriptor);
2163         if (prefixStr == kFieldsInfoPrefixStr) {
2164             isHot = cg->GetMIRModule()->GetProfile().CheckFieldHot(klassJDescriptor);
2165         } else if (prefixStr == kMethodsInfoPrefixStr) {
2166             isHot = cg->GetMIRModule()->GetProfile().CheckMethodHot(klassJDescriptor);
2167         } else {
2168             isHot = cg->GetMIRModule()->GetProfile().CheckClassHot(klassJDescriptor);
2169         }
2170         if (isHot && !forceCold) {
2171             hotFieldInfoSymbolVec.emplace_back(mirSymbol);
2172         } else {
2173             coldFieldInfoSymbolVec.emplace_back(mirSymbol);
2174         }
2175     }
2176 }
2177 
EmitMetaDataSymbolWithMarkFlag(const std::vector<MIRSymbol * > & mirSymbolVec,const std::map<GStrIdx,MIRType * > & strIdx2Type,const std::string & prefixStr,const std::string & sectionName,bool isHotFlag)2178 void Emitter::EmitMetaDataSymbolWithMarkFlag(const std::vector<MIRSymbol *> &mirSymbolVec,
2179                                              const std::map<GStrIdx, MIRType *> &strIdx2Type,
2180                                              const std::string &prefixStr, const std::string &sectionName,
2181                                              bool isHotFlag)
2182 {
2183     if (cg->GetMIRModule()->IsCModule()) {
2184         return;
2185     }
2186     if (mirSymbolVec.empty()) {
2187         return;
2188     }
2189     const std::string &markString = "__MBlock" + prefixStr;
2190     const std::string &hotOrCold = isHotFlag ? "hot" : "cold";
2191     EmitBlockMarker((markString + hotOrCold + "_begin"), sectionName, false);
2192     if (prefixStr == kFieldsInfoCompactPrefixStr || prefixStr == kMethodsInfoCompactPrefixStr ||
2193         prefixStr == kFieldOffsetDataPrefixStr || prefixStr == kMethodAddrDataPrefixStr) {
2194         for (auto s : mirSymbolVec) {
2195             EmitMethodFieldSequential(*s, strIdx2Type, sectionName);
2196         }
2197     } else {
2198         for (auto s : mirSymbolVec) {
2199             EmitClassInfoSequential(*s, strIdx2Type, sectionName);
2200         }
2201     }
2202     EmitBlockMarker((markString + hotOrCold + "_end"), sectionName, false);
2203 }
2204 
MarkVtabOrItabEndFlag(const std::vector<MIRSymbol * > & mirSymbolVec)2205 void Emitter::MarkVtabOrItabEndFlag(const std::vector<MIRSymbol *> &mirSymbolVec)
2206 {
2207     for (auto mirSymbol : mirSymbolVec) {
2208         auto *aggConst = safe_cast<MIRAggConst>(mirSymbol->GetKonst());
2209         if ((aggConst == nullptr) || (aggConst->GetConstVec().empty())) {
2210             continue;
2211         }
2212         size_t size = aggConst->GetConstVec().size();
2213         CHECK_FATAL(size > 0, "must not be zero");
2214         MIRConst *elemConst = aggConst->GetConstVecItem(size - 1);
2215         DEBUG_ASSERT(elemConst != nullptr, "null ptr check");
2216         if (elemConst->GetKind() == kConstAddrofFunc) {
2217             maple::LogInfo::MapleLogger(kLlErr) << "ERROR: the last vtab/itab content should not be funcAddr\n";
2218         } else {
2219             if (elemConst->GetKind() != kConstInt) {
2220                 CHECK_FATAL(elemConst->GetKind() == kConstAddrof, "must be");
2221                 continue;
2222             }
2223             MIRIntConst *tabConst = static_cast<MIRIntConst *>(elemConst);
2224 #ifdef USE_32BIT_REF
2225             /* #define COLD VTAB ITAB END FLAG  0X4000000000000000 */
2226             tabConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
2227                 static_cast<uint32>(tabConst->GetValue()) | 0X40000000, tabConst->GetType());
2228 #else
2229             /* #define COLD VTAB ITAB END FLAG  0X4000000000000000 */
2230             tabConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
2231                 tabConst->GetExtValue() | 0X4000000000000000, tabConst->GetType());
2232 #endif
2233             CHECK_FATAL(size > 0, "must not be zero");
2234             CHECK_FATAL(static_cast<uint32>(size) > 0, "must not be zero");
2235             aggConst->SetItem(static_cast<uint32>(size) - 1, tabConst, aggConst->GetFieldIdItem(size - 1));
2236         }
2237     }
2238 }
2239 
EmitStringPointers()2240 void Emitter::EmitStringPointers()
2241 {
2242     if (CGOptions::OptimizeForSize()) {
2243         (void)Emit(asmInfo->GetSection()).Emit(".rodata,\"aMS\",@progbits,1").Emit("\n");
2244         if (GetCG()->GetTargetMachine()->isX8664()) {
2245             Emit("\t.align 8\n");
2246         } else {
2247             Emit("\t.align 3\n");
2248         }
2249     } else {
2250         (void)Emit(asmInfo->GetSection()).Emit(".rodata").Emit("\n");
2251     }
2252     for (auto idx : localStrPtr) {
2253         if (idx == 0u) {
2254             continue;
2255         }
2256         if (!CGOptions::OptimizeForSize()) {
2257             if (GetCG()->GetTargetMachine()->isX8664()) {
2258                 Emit("\t.align 8\n");
2259             } else {
2260                 Emit("\t.align 3\n");
2261             }
2262         }
2263         uint32 strId = idx.GetIdx();
2264         std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(idx);
2265         (void)Emit(".LUstr_").Emit(strId).Emit(":\n");
2266         std::string mplstr(str);
2267         EmitStr(mplstr, false, true);
2268     }
2269     for (auto idx : stringPtr) {
2270         if (idx == 0u) {
2271             continue;
2272         }
2273         if (!CGOptions::OptimizeForSize()) {
2274             if (GetCG()->GetTargetMachine()->isX8664()) {
2275                 Emit("\t.align 8\n");
2276             } else {
2277                 Emit("\t.align 3\n");
2278             }
2279         }
2280         uint32 strId = idx.GetIdx();
2281         std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(idx);
2282         Emit(asmInfo->GetAlign());
2283         if (GetCG()->GetTargetMachine()->isX8664()) {
2284             Emit("8\n");
2285         } else {
2286             Emit("3\n");
2287         }
2288         Emit(".LSTR__").Emit(strId).Emit(":\n");
2289         std::string mplstr(str);
2290         EmitStr(mplstr, false, true);
2291     }
2292 }
2293 
EmitLocalVariable(const CGFunc & cgFunc)2294 void Emitter::EmitLocalVariable(const CGFunc &cgFunc)
2295 {
2296     /* function local pstatic initialization */
2297     if (cg->GetMIRModule()->IsCModule()) {
2298         CHECK_NULL_FATAL(cgFunc.GetMirModule().CurFunction());
2299         MIRSymbolTable *lSymTab = cgFunc.GetMirModule().CurFunction()->GetSymTab();
2300         if (lSymTab != nullptr) {
2301             size_t lsize = lSymTab->GetSymbolTableSize();
2302             for (size_t i = 0; i < lsize; i++) {
2303                 if (i < cgFunc.GetLSymSize() && !cg->GetMIRModule()->IsCModule()) {
2304                     continue;
2305                 }
2306                 MIRSymbol *st = lSymTab->GetSymbolFromStIdx(static_cast<uint32>(i));
2307                 if (st != nullptr && st->GetStorageClass() == kScPstatic) {
2308                     /*
2309                      * Local static names can repeat.
2310                      * Append the current program unit index to the name.
2311                      */
2312                     CHECK_NULL_FATAL(cgFunc.GetMirModule().CurFunction());
2313                     PUIdx pIdx = cgFunc.GetMirModule().CurFunction()->GetPuidx();
2314                     std::string localname = st->GetName() + std::to_string(pIdx);
2315                     static std::vector<std::string> emittedLocalSym;
2316                     bool found = false;
2317                     for (auto name : emittedLocalSym) {
2318                         if (name == localname) {
2319                             found = true;
2320                             break;
2321                         }
2322                     }
2323                     if (found) {
2324                         continue;
2325                     }
2326                     emittedLocalSym.push_back(localname);
2327 
2328                     /* cg created data should be located in .text */
2329                     /* [cgFunc.GetLSymSize(), lSymTab->GetSymbolTableSize()) -> cg created symbol */
2330                     if (i < cgFunc.GetLSymSize()) {
2331                         if (st->IsThreadLocal()) {
2332                             (void)Emit("\t.section\t.tdata,\"awT\",@progbits\n");
2333                         } else {
2334                             Emit(asmInfo->GetSection());
2335                             Emit(asmInfo->GetData());
2336                             Emit("\n");
2337                         }
2338                     } else {
2339                         CHECK_FATAL(st->GetStorageClass() == kScPstatic && st->GetSKind() == kStConst,
2340                                     "cg should create constant!");
2341                         /* cg created data should be located in .text */
2342                         (void)Emit("\t.section\t.text\n");
2343                     }
2344                     EmitAsmLabel(*st, kAsmAlign);
2345                     EmitAsmLabel(*st, kAsmLocal);
2346                     MIRType *ty = st->GetType();
2347                     MIRConst *ct = st->GetKonst();
2348                     if (ct == nullptr) {
2349                         EmitAsmLabel(*st, kAsmComm);
2350                     } else if (kTypeStruct == ty->GetKind() || kTypeUnion == ty->GetKind() ||
2351                                kTypeClass == ty->GetKind()) {
2352                         EmitAsmLabel(*st, kAsmSyname);
2353                         EmitStructConstant(*ct);
2354                     } else if (kTypeArray == ty->GetKind()) {
2355                         if (ty->GetSize() != 0) {
2356                             EmitAsmLabel(*st, kAsmSyname);
2357                             EmitArrayConstant(*ct);
2358                         }
2359                     } else {
2360                         EmitAsmLabel(*st, kAsmSyname);
2361                         EmitScalarConstant(*ct, true, false, true /* isIndirect */);
2362                     }
2363                 }
2364             }
2365         }
2366     }
2367 }
2368 
EmitGlobalVar(const MIRSymbol & globalVar)2369 void Emitter::EmitGlobalVar(const MIRSymbol &globalVar)
2370 {
2371     EmitAsmLabel(globalVar, kAsmType);
2372     if (globalVar.sectionAttr != UStrIdx(0)) { /* check section info if it is from inline asm */
2373         Emit("\t.section\t");
2374         Emit(GlobalTables::GetUStrTable().GetStringFromStrIdx(globalVar.sectionAttr));
2375         Emit(",\"aw\",%progbits\n");
2376     } else {
2377         EmitAsmLabel(globalVar, kAsmLocal);
2378     }
2379     EmitAsmLabel(globalVar, kAsmComm);
2380 }
2381 
EmitGlobalVars(std::vector<std::pair<MIRSymbol *,bool>> & globalVars)2382 void Emitter::EmitGlobalVars(std::vector<std::pair<MIRSymbol *, bool>> &globalVars)
2383 {
2384     if (GetCG()->IsLmbc() && GetCG()->GetGP() != nullptr) {
2385         (void)Emit(asmInfo->GetLocal()).Emit("\t").Emit(GetCG()->GetGP()->GetName()).Emit("\n");
2386         (void)Emit(asmInfo->GetComm()).Emit("\t").Emit(GetCG()->GetGP()->GetName());
2387         (void)Emit(", ").Emit(GetCG()->GetMIRModule()->GetGlobalMemSize()).Emit(", ").Emit("8\n");
2388     }
2389     /* load globalVars profile */
2390     if (globalVars.empty()) {
2391         return;
2392     }
2393     std::unordered_set<std::string> hotVars;
2394     std::ifstream inFile;
2395     if (!CGOptions::IsGlobalVarProFileEmpty()) {
2396         inFile.open(CGOptions::GetGlobalVarProFile());
2397         if (inFile.fail()) {
2398             maple::LogInfo::MapleLogger(kLlErr)
2399                 << "Cannot open globalVar profile file " << CGOptions::GetGlobalVarProFile() << "\n";
2400         }
2401     }
2402     if (CGOptions::IsGlobalVarProFileEmpty() || inFile.fail()) {
2403         for (const auto &globalVarPair : globalVars) {
2404             EmitGlobalVar(*(globalVarPair.first));
2405         }
2406         return;
2407     }
2408     std::string globalVarName;
2409     while (inFile >> globalVarName) {
2410         (void)hotVars.insert(globalVarName);
2411     }
2412     inFile.close();
2413     bool hotBeginSet = false;
2414     bool coldBeginSet = false;
2415     for (auto &globalVarPair : globalVars) {
2416         if (hotVars.find(globalVarPair.first->GetName()) != hotVars.end()) {
2417             if (!hotBeginSet) {
2418                 /* emit hot globalvar start symbol */
2419                 EmitBlockMarker("__MBlock_globalVars_hot_begin", "", true, globalVarPair.first->GetName());
2420                 hotBeginSet = true;
2421             }
2422             EmitGlobalVar(*(globalVarPair.first));
2423             globalVarPair.second = true;
2424         }
2425     }
2426     for (const auto &globalVarPair : globalVars) {
2427         if (!globalVarPair.second) { /* not emit yet */
2428             if (!coldBeginSet) {
2429                 /* emit hot globalvar start symbol */
2430                 EmitBlockMarker("__MBlock_globalVars_cold_begin", "", true, globalVarPair.first->GetName());
2431                 coldBeginSet = true;
2432             }
2433             EmitGlobalVar(*(globalVarPair.first));
2434         }
2435     }
2436     MIRSymbol *endSym = globalVars.back().first;
2437     MIRType *mirType = endSym->GetType();
2438     ASSERT_NOT_NULL(endSym);
2439     ASSERT_NOT_NULL(mirType);
2440     const std::string kStaticVarEndAdd =
2441         std::to_string(Globals::GetInstance()->GetBECommon()->GetTypeSize(mirType->GetTypeIndex())) + "+" +
2442         endSym->GetName();
2443     EmitBlockMarker("__MBlock_globalVars_cold_end", "", true, kStaticVarEndAdd);
2444 }
2445 
EmitUninitializedSymbolsWithPrefixSection(const MIRSymbol & symbol,const std::string & sectionName)2446 void Emitter::EmitUninitializedSymbolsWithPrefixSection(const MIRSymbol &symbol, const std::string &sectionName)
2447 {
2448     EmitAsmLabel(symbol, kAsmType);
2449     Emit(asmInfo->GetSection());
2450     auto sectionConstrains = symbol.IsThreadLocal() ? ",\"awT\"," : ",\"aw\",";
2451     (void)Emit(sectionName).Emit(sectionConstrains);
2452     if (sectionName == ".bss" || StringUtils::StartsWith(sectionName, ".bss.") || sectionName == ".tbss" ||
2453         StringUtils::StartsWith(sectionName, ".tbss.")) {
2454         Emit("%nobits\n");
2455     } else {
2456         Emit("%progbits\n");
2457     }
2458     if (symbol.GetAttr(ATTR_weak)) {
2459         EmitAsmLabel(symbol, kAsmWeak);
2460     } else if (symbol.GetStorageClass() == kScGlobal) {
2461         EmitAsmLabel(symbol, kAsmGlbl);
2462     }
2463     EmitAsmLabel(symbol, kAsmAlign);
2464     EmitAsmLabel(symbol, kAsmSyname);
2465     EmitAsmLabel(symbol, kAsmZero);
2466     EmitAsmLabel(symbol, kAsmSize);
2467 }
2468 
EmitGlobalVariable()2469 void Emitter::EmitGlobalVariable()
2470 {
2471     std::vector<MIRSymbol *> typeStVec;
2472     std::vector<MIRSymbol *> typeNameStVec;
2473     std::map<GStrIdx, MIRType *> strIdx2Type;
2474 
2475     /* Create name2type map which will be used by reflection. */
2476     for (MIRType *type : GlobalTables::GetTypeTable().GetTypeTable()) {
2477         if (type == nullptr || (type->GetKind() != kTypeClass && type->GetKind() != kTypeInterface)) {
2478             continue;
2479         }
2480         GStrIdx strIdx = type->GetNameStrIdx();
2481         strIdx2Type[strIdx] = type;
2482     }
2483 
2484     /* sort symbols; classinfo-->field-->method */
2485     size_t size = GlobalTables::GetGsymTable().GetSymbolTableSize();
2486     std::vector<MIRSymbol *> classInfoVec;
2487     std::vector<MIRSymbol *> vtabVec;
2488     std::vector<MIRSymbol *> staticFieldsVec;
2489     std::vector<std::pair<MIRSymbol *, bool>> globalVarVec;
2490     std::vector<MIRSymbol *> itabVec;
2491     std::vector<MIRSymbol *> itabConflictVec;
2492     std::vector<MIRSymbol *> vtabOffsetVec;
2493     std::vector<MIRSymbol *> fieldOffsetVec;
2494     std::vector<MIRSymbol *> valueOffsetVec;
2495     std::vector<MIRSymbol *> localClassInfoVec;
2496     std::vector<MIRSymbol *> constStrVec;
2497     std::vector<std::pair<MIRSymbol *, bool>> literalVec;
2498     std::vector<MIRSymbol *> muidVec = {nullptr};
2499     std::vector<MIRSymbol *> fieldOffsetDatas;
2500     std::vector<MIRSymbol *> methodAddrDatas;
2501     std::vector<MIRSymbol *> methodSignatureDatas;
2502     std::vector<MIRSymbol *> staticDecoupleKeyVec;
2503     std::vector<MIRSymbol *> staticDecoupleValueVec;
2504     std::vector<MIRSymbol *> superClassStVec;
2505     std::vector<MIRSymbol *> arrayClassCacheVec;
2506     std::vector<MIRSymbol *> arrayClassCacheNameVec;
2507 
2508     for (size_t i = 0; i < size; ++i) {
2509         MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(i);
2510         if (mirSymbol == nullptr || mirSymbol->IsDeleted() || mirSymbol->GetStorageClass() == kScUnused) {
2511             continue;
2512         }
2513         if (mirSymbol->GetSKind() == maple::MIRSymKind::kStFunc) {
2514             EmitAliasAndRef(*mirSymbol);
2515         }
2516 
2517         if (mirSymbol->GetName().find(VTAB_PREFIX_STR) == 0) {
2518             vtabVec.emplace_back(mirSymbol);
2519             continue;
2520         } else if (mirSymbol->GetName().find(ITAB_PREFIX_STR) == 0) {
2521             itabVec.emplace_back(mirSymbol);
2522             continue;
2523         } else if (mirSymbol->GetName().find(ITAB_CONFLICT_PREFIX_STR) == 0) {
2524             itabConflictVec.emplace_back(mirSymbol);
2525             continue;
2526         } else if (mirSymbol->GetName().find(kVtabOffsetTabStr) == 0) {
2527             vtabOffsetVec.emplace_back(mirSymbol);
2528             continue;
2529         } else if (mirSymbol->GetName().find(kFieldOffsetTabStr) == 0) {
2530             fieldOffsetVec.emplace_back(mirSymbol);
2531             continue;
2532         } else if (mirSymbol->GetName().find(kOffsetTabStr) == 0) {
2533             valueOffsetVec.emplace_back(mirSymbol);
2534             continue;
2535         } else if (mirSymbol->IsArrayClassCache()) {
2536             arrayClassCacheVec.emplace_back(mirSymbol);
2537             continue;
2538         } else if (mirSymbol->IsArrayClassCacheName()) {
2539             arrayClassCacheNameVec.emplace_back(mirSymbol);
2540             continue;
2541         } else if (mirSymbol->GetName().find(kLocalClassInfoStr) == 0) {
2542             localClassInfoVec.emplace_back(mirSymbol);
2543             continue;
2544         } else if (StringUtils::StartsWith(mirSymbol->GetName(), namemangler::kDecoupleStaticKeyStr)) {
2545             staticDecoupleKeyVec.emplace_back(mirSymbol);
2546             continue;
2547         } else if (StringUtils::StartsWith(mirSymbol->GetName(), namemangler::kDecoupleStaticValueStr)) {
2548             staticDecoupleValueVec.emplace_back(mirSymbol);
2549             continue;
2550         } else if (mirSymbol->IsLiteral()) {
2551             literalVec.emplace_back(std::make_pair(mirSymbol, false));
2552             continue;
2553         } else if (mirSymbol->IsConstString() || mirSymbol->IsLiteralPtr()) {
2554             MIRConst *mirConst = mirSymbol->GetKonst();
2555             if (mirConst != nullptr && mirConst->GetKind() == kConstAddrof) {
2556                 constStrVec.emplace_back(mirSymbol);
2557                 continue;
2558             }
2559         } else if (mirSymbol->IsReflectionClassInfoPtr()) {
2560             /* _PTR__cinf is emitted in dataDefTab and dataUndefTab */
2561             continue;
2562         } else if (mirSymbol->IsMuidTab()) {
2563             if (!GetCG()->GetMIRModule()->IsCModule()) {
2564                 muidVec[0] = mirSymbol;
2565                 EmitMuidTable(muidVec, strIdx2Type, mirSymbol->GetMuidTabName());
2566             }
2567             continue;
2568         } else if (mirSymbol->IsCodeLayoutInfo()) {
2569             if (!GetCG()->GetMIRModule()->IsCModule()) {
2570                 EmitFuncLayoutInfo(*mirSymbol);
2571             }
2572             continue;
2573         } else if (mirSymbol->GetName().find(kStaticFieldNamePrefixStr) == 0) {
2574             staticFieldsVec.emplace_back(mirSymbol);
2575             continue;
2576         } else if (mirSymbol->GetName().find(kGcRootList) == 0) {
2577             EmitGlobalRootList(*mirSymbol);
2578             continue;
2579         } else if (mirSymbol->GetName().find(kFunctionProfileTabPrefixStr) == 0) {
2580             muidVec[0] = mirSymbol;
2581             EmitMuidTable(muidVec, strIdx2Type, kFunctionProfileTabPrefixStr);
2582             continue;
2583         } else if (mirSymbol->IsReflectionFieldOffsetData()) {
2584             fieldOffsetDatas.emplace_back(mirSymbol);
2585             continue;
2586         } else if (mirSymbol->IsReflectionMethodAddrData()) {
2587             methodAddrDatas.emplace_back(mirSymbol);
2588             continue;
2589         } else if (mirSymbol->IsReflectionSuperclassInfo()) {
2590             superClassStVec.emplace_back(mirSymbol);
2591             continue;
2592         } else if (mirSymbol->IsReflectionMethodSignature()) {
2593             methodSignatureDatas.push_back(mirSymbol);
2594             continue;
2595         }
2596 
2597         if (mirSymbol->IsReflectionInfo()) {
2598             if (mirSymbol->IsReflectionClassInfo()) {
2599                 classInfoVec.emplace_back(mirSymbol);
2600             }
2601             continue;
2602         }
2603         /* symbols we do not emit here. */
2604         if (mirSymbol->GetSKind() == maple::MIRSymKind::kStFunc) {
2605             continue;
2606         }
2607         if (mirSymbol->GetStorageClass() == kScTypeInfo) {
2608             typeStVec.emplace_back(mirSymbol);
2609             continue;
2610         }
2611         if (mirSymbol->GetStorageClass() == kScTypeInfoName) {
2612             typeNameStVec.emplace_back(mirSymbol);
2613             continue;
2614         }
2615         if (mirSymbol->GetStorageClass() == kScTypeCxxAbi) {
2616             continue;
2617         }
2618 
2619         MIRType *mirType = mirSymbol->GetType();
2620         if (mirType == nullptr) {
2621             continue;
2622         }
2623         if (GetCG()->GetMIRModule()->IsCModule() && mirSymbol->GetStorageClass() == kScExtern) {
2624             /* only emit weak & initialized extern at present */
2625             if (mirSymbol->IsWeak() || mirSymbol->IsConst()) {
2626                 EmitAsmLabel(*mirSymbol, kAsmWeak);
2627             } else {
2628                 continue;
2629             }
2630         }
2631         /*
2632          * emit uninitialized global/static variables.
2633          * these variables store in .comm section.
2634          */
2635         if ((mirSymbol->GetStorageClass() == kScGlobal || mirSymbol->GetStorageClass() == kScFstatic) &&
2636             !mirSymbol->IsConst()) {
2637             if (mirSymbol->IsGctibSym()) {
2638                 /* GCTIB symbols are generated in GenerateObjectMaps */
2639                 continue;
2640             }
2641             if (mirSymbol->GetStorageClass() != kScGlobal) {
2642                 globalVarVec.emplace_back(std::make_pair(mirSymbol, false));
2643                 continue;
2644             }
2645             if (mirSymbol->sectionAttr != UStrIdx(0)) {
2646                 auto &sectionName = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol->sectionAttr);
2647                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, sectionName);
2648                 continue;
2649             } else if (mirSymbol->IsThreadLocal()) {
2650                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, ".tbss");
2651                 continue;
2652             } else if (CGOptions::IsNoCommon() ||
2653                        (!CGOptions::IsNoCommon() && mirSymbol->GetAttr(ATTR_static_init_zero))) {
2654                 EmitUninitializedSymbolsWithPrefixSection(*mirSymbol, ".bss");
2655                 continue;
2656             }
2657             EmitAsmLabel(*mirSymbol, kAsmType);
2658             EmitAsmLabel(*mirSymbol, kAsmComm);
2659             continue;
2660         }
2661 
2662         /* emit initialized global/static variables. */
2663         if (mirSymbol->GetStorageClass() == kScGlobal ||
2664             (mirSymbol->GetStorageClass() == kScExtern && GetCG()->GetMIRModule()->IsCModule()) ||
2665             (mirSymbol->GetStorageClass() == kScFstatic && !mirSymbol->IsReadOnly())) {
2666             /* Emit section */
2667             EmitAsmLabel(*mirSymbol, kAsmType);
2668             if (mirSymbol->IsReflectionStrTab()) {
2669                 std::string sectionName = ".reflection_strtab";
2670                 if (mirSymbol->GetName().find(kReflectionStartHotStrtabPrefixStr) == 0) {
2671                     sectionName = ".reflection_start_hot_strtab";
2672                 } else if (mirSymbol->GetName().find(kReflectionBothHotStrTabPrefixStr) == 0) {
2673                     sectionName = ".reflection_both_hot_strtab";
2674                 } else if (mirSymbol->GetName().find(kReflectionRunHotStrtabPrefixStr) == 0) {
2675                     sectionName = ".reflection_run_hot_strtab";
2676                 }
2677                 Emit("\t.section\t" + sectionName + ",\"a\",%progbits\n");
2678             } else if (mirSymbol->GetName().find(kDecoupleOption) == 0) {
2679                 Emit("\t.section\t." + std::string(kDecoupleStr) + ",\"a\",%progbits\n");
2680             } else if (mirSymbol->IsRegJNITab()) {
2681                 Emit("\t.section\t.reg_jni_tab,\"a\", %progbits\n");
2682             } else if (mirSymbol->GetName().find(kCompilerVersionNum) == 0) {
2683                 Emit("\t.section\t." + std::string(kCompilerVersionNumStr) + ",\"a\", %progbits\n");
2684             } else if (mirSymbol->GetName().find(kSourceMuid) == 0) {
2685                 Emit("\t.section\t." + std::string(kSourceMuidSectionStr) + ",\"a\", %progbits\n");
2686             } else if (mirSymbol->GetName().find(kCompilerMfileStatus) == 0) {
2687                 Emit("\t.section\t." + std::string(kCompilerMfileStatus) + ",\"a\", %progbits\n");
2688             } else if (mirSymbol->IsRegJNIFuncTab()) {
2689                 Emit("\t.section\t.reg_jni_func_tab,\"aw\", %progbits\n");
2690             } else if (mirSymbol->IsReflectionPrimitiveClassInfo()) {
2691                 Emit("\t.section\t.primitive_classinfo,\"awG\", %progbits,__primitive_classinfo__,comdat\n");
2692             } else if (mirSymbol->IsReflectionHashTabBucket()) {
2693                 std::string stName = mirSymbol->GetName();
2694                 const std::string delimiter = "$$";
2695                 if (stName.find(delimiter) == std::string::npos) {
2696                     FATAL(kLncFatal, "Can not find delimiter in target ");
2697                 }
2698                 std::string secName = stName.substr(0, stName.find(delimiter));
2699                 /* remove leading "__" in sec name. */
2700                 secName.erase(0, 2);  // remove 2 chars "__"
2701                 Emit("\t.section\t." + secName + ",\"a\",%progbits\n");
2702             } else {
2703                 bool isThreadLocal = mirSymbol->IsThreadLocal();
2704                 if (mirSymbol->sectionAttr != UStrIdx(0)) {
2705                     auto &sectionName = GlobalTables::GetUStrTable().GetStringFromStrIdx(mirSymbol->sectionAttr);
2706                     auto sectionConstrains = isThreadLocal ? ",\"awT\"," : ",\"aw\",";
2707                     (void)Emit("\t.section\t" + sectionName + sectionConstrains + "@progbits\n");
2708                 } else if (isThreadLocal) {
2709                     (void)Emit("\t.section\t.tdata,\"awT\",@progbits\n");
2710                 } else {
2711                     (void)Emit("\t.data\n");
2712                 }
2713             }
2714             /* Emit size and align by type */
2715             if (mirSymbol->GetStorageClass() == kScGlobal) {
2716                 if (mirSymbol->GetAttr(ATTR_weak) || mirSymbol->IsReflectionPrimitiveClassInfo()) {
2717                     EmitAsmLabel(*mirSymbol, kAsmWeak);
2718                 } else {
2719                     EmitAsmLabel(*mirSymbol, kAsmGlbl);
2720                 }
2721             } else if (mirSymbol->GetStorageClass() == kScFstatic) {
2722                 if (mirSymbol->sectionAttr == UStrIdx(0)) {
2723                     EmitAsmLabel(*mirSymbol, kAsmLocal);
2724                 }
2725             }
2726             if (mirSymbol->IsReflectionStrTab()) { /* reflection-string-tab also aligned to 8B boundaries. */
2727                 Emit(asmInfo->GetAlign());
2728                 if (GetCG()->GetTargetMachine()->isX8664()) {
2729                     Emit("8\n");
2730                 } else {
2731                     Emit("3\n");
2732                 }
2733             } else {
2734                 EmitAsmLabel(*mirSymbol, kAsmAlign);
2735             }
2736             EmitAsmLabel(*mirSymbol, kAsmSyname);
2737             MIRConst *mirConst = mirSymbol->GetKonst();
2738             if (IsPrimitiveVector(mirType->GetPrimType())) {
2739                 EmitVectorConstant(*mirConst);
2740             } else if (IsPrimitiveScalar(mirType->GetPrimType())) {
2741                 if (!CGOptions::IsArm64ilp32()) {
2742                     if (IsAddress(mirType->GetPrimType())) {
2743                         uint32 sizeinbits = GetPrimTypeBitSize(mirConst->GetType().GetPrimType());
2744                         CHECK_FATAL(sizeinbits == k64BitSize, "EmitGlobalVariable: pointer must be of size 8");
2745                     }
2746                 }
2747                 if (cg->GetMIRModule()->IsCModule()) {
2748                     EmitScalarConstant(*mirConst, true, false, true);
2749                 } else {
2750                     EmitScalarConstant(*mirConst);
2751                 }
2752             } else if (mirType->GetKind() == kTypeArray) {
2753                 if (mirSymbol->HasAddrOfValues()) {
2754                     EmitConstantTable(*mirSymbol, *mirConst, strIdx2Type);
2755                 } else {
2756                     EmitArrayConstant(*mirConst);
2757                 }
2758             } else if (mirType->GetKind() == kTypeStruct || mirType->GetKind() == kTypeClass ||
2759                        mirType->GetKind() == kTypeUnion) {
2760                 if (mirSymbol->HasAddrOfValues()) {
2761                     EmitConstantTable(*mirSymbol, *mirConst, strIdx2Type);
2762                 } else {
2763                     EmitStructConstant(*mirConst);
2764                 }
2765             } else {
2766                 DEBUG_ASSERT(false, "NYI");
2767             }
2768             EmitAsmLabel(*mirSymbol, kAsmSize);
2769             /* emit constant float/double */
2770         } else if (mirSymbol->IsReadOnly()) {
2771             MIRConst *mirConst = mirSymbol->GetKonst();
2772             if (mirConst->GetKind() == maple::kConstStrConst) {
2773                 auto strCt = static_cast<MIRStrConst *>(mirConst);
2774                 localStrPtr.push_back(strCt->GetValue());
2775             } else {
2776                 EmitAsmLabel(*mirSymbol, kAsmType);
2777                 (void)Emit(asmInfo->GetSection()).Emit(asmInfo->GetRodata()).Emit("\n");
2778                 if (!CGOptions::OptimizeForSize()) {
2779                     EmitAsmLabel(*mirSymbol, kAsmAlign);
2780                 }
2781                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2782                 EmitScalarConstant(*mirConst);
2783             }
2784         } else if (mirSymbol->GetStorageClass() == kScPstatic) {
2785             EmitAsmLabel(*mirSymbol, kAsmType);
2786             Emit(asmInfo->GetSection());
2787             Emit(asmInfo->GetData());
2788             Emit("\n");
2789             EmitAsmLabel(*mirSymbol, kAsmAlign);
2790             EmitAsmLabel(*mirSymbol, kAsmLocal);
2791             MIRConst *ct = mirSymbol->GetKonst();
2792             if (ct == nullptr) {
2793                 EmitAsmLabel(*mirSymbol, kAsmComm);
2794             } else if (IsPrimitiveScalar(mirType->GetPrimType())) {
2795                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2796                 EmitScalarConstant(*ct, true, false, true);
2797             } else if (kTypeArray == mirType->GetKind()) {
2798                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2799                 EmitArrayConstant(*ct);
2800             } else if (kTypeStruct == mirType->GetKind() || kTypeClass == mirType->GetKind() ||
2801                        kTypeUnion == mirType->GetKind()) {
2802                 EmitAsmLabel(*mirSymbol, kAsmSyname);
2803                 EmitStructConstant(*ct);
2804             } else {
2805                 CHECK_FATAL(0, "Unknown type in Global pstatic");
2806             }
2807         }
2808     } /* end proccess all mirSymbols. */
2809     EmitStringPointers();
2810     /* emit global var */
2811     EmitGlobalVars(globalVarVec);
2812     /* emit literal std::strings */
2813     EmitLiterals(literalVec, strIdx2Type);
2814     /* emit static field std::strings */
2815     EmitStaticFields(staticFieldsVec);
2816 
2817     if (GetCG()->GetMIRModule()->IsCModule()) {
2818         return;
2819     }
2820 
2821     EmitMuidTable(constStrVec, strIdx2Type, kMuidConststrPrefixStr);
2822 
2823     /* emit classinfo, field, method */
2824     std::vector<MIRSymbol *> fieldInfoStVec;
2825     std::vector<MIRSymbol *> fieldInfoStCompactVec;
2826     std::vector<MIRSymbol *> methodInfoStVec;
2827     std::vector<MIRSymbol *> methodInfoStCompactVec;
2828 
2829     std::string sectionName = kMuidClassMetadataPrefixStr;
2830     Emit("\t.section ." + sectionName + ",\"aw\",%progbits\n");
2831     Emit(sectionName + "_begin:\n");
2832 
2833     for (size_t i = 0; i < classInfoVec.size(); ++i) {
2834         MIRSymbol *mirSymbol = classInfoVec[i];
2835         if (mirSymbol != nullptr && mirSymbol->GetKonst() != nullptr && mirSymbol->IsReflectionClassInfo()) {
2836             /* Emit classinfo */
2837             EmitClassInfoSequential(*mirSymbol, strIdx2Type, sectionName);
2838             std::string stName = mirSymbol->GetName();
2839             std::string className = stName.substr(strlen(CLASSINFO_PREFIX_STR));
2840             /* Get classinfo ro symbol */
2841             MIRSymbol *classInfoROSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2842                 GlobalTables::GetStrTable().GetStrIdxFromName(CLASSINFO_RO_PREFIX_STR + className));
2843             EmitClassInfoSequential(*classInfoROSt, strIdx2Type, sectionName);
2844             /* Get fields */
2845             MIRSymbol *fieldSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2846                 GlobalTables::GetStrTable().GetStrIdxFromName(kFieldsInfoPrefixStr + className));
2847             MIRSymbol *fieldStCompact = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2848                 GlobalTables::GetStrTable().GetStrIdxFromName(kFieldsInfoCompactPrefixStr + className));
2849             /* Get methods */
2850             MIRSymbol *methodSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2851                 GlobalTables::GetStrTable().GetStrIdxFromName(kMethodsInfoPrefixStr + className));
2852             MIRSymbol *methodStCompact = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
2853                 GlobalTables::GetStrTable().GetStrIdxFromName(kMethodsInfoCompactPrefixStr + className));
2854 
2855             if (fieldSt != nullptr) {
2856                 fieldInfoStVec.emplace_back(fieldSt);
2857             }
2858             if (fieldStCompact != nullptr) {
2859                 fieldInfoStCompactVec.emplace_back(fieldStCompact);
2860             }
2861             if (methodSt != nullptr) {
2862                 methodInfoStVec.emplace_back(methodSt);
2863             }
2864             if (methodStCompact != nullptr) {
2865                 methodInfoStCompactVec.emplace_back(methodStCompact);
2866             }
2867         }
2868     }
2869     Emit(sectionName + "_end:\n");
2870 
2871     std::vector<MIRSymbol *> hotVtabStVec;
2872     std::vector<MIRSymbol *> coldVtabStVec;
2873     std::vector<MIRSymbol *> hotItabStVec;
2874     std::vector<MIRSymbol *> coldItabStVec;
2875     std::vector<MIRSymbol *> hotItabCStVec;
2876     std::vector<MIRSymbol *> coldItabCStVec;
2877     std::vector<MIRSymbol *> hotMethodsInfoCStVec;
2878     std::vector<MIRSymbol *> coldMethodsInfoCStVec;
2879     std::vector<MIRSymbol *> hotFieldsInfoCStVec;
2880     std::vector<MIRSymbol *> coldFieldsInfoCStVec;
2881     GetHotAndColdMetaSymbolInfo(vtabVec, hotVtabStVec, coldVtabStVec, VTAB_PREFIX_STR,
2882                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2883     GetHotAndColdMetaSymbolInfo(itabVec, hotItabStVec, coldItabStVec, ITAB_PREFIX_STR,
2884                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2885     GetHotAndColdMetaSymbolInfo(itabConflictVec, hotItabCStVec, coldItabCStVec, ITAB_CONFLICT_PREFIX_STR,
2886                                 ((CGOptions::IsLazyBinding() || CGOptions::IsHotFix()) && !cg->IsLibcore()));
2887     GetHotAndColdMetaSymbolInfo(fieldInfoStVec, hotFieldsInfoCStVec, coldFieldsInfoCStVec, kFieldsInfoPrefixStr);
2888     GetHotAndColdMetaSymbolInfo(methodInfoStVec, hotMethodsInfoCStVec, coldMethodsInfoCStVec, kMethodsInfoPrefixStr);
2889 
2890     std::string sectionNameIsEmpty;
2891     std::string fieldSectionName("rometadata.field");
2892     std::string methodSectionName("rometadata.method");
2893 
2894     /* fieldinfo */
2895     EmitMetaDataSymbolWithMarkFlag(hotFieldsInfoCStVec, strIdx2Type, kFieldsInfoPrefixStr, fieldSectionName, true);
2896     EmitMetaDataSymbolWithMarkFlag(coldFieldsInfoCStVec, strIdx2Type, kFieldsInfoPrefixStr, fieldSectionName, false);
2897     EmitMetaDataSymbolWithMarkFlag(fieldInfoStCompactVec, strIdx2Type, kFieldsInfoCompactPrefixStr, fieldSectionName,
2898                                    false);
2899     /* methodinfo */
2900     EmitMetaDataSymbolWithMarkFlag(hotMethodsInfoCStVec, strIdx2Type, kMethodsInfoPrefixStr, methodSectionName, true);
2901     EmitMetaDataSymbolWithMarkFlag(coldMethodsInfoCStVec, strIdx2Type, kMethodsInfoPrefixStr, methodSectionName, false);
2902     EmitMetaDataSymbolWithMarkFlag(methodInfoStCompactVec, strIdx2Type, kMethodsInfoCompactPrefixStr, methodSectionName,
2903                                    false);
2904 
2905     /* itabConflict */
2906     MarkVtabOrItabEndFlag(coldItabCStVec);
2907     EmitMuidTable(hotItabCStVec, strIdx2Type, kMuidItabConflictPrefixStr);
2908     EmitMetaDataSymbolWithMarkFlag(coldItabCStVec, strIdx2Type, ITAB_CONFLICT_PREFIX_STR,
2909                                    kMuidColdItabConflictPrefixStr, false);
2910 
2911     /*
2912      * vtab
2913      * And itab to vtab section
2914      */
2915     for (auto sym : hotItabStVec) {
2916         hotVtabStVec.emplace_back(sym);
2917     }
2918     for (auto sym : coldItabStVec) {
2919         coldVtabStVec.emplace_back(sym);
2920     }
2921     MarkVtabOrItabEndFlag(coldVtabStVec);
2922     EmitMuidTable(hotVtabStVec, strIdx2Type, kMuidVtabAndItabPrefixStr);
2923     EmitMetaDataSymbolWithMarkFlag(coldVtabStVec, strIdx2Type, VTAB_AND_ITAB_PREFIX_STR, kMuidColdVtabAndItabPrefixStr,
2924                                    false);
2925 
2926     /* vtab_offset */
2927     EmitMuidTable(vtabOffsetVec, strIdx2Type, kMuidVtabOffsetPrefixStr);
2928     /* field_offset */
2929     EmitMuidTable(fieldOffsetVec, strIdx2Type, kMuidFieldOffsetPrefixStr);
2930     /* value_offset */
2931     EmitMuidTable(valueOffsetVec, strIdx2Type, kMuidValueOffsetPrefixStr);
2932     /* local clasinfo */
2933     EmitMuidTable(localClassInfoVec, strIdx2Type, kMuidLocalClassInfoStr);
2934     /* Emit decouple static */
2935     EmitMuidTable(staticDecoupleKeyVec, strIdx2Type, kDecoupleStaticKeyStr);
2936     EmitMuidTable(staticDecoupleValueVec, strIdx2Type, kDecoupleStaticValueStr);
2937 
2938     /* super class */
2939     EmitMuidTable(superClassStVec, strIdx2Type, kMuidSuperclassPrefixStr);
2940 
2941     /* field offset rw */
2942     EmitMetaDataSymbolWithMarkFlag(fieldOffsetDatas, strIdx2Type, kFieldOffsetDataPrefixStr, sectionNameIsEmpty, false);
2943     /* method address rw */
2944     EmitMetaDataSymbolWithMarkFlag(methodAddrDatas, strIdx2Type, kMethodAddrDataPrefixStr, sectionNameIsEmpty, false);
2945     /* method address ro */
2946     std::string methodSignatureSectionName("romethodsignature");
2947     EmitMetaDataSymbolWithMarkFlag(methodSignatureDatas, strIdx2Type, kMethodSignaturePrefixStr,
2948                                    methodSignatureSectionName, false);
2949 
2950     /* array class cache table */
2951     EmitMuidTable(arrayClassCacheVec, strIdx2Type, kArrayClassCacheTable);
2952     /* array class cache name table */
2953     EmitMuidTable(arrayClassCacheNameVec, strIdx2Type, kArrayClassCacheNameTable);
2954 
2955 #if !defined(TARGARM32)
2956     /* finally emit __gxx_personality_v0 DW.ref */
2957     if (!cg->GetMIRModule()->IsCModule()) {
2958         EmitDWRef("__mpl_personality_v0");
2959     }
2960 #endif
2961 }
EmitAddressString(const std::string & address)2962 void Emitter::EmitAddressString(const std::string &address)
2963 {
2964 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
2965     EmitAsmLabel(kAsmQuad);
2966     Emit(address);
2967 #else
2968     Emit("\t.word\t" + address);
2969 #endif
2970 }
EmitGlobalRootList(const MIRSymbol & mirSymbol)2971 void Emitter::EmitGlobalRootList(const MIRSymbol &mirSymbol)
2972 {
2973     Emit("\t.section .maple.gcrootsmap").Emit(",\"aw\",%progbits\n");
2974     std::vector<std::string> nameVec;
2975     std::string name = mirSymbol.GetName();
2976     nameVec.emplace_back(name);
2977     nameVec.emplace_back(name + "Size");
2978     bool gcrootsFlag = true;
2979     uint64 vecSize = 0;
2980     for (const auto &gcrootsName : nameVec) {
2981 #if TARGAARCH64 || TARGRISCV64 || TARGX86_64
2982         Emit("\t.type\t" + gcrootsName + ", @object\n" + "\t.p2align 3\n");
2983 #else
2984         Emit("\t.type\t" + gcrootsName + ", %object\n" + "\t.p2align 3\n");
2985 #endif
2986         Emit("\t.global\t" + gcrootsName + "\n");
2987         if (gcrootsFlag) {
2988             Emit(kMuidGlobalRootlistPrefixStr).Emit("_begin:\n");
2989         }
2990         Emit(gcrootsName + ":\n");
2991         if (gcrootsFlag) {
2992             MIRAggConst *aggConst = safe_cast<MIRAggConst>(mirSymbol.GetKonst());
2993             if (aggConst == nullptr) {
2994                 continue;
2995             }
2996             size_t i = 0;
2997             while (i < aggConst->GetConstVec().size()) {
2998                 MIRConst *elemConst = aggConst->GetConstVecItem(i);
2999                 if (elemConst->GetKind() == kConstAddrof) {
3000                     MIRAddrofConst *symAddr = safe_cast<MIRAddrofConst>(elemConst);
3001                     CHECK_FATAL(symAddr != nullptr, "nullptr of symAddr");
3002                     MIRSymbol *symAddrSym =
3003                         GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr->GetSymbolIndex().Idx());
3004                     CHECK_FATAL(symAddrSym != nullptr, "nullptr check");
3005                     const std::string &symAddrName = symAddrSym->GetName();
3006                     EmitAddressString(symAddrName + "\n");
3007                 } else {
3008                     EmitScalarConstant(*elemConst);
3009                 }
3010                 i++;
3011             }
3012             vecSize = i;
3013         } else {
3014             EmitAddressString(std::to_string(vecSize) + "\n");
3015         }
3016         Emit("\t.size\t" + gcrootsName + ",.-").Emit(gcrootsName + "\n");
3017         if (gcrootsFlag) {
3018             Emit(kMuidGlobalRootlistPrefixStr).Emit("_end:\n");
3019         }
3020         gcrootsFlag = false;
3021     }
3022 }
3023 
EmitMuidTable(const std::vector<MIRSymbol * > & vec,const std::map<GStrIdx,MIRType * > & strIdx2Type,const std::string & sectionName)3024 void Emitter::EmitMuidTable(const std::vector<MIRSymbol *> &vec, const std::map<GStrIdx, MIRType *> &strIdx2Type,
3025                             const std::string &sectionName)
3026 {
3027     MIRSymbol *st = nullptr;
3028     if (!vec.empty()) {
3029         st = vec[0];
3030     }
3031     if (st != nullptr && st->IsMuidRoTab()) {
3032         Emit("\t.section  ." + sectionName + ",\"a\",%progbits\n");
3033     } else {
3034         Emit("\t.section  ." + sectionName + ",\"aw\",%progbits\n");
3035     }
3036     Emit(sectionName + "_begin:\n");
3037     bool isConstString = sectionName == kMuidConststrPrefixStr;
3038     for (size_t i = 0; i < vec.size(); i++) {
3039         MIRSymbol *st1 = vec[i];
3040         DEBUG_ASSERT(st1 != nullptr, "null ptr check");
3041         if (st1->GetStorageClass() == kScUnused) {
3042             continue;
3043         }
3044         EmitAsmLabel(*st1, kAsmType);
3045         if (st1->GetStorageClass() == kScFstatic) {
3046             EmitAsmLabel(*st1, kAsmLocal);
3047         } else {
3048             EmitAsmLabel(*st1, kAsmGlbl);
3049             EmitAsmLabel(*st1, kAsmHidden);
3050         }
3051         EmitAsmLabel(*st1, kAsmAlign);
3052         EmitAsmLabel(*st1, kAsmSyname);
3053         MIRConst *mirConst = st1->GetKonst();
3054         CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitMuidTable");
3055         if (mirConst->GetKind() == kConstAddrof) {
3056             MIRAddrofConst *symAddr = safe_cast<MIRAddrofConst>(mirConst);
3057             CHECK_FATAL(symAddr != nullptr, "call static_cast failed in EmitMuidTable");
3058             MIRSymbol *symAddrSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(symAddr->GetSymbolIndex().Idx());
3059             DEBUG_ASSERT(symAddrSym != nullptr, "null ptr check");
3060             if (isConstString) {
3061                 EmitAddressString(symAddrSym->GetName() + " - . + ");
3062                 Emit(kDataRefIsOffset);
3063                 Emit("\n");
3064             } else {
3065                 EmitAddressString(symAddrSym->GetName() + "\n");
3066             }
3067         } else if (mirConst->GetKind() == kConstInt) {
3068             EmitScalarConstant(*mirConst, true);
3069         } else {
3070             EmitConstantTable(*st1, *mirConst, strIdx2Type);
3071         }
3072         EmitAsmLabel(*st1, kAsmSize);
3073     }
3074     Emit(sectionName + "_end:\n");
3075 }
3076 
EmitClassInfoSequential(const MIRSymbol & mirSymbol,const std::map<GStrIdx,MIRType * > & strIdx2Type,const std::string & sectionName)3077 void Emitter::EmitClassInfoSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
3078                                       const std::string &sectionName)
3079 {
3080     EmitAsmLabel(mirSymbol, kAsmType);
3081     if (!sectionName.empty()) {
3082         Emit("\t.section ." + sectionName);
3083         if (StringUtils::StartsWith(sectionName, "ro")) {
3084             Emit(",\"a\",%progbits\n");
3085         } else {
3086             Emit(",\"aw\",%progbits\n");
3087         }
3088     } else {
3089         EmitAsmLabel(kAsmData);
3090     }
3091     EmitAsmLabel(mirSymbol, kAsmGlbl);
3092     EmitAsmLabel(mirSymbol, kAsmHidden);
3093     EmitAsmLabel(mirSymbol, kAsmAlign);
3094     EmitAsmLabel(mirSymbol, kAsmSyname);
3095     MIRConst *mirConst = mirSymbol.GetKonst();
3096     CHECK_FATAL(mirConst != nullptr, "mirConst should not be nullptr in EmitClassInfoSequential");
3097     EmitConstantTable(mirSymbol, *mirConst, strIdx2Type);
3098     EmitAsmLabel(mirSymbol, kAsmSize);
3099 }
3100 
EmitMethodDeclaringClass(const MIRSymbol & mirSymbol,const std::string & sectionName)3101 void Emitter::EmitMethodDeclaringClass(const MIRSymbol &mirSymbol, const std::string &sectionName)
3102 {
3103     std::string symName = mirSymbol.GetName();
3104     std::string emitSyName = symName + "_DeclaringClass";
3105     std::string declaringClassName = symName.substr(strlen(kFieldsInfoCompactPrefixStr) + 1);
3106     Emit(asmInfo->GetType());
3107     Emit(emitSyName + ", %object\n");
3108     if (!sectionName.empty()) {
3109         Emit("\t.section  ." + sectionName + "\n");
3110     } else {
3111         EmitAsmLabel(kAsmData);
3112     }
3113     Emit(asmInfo->GetLocal());
3114     Emit(emitSyName + "\n");
3115     Emit(asmInfo->GetAlign());
3116     Emit("  2\n" + emitSyName + ":\n");
3117     Emit("\t.long\t");
3118     Emit(CLASSINFO_PREFIX_STR + declaringClassName + " - .\n");
3119     Emit(asmInfo->GetSize());
3120     Emit(emitSyName + ", 4\n");
3121 }
3122 
EmitMethodFieldSequential(const MIRSymbol & mirSymbol,const std::map<GStrIdx,MIRType * > & strIdx2Type,const std::string & sectionName)3123 void Emitter::EmitMethodFieldSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
3124                                         const std::string &sectionName)
3125 {
3126     std::string symName = mirSymbol.GetName();
3127     if (symName.find(kMethodsInfoCompactPrefixStr) != std::string::npos) {
3128         EmitMethodDeclaringClass(mirSymbol, sectionName);
3129     }
3130     EmitAsmLabel(mirSymbol, kAsmType);
3131     if (!sectionName.empty()) {
3132         Emit("\t.section  ." + sectionName + "\n");
3133     } else {
3134         EmitAsmLabel(kAsmData);
3135     }
3136     EmitAsmLabel(mirSymbol, kAsmLocal);
3137 
3138     /* Emit(2) is 4 bit align */
3139     Emit(asmInfo->GetAlign()).Emit(2).Emit("\n");
3140     EmitAsmLabel(mirSymbol, kAsmSyname);
3141     MIRConst *ct = mirSymbol.GetKonst();
3142     EmitConstantTable(mirSymbol, *ct, strIdx2Type);
3143     std::string symbolName = mirSymbol.GetName();
3144     Emit("\t.size\t" + symbolName + ", .-");
3145     Emit(symbolName + "\n");
3146 }
3147 
EmitDWRef(const std::string & name)3148 void Emitter::EmitDWRef(const std::string &name)
3149 {
3150     /*
3151      *   .hidden DW.ref._ZTI3xxx
3152      *   .weak DW.ref._ZTI3xxx
3153      *   .section  .data.DW.ref._ZTI3xxx,"awG",@progbits,DW.ref._ZTI3xxx,comdat
3154      *   .align  3
3155      *   .type DW.ref._ZTI3xxx, %object
3156      *   .size DW.ref._ZTI3xxx, 8
3157      * DW.ref._ZTI3xxx:
3158      *   .xword  _ZTI3xxx
3159      */
3160     Emit("\t.hidden DW.ref." + name + "\n");
3161     Emit("\t.weak DW.ref." + name + "\n");
3162     Emit("\t.section .data.DW.ref." + name + ",\"awG\",%progbits,DW.ref.");
3163     Emit(name + ",comdat\n");
3164     Emit(asmInfo->GetAlign());
3165     if (GetCG()->GetTargetMachine()->isX8664()) {
3166         Emit("8\n");
3167     } else {
3168         Emit("3\n");
3169     }
3170     Emit("\t.type DW.ref." + name + ", \%object\n");
3171     Emit("\t.size DW.ref." + name + ",8\n");
3172     Emit("DW.ref." + name + ":\n");
3173     if (GetCG()->GetTargetMachine()->isAArch64()) {
3174         Emit("\t.xword " + name + "\n");
3175     } else {
3176         Emit("\t.word " + name + "\n");
3177     }
3178 }
3179 
EmitDecSigned(int64 num)3180 void Emitter::EmitDecSigned(int64 num)
3181 {
3182     std::ios::fmtflags flag(outStream.flags());
3183     outStream << std::dec << num;
3184     outStream.flags(flag);
3185 }
3186 
EmitDecUnsigned(uint64 num)3187 void Emitter::EmitDecUnsigned(uint64 num)
3188 {
3189     std::ios::fmtflags flag(outStream.flags());
3190     outStream << std::dec << num;
3191     outStream.flags(flag);
3192 }
3193 
EmitHexUnsigned(uint64 num)3194 void Emitter::EmitHexUnsigned(uint64 num)
3195 {
3196     std::ios::fmtflags flag(outStream.flags());
3197     outStream << "0x" << std::hex << num;
3198     outStream.flags(flag);
3199 }
3200 
3201 #ifndef TARGX86_64
3202 #define XSTR(s) str(s)
3203 #endif
3204 #define str(s) #s
3205 
EmitDIHeader()3206 void Emitter::EmitDIHeader()
3207 {
3208     if (cg->GetMIRModule()->GetSrcLang() == kSrcLangC) {
3209         (void)Emit("\t.section ." + std::string("c_text") + ",\"ax\"\n");
3210     }
3211     Emit(".L" XSTR(TEXT_BEGIN) ":\n");
3212 }
3213 
EmitDIFooter()3214 void Emitter::EmitDIFooter()
3215 {
3216     if (cg->GetMIRModule()->GetSrcLang() == kSrcLangC) {
3217         (void)Emit("\t.section ." + std::string("c_text") + ",\"ax\"\n");
3218     }
3219     Emit(".L" XSTR(TEXT_END) ":\n");
3220 }
3221 
EmitDIHeaderFileInfo()3222 void Emitter::EmitDIHeaderFileInfo()
3223 {
3224     Emit("// dummy header file 1\n");
3225     Emit("// dummy header file 2\n");
3226     Emit("// dummy header file 3\n");
3227 }
3228 
AddLabelDieToLabelIdxMapping(DBGDie * lblDie,LabelIdx lblIdx)3229 void Emitter::AddLabelDieToLabelIdxMapping(DBGDie *lblDie, LabelIdx lblIdx)
3230 {
3231     InsertLabdie2labidxTable(lblDie, lblIdx);
3232 }
3233 
GetLabelIdxForLabelDie(DBGDie * lblDie)3234 LabelIdx Emitter::GetLabelIdxForLabelDie(DBGDie *lblDie)
3235 {
3236     auto it = labdie2labidxTable.find(lblDie);
3237     CHECK_FATAL(it != labdie2labidxTable.end(), "");
3238     return it->second;
3239 }
3240 
ApplyInPrefixOrder(DBGDie * die,const std::function<void (DBGDie *)> & func)3241 void Emitter::ApplyInPrefixOrder(DBGDie *die, const std::function<void(DBGDie *)> &func)
3242 {
3243     func(die);
3244     DEBUG_ASSERT(die, "");
3245     if (die->GetSubDieVec().size() > 0) {
3246         for (auto c : die->GetSubDieVec()) {
3247             ApplyInPrefixOrder(c, func);
3248         }
3249         /* mark the end of the sibling list */
3250         func(nullptr);
3251     }
3252 }
3253 
EmitDIFormSpecification(unsigned int dwform)3254 void Emitter::EmitDIFormSpecification(unsigned int dwform)
3255 {
3256     switch (dwform) {
3257         case DW_FORM_string:
3258             Emit(".string  ");
3259             break;
3260         case DW_FORM_strp:
3261         case DW_FORM_data4:
3262         case DW_FORM_ref4:
3263             Emit(".4byte   ");
3264             break;
3265         case DW_FORM_data1:
3266             Emit(".byte    ");
3267             break;
3268         case DW_FORM_data2:
3269             Emit(".2byte   ");
3270             break;
3271         case DW_FORM_data8:
3272             Emit(".8byte   ");
3273             break;
3274         case DW_FORM_sec_offset:
3275             /* if DWARF64, should be .8byte? */
3276             Emit(".4byte   ");
3277             break;
3278         case DW_FORM_addr: /* Should we use DWARF64? for now, we generate .8byte as gcc does for DW_FORM_addr */
3279             Emit(".8byte   ");
3280             break;
3281         case DW_FORM_exprloc:
3282             Emit(".uleb128 ");
3283             break;
3284         default:
3285             CHECK_FATAL(maple::GetDwFormName(dwform) != nullptr,
3286                         "GetDwFormName() return null in Emitter::EmitDIFormSpecification");
3287             LogInfo::MapleLogger() << "unhandled : " << maple::GetDwFormName(dwform) << std::endl;
3288             DEBUG_ASSERT(0, "NYI");
3289     }
3290 }
3291 
EmitDIAttrValue(DBGDie * die,DBGDieAttr * attr,DwAt attrName,DwTag tagName,DebugInfo * di)3292 void Emitter::EmitDIAttrValue(DBGDie *die, DBGDieAttr *attr, DwAt attrName, DwTag tagName, DebugInfo *di)
3293 {
3294     MapleVector<DBGDieAttr *> &attrvec = die->GetAttrVec();
3295     switch (attr->GetDwForm()) {
3296         case DW_FORM_string: {
3297             const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(attr->GetId());
3298             Emit("\"").Emit(name).Emit("\"");
3299             Emit(CMNT "len = ");
3300             EmitDecUnsigned(name.length() + 1);
3301             break;
3302         }
3303         case DW_FORM_strp:
3304             Emit(".L" XSTR(DEBUG_STR_LABEL));
3305             outStream << attr->GetId();
3306             break;
3307         case DW_FORM_data1:
3308 #if DEBUG
3309             if (static_cast<uint32>(attr->GetI()) == kDbgDefaultVal) {
3310                 EmitHexUnsigned(attr->GetI());
3311             } else
3312 #endif
3313                 EmitHexUnsigned(uint8_t(attr->GetI()));
3314             break;
3315         case DW_FORM_data2:
3316 #if DEBUG
3317             if (static_cast<uint32>(attr->GetI()) == kDbgDefaultVal) {
3318                 EmitHexUnsigned(attr->GetI());
3319             } else
3320 #endif
3321                 EmitHexUnsigned(uint16_t(attr->GetI()));
3322             break;
3323         case DW_FORM_data4:
3324 #if DEBUG
3325             if (static_cast<uint32>(attr->GetI()) == kDbgDefaultVal) {
3326                 EmitHexUnsigned(attr->GetI());
3327             } else
3328 #endif
3329                 EmitHexUnsigned(uint32_t(attr->GetI()));
3330             break;
3331         case DW_FORM_data8:
3332             if (attrName == DW_AT_high_pc) {
3333                 if (tagName == DW_TAG_compile_unit) {
3334                     Emit(".L" XSTR(TEXT_END) "-.L" XSTR(TEXT_BEGIN));
3335                 } else if (tagName == DW_TAG_subprogram) {
3336                     DBGDieAttr *name = LFindAttribute(attrvec, DW_AT_name);
3337                     if (name == nullptr) {
3338                         DBGDieAttr *spec = LFindAttribute(attrvec, DW_AT_specification);
3339                         CHECK_FATAL(spec != nullptr, "spec is null in Emitter::EmitDIAttrValue");
3340                         DBGDie *decl = di->GetDie(spec->GetId());
3341                         name = LFindAttribute(decl->GetAttrVec(), DW_AT_name);
3342                     }
3343                     CHECK_FATAL(name != nullptr, "name is null in Emitter::EmitDIAttrValue");
3344                     const std::string &str = GlobalTables::GetStrTable().GetStringFromStrIdx(name->GetId());
3345 
3346                     MIRBuilder *mirbuilder = GetCG()->GetMIRModule()->GetMIRBuilder();
3347                     MIRFunction *mfunc = mirbuilder->GetFunctionFromName(str);
3348                     MapleMap<MIRFunction *, std::pair<LabelIdx, LabelIdx>>::iterator it =
3349                         CG::GetFuncWrapLabels().find(mfunc);
3350                     if (it != CG::GetFuncWrapLabels().end()) {
3351                         EmitLabelForFunc(mfunc, (*it).second.second); /* end label */
3352                     } else {
3353                         EmitLabelRef(attr->GetId()); /* maybe deadbeef */
3354                     }
3355                     Emit("-");
3356                     if (it != CG::GetFuncWrapLabels().end()) {
3357                         EmitLabelForFunc(mfunc, (*it).second.first); /* start label */
3358                     } else {
3359                         DBGDieAttr *lowpc = LFindAttribute(attrvec, DW_AT_low_pc);
3360                         CHECK_FATAL(lowpc != nullptr, "lowpc is null in Emitter::EmitDIAttrValue");
3361                         EmitLabelRef(lowpc->GetId()); /* maybe deadbeef */
3362                     }
3363                 }
3364             } else {
3365                 EmitHexUnsigned(static_cast<uint64>(static_cast<int64>(attr->GetI())));
3366             }
3367             break;
3368         case DW_FORM_sec_offset:
3369             if (attrName == DW_AT_stmt_list) {
3370                 Emit(".L");
3371                 Emit(XSTR(DEBUG_LINE_0));
3372             }
3373             break;
3374         case DW_FORM_addr:
3375             if (attrName == DW_AT_low_pc) {
3376                 if (tagName == DW_TAG_compile_unit) {
3377                     Emit(".L" XSTR(TEXT_BEGIN));
3378                 } else if (tagName == DW_TAG_subprogram) {
3379                     /* if decl, name should be found; if def, we try DW_AT_specification */
3380                     DBGDieAttr *name = LFindAttribute(attrvec, DW_AT_name);
3381                     if (name == nullptr) {
3382                         DBGDieAttr *spec = LFindAttribute(attrvec, DW_AT_specification);
3383                         CHECK_FATAL(spec != nullptr, "spec is null in Emitter::EmitDIAttrValue");
3384                         DBGDie *decl = di->GetDie(spec->GetId());
3385                         name = LFindAttribute(decl->GetAttrVec(), DW_AT_name);
3386                     }
3387                     CHECK_FATAL(name != nullptr, "name is null in Emitter::EmitDIAttrValue");
3388                     const std::string &str = GlobalTables::GetStrTable().GetStringFromStrIdx(name->GetId());
3389                     MIRBuilder *mirbuilder = GetCG()->GetMIRModule()->GetMIRBuilder();
3390                     MIRFunction *mfunc = mirbuilder->GetFunctionFromName(str);
3391                     MapleMap<MIRFunction *, std::pair<LabelIdx, LabelIdx>>::iterator it =
3392                         CG::GetFuncWrapLabels().find(mfunc);
3393                     if (it != CG::GetFuncWrapLabels().end()) {
3394                         EmitLabelForFunc(mfunc, (*it).second.first); /* it is a <pair> */
3395                     } else {
3396                         EmitLabelRef(attr->GetId()); /* maybe deadbeef */
3397                     }
3398                 } else if (tagName == DW_TAG_label) {
3399                     LabelIdx labelIdx = GetLabelIdxForLabelDie(die);
3400                     DBGDie *subpgm = die->GetParent();
3401                     DEBUG_ASSERT(subpgm->GetTag() == DW_TAG_subprogram,
3402                                  "Label DIE should be a child of a Subprogram DIE");
3403                     DBGDieAttr *fnameAttr = LFindAttribute(subpgm->GetAttrVec(), DW_AT_name);
3404                     if (!fnameAttr) {
3405                         DBGDieAttr *specAttr = LFindAttribute(subpgm->GetAttrVec(), DW_AT_specification);
3406                         CHECK_FATAL(specAttr, "pointer is null");
3407                         DBGDie *twin = di->GetDie(static_cast<uint32>(specAttr->GetU()));
3408                         fnameAttr = LFindAttribute(twin->GetAttrVec(), DW_AT_name);
3409                     }
3410                     CHECK_FATAL(fnameAttr, "");
3411                     const std::string &fnameStr = GlobalTables::GetStrTable().GetStringFromStrIdx(fnameAttr->GetId());
3412                     auto *res = memPool->New<cfi::LabelOperand>(fnameStr.c_str(), labelIdx, *memPool);
3413                     cfi::CFIOpndEmitVisitor cfiVisitor(*this);
3414                     res->Accept(cfiVisitor);
3415                 }
3416             } else if (attrName == DW_AT_high_pc) {
3417                 if (tagName == DW_TAG_compile_unit) {
3418                     Emit(".L" XSTR(TEXT_END) "-.L" XSTR(TEXT_BEGIN));
3419                 }
3420             } else {
3421                 Emit("XXX--ADDR--XXX");
3422             }
3423             break;
3424         case DW_FORM_ref4:
3425             if (attrName == DW_AT_type) {
3426                 DBGDie *die0 = di->GetDie(static_cast<uint32>(attr->GetU()));
3427                 if (die0->GetOffset()) {
3428                     EmitHexUnsigned(die0->GetOffset());
3429                 } else {
3430                     /* unknown type, missing mplt */
3431                     EmitHexUnsigned(di->GetDummyTypeDie()->GetOffset());
3432                     Emit(CMNT "Warning: dummy type used");
3433                 }
3434             } else if (attrName == DW_AT_specification || attrName == DW_AT_sibling) {
3435                 DBGDie *die0 = di->GetDie(static_cast<uint32>(attr->GetU()));
3436                 DEBUG_ASSERT(die0->GetOffset(), "");
3437                 EmitHexUnsigned(die0->GetOffset());
3438             } else if (attrName == DW_AT_object_pointer) {
3439                 GStrIdx thisIdx = GlobalTables::GetStrTable().GetStrIdxFromName(kDebugMapleThis);
3440                 DBGDie *that = LFindChildDieWithName(die, DW_TAG_formal_parameter, thisIdx);
3441                 /* need to find the this or self based on the source language
3442                    what is the name for 'this' used in mapleir?
3443                    this has to be with respect to a function */
3444                 if (that) {
3445                     EmitHexUnsigned(that->GetOffset());
3446                 } else {
3447                     EmitHexUnsigned(attr->GetU());
3448                 }
3449             } else {
3450                 Emit(" OFFSET ");
3451                 EmitHexUnsigned(attr->GetU());
3452             }
3453             break;
3454         case DW_FORM_exprloc: {
3455             DBGExprLoc *elp = attr->GetPtr();
3456             switch (elp->GetOp()) {
3457                 case DW_OP_call_frame_cfa:
3458                     EmitHexUnsigned(1);
3459                     Emit("\n\t.byte    ");
3460                     EmitHexUnsigned(elp->GetOp());
3461                     break;
3462                 case DW_OP_addr:
3463                     EmitHexUnsigned(k9ByteSize);
3464                     Emit("\n\t.byte    ");
3465                     EmitHexUnsigned(elp->GetOp());
3466                     Emit("\n\t.8byte   ");
3467                     (void)Emit(GlobalTables::GetStrTable().GetStringFromStrIdx(
3468                         static_cast<uint32>(elp->GetGvarStridx())).c_str());
3469                     break;
3470                 case DW_OP_fbreg:
3471                     EmitHexUnsigned(1 + namemangler::GetSleb128Size(elp->GetFboffset()));
3472                     Emit("\n\t.byte    ");
3473                     EmitHexUnsigned(elp->GetOp());
3474                     Emit("\n\t.sleb128 ");
3475                     EmitDecSigned(elp->GetFboffset());
3476                     break;
3477                 default:
3478                     EmitHexUnsigned(uintptr_t(elp));
3479                     break;
3480             }
3481             break;
3482         }
3483         default:
3484             CHECK_FATAL(maple::GetDwFormName(attr->GetDwForm()) != nullptr,
3485                         "GetDwFormName return null in Emitter::EmitDIAttrValue");
3486             LogInfo::MapleLogger() << "unhandled : " << maple::GetDwFormName(attr->GetDwForm()) << std::endl;
3487             DEBUG_ASSERT(0, "NYI");
3488     }
3489 }
3490 
EmitDIDebugInfoSection(DebugInfo * mirdi)3491 void Emitter::EmitDIDebugInfoSection(DebugInfo *mirdi)
3492 {
3493     /* From DWARF Standard Specification V4. 7.5.1
3494        collect section size */
3495     Emit("\t.section\t.debug_info,\"\",@progbits\n");
3496     /* label to mark start of the .debug_info section */
3497     Emit(".L" XSTR(DEBUG_INFO_0) ":\n");
3498     /* $ 7.5.1.1 */
3499     Emit("\t.4byte\t");
3500     EmitHexUnsigned(mirdi->GetDebugInfoLength());
3501     Emit(CMNT "section length\n");
3502     /* DWARF version. uhalf. */
3503     Emit("\t.2byte\t");
3504     /* 4 for version 4. */
3505     EmitHexUnsigned(kDwarfVersion);
3506     Emit("\n");
3507     /* debug_abbrev_offset. 4byte for 32-bit, 8byte for 64-bit */
3508     Emit("\t.4byte\t.L" XSTR(DEBUG_ABBREV_0) "\n");
3509     /* address size. ubyte */
3510     Emit("\t.byte\t");
3511     EmitHexUnsigned(kSizeOfPTR);
3512     Emit("\n");
3513     /*
3514      * 7.5.1.2 type unit header
3515      * currently empty...
3516      *
3517      * 7.5.2 Debugging Information Entry (DIE)
3518      */
3519     Emitter *emitter = this;
3520     MapleVector<DBGAbbrevEntry *> &abbrevVec = mirdi->GetAbbrevVec();
3521     ApplyInPrefixOrder(mirdi->GetCompUnit(), [&abbrevVec, &emitter, &mirdi](DBGDie *die) {
3522         if (!die) {
3523             /* emit the null entry and return */
3524             emitter->Emit("\t.byte    0x0\n");
3525             return;
3526         }
3527         bool verbose = emitter->GetCG()->GenerateVerboseAsm();
3528         if (verbose) {
3529             emitter->Emit("\n");
3530         }
3531         emitter->Emit("\t.uleb128 ");
3532         emitter->EmitHexUnsigned(die->GetAbbrevId());
3533         if (verbose) {
3534             emitter->Emit(CMNT);
3535             CHECK_FATAL(maple::GetDwTagName(die->GetTag()) != nullptr,
3536                         "GetDwTagName(die->GetTag()) return null in Emitter::EmitDIDebugInfoSection");
3537             emitter->Emit(maple::GetDwTagName(die->GetTag()));
3538             emitter->Emit(" Offset= ");
3539             emitter->EmitHexUnsigned(die->GetOffset());
3540             emitter->Emit(" (");
3541             emitter->EmitDecUnsigned(die->GetOffset());
3542             emitter->Emit(" ),  Size= ");
3543             emitter->EmitHexUnsigned(die->GetSize());
3544             emitter->Emit(" (");
3545             emitter->EmitDecUnsigned(die->GetSize());
3546             emitter->Emit(" )\n");
3547         } else {
3548             emitter->Emit("\n");
3549         }
3550         DBGAbbrevEntry *diae = LFindAbbrevEntry(abbrevVec, die->GetAbbrevId());
3551         CHECK_FATAL(diae != nullptr, "diae is null in Emitter::EmitDIDebugInfoSection");
3552         MapleVector<uint32> &apl = diae->GetAttrPairs(); /* attribute pair list */
3553 
3554         std::string sfile, spath;
3555         if (diae->GetTag() == DW_TAG_compile_unit && sfile.empty()) {
3556             /* get full source path from fileMap[2] */
3557             if (emitter->GetFileMap().size() > k2ByteSize) { /* have src file map */
3558                 std::string srcPath = emitter->GetFileMap()[k2ByteSize];
3559                 size_t t = srcPath.rfind("/");
3560                 DEBUG_ASSERT(t != std::string::npos, "");
3561                 sfile = srcPath.substr(t + 1);
3562                 spath = srcPath.substr(0, t);
3563             }
3564         }
3565 
3566         for (size_t i = 0; i < diae->GetAttrPairs().size(); i += k2ByteSize) {
3567             DBGDieAttr *attr = LFindAttribute(die->GetAttrVec(), DwAt(apl[i]));
3568             DEBUG_ASSERT(attr != nullptr, "null ptr check");
3569             if (!LShouldEmit(unsigned(apl[i + 1]))) {
3570                 continue;
3571             }
3572             /* update DW_AT_name and DW_AT_comp_dir attrs under DW_TAG_compile_unit
3573                to be C/C++ */
3574             if (!sfile.empty()) {
3575                 if (attr->GetDwAt() == DW_AT_name) {
3576                     attr->SetId(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(sfile).GetIdx());
3577                     emitter->GetCG()->GetMIRModule()->GetDbgInfo()->AddStrps(attr->GetId());
3578                 } else if (attr->GetDwAt() == DW_AT_comp_dir) {
3579                     attr->SetId(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(spath).GetIdx());
3580                     emitter->GetCG()->GetMIRModule()->GetDbgInfo()->AddStrps(attr->GetId());
3581                 }
3582             }
3583             emitter->Emit("\t");
3584             emitter->EmitDIFormSpecification(unsigned(apl[i + 1]));
3585             emitter->EmitDIAttrValue(die, attr, unsigned(apl[i]), diae->GetTag(), mirdi);
3586             if (verbose) {
3587                 emitter->Emit(CMNT);
3588                 emitter->Emit(maple::GetDwAtName(unsigned(apl[i])));
3589                 emitter->Emit(" : ");
3590                 emitter->Emit(maple::GetDwFormName(unsigned(apl[i + 1])));
3591                 if (apl[i + 1] == DW_FORM_strp || apl[i + 1] == DW_FORM_string) {
3592                     emitter->Emit(" : ");
3593                     emitter->Emit(GlobalTables::GetStrTable().GetStringFromStrIdx(attr->GetId()).c_str());
3594                 } else if (apl[i] == DW_AT_data_member_location) {
3595                     emitter->Emit(" : ");
3596                     emitter->Emit(apl[i + 1]).Emit("  attr= ");
3597                     emitter->EmitHexUnsigned(uintptr_t(attr));
3598                 }
3599             }
3600             emitter->Emit("\n");
3601         }
3602     });
3603 }
3604 
EmitDIDebugAbbrevSection(DebugInfo * mirdi)3605 void Emitter::EmitDIDebugAbbrevSection(DebugInfo *mirdi)
3606 {
3607     Emit("\t.section\t.debug_abbrev,\"\",@progbits\n");
3608     Emit(".L" XSTR(DEBUG_ABBREV_0) ":\n");
3609 
3610     /* construct a list of DI abbrev entries
3611        1. DW_TAG_compile_unit 0x11
3612        2. DW_TAG_subprogram   0x2e */
3613     bool verbose = GetCG()->GenerateVerboseAsm();
3614     for (DBGAbbrevEntry *diae : mirdi->GetAbbrevVec()) {
3615         if (!diae) {
3616             continue;
3617         }
3618         /* ID */
3619         if (verbose) {
3620             Emit("\n");
3621         }
3622         Emit("\t.uleb128 ");
3623         EmitHexUnsigned(diae->GetAbbrevId());
3624         if (verbose) {
3625             Emit(CMNT "Abbrev Entry ID");
3626         }
3627         Emit("\n");
3628         /* TAG */
3629         Emit("\t.uleb128 ");
3630         EmitHexUnsigned(diae->GetTag());
3631         CHECK_FATAL(maple::GetDwTagName(diae->GetTag()) != nullptr,
3632                     "GetDwTagName return null in Emitter::EmitDIDebugAbbrevSection");
3633         if (verbose) {
3634             Emit(CMNT);
3635             Emit(maple::GetDwTagName(diae->GetTag()));
3636         }
3637         Emit("\n");
3638 
3639         MapleVector<uint32> &apl = diae->GetAttrPairs(); /* attribute pair list */
3640         /* children? */
3641         Emit("\t.byte    ");
3642         EmitHexUnsigned(diae->GetWithChildren());
3643         if (verbose) {
3644             Emit(diae->GetWithChildren() ? CMNT "DW_CHILDREN_yes" : CMNT "DW_CHILDREN_no");
3645         }
3646         Emit("\n");
3647 
3648         for (size_t i = 0; i < diae->GetAttrPairs().size(); i += k2ByteSize) {
3649             /* odd entry -- DW_AT_*, even entry -- DW_FORM_* */
3650             Emit("\t.uleb128 ");
3651             EmitHexUnsigned(apl[i]);
3652             CHECK_FATAL(maple::GetDwAtName(unsigned(apl[i])) != nullptr,
3653                         "GetDwAtName return null in Emitter::EmitDIDebugAbbrevSection");
3654             if (verbose) {
3655                 Emit(CMNT);
3656                 Emit(maple::GetDwAtName(unsigned(apl[i])));
3657             }
3658             Emit("\n");
3659             Emit("\t.uleb128 ");
3660             EmitHexUnsigned(apl[i + 1]);
3661             CHECK_FATAL(maple::GetDwFormName(unsigned(apl[i + 1])) != nullptr,
3662                         "GetDwFormName return null in Emitter::EmitDIDebugAbbrevSection");
3663             if (verbose) {
3664                 Emit(CMNT);
3665                 Emit(maple::GetDwFormName(unsigned(apl[i + 1])));
3666             }
3667             Emit("\n");
3668         }
3669         /* end of an abbreviation record */
3670         Emit("\t.byte    0x0\n");
3671         Emit("\t.byte    0x0\n");
3672     }
3673     Emit("\t.byte    0x0\n");
3674 }
3675 
EmitDIDebugARangesSection()3676 void Emitter::EmitDIDebugARangesSection()
3677 {
3678     Emit("\t.section\t.debug_aranges,\"\",@progbits\n");
3679 }
3680 
EmitDIDebugRangesSection()3681 void Emitter::EmitDIDebugRangesSection()
3682 {
3683     Emit("\t.section\t.debug_ranges,\"\",@progbits\n");
3684 }
3685 
EmitDIDebugLineSection()3686 void Emitter::EmitDIDebugLineSection()
3687 {
3688     Emit("\t.section\t.debug_line,\"\",@progbits\n");
3689     Emit(".L" XSTR(DEBUG_LINE_0) ":\n");
3690 }
3691 
EmitDIDebugStrSection()3692 void Emitter::EmitDIDebugStrSection()
3693 {
3694     Emit("\t.section\t.debug_str,\"MS\",@progbits,1\n");
3695     for (auto it : GetCG()->GetMIRModule()->GetDbgInfo()->GetStrps()) {
3696         Emit(".L" XSTR(DEBUG_STR_LABEL));
3697         outStream << it;
3698         Emit(":\n");
3699         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(it);
3700         Emit("\t.string \"").Emit(name).Emit("\"\n");
3701     }
3702 }
3703 
FillInClassByteSize(DBGDie * die,DBGDieAttr * byteSizeAttr)3704 void Emitter::FillInClassByteSize(DBGDie *die, DBGDieAttr *byteSizeAttr)
3705 {
3706     DEBUG_ASSERT(byteSizeAttr->GetDwForm() == DW_FORM_data1 || byteSizeAttr->GetDwForm() == DW_FORM_data2 ||
3707                      byteSizeAttr->GetDwForm() == DW_FORM_data4 || byteSizeAttr->GetDwForm() == DW_FORM_data8,
3708                  "Unknown FORM value for DW_AT_byte_size");
3709     if (static_cast<uint32>(byteSizeAttr->GetI()) == kDbgDefaultVal) {
3710         /* get class size */
3711         DBGDieAttr *nameAttr = LFindDieAttr(die, DW_AT_name);
3712         CHECK_FATAL(nameAttr != nullptr, "name_attr is nullptr in Emitter::FillInClassByteSize");
3713         /* hope this is a global string index as it is a type name */
3714         TyIdx tyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(GStrIdx(nameAttr->GetId()));
3715         CHECK_FATAL(tyIdx.GetIdx() < Globals::GetInstance()->GetBECommon()->GetSizeOfTypeSizeTable(),
3716                     "index out of range in Emitter::FillInClassByteSize");
3717         int64_t byteSize = static_cast<int64_t>(Globals::GetInstance()->GetBECommon()->GetTypeSize(tyIdx.GetIdx()));
3718         LUpdateAttrValue(byteSizeAttr, byteSize);
3719     }
3720 }
3721 
SetupDBGInfo(DebugInfo * mirdi)3722 void Emitter::SetupDBGInfo(DebugInfo *mirdi)
3723 {
3724     Emitter *emitter = this;
3725     MapleVector<DBGAbbrevEntry *> &abbrevVec = mirdi->GetAbbrevVec();
3726     ApplyInPrefixOrder(mirdi->GetCompUnit(), [&abbrevVec, &emitter](DBGDie *die) {
3727         if (!die) {
3728             return;
3729         }
3730 
3731         CHECK_FATAL(maple::GetDwTagName(die->GetTag()) != nullptr,
3732                     "maple::GetDwTagName(die->GetTag()) is nullptr in Emitter::SetupDBGInfo");
3733         if (die->GetAbbrevId() == 0) {
3734             LogInfo::MapleLogger() << maple::GetDwTagName(die->GetTag()) << std::endl;
3735         }
3736         CHECK_FATAL(die->GetAbbrevId() < abbrevVec.size(), "index out of range in Emitter::SetupDBGInfo");
3737         DEBUG_ASSERT(abbrevVec[die->GetAbbrevId()]->GetAbbrevId() == die->GetAbbrevId(), "");
3738         DBGAbbrevEntry *diae = abbrevVec[die->GetAbbrevId()];
3739         switch (diae->GetTag()) {
3740             case DW_TAG_subprogram: {
3741                 DBGExprLoc *exprloc = emitter->memPool->New<DBGExprLoc>(emitter->GetCG()->GetMIRModule());
3742                 exprloc->GetSimpLoc()->SetDwOp(DW_OP_call_frame_cfa);
3743                 die->SetAttr(DW_AT_frame_base, exprloc);
3744                 break;
3745             }
3746             case DW_TAG_structure_type:
3747             case DW_TAG_union_type:
3748             case DW_TAG_class_type:
3749             case DW_TAG_interface_type: {
3750                 DBGDieAttr *byteSizeAttr = LFindDieAttr(die, DW_AT_byte_size);
3751                 if (byteSizeAttr) {
3752                     emitter->FillInClassByteSize(die, byteSizeAttr);
3753                 }
3754                 /* get the name */
3755                 DBGDieAttr *atName = LFindDieAttr(die, DW_AT_name);
3756                 CHECK_FATAL(atName != nullptr, "at_name is null in Emitter::SetupDBGInfo");
3757                 /* get the type from string name */
3758                 TyIdx ctyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(GStrIdx(atName->GetId()));
3759                 MIRType *mty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ctyIdx);
3760                 MIRStructType *sty = static_cast<MIRStructType *>(mty);
3761                 CHECK_FATAL(sty != nullptr, "pointer cast failed");
3762                 CHECK_FATAL(sty->GetTypeIndex().GetIdx() <
3763                                 Globals::GetInstance()->GetBECommon()->GetSizeOfStructFieldCountTable(),
3764                             "");
3765                 uint32 embeddedIDs = 0;
3766                 MIRStructType *prevSubstruct = nullptr;
3767                 for (size_t i = 0; i < sty->GetFields().size(); i++) {
3768                     TyIdx fieldtyidx = sty->GetFieldsElemt(i).second.first;
3769                     MIRType *fieldty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldtyidx);
3770                     if (prevSubstruct) {
3771                         embeddedIDs += static_cast<uint32>(Globals::GetInstance()->GetBECommon()->GetStructFieldCount(
3772                             static_cast<uint32>(prevSubstruct->GetTypeIndex().GetIdx())));
3773                     }
3774                     prevSubstruct = fieldty->EmbeddedStructType();
3775                     FieldID fieldID = static_cast<int32>(i + embeddedIDs) + 1;
3776                     int offset = Globals::GetInstance()->GetBECommon()->GetFieldOffset(*sty, fieldID).first;
3777                     GStrIdx fldName = sty->GetFieldsElemt(i).first;
3778                     DBGDie *cdie = LFindChildDieWithName(die, DW_TAG_member, fldName);
3779                     CHECK_FATAL(cdie != nullptr, "cdie is null in Emitter::SetupDBGInfo");
3780                     DBGDieAttr *mloc = LFindDieAttr(cdie, DW_AT_data_member_location);
3781                     CHECK_FATAL(mloc != nullptr, "mloc is null in Emitter::SetupDBGInfo");
3782                     DBGAbbrevEntry *childDiae = abbrevVec[cdie->GetAbbrevId()];
3783                     CHECK_FATAL(childDiae != nullptr, "child_diae is null in Emitter::SetupDBGInfo");
3784                     LUpdateAttrValue(mloc, offset);
3785                 }
3786                 break;
3787             }
3788             default:
3789                 break;
3790         }
3791     });
3792 
3793     /* compute DIE sizes and offsets */
3794     mirdi->ComputeSizeAndOffsets();
3795 }
3796 
EmitAliasAndRef(const MIRSymbol & sym)3797 void Emitter::EmitAliasAndRef(const MIRSymbol &sym)
3798 {
3799     MIRFunction *mFunc = sym.GetFunction();
3800     if (mFunc == nullptr || !mFunc->GetAttr(FUNCATTR_alias)) {
3801         return;
3802     }
3803     if (mFunc->GetAttr(FUNCATTR_extern)) {
3804         Emit(asmInfo->GetGlobal()).Emit(mFunc->GetName()).Emit("\n");
3805     }
3806     auto &aliasPrefix = mFunc->GetAttr(FUNCATTR_weakref) ? asmInfo->GetWeakref() : asmInfo->GetSet();
3807     Emit(aliasPrefix);
3808     Emit(sym.GetName()).Emit(",").Emit(mFunc->GetAttrs().GetAliasFuncName()).Emit("\n");
3809 }
3810 
EmitHugeSoRoutines(bool lastRoutine)3811 void Emitter::EmitHugeSoRoutines(bool lastRoutine)
3812 {
3813     if (!lastRoutine &&
3814         (soInsnCount < (static_cast<uint64>(hugeSoSeqence) * static_cast<uint64>(kHugeSoInsnCountThreshold)))) {
3815         return;
3816     }
3817     for (auto &target : hugeSoTargets) {
3818         if (GetCG()->GetTargetMachine()->isX8664()) {
3819                 Emit("\t.align\t8\n");
3820         } else {
3821                 Emit("\t.align 3\n");
3822         }
3823         std::string routineName = target + HugeSoPostFix();
3824         Emit("\t.type\t" + routineName + ", %function\n");
3825         Emit(routineName + ":\n");
3826         Emit("\tadrp\tx17, :got:" + target + "\n");
3827         Emit("\tldr\tx17, [x17, :got_lo12:" + target + "]\n");
3828         Emit("\tbr\tx17\n");
3829         soInsnCount += kSizeOfHugesoRoutine;
3830     }
3831     hugeSoTargets.clear();
3832     ++hugeSoSeqence;
3833 }
3834 
Dump() const3835 void ImmOperand::Dump() const
3836 {
3837     LogInfo::MapleLogger() << "imm:" << value;
3838 }
3839 
Dump() const3840 void LabelOperand::Dump() const
3841 {
3842     LogInfo::MapleLogger() << "label:" << labelIndex;
3843 }
3844 
3845 /* new phase manager */
PhaseRun(maplebe::CGFunc & f)3846 bool CgEmission::PhaseRun(maplebe::CGFunc &f)
3847 {
3848     if (Triple::GetTriple().IsAarch64BeOrLe()) {
3849         f.GetCG()->template Emit<CG::EmitterType::AsmEmitter>([&f](Emitter *emitter) {
3850             AsmFuncEmitInfo funcEmitInfo(f);
3851             emitter->EmitLocalVariable(f);
3852             static_cast<AArch64AsmEmitter *>(emitter)->Run(funcEmitInfo);
3853             emitter->EmitHugeSoRoutines();
3854         });
3855         f.GetCG()->template Emit<CG::EmitterType::ObjEmiter>([&f](Emitter *emitter) {
3856             auto objEmitter = static_cast<AArch64ObjEmitter *>(emitter);
3857             FuncEmitInfo &funcEmitInfo = objEmitter->CreateFuncEmitInfo(f);
3858             objEmitter->Run(funcEmitInfo);
3859             f.SetFuncEmitInfo(&funcEmitInfo);
3860         });
3861     } else if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
3862         f.GetCG()->Emit([&f](Emitter *emitter) {
3863             CHECK_NULL_FATAL(emitter);
3864             static_cast<X64Emitter *>(emitter)->Run(f);
3865         });
3866     } else {
3867         CHECK_FATAL(false, "unsupportted");
3868     }
3869     return false;
3870 }
3871 MAPLE_TRANSFORM_PHASE_REGISTER(CgEmission, cgemit)
3872 } /* namespace maplebe */
3873