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