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