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 "mir_function.h"
17 #include <cstdio>
18 #include <iostream>
19 #include "mir_nodes.h"
20 #include "printing.h"
21 #include "string_utils.h"
22
23 namespace {
24 using namespace maple;
25 enum FuncProp : uint32_t {
26 kFuncPropHasCall = 1U, // the function has call
27 kFuncPropRetStruct = 1U << 1, // the function returns struct
28 kFuncPropUserFunc = 1U << 2, // the function is a user func
29 kFuncPropInfoPrinted = 1U << 3, // to avoid printing frameSize/moduleid/funcSize info more
30 // than once per function since they
31 // can only be printed at the beginning of a block
32 kFuncPropNeverReturn = 1U << 4, // the function when called never returns
33 kFuncPropHasSetjmp = 1U << 5, // the function contains call to setjmp
34 kFuncPropHasAsm = 1U << 6, // the function has use of inline asm
35 kFuncPropStructReturnedInRegs = 1U << 7, // the function returns struct in registers
36 };
37 } // namespace
38
39 namespace maple {
GetFuncSymbol() const40 const MIRSymbol *MIRFunction::GetFuncSymbol() const
41 {
42 return GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
43 }
GetFuncSymbol()44 MIRSymbol *MIRFunction::GetFuncSymbol()
45 {
46 const MIRFunction *mirFunc = const_cast<const MIRFunction *>(this);
47 DEBUG_ASSERT(mirFunc != nullptr, "null ptr check");
48 return const_cast<MIRSymbol *>(mirFunc->GetFuncSymbol());
49 }
50
GetName() const51 const std::string &MIRFunction::GetName() const
52 {
53 MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
54 DEBUG_ASSERT(mirSymbol != nullptr, "null ptr check");
55 return mirSymbol->GetName();
56 }
57
GetNameStrIdx() const58 GStrIdx MIRFunction::GetNameStrIdx() const
59 {
60 MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
61 DEBUG_ASSERT(mirSymbol != nullptr, "null ptr check");
62 return mirSymbol->GetNameStrIdx();
63 }
64
GetBaseClassName() const65 const std::string &MIRFunction::GetBaseClassName() const
66 {
67 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseClassStrIdx);
68 }
69
GetBaseFuncName() const70 const std::string &MIRFunction::GetBaseFuncName() const
71 {
72 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseFuncStrIdx);
73 }
74
GetBaseFuncNameWithType() const75 const std::string &MIRFunction::GetBaseFuncNameWithType() const
76 {
77 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseFuncWithTypeStrIdx);
78 }
79
GetBaseFuncSig() const80 const std::string &MIRFunction::GetBaseFuncSig() const
81 {
82 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseFuncSigStrIdx);
83 }
84
GetSignature() const85 const std::string &MIRFunction::GetSignature() const
86 {
87 return GlobalTables::GetStrTable().GetStringFromStrIdx(signatureStrIdx);
88 }
89
GetReturnType() const90 const MIRType *MIRFunction::GetReturnType() const
91 {
92 CHECK_FATAL(funcType != nullptr, "funcType should not be nullptr");
93 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx());
94 }
GetReturnType()95 MIRType *MIRFunction::GetReturnType()
96 {
97 return const_cast<MIRType *>(const_cast<const MIRFunction *>(this)->GetReturnType());
98 }
GetClassType() const99 const MIRType *MIRFunction::GetClassType() const
100 {
101 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(classTyIdx);
102 }
GetNthParamType(size_t i) const103 const MIRType *MIRFunction::GetNthParamType(size_t i) const
104 {
105 CHECK_FATAL(funcType != nullptr, "funcType should not be nullptr");
106 DEBUG_ASSERT(i < funcType->GetParamTypeList().size(), "array index out of range");
107 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetParamTypeList()[i]);
108 }
GetNthParamType(size_t i)109 MIRType *MIRFunction::GetNthParamType(size_t i)
110 {
111 return const_cast<MIRType *>(const_cast<const MIRFunction *>(this)->GetNthParamType(i));
112 }
113
114 // reconstruct formals, and return a new MIRFuncType
ReconstructFormals(const std::vector<MIRSymbol * > & symbols,bool clearOldArgs)115 MIRFuncType *MIRFunction::ReconstructFormals(const std::vector<MIRSymbol *> &symbols, bool clearOldArgs)
116 {
117 auto *newFuncType = static_cast<MIRFuncType *>(funcType->CopyMIRTypeNode());
118 if (clearOldArgs) {
119 formalDefVec.clear();
120 newFuncType->GetParamTypeList().clear();
121 newFuncType->GetParamAttrsList().clear();
122 }
123 for (auto *symbol : symbols) {
124 FormalDef formalDef(symbol->GetNameStrIdx(), symbol, symbol->GetTyIdx(), symbol->GetAttrs());
125 formalDefVec.push_back(formalDef);
126 newFuncType->GetParamTypeList().push_back(symbol->GetTyIdx());
127 newFuncType->GetParamAttrsList().push_back(symbol->GetAttrs());
128 }
129 return newFuncType;
130 }
131
UpdateFuncTypeAndFormals(const std::vector<MIRSymbol * > & symbols,bool clearOldArgs)132 void MIRFunction::UpdateFuncTypeAndFormals(const std::vector<MIRSymbol *> &symbols, bool clearOldArgs)
133 {
134 auto *newFuncType = ReconstructFormals(symbols, clearOldArgs);
135 auto newFuncTypeIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(newFuncType);
136 funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(newFuncTypeIdx));
137 delete newFuncType;
138 }
139
UpdateFuncTypeAndFormalsAndReturnType(const std::vector<MIRSymbol * > & symbols,const TyIdx & retTyIdx,bool clearOldArgs)140 void MIRFunction::UpdateFuncTypeAndFormalsAndReturnType(const std::vector<MIRSymbol *> &symbols, const TyIdx &retTyIdx,
141 bool clearOldArgs)
142 {
143 auto *newFuncType = ReconstructFormals(symbols, clearOldArgs);
144 newFuncType->SetRetTyIdx(retTyIdx);
145 auto newFuncTypeIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(newFuncType);
146 funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(newFuncTypeIdx));
147 delete newFuncType;
148 }
149
GetOrCreateLableIdxFromName(const std::string & name)150 LabelIdx MIRFunction::GetOrCreateLableIdxFromName(const std::string &name)
151 {
152 GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name);
153 LabelIdx labelIdx = GetLabelTab()->GetLabelIdxFromStrIdx(strIdx);
154 if (labelIdx == 0) {
155 labelIdx = GetLabelTab()->CreateLabel();
156 GetLabelTab()->SetSymbolFromStIdx(labelIdx, strIdx);
157 GetLabelTab()->AddToStringLabelMap(labelIdx);
158 }
159 return labelIdx;
160 }
161
HasCall() const162 bool MIRFunction::HasCall() const
163 {
164 return flag & kFuncPropHasCall;
165 }
SetHasCall()166 void MIRFunction::SetHasCall()
167 {
168 flag |= kFuncPropHasCall;
169 }
170
IsReturnStruct() const171 bool MIRFunction::IsReturnStruct() const
172 {
173 return flag & kFuncPropRetStruct;
174 }
SetReturnStruct()175 void MIRFunction::SetReturnStruct()
176 {
177 flag |= kFuncPropRetStruct;
178 }
SetReturnStruct(const MIRType & retType)179 void MIRFunction::SetReturnStruct(const MIRType &retType)
180 {
181 if (retType.IsStructType()) {
182 flag |= kFuncPropRetStruct;
183 }
184 }
SetReturnStruct(const MIRType * retType)185 void MIRFunction::SetReturnStruct(const MIRType *retType)
186 {
187 switch (retType->GetKind()) {
188 case kTypeUnion:
189 case kTypeStruct:
190 case kTypeStructIncomplete:
191 case kTypeClass:
192 case kTypeClassIncomplete:
193 case kTypeInterface:
194 case kTypeInterfaceIncomplete:
195 flag |= kFuncPropRetStruct;
196 break;
197 default:;
198 }
199 }
200
IsUserFunc() const201 bool MIRFunction::IsUserFunc() const
202 {
203 return flag & kFuncPropUserFunc;
204 }
SetUserFunc()205 void MIRFunction::SetUserFunc()
206 {
207 flag |= kFuncPropUserFunc;
208 }
209
IsInfoPrinted() const210 bool MIRFunction::IsInfoPrinted() const
211 {
212 return flag & kFuncPropInfoPrinted;
213 }
SetInfoPrinted()214 void MIRFunction::SetInfoPrinted()
215 {
216 flag |= kFuncPropInfoPrinted;
217 }
ResetInfoPrinted()218 void MIRFunction::ResetInfoPrinted()
219 {
220 flag &= ~kFuncPropInfoPrinted;
221 }
222
SetNoReturn()223 void MIRFunction::SetNoReturn()
224 {
225 flag |= kFuncPropNeverReturn;
226 }
NeverReturns() const227 bool MIRFunction::NeverReturns() const
228 {
229 return flag & kFuncPropNeverReturn;
230 }
231
SetHasSetjmp()232 void MIRFunction::SetHasSetjmp()
233 {
234 flag |= kFuncPropHasSetjmp;
235 }
236
HasSetjmp() const237 bool MIRFunction::HasSetjmp() const
238 {
239 return ((flag & kFuncPropHasSetjmp) != kTypeflagZero);
240 }
241
SetHasAsm()242 void MIRFunction::SetHasAsm()
243 {
244 flag |= kFuncPropHasAsm;
245 }
246
HasAsm() const247 bool MIRFunction::HasAsm() const
248 {
249 return ((flag & kFuncPropHasAsm) != kTypeflagZero);
250 }
251
SetStructReturnedInRegs()252 void MIRFunction::SetStructReturnedInRegs()
253 {
254 flag |= kFuncPropStructReturnedInRegs;
255 }
256
StructReturnedInRegs() const257 bool MIRFunction::StructReturnedInRegs() const
258 {
259 return ((flag & kFuncPropStructReturnedInRegs) != kTypeflagZero);
260 }
261
SetAttrsFromSe(uint8 specialEffect)262 void MIRFunction::SetAttrsFromSe(uint8 specialEffect)
263 {
264 // NoPrivateDefEffect
265 if ((specialEffect & kDefEffect) == kDefEffect) {
266 funcAttrs.SetAttr(FUNCATTR_noprivate_defeffect);
267 }
268 // NoPrivateUseEffect
269 if ((specialEffect & kUseEffect) == kUseEffect) {
270 funcAttrs.SetAttr(FUNCATTR_noretarg);
271 }
272 // IpaSeen
273 if ((specialEffect & kIpaSeen) == kIpaSeen) {
274 funcAttrs.SetAttr(FUNCATTR_ipaseen);
275 }
276 // Pure
277 if ((specialEffect & kPureFunc) == kPureFunc) {
278 funcAttrs.SetAttr(FUNCATTR_pure);
279 }
280 // NoDefArgEffect
281 if ((specialEffect & kNoDefArgEffect) == kNoDefArgEffect) {
282 funcAttrs.SetAttr(FUNCATTR_nodefargeffect);
283 }
284 // NoDefEffect
285 if ((specialEffect & kNoDefEffect) == kNoDefEffect) {
286 funcAttrs.SetAttr(FUNCATTR_nodefeffect);
287 }
288 // NoRetNewlyAllocObj
289 if ((specialEffect & kNoRetNewlyAllocObj) == kNoRetNewlyAllocObj) {
290 funcAttrs.SetAttr(FUNCATTR_noretglobal);
291 }
292 // NoThrowException
293 if ((specialEffect & kNoThrowException) == kNoThrowException) {
294 funcAttrs.SetAttr(FUNCATTR_nothrow_exception);
295 }
296 }
297
DumpAttributes() const298 void FuncAttrs::DumpAttributes() const
299 {
300 // parse no content of attr
301 #define STRING(s) #s
302 #define FUNC_ATTR
303 #define NOCONTENT_ATTR
304 #define ATTR(AT) \
305 if (GetAttr(FUNCATTR_##AT)) { \
306 LogInfo::MapleLogger() << " " << STRING(AT); \
307 }
308 #include "all_attributes.def"
309 #undef ATTR
310 #undef NOCONTENT_ATTR
311 #undef FUNC_ATTR
312 // parse content of attr
313 if (GetAttr(FUNCATTR_alias) && !GetAliasFuncName().empty()) {
314 LogInfo::MapleLogger() << " alias ( \"" << GetAliasFuncName() << "\" )";
315 }
316 if (GetAttr(FUNCATTR_constructor_priority) && GetConstructorPriority() != -1) {
317 LogInfo::MapleLogger() << " constructor_priority ( " << GetConstructorPriority() << " )";
318 }
319 if (GetAttr(FUNCATTR_destructor_priority) && GetDestructorPriority() != -1) {
320 LogInfo::MapleLogger() << " destructor_priority ( " << GetDestructorPriority() << " )";
321 }
322 if (GetAttr(FUNCATTR_frame_pointer) && !framePointer.empty()) {
323 LogInfo::MapleLogger() << " frame-pointer ( " << framePointer << " )";
324 }
325 if (GetAttr(FUNCATTR_frame_reserved_slots) && GetFrameResverdSlot() != 0) {
326 LogInfo::MapleLogger() << " frame-reserved-slots ( " << GetFrameResverdSlot() << " )";
327 }
328 }
329
DumpFlavorLoweredThanMmpl() const330 void MIRFunction::DumpFlavorLoweredThanMmpl() const
331 {
332 LogInfo::MapleLogger() << " (";
333
334 // Dump arguments
335 bool hasPrintedFormal = false;
336 for (uint32 i = 0; i < formalDefVec.size(); i++) {
337 MIRSymbol *symbol = formalDefVec[i].formalSym;
338 if (symbol == nullptr &&
339 (formalDefVec[i].formalStrIdx.GetIdx() == 0 ||
340 GlobalTables::GetStrTable().GetStringFromStrIdx(formalDefVec[i].formalStrIdx).empty())) {
341 break;
342 }
343 hasPrintedFormal = true;
344 if (symbol == nullptr) {
345 LogInfo::MapleLogger() << "var %"
346 << GlobalTables::GetStrTable().GetStringFromStrIdx(formalDefVec[i].formalStrIdx)
347 << " ";
348 } else {
349 if (symbol->GetSKind() != kStPreg) {
350 LogInfo::MapleLogger() << "var %" << symbol->GetName() << " ";
351 } else {
352 LogInfo::MapleLogger() << "reg %" << symbol->GetPreg()->GetPregNo() << " ";
353 }
354 }
355 MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDefVec[i].formalTyIdx);
356 constexpr uint8 indent = 2;
357 ty->Dump(indent);
358 if (symbol != nullptr) {
359 symbol->GetAttrs().DumpAttributes();
360 } else {
361 formalDefVec[i].formalAttrs.DumpAttributes();
362 }
363 if (i != (formalDefVec.size() - 1)) {
364 LogInfo::MapleLogger() << ", ";
365 }
366 }
367 if (IsVarargs()) {
368 if (!hasPrintedFormal) {
369 LogInfo::MapleLogger() << "...";
370 } else {
371 LogInfo::MapleLogger() << ", ...";
372 }
373 }
374
375 LogInfo::MapleLogger() << ") ";
376 GetReturnType()->Dump(1);
377 }
378
Dump(bool withoutBody)379 void MIRFunction::Dump(bool withoutBody)
380 {
381 // skip the functions that are added during process methods in
382 // class and interface decls. these has nothing in formals
383 // they do have paramtypelist_. this can not skip ones without args
384 // but for them at least the func decls are valid
385 if ((module->IsJavaModule() && GetParamSize() != formalDefVec.size()) || GetAttr(FUNCATTR_optimized)) {
386 return;
387 }
388
389 // save the module's curFunction and set it to the one currently Dump()ing
390 MIRFunction *savedFunc = module->CurFunction();
391 module->SetCurFunction(this);
392
393 MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
394 DEBUG_ASSERT(symbol != nullptr, "symbol MIRSymbol is null");
395 if (!withoutBody) {
396 symbol->GetSrcPosition().DumpLoc(MIRSymbol::LastPrintedLineNumRef(), MIRSymbol::LastPrintedColumnNumRef());
397 }
398 LogInfo::MapleLogger() << "func "
399 << "&" << symbol->GetName();
400 theMIRModule = module;
401 funcAttrs.DumpAttributes();
402
403 if (symbol->GetWeakrefAttr().first) {
404 LogInfo::MapleLogger() << " weakref";
405 if (symbol->GetWeakrefAttr().second != UStrIdx(0)) {
406 LogInfo::MapleLogger() << " (";
407 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->GetWeakrefAttr().second));
408 LogInfo::MapleLogger() << " )";
409 }
410 }
411
412 if (symbol->sectionAttr != UStrIdx(0)) {
413 LogInfo::MapleLogger() << " section (";
414 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->sectionAttr));
415 LogInfo::MapleLogger() << " )";
416 }
417
418 if (module->GetFlavor() != kMmpl) {
419 DumpFlavorLoweredThanMmpl();
420 }
421
422 // codeMemPool is nullptr, means maple_ir has been released for memory's sake
423 if (codeMemPool == nullptr) {
424 LogInfo::MapleLogger() << '\n';
425 } else if (GetBody() != nullptr && !withoutBody && symbol->GetStorageClass() != kScExtern) {
426 ResetInfoPrinted(); // this ensures funcinfo will be printed
427 GetBody()->Dump(0, module->GetFlavor() == kMmpl ? nullptr : GetSymTab(),
428 module->GetFlavor() < kMmpl ? GetPregTab() : nullptr, false, true,
429 module->GetFlavor()); // Dump body
430 } else {
431 LogInfo::MapleLogger() << '\n';
432 }
433
434 // restore the curFunction
435 module->SetCurFunction(savedFunc);
436 }
437
DumpUpFormal(int32 indent) const438 void MIRFunction::DumpUpFormal(int32 indent) const
439 {
440 PrintIndentation(indent + 1);
441
442 LogInfo::MapleLogger() << "upformalsize " << GetUpFormalSize() << '\n';
443 if (localWordsTypeTagged != nullptr) {
444 PrintIndentation(indent + 1);
445 LogInfo::MapleLogger() << "formalWordsTypeTagged = [ ";
446 const auto *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
447 LogInfo::MapleLogger() << std::hex;
448 while (p <
449 reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetUpFormalSize()))) {
450 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
451 ++p;
452 }
453 LogInfo::MapleLogger() << std::dec << "]\n";
454 }
455
456 if (formalWordsRefCounted != nullptr) {
457 PrintIndentation(indent + 1);
458 LogInfo::MapleLogger() << "formalWordsRefCounted = [ ";
459 const uint32 *p = reinterpret_cast<const uint32 *>(formalWordsRefCounted);
460 LogInfo::MapleLogger() << std::hex;
461 while (p <
462 reinterpret_cast<const uint32 *>(formalWordsRefCounted + BlockSize2BitVectorSize(GetUpFormalSize()))) {
463 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
464 ++p;
465 }
466 LogInfo::MapleLogger() << std::dec << "]\n";
467 }
468 }
469
DumpFrame(int32 indent) const470 void MIRFunction::DumpFrame(int32 indent) const
471 {
472 PrintIndentation(indent + 1);
473
474 LogInfo::MapleLogger() << "framesize " << static_cast<uint32>(GetFrameSize()) << '\n';
475 if (localWordsTypeTagged != nullptr) {
476 PrintIndentation(indent + 1);
477 LogInfo::MapleLogger() << "localWordsTypeTagged = [ ";
478 const uint32 *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
479 LogInfo::MapleLogger() << std::hex;
480 while (p < reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetFrameSize()))) {
481 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
482 ++p;
483 }
484 LogInfo::MapleLogger() << std::dec << "]\n";
485 }
486
487 if (localWordsRefCounted != nullptr) {
488 PrintIndentation(indent + 1);
489 LogInfo::MapleLogger() << "localWordsRefCounted = [ ";
490 const uint32 *p = reinterpret_cast<const uint32 *>(localWordsRefCounted);
491 LogInfo::MapleLogger() << std::hex;
492 while (p < reinterpret_cast<const uint32 *>(localWordsRefCounted + BlockSize2BitVectorSize(GetFrameSize()))) {
493 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
494 ++p;
495 }
496 LogInfo::MapleLogger() << std::dec << "]\n";
497 }
498 }
499
DumpScope()500 void MIRFunction::DumpScope()
501 {
502 scope->Dump(0);
503 }
504
DumpFuncBody(int32 indent)505 void MIRFunction::DumpFuncBody(int32 indent)
506 {
507 LogInfo::MapleLogger() << " funcid " << GetPuidxOrigin() << '\n';
508
509 if (IsInfoPrinted()) {
510 return;
511 }
512
513 SetInfoPrinted();
514
515 if (GetUpFormalSize() > 0) {
516 DumpUpFormal(indent);
517 }
518
519 if (GetFrameSize() > 0) {
520 DumpFrame(indent);
521 }
522
523 if (GetOutParmSize() > 0) {
524 PrintIndentation(indent + 1);
525 LogInfo::MapleLogger() << "outparmsize " << GetOutParmSize() << '\n';
526 }
527
528 if (GetModuleId() > 0) {
529 PrintIndentation(indent + 1);
530 LogInfo::MapleLogger() << "moduleID " << static_cast<uint32>(GetModuleId()) << '\n';
531 }
532
533 if (GetFuncSize() > 0) {
534 PrintIndentation(indent + 1);
535 LogInfo::MapleLogger() << "funcSize " << GetFuncSize() << '\n';
536 }
537
538 if (GetInfoVector().empty()) {
539 return;
540 }
541
542 const MIRInfoVector &funcInfo = GetInfoVector();
543 const MapleVector<bool> &funcInfoIsString = InfoIsString();
544 PrintIndentation(indent + 1);
545 LogInfo::MapleLogger() << "funcinfo {\n";
546 size_t size = funcInfo.size();
547 constexpr int kIndentOffset = 2;
548 for (size_t i = 0; i < size; ++i) {
549 PrintIndentation(indent + kIndentOffset);
550 LogInfo::MapleLogger() << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(funcInfo[i].first) << " ";
551 if (!funcInfoIsString[i]) {
552 LogInfo::MapleLogger() << funcInfo[i].second;
553 } else {
554 LogInfo::MapleLogger() << "\""
555 << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(funcInfo[i].second))
556 << "\"";
557 }
558 if (i < size - 1) {
559 LogInfo::MapleLogger() << ",\n";
560 } else {
561 LogInfo::MapleLogger() << "}\n";
562 }
563 }
564 LogInfo::MapleLogger() << '\n';
565 }
566
IsEmpty() const567 bool MIRFunction::IsEmpty() const
568 {
569 return (body == nullptr || body->IsEmpty());
570 }
571
IsClinit() const572 bool MIRFunction::IsClinit() const
573 {
574 const std::string clinitPostfix = "_7C_3Cclinit_3E_7C_28_29V";
575 const std::string &funcName = this->GetName();
576 // this does not work for smali files like test/511-clinit-interface/smali/BogusInterface.smali,
577 // which is decorated without "constructor".
578 return StringUtils::EndsWith(funcName, clinitPostfix);
579 }
580
GetInfo(GStrIdx strIdx) const581 uint32 MIRFunction::GetInfo(GStrIdx strIdx) const
582 {
583 for (const auto &item : info) {
584 if (item.first == strIdx) {
585 return item.second;
586 }
587 }
588 DEBUG_ASSERT(false, "get info error");
589 return 0;
590 }
591
GetInfo(const std::string & string) const592 uint32 MIRFunction::GetInfo(const std::string &string) const
593 {
594 GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(string);
595 return GetInfo(strIdx);
596 }
597
OverrideBaseClassFuncNames(GStrIdx strIdx)598 void MIRFunction::OverrideBaseClassFuncNames(GStrIdx strIdx)
599 {
600 baseClassStrIdx.reset();
601 baseFuncStrIdx.reset();
602 SetBaseClassFuncNames(strIdx);
603 }
604
605 // there are two ways to represent the delimiter: '|' or "_7C"
606 // where 7C is the ascii value of char '|' in hex
SetBaseClassFuncNames(GStrIdx strIdx)607 void MIRFunction::SetBaseClassFuncNames(GStrIdx strIdx)
608 {
609 if (baseClassStrIdx != 0u || baseFuncStrIdx != 0u) {
610 return;
611 }
612 const std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx);
613 std::string delimiter = "|";
614 uint32 width = 1; // delimiter width
615 size_t pos = name.find(delimiter);
616 if (pos == std::string::npos) {
617 delimiter = namemangler::kNameSplitterStr;
618 width = 3; // delimiter "_7C" width is 3
619 pos = name.find(delimiter);
620 // make sure it is not __7C, but ___7C ok. stop find loop if last 2 char is '_'
621 while (pos != std::string::npos && (name[pos - 1] == '_' && name[pos - 2] != '_')) {
622 pos = name.find(delimiter, pos + width);
623 }
624 }
625 if (pos != std::string::npos && pos > 0) {
626 const std::string className = name.substr(0, pos);
627 baseClassStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(className);
628 std::string funcNameWithType = name.substr(pos + width, name.length() - pos - width);
629 baseFuncWithTypeStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcNameWithType);
630 size_t index = name.find(namemangler::kRightBracketStr);
631 if (index != std::string::npos) {
632 size_t posEnd = index + (std::string(namemangler::kRightBracketStr)).length();
633 funcNameWithType = name.substr(pos + width, posEnd - pos - width);
634 }
635 baseFuncSigStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcNameWithType);
636 size_t newPos = name.find(delimiter, pos + width);
637 // make sure it is not __7C, but ___7C ok. stop find loop if last 2 char is '_'
638 while (newPos != std::string::npos && (name[newPos - 1] == '_' && name[newPos - 2] != '_')) {
639 newPos = name.find(delimiter, newPos + width);
640 }
641 if (newPos != 0) {
642 std::string funcName = name.substr(pos + width, newPos - pos - width);
643 baseFuncStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName);
644 std::string signature = name.substr(newPos + width, name.length() - newPos - width);
645 signatureStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(signature);
646 }
647 return;
648 }
649 baseFuncStrIdx = strIdx;
650 }
651
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst) const652 const MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst) const
653 {
654 return idx.Islocal() ? GetSymbolTabItem(idx.Idx(), checkFirst)
655 : GlobalTables::GetGsymTable().GetSymbolFromStidx(idx.Idx(), checkFirst);
656 }
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst)657 MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst)
658 {
659 return const_cast<MIRSymbol *>(const_cast<const MIRFunction *>(this)->GetLocalOrGlobalSymbol(idx, checkFirst));
660 }
661
GetNodeType(const BaseNode & node) const662 const MIRType *MIRFunction::GetNodeType(const BaseNode &node) const
663 {
664 if (node.GetOpCode() == OP_dread) {
665 const MIRSymbol *sym = GetLocalOrGlobalSymbol(static_cast<const DreadNode &>(node).GetStIdx());
666 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(sym->GetTyIdx());
667 }
668 if (node.GetOpCode() == OP_regread) {
669 const auto &nodeReg = static_cast<const RegreadNode &>(node);
670 const MIRPreg *pReg = GetPregTab()->PregFromPregIdx(nodeReg.GetRegIdx());
671 if (pReg->GetPrimType() == PTY_ref) {
672 return pReg->GetMIRType();
673 }
674 }
675 return nullptr;
676 }
677
EnterFormals()678 void MIRFunction::EnterFormals()
679 {
680 for (auto &formalDef : formalDefVec) {
681 formalDef.formalSym = symTab->CreateSymbol(kScopeLocal);
682 formalDef.formalSym->SetStorageClass(kScFormal);
683 formalDef.formalSym->SetNameStrIdx(formalDef.formalStrIdx);
684 formalDef.formalSym->SetTyIdx(formalDef.formalTyIdx);
685 formalDef.formalSym->SetAttrs(formalDef.formalAttrs);
686 const std::string &formalName = GlobalTables::GetStrTable().GetStringFromStrIdx(formalDef.formalStrIdx);
687 if (!isdigit(formalName.front())) {
688 formalDef.formalSym->SetSKind(kStVar);
689 (void)symTab->AddToStringSymbolMap(*formalDef.formalSym);
690 } else {
691 formalDef.formalSym->SetSKind(kStPreg);
692 uint32 thepregno = static_cast<uint32>(std::stoi(formalName));
693 MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDef.formalTyIdx);
694 PrimType pType = mirType->GetPrimType();
695 // if mirType info is not needed, set mirType to nullptr
696 if (pType != PTY_ref && pType != PTY_ptr) {
697 mirType = nullptr;
698 } else if (pType == PTY_ptr && mirType->IsMIRPtrType()) {
699 MIRType *pointedType = static_cast<MIRPtrType *>(mirType)->GetPointedType();
700 if (pointedType == nullptr || pointedType->GetKind() != kTypeFunction) {
701 mirType = nullptr;
702 }
703 }
704 PregIdx pregIdx = pregTab->EnterPregNo(thepregno, pType, mirType);
705 MIRPreg *preg = pregTab->PregFromPregIdx(pregIdx);
706 formalDef.formalSym->SetPreg(preg);
707 }
708 }
709 }
710
NewBody()711 void MIRFunction::NewBody()
712 {
713 codeMemPool = GetCodeMemPool();
714 SetBody(codeMemPool->New<BlockNode>());
715 SetLastPosBody(codeMemPool->New<BlockNode>());
716 // If mir_function.has been seen as a declaration, its symtab has to be moved
717 // from module mempool to function mempool.
718 MIRSymbolTable *oldSymTable = GetSymTab();
719 MIRPregTable *oldPregTable = GetPregTab();
720 MIRTypeNameTable *oldTypeNameTable = typeNameTab;
721 MIRLabelTable *oldLabelTable = GetLabelTab();
722 symTab = module->GetMemPool()->New<MIRSymbolTable>(module->GetMPAllocator());
723 pregTab = module->GetMemPool()->New<MIRPregTable>(&module->GetMPAllocator());
724 typeNameTab = module->GetMemPool()->New<MIRTypeNameTable>(module->GetMPAllocator());
725 labelTab = module->GetMemPool()->New<MIRLabelTable>(module->GetMPAllocator());
726
727 if (oldSymTable == nullptr) {
728 // formals not yet entered into symTab; enter them now
729 EnterFormals();
730 } else {
731 for (size_t i = 1; i < oldSymTable->GetSymbolTableSize(); ++i) {
732 (void)GetSymTab()->AddStOutside(oldSymTable->GetSymbolFromStIdx(i));
733 }
734 }
735 if (oldPregTable != nullptr) {
736 for (size_t i = 1; i < oldPregTable->Size(); ++i) {
737 (void)GetPregTab()->AddPreg(*oldPregTable->PregFromPregIdx(static_cast<PregIdx>(i)));
738 }
739 }
740 if (oldTypeNameTable != nullptr) {
741 DEBUG_ASSERT(oldTypeNameTable->Size() == typeNameTab->Size(),
742 "Does not expect to process typeNameTab in MIRFunction::NewBody");
743 }
744 if (oldLabelTable != nullptr) {
745 DEBUG_ASSERT(oldLabelTable->Size() == GetLabelTab()->Size(),
746 "Does not expect to process labelTab in MIRFunction::NewBody");
747 }
748 }
749
750 #ifdef DEBUGME
SetUpGDBEnv()751 void MIRFunction::SetUpGDBEnv()
752 {
753 if (codeMemPool != nullptr) {
754 delete codeMemPool;
755 }
756 codeMemPool = new ThreadLocalMemPool(memPoolCtrler, "tmp debug");
757 codeMemPoolAllocator.SetMemPool(codeMemPool);
758 }
759
ResetGDBEnv()760 void MIRFunction::ResetGDBEnv()
761 {
762 delete codeMemPool;
763 codeMemPool = nullptr;
764 }
765 #endif
766 } // namespace maple
767