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