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 "printing.h"
18
19 namespace {
20 using namespace maple;
21 enum FuncProp : uint32_t {
22 kFuncPropHasCall = 1U, // the function has call
23 #ifdef ARK_LITECG_DEBUG
24 kFuncPropInfoPrinted = 1U << 3, // to avoid printing frameSize/moduleid/funcSize info more
25 // than once per function since they
26 // can only be printed at the beginning of a block
27 #endif
28 };
29 } // namespace
30
31 namespace maple {
GetFuncSymbol() const32 const MIRSymbol *MIRFunction::GetFuncSymbol() const
33 {
34 return GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
35 }
GetFuncSymbol()36 MIRSymbol *MIRFunction::GetFuncSymbol()
37 {
38 const MIRFunction *mirFunc = const_cast<const MIRFunction *>(this);
39 DEBUG_ASSERT(mirFunc != nullptr, "null ptr check");
40 return const_cast<MIRSymbol *>(mirFunc->GetFuncSymbol());
41 }
42
GetName() const43 const std::string &MIRFunction::GetName() const
44 {
45 MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
46 DEBUG_ASSERT(mirSymbol != nullptr, "null ptr check");
47 return mirSymbol->GetName();
48 }
49
50 #ifdef ARK_LITECG_DEBUG
GetNameStrIdx() const51 GStrIdx MIRFunction::GetNameStrIdx() const
52 {
53 MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
54 DEBUG_ASSERT(mirSymbol != nullptr, "null ptr check");
55 return mirSymbol->GetNameStrIdx();
56 }
57 #endif
58
GetBaseClassName() const59 const std::string &MIRFunction::GetBaseClassName() const
60 {
61 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseClassStrIdx);
62 }
63
GetBaseFuncName() const64 const std::string &MIRFunction::GetBaseFuncName() const
65 {
66 return GlobalTables::GetStrTable().GetStringFromStrIdx(baseFuncStrIdx);
67 }
68
GetReturnType() const69 const MIRType *MIRFunction::GetReturnType() const
70 {
71 CHECK_FATAL(funcType != nullptr, "funcType should not be nullptr");
72 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx());
73 }
GetReturnType()74 MIRType *MIRFunction::GetReturnType()
75 {
76 return const_cast<MIRType *>(const_cast<const MIRFunction *>(this)->GetReturnType());
77 }
78
GetNthParamType(size_t i) const79 const MIRType *MIRFunction::GetNthParamType(size_t i) const
80 {
81 CHECK_FATAL(funcType != nullptr, "funcType should not be nullptr");
82 DEBUG_ASSERT(i < funcType->GetParamTypeList().size(), "array index out of range");
83 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetParamTypeList()[i]);
84 }
GetNthParamType(size_t i)85 MIRType *MIRFunction::GetNthParamType(size_t i)
86 {
87 return const_cast<MIRType *>(const_cast<const MIRFunction *>(this)->GetNthParamType(i));
88 }
89
90 // reconstruct formals, and return a new MIRFuncType
ReconstructFormals(const std::vector<MIRSymbol * > & symbols,bool clearOldArgs)91 MIRFuncType *MIRFunction::ReconstructFormals(const std::vector<MIRSymbol *> &symbols, bool clearOldArgs)
92 {
93 auto *newFuncType = static_cast<MIRFuncType *>(funcType->CopyMIRTypeNode());
94 if (clearOldArgs) {
95 formalDefVec.clear();
96 newFuncType->GetParamTypeList().clear();
97 newFuncType->GetParamAttrsList().clear();
98 }
99 for (auto *symbol : symbols) {
100 FormalDef formalDef(symbol->GetNameStrIdx(), symbol, symbol->GetTyIdx(), symbol->GetAttrs());
101 formalDefVec.push_back(formalDef);
102 newFuncType->GetParamTypeList().push_back(symbol->GetTyIdx());
103 newFuncType->GetParamAttrsList().push_back(symbol->GetAttrs());
104 }
105 return newFuncType;
106 }
107
UpdateFuncTypeAndFormalsAndReturnType(const std::vector<MIRSymbol * > & symbols,const TyIdx & retTyIdx,bool clearOldArgs)108 void MIRFunction::UpdateFuncTypeAndFormalsAndReturnType(const std::vector<MIRSymbol *> &symbols, const TyIdx &retTyIdx,
109 bool clearOldArgs)
110 {
111 auto *newFuncType = ReconstructFormals(symbols, clearOldArgs);
112 newFuncType->SetRetTyIdx(retTyIdx);
113 auto newFuncTypeIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(newFuncType);
114 funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(newFuncTypeIdx));
115 delete newFuncType;
116 }
117
GetOrCreateLableIdxFromName(const std::string & name)118 LabelIdx MIRFunction::GetOrCreateLableIdxFromName(const std::string &name)
119 {
120 GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name);
121 LabelIdx labelIdx = GetLabelTab()->GetLabelIdxFromStrIdx(strIdx);
122 if (labelIdx == 0) {
123 labelIdx = GetLabelTab()->CreateLabel();
124 GetLabelTab()->SetSymbolFromStIdx(labelIdx, strIdx);
125 GetLabelTab()->AddToStringLabelMap(labelIdx);
126 }
127 return labelIdx;
128 }
129
HasCall() const130 bool MIRFunction::HasCall() const
131 {
132 return flag & kFuncPropHasCall;
133 }
SetHasCall()134 void MIRFunction::SetHasCall()
135 {
136 flag |= kFuncPropHasCall;
137 }
138
139 #ifdef ARK_LITECG_DEBUG
IsInfoPrinted() const140 bool MIRFunction::IsInfoPrinted() const
141 {
142 return flag & kFuncPropInfoPrinted;
143 }
144
SetInfoPrinted()145 void MIRFunction::SetInfoPrinted()
146 {
147 flag |= kFuncPropInfoPrinted;
148 }
149
ResetInfoPrinted()150 void MIRFunction::ResetInfoPrinted()
151 {
152 flag &= ~kFuncPropInfoPrinted;
153 }
154
DumpAttributes() const155 void FuncAttrs::DumpAttributes() const
156 {
157 // parse no content of attr
158 #define STRING(s) #s
159 #define FUNC_ATTR
160 #define NOCONTENT_ATTR
161 #define ATTR(AT) \
162 if (GetAttr(FUNCATTR_##AT)) { \
163 LogInfo::MapleLogger() << " " << STRING(AT); \
164 }
165 #include "all_attributes.def"
166 #undef ATTR
167 #undef NOCONTENT_ATTR
168 #undef FUNC_ATTR
169 // parse content of attr
170 if (GetAttr(FUNCATTR_alias) && !GetAliasFuncName().empty()) {
171 LogInfo::MapleLogger() << " alias ( \"" << GetAliasFuncName() << "\" )";
172 }
173 if (GetAttr(FUNCATTR_constructor_priority) && GetConstructorPriority() != -1) {
174 LogInfo::MapleLogger() << " constructor_priority ( " << GetConstructorPriority() << " )";
175 }
176 if (GetAttr(FUNCATTR_destructor_priority) && GetDestructorPriority() != -1) {
177 LogInfo::MapleLogger() << " destructor_priority ( " << GetDestructorPriority() << " )";
178 }
179 if (GetAttr(FUNCATTR_frame_pointer) && !framePointer.empty()) {
180 LogInfo::MapleLogger() << " frame-pointer ( " << framePointer << " )";
181 }
182 if (GetAttr(FUNCATTR_frame_reserved_slots) && GetFrameResverdSlot() != 0) {
183 LogInfo::MapleLogger() << " frame-reserved-slots ( " << GetFrameResverdSlot() << " )";
184 }
185 }
186
DumpFlavorLoweredThanMmpl() const187 void MIRFunction::DumpFlavorLoweredThanMmpl() const
188 {
189 LogInfo::MapleLogger() << " (";
190
191 // Dump arguments
192 bool hasPrintedFormal = false;
193 for (uint32 i = 0; i < formalDefVec.size(); i++) {
194 MIRSymbol *symbol = formalDefVec[i].formalSym;
195 if (symbol == nullptr &&
196 (formalDefVec[i].formalStrIdx.GetIdx() == 0 ||
197 GlobalTables::GetStrTable().GetStringFromStrIdx(formalDefVec[i].formalStrIdx).empty())) {
198 break;
199 }
200 hasPrintedFormal = true;
201 if (symbol == nullptr) {
202 LogInfo::MapleLogger() << "var %"
203 << GlobalTables::GetStrTable().GetStringFromStrIdx(formalDefVec[i].formalStrIdx)
204 << " ";
205 } else {
206 if (symbol->GetSKind() != kStPreg) {
207 LogInfo::MapleLogger() << "var %" << symbol->GetName() << " ";
208 } else {
209 LogInfo::MapleLogger() << "reg %" << symbol->GetPreg()->GetPregNo() << " ";
210 }
211 }
212 MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDefVec[i].formalTyIdx);
213 constexpr uint8 indent = 2;
214 ty->Dump(indent);
215 if (symbol != nullptr) {
216 symbol->GetAttrs().DumpAttributes();
217 } else {
218 formalDefVec[i].formalAttrs.DumpAttributes();
219 }
220 DEBUG_ASSERT(formalDefVec.size() > 0, "must not be zero");
221 if (i != (formalDefVec.size() - 1)) {
222 LogInfo::MapleLogger() << ", ";
223 }
224 }
225 if (IsVarargs()) {
226 if (!hasPrintedFormal) {
227 LogInfo::MapleLogger() << "...";
228 } else {
229 LogInfo::MapleLogger() << ", ...";
230 }
231 }
232
233 LogInfo::MapleLogger() << ") ";
234 GetReturnType()->Dump(1);
235 }
236
Dump(bool withoutBody)237 void MIRFunction::Dump(bool withoutBody)
238 {
239 // skip the functions that are added during process methods in
240 // class and interface decls. these has nothing in formals
241 // they do have paramtypelist_. this can not skip ones without args
242 // but for them at least the func decls are valid
243 if (GetAttr(FUNCATTR_optimized)) {
244 return;
245 }
246
247 // save the module's curFunction and set it to the one currently Dump()ing
248 MIRFunction *savedFunc = module->CurFunction();
249 module->SetCurFunction(this);
250
251 MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx());
252 DEBUG_ASSERT(symbol != nullptr, "symbol MIRSymbol is null");
253 if (!withoutBody) {
254 symbol->GetSrcPosition().DumpLoc(MIRSymbol::LastPrintedLineNumRef(), MIRSymbol::LastPrintedColumnNumRef());
255 }
256 LogInfo::MapleLogger() << "func "
257 << "&" << symbol->GetName();
258 theMIRModule = module;
259 funcAttrs.DumpAttributes();
260
261 if (symbol->GetWeakrefAttr().first) {
262 LogInfo::MapleLogger() << " weakref";
263 if (symbol->GetWeakrefAttr().second != UStrIdx(0)) {
264 LogInfo::MapleLogger() << " (";
265 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->GetWeakrefAttr().second));
266 LogInfo::MapleLogger() << " )";
267 }
268 }
269
270 if (symbol->sectionAttr != UStrIdx(0)) {
271 LogInfo::MapleLogger() << " section (";
272 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->sectionAttr));
273 LogInfo::MapleLogger() << " )";
274 }
275
276 if (module->GetFlavor() != kMmpl) {
277 DumpFlavorLoweredThanMmpl();
278 }
279
280 // codeMemPool is nullptr, means maple_ir has been released for memory's sake
281 if (codeMemPool == nullptr) {
282 LogInfo::MapleLogger() << '\n';
283 } else if (GetBody() != nullptr && !withoutBody && symbol->GetStorageClass() != kScExtern) {
284 ResetInfoPrinted(); // this ensures funcinfo will be printed
285 GetBody()->Dump(0, module->GetFlavor() == kMmpl ? nullptr : GetSymTab(),
286 module->GetFlavor() < kMmpl ? GetPregTab() : nullptr, false, true,
287 module->GetFlavor()); // Dump body
288 } else {
289 LogInfo::MapleLogger() << '\n';
290 }
291
292 // restore the curFunction
293 module->SetCurFunction(savedFunc);
294 }
295
DumpUpFormal(int32 indent) const296 void MIRFunction::DumpUpFormal(int32 indent) const
297 {
298 PrintIndentation(indent + 1);
299
300 LogInfo::MapleLogger() << "upformalsize " << GetUpFormalSize() << '\n';
301 if (localWordsTypeTagged != nullptr) {
302 PrintIndentation(indent + 1);
303 LogInfo::MapleLogger() << "formalWordsTypeTagged = [ ";
304 const auto *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
305 LogInfo::MapleLogger() << std::hex;
306 while (p <
307 reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetUpFormalSize()))) {
308 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
309 ++p;
310 }
311 LogInfo::MapleLogger() << std::dec << "]\n";
312 }
313
314 if (formalWordsRefCounted != nullptr) {
315 PrintIndentation(indent + 1);
316 LogInfo::MapleLogger() << "formalWordsRefCounted = [ ";
317 const uint32 *p = reinterpret_cast<const uint32 *>(formalWordsRefCounted);
318 LogInfo::MapleLogger() << std::hex;
319 while (p <
320 reinterpret_cast<const uint32 *>(formalWordsRefCounted + BlockSize2BitVectorSize(GetUpFormalSize()))) {
321 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
322 ++p;
323 }
324 LogInfo::MapleLogger() << std::dec << "]\n";
325 }
326 }
327
DumpFrame(int32 indent) const328 void MIRFunction::DumpFrame(int32 indent) const
329 {
330 PrintIndentation(indent + 1);
331
332 LogInfo::MapleLogger() << "framesize " << static_cast<uint32>(GetFrameSize()) << '\n';
333 if (localWordsTypeTagged != nullptr) {
334 PrintIndentation(indent + 1);
335 LogInfo::MapleLogger() << "localWordsTypeTagged = [ ";
336 const uint32 *p = reinterpret_cast<const uint32 *>(localWordsTypeTagged);
337 LogInfo::MapleLogger() << std::hex;
338 while (p < reinterpret_cast<const uint32 *>(localWordsTypeTagged + BlockSize2BitVectorSize(GetFrameSize()))) {
339 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
340 ++p;
341 }
342 LogInfo::MapleLogger() << std::dec << "]\n";
343 }
344
345 if (localWordsRefCounted != nullptr) {
346 PrintIndentation(indent + 1);
347 LogInfo::MapleLogger() << "localWordsRefCounted = [ ";
348 const uint32 *p = reinterpret_cast<const uint32 *>(localWordsRefCounted);
349 LogInfo::MapleLogger() << std::hex;
350 while (p < reinterpret_cast<const uint32 *>(localWordsRefCounted + BlockSize2BitVectorSize(GetFrameSize()))) {
351 LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
352 ++p;
353 }
354 LogInfo::MapleLogger() << std::dec << "]\n";
355 }
356 }
357
DumpFuncBody(int32 indent)358 void MIRFunction::DumpFuncBody(int32 indent)
359 {
360 LogInfo::MapleLogger() << " funcid " << GetPuidxOrigin() << '\n';
361
362 if (IsInfoPrinted()) {
363 return;
364 }
365
366 SetInfoPrinted();
367
368 if (GetUpFormalSize() > 0) {
369 DumpUpFormal(indent);
370 }
371
372 if (GetFrameSize() > 0) {
373 DumpFrame(indent);
374 }
375
376 if (GetOutParmSize() > 0) {
377 PrintIndentation(indent + 1);
378 LogInfo::MapleLogger() << "outparmsize " << GetOutParmSize() << '\n';
379 }
380
381 if (GetModuleId() > 0) {
382 PrintIndentation(indent + 1);
383 LogInfo::MapleLogger() << "moduleID " << static_cast<uint32>(GetModuleId()) << '\n';
384 }
385
386 if (GetFuncSize() > 0) {
387 PrintIndentation(indent + 1);
388 LogInfo::MapleLogger() << "funcSize " << GetFuncSize() << '\n';
389 }
390
391 if (GetInfoVector().empty()) {
392 return;
393 }
394
395 const MIRInfoVector &funcInfo = GetInfoVector();
396 const MapleVector<bool> &funcInfoIsString = InfoIsString();
397 PrintIndentation(indent + 1);
398 LogInfo::MapleLogger() << "funcinfo {\n";
399 size_t size = funcInfo.size();
400 constexpr int kIndentOffset = 2;
401 for (size_t i = 0; i < size; ++i) {
402 PrintIndentation(indent + kIndentOffset);
403 LogInfo::MapleLogger() << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(funcInfo[i].first) << " ";
404 if (!funcInfoIsString[i]) {
405 LogInfo::MapleLogger() << funcInfo[i].second;
406 } else {
407 LogInfo::MapleLogger() << "\""
408 << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(funcInfo[i].second))
409 << "\"";
410 }
411 if (i < size - 1) {
412 LogInfo::MapleLogger() << ",\n";
413 } else {
414 LogInfo::MapleLogger() << "}\n";
415 }
416 }
417 LogInfo::MapleLogger() << '\n';
418 }
419 #endif
420
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst) const421 const MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst) const
422 {
423 return idx.Islocal() ? GetSymbolTabItem(idx.Idx(), checkFirst)
424 : GlobalTables::GetGsymTable().GetSymbolFromStidx(idx.Idx(), checkFirst);
425 }
GetLocalOrGlobalSymbol(const StIdx & idx,bool checkFirst)426 MIRSymbol *MIRFunction::GetLocalOrGlobalSymbol(const StIdx &idx, bool checkFirst)
427 {
428 DEBUG_ASSERT(const_cast<MIRSymbol *>(const_cast<const MIRFunction *>(this)->
429 GetLocalOrGlobalSymbol(idx, checkFirst)) != nullptr,
430 "this->GetLocalOrGlobalSymbol(idx, checkFirst) should not be nullptr");
431 return const_cast<MIRSymbol *>(const_cast<const MIRFunction *>(this)->GetLocalOrGlobalSymbol(idx, checkFirst));
432 }
433
EnterFormals()434 void MIRFunction::EnterFormals()
435 {
436 for (auto &formalDef : formalDefVec) {
437 formalDef.formalSym = symTab->CreateSymbol(kScopeLocal);
438 formalDef.formalSym->SetStorageClass(kScFormal);
439 formalDef.formalSym->SetNameStrIdx(formalDef.formalStrIdx);
440 formalDef.formalSym->SetTyIdx(formalDef.formalTyIdx);
441 formalDef.formalSym->SetAttrs(formalDef.formalAttrs);
442 const std::string &formalName = GlobalTables::GetStrTable().GetStringFromStrIdx(formalDef.formalStrIdx);
443 if (!isdigit(formalName.front())) {
444 formalDef.formalSym->SetSKind(kStVar);
445 (void)symTab->AddToStringSymbolMap(*formalDef.formalSym);
446 } else {
447 formalDef.formalSym->SetSKind(kStPreg);
448 uint32 thepregno = static_cast<uint32>(std::stoi(formalName));
449 MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDef.formalTyIdx);
450 PrimType pType = mirType->GetPrimType();
451 // if mirType info is not needed, set mirType to nullptr
452 if (pType != PTY_ref && pType != PTY_ptr) {
453 mirType = nullptr;
454 } else if (pType == PTY_ptr && mirType->IsMIRPtrType()) {
455 MIRType *pointedType = static_cast<MIRPtrType *>(mirType)->GetPointedType();
456 if (pointedType == nullptr || pointedType->GetKind() != kTypeFunction) {
457 mirType = nullptr;
458 }
459 }
460 PregIdx pregIdx = pregTab->EnterPregNo(thepregno, pType, mirType);
461 MIRPreg *preg = pregTab->PregFromPregIdx(pregIdx);
462 formalDef.formalSym->SetPreg(preg);
463 }
464 }
465 }
466
NewBody()467 void MIRFunction::NewBody()
468 {
469 codeMemPool = GetCodeMemPool();
470 SetBody(codeMemPool->New<BlockNode>());
471 SetLastPosBody(codeMemPool->New<BlockNode>());
472 // If mir_function.has been seen as a declaration, its symtab has to be moved
473 // from module mempool to function mempool.
474 MIRSymbolTable *oldSymTable = GetSymTab();
475 MIRPregTable *oldPregTable = GetPregTab();
476 MIRTypeNameTable *oldTypeNameTable = typeNameTab;
477 MIRLabelTable *oldLabelTable = GetLabelTab();
478 symTab = module->GetMemPool()->New<MIRSymbolTable>(module->GetMPAllocator());
479 pregTab = module->GetMemPool()->New<MIRPregTable>(&module->GetMPAllocator());
480 typeNameTab = module->GetMemPool()->New<MIRTypeNameTable>(module->GetMPAllocator());
481 labelTab = module->GetMemPool()->New<MIRLabelTable>(module->GetMPAllocator());
482
483 if (oldSymTable == nullptr) {
484 // formals not yet entered into symTab; enter them now
485 EnterFormals();
486 } else {
487 for (size_t i = 1; i < oldSymTable->GetSymbolTableSize(); ++i) {
488 (void)GetSymTab()->AddStOutside(oldSymTable->GetSymbolFromStIdx(i));
489 }
490 }
491 if (oldPregTable != nullptr) {
492 for (size_t i = 1; i < oldPregTable->Size(); ++i) {
493 (void)GetPregTab()->AddPreg(*oldPregTable->PregFromPregIdx(static_cast<PregIdx>(i)));
494 }
495 }
496 if (oldTypeNameTable != nullptr) {
497 DEBUG_ASSERT(oldTypeNameTable->Size() == typeNameTab->Size(),
498 "Does not expect to process typeNameTab in MIRFunction::NewBody");
499 }
500 if (oldLabelTable != nullptr) {
501 DEBUG_ASSERT(oldLabelTable->Size() == GetLabelTab()->Size(),
502 "Does not expect to process labelTab in MIRFunction::NewBody");
503 }
504 }
505 } // namespace maple
506