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