• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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