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