• 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         DEBUG_ASSERT(formalDefVec.size() > 0, "must not be zero");
364         if (i != (formalDefVec.size() - 1)) {
365             LogInfo::MapleLogger() << ", ";
366         }
367     }
368     if (IsVarargs()) {
369         if (!hasPrintedFormal) {
370             LogInfo::MapleLogger() << "...";
371         } else {
372             LogInfo::MapleLogger() << ", ...";
373         }
374     }
375 
376     LogInfo::MapleLogger() << ") ";
377     GetReturnType()->Dump(1);
378 }
379 
Dump(bool withoutBody)380 void MIRFunction::Dump(bool withoutBody)
381 {
382     // skip the functions that are added during process methods in
383     // class and interface decls.  these has nothing in formals
384     // they do have paramtypelist_. this can not skip ones without args
385     // but for them at least the func decls are valid
386     if (GetAttr(FUNCATTR_optimized)) {
387         return;
388     }
389 
390     // save the module's curFunction and set it to the one currently Dump()ing
391     MIRFunction *savedFunc = module->CurFunction();
392     module->SetCurFunction(this);
393 
394     MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
395     DEBUG_ASSERT(symbol != nullptr, "symbol MIRSymbol is null");
396     if (!withoutBody) {
397         symbol->GetSrcPosition().DumpLoc(MIRSymbol::LastPrintedLineNumRef(), MIRSymbol::LastPrintedColumnNumRef());
398     }
399     LogInfo::MapleLogger() << "func "
400                            << "&" << symbol->GetName();
401     theMIRModule = module;
402     funcAttrs.DumpAttributes();
403 
404     if (symbol->GetWeakrefAttr().first) {
405         LogInfo::MapleLogger() << " weakref";
406         if (symbol->GetWeakrefAttr().second != UStrIdx(0)) {
407             LogInfo::MapleLogger() << " (";
408             PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->GetWeakrefAttr().second));
409             LogInfo::MapleLogger() << " )";
410         }
411     }
412 
413     if (symbol->sectionAttr != UStrIdx(0)) {
414         LogInfo::MapleLogger() << " section (";
415         PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->sectionAttr));
416         LogInfo::MapleLogger() << " )";
417     }
418 
419     if (module->GetFlavor() != kMmpl) {
420         DumpFlavorLoweredThanMmpl();
421     }
422 
423     // codeMemPool is nullptr, means maple_ir has been released for memory's sake
424     if (codeMemPool == nullptr) {
425         LogInfo::MapleLogger() << '\n';
426     } else if (GetBody() != nullptr && !withoutBody && symbol->GetStorageClass() != kScExtern) {
427         ResetInfoPrinted();  // this ensures funcinfo will be printed
428         GetBody()->Dump(0, module->GetFlavor() == kMmpl ? nullptr : GetSymTab(),
429                         module->GetFlavor() < kMmpl ? GetPregTab() : nullptr, false, true,
430                         module->GetFlavor());  // Dump body
431     } else {
432         LogInfo::MapleLogger() << '\n';
433     }
434 
435     // restore the curFunction
436     module->SetCurFunction(savedFunc);
437 }
438 
DumpUpFormal(int32 indent) const439 void MIRFunction::DumpUpFormal(int32 indent) const
440 {
441     PrintIndentation(indent + 1);
442 
443     LogInfo::MapleLogger() << "upformalsize " << GetUpFormalSize() << '\n';
444     if (localWordsTypeTagged != nullptr) {
445         PrintIndentation(indent + 1);
446         LogInfo::MapleLogger() << "formalWordsTypeTagged = [ ";
447         const auto *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
448         LogInfo::MapleLogger() << std::hex;
449         while (p <
450                reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetUpFormalSize()))) {
451             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
452             ++p;
453         }
454         LogInfo::MapleLogger() << std::dec << "]\n";
455     }
456 
457     if (formalWordsRefCounted != nullptr) {
458         PrintIndentation(indent + 1);
459         LogInfo::MapleLogger() << "formalWordsRefCounted = [ ";
460         const uint32 *p = reinterpret_cast<const uint32 *>(formalWordsRefCounted);
461         LogInfo::MapleLogger() << std::hex;
462         while (p <
463                reinterpret_cast<const uint32 *>(formalWordsRefCounted + BlockSize2BitVectorSize(GetUpFormalSize()))) {
464             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
465             ++p;
466         }
467         LogInfo::MapleLogger() << std::dec << "]\n";
468     }
469 }
470 
DumpFrame(int32 indent) const471 void MIRFunction::DumpFrame(int32 indent) const
472 {
473     PrintIndentation(indent + 1);
474 
475     LogInfo::MapleLogger() << "framesize " << static_cast<uint32>(GetFrameSize()) << '\n';
476     if (localWordsTypeTagged != nullptr) {
477         PrintIndentation(indent + 1);
478         LogInfo::MapleLogger() << "localWordsTypeTagged = [ ";
479         const uint32 *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
480         LogInfo::MapleLogger() << std::hex;
481         while (p < reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetFrameSize()))) {
482             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
483             ++p;
484         }
485         LogInfo::MapleLogger() << std::dec << "]\n";
486     }
487 
488     if (localWordsRefCounted != nullptr) {
489         PrintIndentation(indent + 1);
490         LogInfo::MapleLogger() << "localWordsRefCounted = [ ";
491         const uint32 *p = reinterpret_cast<const uint32 *>(localWordsRefCounted);
492         LogInfo::MapleLogger() << std::hex;
493         while (p < reinterpret_cast<const uint32 *>(localWordsRefCounted + BlockSize2BitVectorSize(GetFrameSize()))) {
494             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
495             ++p;
496         }
497         LogInfo::MapleLogger() << std::dec << "]\n";
498     }
499 }
500 
DumpScope()501 void MIRFunction::DumpScope()
502 {
503     scope->Dump(0);
504 }
505 
DumpFuncBody(int32 indent)506 void MIRFunction::DumpFuncBody(int32 indent)
507 {
508     LogInfo::MapleLogger() << "  funcid " << GetPuidxOrigin() << '\n';
509 
510     if (IsInfoPrinted()) {
511         return;
512     }
513 
514     SetInfoPrinted();
515 
516     if (GetUpFormalSize() > 0) {
517         DumpUpFormal(indent);
518     }
519 
520     if (GetFrameSize() > 0) {
521         DumpFrame(indent);
522     }
523 
524     if (GetOutParmSize() > 0) {
525         PrintIndentation(indent + 1);
526         LogInfo::MapleLogger() << "outparmsize " << GetOutParmSize() << '\n';
527     }
528 
529     if (GetModuleId() > 0) {
530         PrintIndentation(indent + 1);
531         LogInfo::MapleLogger() << "moduleID " << static_cast<uint32>(GetModuleId()) << '\n';
532     }
533 
534     if (GetFuncSize() > 0) {
535         PrintIndentation(indent + 1);
536         LogInfo::MapleLogger() << "funcSize " << GetFuncSize() << '\n';
537     }
538 
539     if (GetInfoVector().empty()) {
540         return;
541     }
542 
543     const MIRInfoVector &funcInfo = GetInfoVector();
544     const MapleVector<bool> &funcInfoIsString = InfoIsString();
545     PrintIndentation(indent + 1);
546     LogInfo::MapleLogger() << "funcinfo {\n";
547     size_t size = funcInfo.size();
548     constexpr int kIndentOffset = 2;
549     for (size_t i = 0; i < size; ++i) {
550         PrintIndentation(indent + kIndentOffset);
551         LogInfo::MapleLogger() << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(funcInfo[i].first) << " ";
552         if (!funcInfoIsString[i]) {
553             LogInfo::MapleLogger() << funcInfo[i].second;
554         } else {
555             LogInfo::MapleLogger() << "\""
556                                    << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(funcInfo[i].second))
557                                    << "\"";
558         }
559         if (i < size - 1) {
560             LogInfo::MapleLogger() << ",\n";
561         } else {
562             LogInfo::MapleLogger() << "}\n";
563         }
564     }
565     LogInfo::MapleLogger() << '\n';
566 }
567 
IsEmpty() const568 bool MIRFunction::IsEmpty() const
569 {
570     return (body == nullptr || body->IsEmpty());
571 }
572 
IsClinit() const573 bool MIRFunction::IsClinit() const
574 {
575     const std::string clinitPostfix = "_7C_3Cclinit_3E_7C_28_29V";
576     const std::string &funcName = this->GetName();
577     // this does not work for smali files like test/511-clinit-interface/smali/BogusInterface.smali,
578     // which is decorated without "constructor".
579     return StringUtils::EndsWith(funcName, clinitPostfix);
580 }
581 
GetInfo(GStrIdx strIdx) const582 uint32 MIRFunction::GetInfo(GStrIdx strIdx) const
583 {
584     for (const auto &item : info) {
585         if (item.first == strIdx) {
586             return item.second;
587         }
588     }
589     DEBUG_ASSERT(false, "get info error");
590     return 0;
591 }
592 
GetInfo(const std::string & string) const593 uint32 MIRFunction::GetInfo(const std::string &string) const
594 {
595     GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(string);
596     return GetInfo(strIdx);
597 }
598 
OverrideBaseClassFuncNames(GStrIdx strIdx)599 void MIRFunction::OverrideBaseClassFuncNames(GStrIdx strIdx)
600 {
601     baseClassStrIdx.reset();
602     baseFuncStrIdx.reset();
603     SetBaseClassFuncNames(strIdx);
604 }
605 
606 // there are two ways to represent the delimiter: '|' or "_7C"
607 // where 7C is the ascii value of char '|' in hex
SetBaseClassFuncNames(GStrIdx strIdx)608 void MIRFunction::SetBaseClassFuncNames(GStrIdx strIdx)
609 {
610     if (baseClassStrIdx != 0u || baseFuncStrIdx != 0u) {
611         return;
612     }
613     const std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx);
614     std::string delimiter = "|";
615     uint32 width = 1;  // delimiter width
616     size_t pos = name.find(delimiter);
617     if (pos == std::string::npos) {
618         delimiter = namemangler::kNameSplitterStr;
619         width = 3;  // delimiter "_7C" width is 3
620         pos = name.find(delimiter);
621         // make sure it is not __7C, but ___7C ok. stop find loop if last 2 char is '_'
622         while (pos != std::string::npos &&
623                ((pos == 1 && name[pos - 1] == '_') ||
624                 (pos > 1 && name[pos - 1] == '_' && name[pos - 2] != '_'))) {  // last 2 char is '_'
625             pos = name.find(delimiter, pos + width);
626         }
627     }
628     if (pos != std::string::npos && pos > 0) {
629         const std::string className = name.substr(0, pos);
630         baseClassStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(className);
631         std::string funcNameWithType = name.substr(pos + width, name.length() - pos - width);
632         baseFuncWithTypeStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcNameWithType);
633         size_t index = name.find(namemangler::kRightBracketStr);
634         if (index != std::string::npos) {
635             size_t posEnd = index + (std::string(namemangler::kRightBracketStr)).length();
636             DEBUG_ASSERT(posEnd - pos > width, "must not be zero");
637             funcNameWithType = name.substr(pos + width, posEnd - pos - width);
638         }
639         baseFuncSigStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcNameWithType);
640         size_t newPos = name.find(delimiter, pos + width);
641         // make sure it is not __7C, but ___7C ok. stop find loop if last 2 char is '_'
642         while (newPos != std::string::npos && newPos >= 2 && (name[newPos - 1] == '_' &&
643                name[newPos - 2] != '_')) {  // last 2 char is '_'
644             newPos = name.find(delimiter, newPos + width);
645         }
646         if (newPos != 0) {
647             DEBUG_ASSERT(newPos - pos > width, "must not be zero");
648             std::string funcName = name.substr(pos + width, newPos - pos - width);
649             baseFuncStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName);
650             std::string signature = name.substr(newPos + width, name.length() - newPos - width);
651             signatureStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(signature);
652         }
653         return;
654     }
655     baseFuncStrIdx = strIdx;
656 }
657 
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst) const658 const MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst) const
659 {
660     return idx.Islocal() ? GetSymbolTabItem(idx.Idx(), checkFirst)
661                          : GlobalTables::GetGsymTable().GetSymbolFromStidx(idx.Idx(), checkFirst);
662 }
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst)663 MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst)
664 {
665     DEBUG_ASSERT(const_cast<MIRSymbol *>(const_cast<const MIRFunction *>(this)->
666                  GetLocalOrGlobalSymbol(idx, checkFirst)) != nullptr,
667                  "this->GetLocalOrGlobalSymbol(idx, checkFirst) should not be nullptr");
668     return const_cast<MIRSymbol *>(const_cast<const MIRFunction *>(this)->GetLocalOrGlobalSymbol(idx, checkFirst));
669 }
670 
GetNodeType(const BaseNode & node) const671 const MIRType *MIRFunction::GetNodeType(const BaseNode &node) const
672 {
673     if (node.GetOpCode() == OP_dread) {
674         const MIRSymbol *sym = GetLocalOrGlobalSymbol(static_cast<const DreadNode &>(node).GetStIdx());
675         CHECK_NULL_FATAL(sym);
676         return GlobalTables::GetTypeTable().GetTypeFromTyIdx(sym->GetTyIdx());
677     }
678     if (node.GetOpCode() == OP_regread) {
679         const auto &nodeReg = static_cast<const RegreadNode &>(node);
680         const MIRPreg *pReg = GetPregTab()->PregFromPregIdx(nodeReg.GetRegIdx());
681         if (pReg->GetPrimType() == PTY_ref) {
682             return pReg->GetMIRType();
683         }
684     }
685     return nullptr;
686 }
687 
EnterFormals()688 void MIRFunction::EnterFormals()
689 {
690     for (auto &formalDef : formalDefVec) {
691         formalDef.formalSym = symTab->CreateSymbol(kScopeLocal);
692         formalDef.formalSym->SetStorageClass(kScFormal);
693         formalDef.formalSym->SetNameStrIdx(formalDef.formalStrIdx);
694         formalDef.formalSym->SetTyIdx(formalDef.formalTyIdx);
695         formalDef.formalSym->SetAttrs(formalDef.formalAttrs);
696         const std::string &formalName = GlobalTables::GetStrTable().GetStringFromStrIdx(formalDef.formalStrIdx);
697         if (!isdigit(formalName.front())) {
698             formalDef.formalSym->SetSKind(kStVar);
699             (void)symTab->AddToStringSymbolMap(*formalDef.formalSym);
700         } else {
701             formalDef.formalSym->SetSKind(kStPreg);
702             uint32 thepregno = static_cast<uint32>(std::stoi(formalName));
703             MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDef.formalTyIdx);
704             PrimType pType = mirType->GetPrimType();
705             // if mirType info is not needed, set mirType to nullptr
706             if (pType != PTY_ref && pType != PTY_ptr) {
707                 mirType = nullptr;
708             } else if (pType == PTY_ptr && mirType->IsMIRPtrType()) {
709                 MIRType *pointedType = static_cast<MIRPtrType *>(mirType)->GetPointedType();
710                 if (pointedType == nullptr || pointedType->GetKind() != kTypeFunction) {
711                     mirType = nullptr;
712                 }
713             }
714             PregIdx pregIdx = pregTab->EnterPregNo(thepregno, pType, mirType);
715             MIRPreg *preg = pregTab->PregFromPregIdx(pregIdx);
716             formalDef.formalSym->SetPreg(preg);
717         }
718     }
719 }
720 
NewBody()721 void MIRFunction::NewBody()
722 {
723     codeMemPool = GetCodeMemPool();
724     SetBody(codeMemPool->New<BlockNode>());
725     SetLastPosBody(codeMemPool->New<BlockNode>());
726     // If mir_function.has been seen as a declaration, its symtab has to be moved
727     // from module mempool to function mempool.
728     MIRSymbolTable *oldSymTable = GetSymTab();
729     MIRPregTable *oldPregTable = GetPregTab();
730     MIRTypeNameTable *oldTypeNameTable = typeNameTab;
731     MIRLabelTable *oldLabelTable = GetLabelTab();
732     symTab = module->GetMemPool()->New<MIRSymbolTable>(module->GetMPAllocator());
733     pregTab = module->GetMemPool()->New<MIRPregTable>(&module->GetMPAllocator());
734     typeNameTab = module->GetMemPool()->New<MIRTypeNameTable>(module->GetMPAllocator());
735     labelTab = module->GetMemPool()->New<MIRLabelTable>(module->GetMPAllocator());
736 
737     if (oldSymTable == nullptr) {
738         // formals not yet entered into symTab; enter them now
739         EnterFormals();
740     } else {
741         for (size_t i = 1; i < oldSymTable->GetSymbolTableSize(); ++i) {
742             (void)GetSymTab()->AddStOutside(oldSymTable->GetSymbolFromStIdx(i));
743         }
744     }
745     if (oldPregTable != nullptr) {
746         for (size_t i = 1; i < oldPregTable->Size(); ++i) {
747             (void)GetPregTab()->AddPreg(*oldPregTable->PregFromPregIdx(static_cast<PregIdx>(i)));
748         }
749     }
750     if (oldTypeNameTable != nullptr) {
751         DEBUG_ASSERT(oldTypeNameTable->Size() == typeNameTab->Size(),
752                      "Does not expect to process typeNameTab in MIRFunction::NewBody");
753     }
754     if (oldLabelTable != nullptr) {
755         DEBUG_ASSERT(oldLabelTable->Size() == GetLabelTab()->Size(),
756                      "Does not expect to process labelTab in MIRFunction::NewBody");
757     }
758 }
759 
760 #ifdef DEBUGME
SetUpGDBEnv()761 void MIRFunction::SetUpGDBEnv()
762 {
763     if (codeMemPool != nullptr) {
764         delete codeMemPool;
765     }
766     codeMemPool = new ThreadLocalMemPool(memPoolCtrler, "tmp debug");
767     codeMemPoolAllocator.SetMemPool(codeMemPool);
768 }
769 
ResetGDBEnv()770 void MIRFunction::ResetGDBEnv()
771 {
772     delete codeMemPool;
773     codeMemPool = nullptr;
774 }
775 #endif
776 }  // namespace maple
777