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