• 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_module.h"
17 #include "mir_const.h"
18 #include "mir_preg.h"
19 #include "mir_function.h"
20 #include "mir_builder.h"
21 #include "debug_info.h"
22 #include "intrinsics.h"
23 #include "bin_mplt.h"
24 
25 namespace maple {
26 #if MIR_FEATURE_FULL  // to avoid compilation error when MIR_FEATURE_FULL=0
MIRModule(const std::string & fn)27 MIRModule::MIRModule(const std::string &fn)
28     : memPool(new ThreadShareMemPool(memPoolCtrler, "maple_ir mempool")),
29       pragmaMemPool(memPoolCtrler.NewMemPool("pragma mempool", false /* isLcalPool */)),
30       memPoolAllocator(memPool),
31       pragmaMemPoolAllocator(pragmaMemPool),
32       functionList(memPoolAllocator.Adapter()),
33       importedMplt(memPoolAllocator.Adapter()),
34       typeDefOrder(memPoolAllocator.Adapter()),
35       externStructTypeSet(std::less<TyIdx>(), memPoolAllocator.Adapter()),
36       symbolSet(std::less<StIdx>(), memPoolAllocator.Adapter()),
37       symbolDefOrder(memPoolAllocator.Adapter()),
38       out(LogInfo::MapleLogger()),
39       fileName(fn),
40       fileInfo(memPoolAllocator.Adapter()),
41       fileInfoIsString(memPoolAllocator.Adapter()),
42       fileData(memPoolAllocator.Adapter()),
43       srcFileInfo(memPoolAllocator.Adapter()),
44       importFiles(memPoolAllocator.Adapter()),
45       importPaths(memPoolAllocator.Adapter()),
46       asmDecls(memPoolAllocator.Adapter()),
47       classList(memPoolAllocator.Adapter()),
48       optimizedFuncs(memPoolAllocator.Adapter()),
49       optimizedFuncsType(memPoolAllocator.Adapter()),
50       puIdxFieldInitializedMap(std::less<PUIdx>(), memPoolAllocator.Adapter()),
51       inliningGlobals(memPoolAllocator.Adapter()),
52       partO2FuncList(memPoolAllocator.Adapter()),
53       safetyWarningMap(memPoolAllocator.Adapter())
54 {
55     GlobalTables::GetGsymTable().SetModule(this);
56     typeNameTab = memPool->New<MIRTypeNameTable>(memPoolAllocator);
57     mirBuilder = memPool->New<MIRBuilder>(this);
58     dbgInfo = memPool->New<DebugInfo>(this);
59     IntrinDesc::InitMIRModule(this);
60 }
61 
~MIRModule()62 MIRModule::~MIRModule()
63 {
64     for (MIRFunction *mirFunc : functionList) {
65         mirFunc->ReleaseCodeMemory();
66     }
67     ReleasePragmaMemPool();
68     delete memPool;
69     delete binMplt;
70 }
71 
CurFuncCodeMemPool() const72 MemPool *MIRModule::CurFuncCodeMemPool() const
73 {
74     DEBUG_ASSERT(CurFunction() != nullptr, "CurFunction() should not be nullptr");
75     if (useFuncCodeMemPoolTmp) {
76         return CurFunction()->GetCodeMemPoolTmp();
77     }
78     return CurFunction()->GetCodeMemPool();
79 }
80 
CurFuncCodeMemPoolAllocator() const81 MapleAllocator *MIRModule::CurFuncCodeMemPoolAllocator() const
82 {
83     MIRFunction *curFunc = CurFunction();
84     CHECK_FATAL(curFunc != nullptr, "curFunction is null");
85     return &curFunc->GetCodeMempoolAllocator();
86 }
87 
GetCurFuncCodeMPAllocator() const88 MapleAllocator &MIRModule::GetCurFuncCodeMPAllocator() const
89 {
90     MIRFunction *curFunc = CurFunction();
91     CHECK_FATAL(curFunc != nullptr, "curFunction is null");
92     return curFunc->GetCodeMPAllocator();
93 }
94 
AddExternStructType(TyIdx tyIdx)95 void MIRModule::AddExternStructType(TyIdx tyIdx)
96 {
97     (void)externStructTypeSet.insert(tyIdx);
98 }
99 
AddExternStructType(const MIRType * t)100 void MIRModule::AddExternStructType(const MIRType *t)
101 {
102     DEBUG_ASSERT(t != nullptr, "MIRType is null");
103     (void)externStructTypeSet.insert(t->GetTypeIndex());
104 }
105 
AddSymbol(StIdx stIdx)106 void MIRModule::AddSymbol(StIdx stIdx)
107 {
108     auto it = symbolSet.find(stIdx);
109     if (it == symbolSet.end()) {
110         symbolDefOrder.push_back(stIdx);
111     }
112     (void)symbolSet.insert(stIdx);
113 }
114 
AddSymbol(const MIRSymbol * s)115 void MIRModule::AddSymbol(const MIRSymbol *s)
116 {
117     DEBUG_ASSERT(s != nullptr, "s is null");
118     AddSymbol(s->GetStIdx());
119 }
120 
DumpGlobals(bool emitStructureType) const121 void MIRModule::DumpGlobals(bool emitStructureType) const
122 {
123     if (flavor != kFlavorUnknown) {
124         LogInfo::MapleLogger() << "flavor " << flavor << '\n';
125     }
126     if (srcLang != kSrcLangUnknown) {
127         LogInfo::MapleLogger() << "srclang " << srcLang << '\n';
128     }
129     LogInfo::MapleLogger() << "id " << id << '\n';
130     if (globalMemSize != 0) {
131         LogInfo::MapleLogger() << "globalmemsize " << globalMemSize << '\n';
132     }
133     if (globalBlkMap != nullptr) {
134         LogInfo::MapleLogger() << "globalmemmap = [ ";
135         auto *p = reinterpret_cast<uint32 *>(globalBlkMap);
136         LogInfo::MapleLogger() << std::hex;
137         while (p < reinterpret_cast<uint32 *>(globalBlkMap + globalMemSize)) {
138             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
139             p++;
140         }
141         LogInfo::MapleLogger() << std::dec << "]\n";
142     }
143     if (globalWordsTypeTagged != nullptr) {
144         LogInfo::MapleLogger() << "globalwordstypetagged = [ ";
145         auto *p = reinterpret_cast<uint32 *>(globalWordsTypeTagged);
146         LogInfo::MapleLogger() << std::hex;
147         while (p < reinterpret_cast<uint32 *>(globalWordsTypeTagged + BlockSize2BitVectorSize(globalMemSize))) {
148             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
149             ++p;
150         }
151         LogInfo::MapleLogger() << std::dec << "]\n";
152     }
153     if (globalWordsRefCounted != nullptr) {
154         LogInfo::MapleLogger() << "globalwordsrefcounted = [ ";
155         auto *p = reinterpret_cast<uint32 *>(globalWordsRefCounted);
156         LogInfo::MapleLogger() << std::hex;
157         while (p < reinterpret_cast<uint32 *>(globalWordsRefCounted + BlockSize2BitVectorSize(globalMemSize))) {
158             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
159             ++p;
160         }
161         LogInfo::MapleLogger() << std::dec << "]\n";
162     }
163     LogInfo::MapleLogger() << "numfuncs " << numFuncs << '\n';
164     if (!importFiles.empty()) {
165         // Output current module's mplt on top, imported ones at below
166         for (auto it = importFiles.rbegin(); it != importFiles.rend(); ++it) {
167             LogInfo::MapleLogger() << "import \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(*it) << "\"\n";
168         }
169     }
170     if (!importPaths.empty()) {
171         size_t size = importPaths.size();
172         for (size_t i = 0; i < size; ++i) {
173             LogInfo::MapleLogger() << "importpath \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(importPaths[i])
174                                    << "\"\n";
175         }
176     }
177     if (!asmDecls.empty()) {
178         size_t size = asmDecls.size();
179         for (size_t i = 0; i < size; ++i) {
180             LogInfo::MapleLogger() << "asmdecl ";
181             EmitStr(asmDecls[i]);
182         }
183     }
184     if (entryFuncName.length()) {
185         LogInfo::MapleLogger() << "entryfunc &" << entryFuncName << '\n';
186     }
187     if (!fileInfo.empty()) {
188         LogInfo::MapleLogger() << "fileinfo {\n";
189         size_t size = fileInfo.size();
190         for (size_t i = 0; i < size; ++i) {
191             LogInfo::MapleLogger() << "  @" << GlobalTables::GetStrTable().GetStringFromStrIdx(fileInfo[i].first)
192                                    << " ";
193             if (!fileInfoIsString[i]) {
194                 LogInfo::MapleLogger() << "0x" << std::hex << fileInfo[i].second;
195             } else {
196                 LogInfo::MapleLogger() << "\""
197                                        << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(fileInfo[i].second))
198                                        << "\"";
199             }
200             if (i < size - 1) {
201                 LogInfo::MapleLogger() << ",\n";
202             } else {
203                 LogInfo::MapleLogger() << "}\n";
204             }
205         }
206         LogInfo::MapleLogger() << std::dec;
207     }
208     if (!srcFileInfo.empty()) {
209         LogInfo::MapleLogger() << "srcfileinfo {\n";
210         size_t size = srcFileInfo.size();
211         size_t i = 0;
212         for (auto infoElem : srcFileInfo) {
213             LogInfo::MapleLogger() << "  " << infoElem.second;
214             LogInfo::MapleLogger() << " \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(infoElem.first) << "\"";
215             DEBUG_ASSERT(size > 0, "must not be zero");
216             if (i++ < size - 1) {
217                 LogInfo::MapleLogger() << ",\n";
218             } else {
219                 LogInfo::MapleLogger() << "}\n";
220             }
221         }
222     }
223     if (!fileData.empty()) {
224         LogInfo::MapleLogger() << "filedata {\n";
225         size_t size = fileData.size();
226         for (size_t i = 0; i < size; ++i) {
227             LogInfo::MapleLogger() << "  @" << GlobalTables::GetStrTable().GetStringFromStrIdx(fileData[i].first)
228                                    << " ";
229             size_t dataSize = fileData[i].second.size();
230             for (size_t j = 0; j < dataSize; ++j) {
231                 uint8 data = fileData[i].second[j];
232                 LogInfo::MapleLogger() << "0x" << std::hex << static_cast<uint32>(data);
233                 if (j < dataSize - 1) {
234                     LogInfo::MapleLogger() << ' ';
235                 }
236             }
237             if (i < size - 1) {
238                 LogInfo::MapleLogger() << ",\n";
239             } else {
240                 LogInfo::MapleLogger() << "}\n";
241             }
242         }
243         LogInfo::MapleLogger() << std::dec;
244     }
245     if (flavor < kMmpl || flavor == kFlavorLmbc) {
246         for (auto it = typeDefOrder.begin(); it != typeDefOrder.end(); ++it) {
247             TyIdx tyIdx = typeNameTab->GetTyIdxFromGStrIdx(*it);
248             const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(*it);
249             MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
250             DEBUG_ASSERT(type != nullptr, "type should not be nullptr here");
251             bool isStructType = type->IsStructType();
252             if (isStructType) {
253                 auto *structType = static_cast<MIRStructType *>(type);
254                 // still emit what in extern_structtype_set_
255                 if (!emitStructureType &&
256                     externStructTypeSet.find(structType->GetTypeIndex()) == externStructTypeSet.end()) {
257                     continue;
258                 }
259                 if (structType->IsImported()) {
260                     continue;
261                 }
262             }
263 
264             LogInfo::MapleLogger() << "type $" << name << " ";
265             if (type->GetKind() == kTypeByName) {
266                 LogInfo::MapleLogger() << "void";
267             } else if (type->GetNameStrIdx() == *it) {
268                 type->Dump(1, true);
269             } else {
270                 type->Dump(1);
271             }
272             LogInfo::MapleLogger() << '\n';
273         }
274         if (someSymbolNeedForwDecl) {
275             // an extra pass thru the global symbol table to print forward decl
276             for (auto sit = symbolSet.begin(); sit != symbolSet.end(); ++sit) {
277                 MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx((*sit).Idx());
278                 DEBUG_ASSERT(s != nullptr, "nullptr check");
279                 if (s->IsNeedForwDecl()) {
280                     s->Dump(false, 0, true);
281                 }
282             }
283         }
284         for (auto sit = symbolDefOrder.begin(); sit != symbolDefOrder.end(); ++sit) {
285             MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx((*sit).Idx());
286             CHECK_FATAL(s != nullptr, "nullptr check");
287             if (!s->IsDeleted() && !s->GetIsImported() && !s->GetIsImportedDecl()) {
288                 s->Dump(false, 0);
289             }
290         }
291     }
292 }
293 
Dump(bool emitStructureType,const std::unordered_set<std::string> * dumpFuncSet) const294 void MIRModule::Dump(bool emitStructureType, const std::unordered_set<std::string> *dumpFuncSet) const
295 {
296     DumpGlobals(emitStructureType);
297     DumpFunctionList(dumpFuncSet);
298 }
299 
DumpGlobalArraySymbol() const300 void MIRModule::DumpGlobalArraySymbol() const
301 {
302     for (StIdx stIdx : symbolSet) {
303         MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx());
304         DEBUG_ASSERT(symbol != nullptr, "null ptr check");
305         MIRType *symbolType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(symbol->GetTyIdx());
306         DEBUG_ASSERT(symbolType != nullptr, "null ptr check");
307         if (symbolType == nullptr || symbolType->GetKind() != kTypeArray) {
308             continue;
309         }
310         symbol->Dump(false, 0);
311     }
312 }
313 
Emit(const std::string & outFileName) const314 void MIRModule::Emit(const std::string &outFileName) const
315 {
316     std::ofstream file;
317     // Change cout's buffer to file.
318     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
319     LogInfo::MapleLogger().rdbuf(file.rdbuf());
320     file.open(outFileName, std::ios::trunc);
321     DumpGlobals();
322     for (MIRFunction *mirFunc : functionList) {
323         mirFunc->Dump();
324     }
325     // Restore cout's buffer.
326     LogInfo::MapleLogger().rdbuf(backup);
327     file.close();
328 }
329 
DumpFunctionList(const std::unordered_set<std::string> * dumpFuncSet) const330 void MIRModule::DumpFunctionList(const std::unordered_set<std::string> *dumpFuncSet) const
331 {
332     for (MIRFunction *mirFunc : functionList) {
333         if (dumpFuncSet == nullptr || dumpFuncSet->empty()) {
334             mirFunc->Dump();
335         } else {  // dump only if this func matches any name in *dumpFuncSet
336             const std::string &name = mirFunc->GetName();
337             bool matched = false;
338             for (std::string elem : *dumpFuncSet) {
339                 if (name.find(elem.c_str()) != std::string::npos) {
340                     matched = true;
341                     break;
342                 }
343             }
344             if (matched) {
345                 mirFunc->Dump();
346             }
347         }
348     }
349 }
350 
OutputFunctionListAsciiMpl(const std::string & phaseName)351 void MIRModule::OutputFunctionListAsciiMpl(const std::string &phaseName)
352 {
353     std::string fileStem;
354     std::string::size_type lastDot = fileName.find_last_of('.');
355     if (lastDot == std::string::npos) {
356         fileStem = fileName.append(phaseName);
357     } else {
358         fileStem = fileName.substr(0, lastDot).append(phaseName);
359     }
360     std::string outfileName;
361     if (flavor >= kMmpl) {
362         outfileName = fileStem.append(".mmpl");
363     } else {
364         outfileName = fileStem.append(".mpl");
365     }
366     std::ofstream mplFile;
367     mplFile.open(outfileName, std::ios::app);
368     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
369     LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());  // change cout's buffer to that of file
370     DumpGlobalArraySymbol();
371     DumpFunctionList(nullptr);
372     LogInfo::MapleLogger().rdbuf(backup);  // restore cout's buffer
373     mplFile.close();
374 }
375 
DumpToFile(const std::string & fileNameStr,bool emitStructureType) const376 void MIRModule::DumpToFile(const std::string &fileNameStr, bool emitStructureType) const
377 {
378     std::ofstream file;
379     file.open(fileNameStr, std::ios::trunc);
380     if (!file.is_open()) {
381         ERR(kLncErr, "Cannot open %s", fileNameStr.c_str());
382         return;
383     }
384     // Change cout's buffer to file.
385     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
386     LogInfo::MapleLogger().rdbuf(file.rdbuf());
387     Dump(emitStructureType);
388     // Restore cout's buffer.
389     LogInfo::MapleLogger().rdbuf(backup);
390     file.close();
391 }
392 
DumpDefType()393 void MIRModule::DumpDefType()
394 {
395     for (auto it = typeDefOrder.begin(); it != typeDefOrder.end(); ++it) {
396         TyIdx tyIdx = typeNameTab->GetTyIdxFromGStrIdx(*it);
397         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(*it);
398         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
399         DEBUG_ASSERT(type != nullptr, "type should not be nullptr here");
400         bool isStructType = type->IsStructType();
401         if (isStructType) {
402             auto *structType = static_cast<MIRStructType *>(type);
403             if (structType->IsImported()) {
404                 continue;
405             }
406         }
407         LogInfo::MapleLogger() << "type $" << name << " ";
408         if (type->GetKind() == kTypeByName) {
409             LogInfo::MapleLogger() << "void";
410         } else if (type->GetNameStrIdx() == *it) {
411             type->Dump(1, true);
412         } else {
413             type->Dump(1);
414         }
415         LogInfo::MapleLogger() << '\n';
416     }
417 }
418 
DumpInlineCandidateToFile(const std::string & fileNameStr)419 void MIRModule::DumpInlineCandidateToFile(const std::string &fileNameStr)
420 {
421     if (optimizedFuncs.empty()) {
422         return;
423     }
424     std::ofstream file;
425     // Change cout's buffer to file.
426     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
427     LogInfo::MapleLogger().rdbuf(file.rdbuf());
428     file.open(fileNameStr, std::ios::trunc);
429     if (IsCModule()) {
430         DumpDefType();
431     }
432     // dump global variables needed for inlining file
433     for (auto symbolIdx : inliningGlobals) {
434         MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolIdx);
435         DEBUG_ASSERT(s != nullptr, "null ptr check");
436         if (s->GetStorageClass() == kScFstatic) {
437             if (s->IsNeedForwDecl()) {
438                 // const string, including initialization
439                 s->Dump(false, 0, false);
440             }
441         }
442     }
443     for (auto symbolIdx : inliningGlobals) {
444         MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolIdx);
445         DEBUG_ASSERT(s != nullptr, "null ptr check");
446         MIRStorageClass sc = s->GetStorageClass();
447         if (s->GetStorageClass() == kScFstatic) {
448             if (!s->IsNeedForwDecl()) {
449                 // const string, including initialization
450                 s->Dump(false, 0, false);
451             }
452         } else if (s->GetSKind() == kStFunc) {
453             s->GetFunction()->Dump(true);
454         } else {
455             // static fields as extern
456             s->SetStorageClass(kScExtern);
457             s->Dump(false, 0, true);
458         }
459         s->SetStorageClass(sc);
460     }
461     for (auto *func : optimizedFuncs) {
462         func->SetWithLocInfo(false);
463         func->Dump();
464     }
465     // Restore cout's buffer.
466     LogInfo::MapleLogger().rdbuf(backup);
467     file.close();
468 }
469 
470 // This is not efficient. Only used in debug mode for now.
GetFileNameFromFileNum(uint32 fileNum) const471 const std::string &MIRModule::GetFileNameFromFileNum(uint32 fileNum) const
472 {
473     GStrIdx nameIdx(0);
474     for (auto &info : srcFileInfo) {
475         if (info.second == fileNum) {
476             nameIdx = info.first;
477             break;
478         }
479     }
480     return GlobalTables::GetStrTable().GetStringFromStrIdx(nameIdx);
481 }
482 
DumpToHeaderFile(bool binaryMplt,const std::string & outputName)483 void MIRModule::DumpToHeaderFile(bool binaryMplt, const std::string &outputName)
484 {
485     std::string outfileName;
486     std::string fileNameLocal = !outputName.empty() ? outputName : fileName;
487     std::string::size_type lastDot = fileNameLocal.find_last_of('.');
488     if (lastDot == std::string::npos) {
489         outfileName = fileNameLocal.append(".mplt");
490     } else {
491         outfileName = fileNameLocal.substr(0, lastDot).append(".mplt");
492     }
493     if (binaryMplt) {
494         BinaryMplt binaryMpltTmp(*this);
495         binaryMpltTmp.Export(outfileName);
496     } else {
497         std::ofstream mpltFile;
498         mpltFile.open(outfileName, std::ios::trunc);
499         std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
500         LogInfo::MapleLogger().rdbuf(mpltFile.rdbuf());  // change cout's buffer to that of file
501         for (std::pair<std::u16string, MIRSymbol *> entity : GlobalTables::GetConstPool().GetConstU16StringPool()) {
502             LogInfo::MapleLogger() << "var $";
503             entity.second->DumpAsLiteralVar();
504             LogInfo::MapleLogger() << '\n';
505         }
506         for (auto it = classList.begin(); it != classList.end(); ++it) {
507             TyIdx curTyIdx(*it);
508             MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curTyIdx);
509             const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(type->GetNameStrIdx());
510             if (type->GetKind() == kTypeClass || type->GetKind() == kTypeInterface) {
511                 auto *structType = static_cast<MIRStructType *>(type);
512                 // skip imported class/interface and incomplete types
513                 if (!structType->IsImported() && !structType->IsIncomplete()) {
514                     LogInfo::MapleLogger() << "type $" << name << " ";
515                     type->Dump(1, true);
516                     LogInfo::MapleLogger() << '\n';
517                 }
518             }
519         }
520         /* restore cout */
521         LogInfo::MapleLogger().rdbuf(backup);
522         mpltFile.close();
523     }
524 }
525 
DumpTypeTreeToCxxHeaderFile(MIRType & ty,std::unordered_set<MIRType * > & dumpedClasses) const526 void MIRModule::DumpTypeTreeToCxxHeaderFile(MIRType &ty, std::unordered_set<MIRType *> &dumpedClasses) const
527 {
528     if (dumpedClasses.find(&ty) != dumpedClasses.end()) {
529         return;
530     }
531     // first, insert ty to the dumped_classes to prevent infinite recursion
532     (void)dumpedClasses.insert(&ty);
533     DEBUG_ASSERT(ty.GetKind() == kTypeClass || ty.GetKind() == kTypeStruct || ty.GetKind() == kTypeUnion ||
534                      ty.GetKind() == kTypeInterface,
535                  "Unexpected MIRType.");
536     /* No need to emit interfaces; because "interface variables are
537        final and static by default and methods are public and abstract"
538      */
539     if (ty.GetKind() == kTypeInterface) {
540         return;
541     }
542     // dump all of its parents
543     if (srcLang == kSrcLangC || srcLang == kSrcLangCPlusPlus) {
544         DEBUG_ASSERT((ty.GetKind() == kTypeStruct || ty.GetKind() == kTypeUnion),
545                      "type should be either struct or union");
546     } else {
547         DEBUG_ASSERT(false, "source languages other than C/C++ are not supported yet");
548     }
549     if (srcLang == kSrcLangC || srcLang == kSrcLangCPlusPlus) {
550         // how to access parent fields????
551         DEBUG_ASSERT(false, "not yet implemented");
552     }
553 }
554 
DumpToCxxHeaderFile(std::set<std::string> & leafClasses,const std::string & pathToOutf) const555 void MIRModule::DumpToCxxHeaderFile(std::set<std::string> &leafClasses, const std::string &pathToOutf) const
556 {
557     if (pathToOutf.empty()) {
558         return;
559     }
560     std::ofstream mpltFile;
561     mpltFile.open(pathToOutf, std::ios::trunc);
562     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
563     LogInfo::MapleLogger().rdbuf(mpltFile.rdbuf());  // change cout's buffer to that of file
564     char *headerGuard = strdup(pathToOutf.c_str());
565     CHECK_FATAL(headerGuard != nullptr, "strdup failed");
566     for (char *p = headerGuard; *p; ++p) {
567         if (!isalnum(*p)) {
568             *p = '_';
569         } else if (isalpha(*p) && islower(*p)) {
570             *p = toupper(*p);
571         }
572     }
573     // define a hash table
574     std::unordered_set<MIRType *> dumpedClasses;
575     const char *prefix = "__SRCLANG_UNKNOWN_";
576     if (srcLang == kSrcLangC || srcLang == kSrcLangCPlusPlus) {
577         prefix = "__SRCLANG_CXX_";
578     }
579     LogInfo::MapleLogger() << "#ifndef " << prefix << headerGuard << "__\n";
580     LogInfo::MapleLogger() << "#define " << prefix << headerGuard << "__\n";
581     LogInfo::MapleLogger() << "/* this file is compiler-generated; do not edit */\n\n";
582     LogInfo::MapleLogger() << "#include <stdint.h>\n";
583     LogInfo::MapleLogger() << "#include <complex.h>\n";
584     for (auto &s : leafClasses) {
585         CHECK_FATAL(!s.empty(), "string is null");
586         GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(s);
587         TyIdx tyIdx = typeNameTab->GetTyIdxFromGStrIdx(strIdx);
588         MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
589         if (ty == nullptr) {
590             continue;
591         }
592         DEBUG_ASSERT(ty->GetKind() == kTypeClass || ty->GetKind() == kTypeStruct || ty->GetKind() == kTypeUnion ||
593                          ty->GetKind() == kTypeInterface,
594                      "");
595         DumpTypeTreeToCxxHeaderFile(*ty, dumpedClasses);
596     }
597     LogInfo::MapleLogger() << "#endif /* " << prefix << headerGuard << "__ */\n";
598     /* restore cout */
599     LogInfo::MapleLogger().rdbuf(backup);
600     free(headerGuard);
601     headerGuard = nullptr;
602     mpltFile.close();
603 }
604 
DumpClassToFile(const std::string & path) const605 void MIRModule::DumpClassToFile(const std::string &path) const
606 {
607     std::string strPath(path);
608     strPath.append("/");
609     for (auto it : typeNameTab->GetGStrIdxToTyIdxMap()) {
610         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(it.first);
611         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(it.second);
612         std::string outClassFile(name);
613         /* replace class name / with - */
614         std::replace(outClassFile.begin(), outClassFile.end(), '/', '-');
615         (void)outClassFile.insert(0, strPath);
616         outClassFile.append(".mpl");
617         std::ofstream mplFile;
618         mplFile.open(outClassFile, std::ios::trunc);
619         std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
620         LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());
621         /* dump class type */
622         LogInfo::MapleLogger() << "type $" << name << " ";
623         if (type->GetNameStrIdx() == it.first && type->GetKind() != kTypeByName) {
624             type->Dump(1, true);
625         } else {
626             type->Dump(1);
627         }
628         LogInfo::MapleLogger() << '\n';
629         /* restore cout */
630         LogInfo::MapleLogger().rdbuf(backup);
631         mplFile.close();
632         ;
633     }
634 }
635 
FindEntryFunction()636 MIRFunction *MIRModule::FindEntryFunction()
637 {
638     for (MIRFunction *currFunc : functionList) {
639         if (currFunc->GetName() == entryFuncName) {
640             entryFunc = currFunc;
641             return currFunc;
642         }
643     }
644     return nullptr;
645 }
646 
647 // given the phase name (including '.' at beginning), output the program in the
648 // module to the file with given file suffix, and file stem from
649 // this->fileName appended with phaseName
OutputAsciiMpl(const char * phaseName,const char * suffix,const std::unordered_set<std::string> * dumpFuncSet,bool emitStructureType,bool binaryform)650 void MIRModule::OutputAsciiMpl(const char *phaseName, const char *suffix,
651                                const std::unordered_set<std::string> *dumpFuncSet, bool emitStructureType,
652                                bool binaryform)
653 {
654     DEBUG_ASSERT(!(emitStructureType && binaryform), "Cannot emit type info in .bpl");
655     std::string fileStem;
656     std::string::size_type lastDot = fileName.find_last_of('.');
657     if (lastDot == std::string::npos) {
658         fileStem = fileName.append(phaseName);
659     } else {
660         fileStem = fileName.substr(0, lastDot).append(phaseName);
661     }
662     std::string outfileName = fileStem + suffix;
663     if (!binaryform) {
664         std::ofstream mplFile;
665         mplFile.open(outfileName, std::ios::trunc);
666         std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
667         LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());  // change LogInfo::MapleLogger()'s buffer to that of file
668         Dump(emitStructureType, dumpFuncSet);
669         LogInfo::MapleLogger().rdbuf(backup);  // restore LogInfo::MapleLogger()'s buffer
670         mplFile.close();
671     } else {
672         BinaryMplt binaryMplt(*this);
673         binaryMplt.GetBinExport().not2mplt = true;
674         binaryMplt.Export(outfileName);
675     }
676     std::ofstream mplFile;
677     mplFile.open(outfileName, std::ios::trunc);
678     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
679     LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());  // change cout's buffer to that of file
680     Dump(emitStructureType);
681     if (withDbgInfo) {
682         dbgInfo->Dump(0);
683     }
684     LogInfo::MapleLogger().rdbuf(backup);  // restore cout's buffer
685     mplFile.close();
686 }
687 
GetFileinfo(GStrIdx strIdx) const688 uint32 MIRModule::GetFileinfo(GStrIdx strIdx) const
689 {
690     for (auto &infoElem : fileInfo) {
691         if (infoElem.first == strIdx) {
692             return infoElem.second;
693         }
694     }
695     DEBUG_ASSERT(false, "should not be here");
696     return 0;
697 }
698 
GetFileNameAsPostfix() const699 std::string MIRModule::GetFileNameAsPostfix() const
700 {
701     std::string fileNameStr = namemangler::kFileNameSplitterStr;
702     if (!fileInfo.empty()) {
703         // option 1: file name in INFO
704         uint32 fileNameIdx = GetFileinfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("INFO_filename"));
705         fileNameStr += GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(fileNameIdx));
706     } else {
707         // option 2: src file name removing ext name.
708         if (GetSrcFileInfo().size() != 0) {
709             GStrIdx idx = GetSrcFileInfo()[0].first;
710             const std::string kStr = GlobalTables::GetStrTable().GetStringFromStrIdx(idx);
711             DEBUG_ASSERT(kStr.find_last_of('.') != kStr.npos, "not found .");
712             fileNameStr += kStr.substr(0, kStr.find_last_of('.'));
713         } else {
714             DEBUG_ASSERT(0, "No fileinfo and no srcfileinfo in mpl file");
715         }
716     }
717     for (char &c : fileNameStr) {
718         if (!isalpha(c) && !isdigit(c) && c != '_' && c != '$') {
719             c = '_';
720         }
721     }
722     return fileNameStr;
723 }
724 
AddClass(TyIdx tyIdx)725 void MIRModule::AddClass(TyIdx tyIdx)
726 {
727     (void)classList.insert(tyIdx);
728 }
729 
RemoveClass(TyIdx tyIdx)730 void MIRModule::RemoveClass(TyIdx tyIdx)
731 {
732     (void)classList.erase(tyIdx);
733 }
734 
735 #endif  // MIR_FEATURE_FULL
ReleaseCurFuncMemPoolTmp()736 void MIRModule::ReleaseCurFuncMemPoolTmp()
737 {
738     DEBUG_ASSERT(CurFunction() != nullptr, "CurFunction() should not be nullptr");
739     CurFunction()->ReleaseMemory();
740 }
741 
SetFuncInfoPrinted() const742 void MIRModule::SetFuncInfoPrinted() const
743 {
744     DEBUG_ASSERT(CurFunction() != nullptr, "CurFunction() should not be nullptr");
745     CurFunction()->SetInfoPrinted();
746 }
747 
InitPartO2List(const std::string & list)748 void MIRModule::InitPartO2List(const std::string &list)
749 {
750     if (list.empty()) {
751         return;
752     }
753     SetHasPartO2List(true);
754     std::ifstream infile(list);
755     if (!infile.is_open()) {
756         LogInfo::MapleLogger(kLlErr) << "Cannot open partO2 function list file " << list << '\n';
757         return;
758     }
759     std::string str;
760 
761     while (getline(infile, str)) {
762         if (str.empty()) {
763             continue;
764         }
765         GStrIdx funcStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(str);
766         partO2FuncList.insert(funcStrIdx);
767     }
768     infile.close();
769 }
770 
HasNotWarned(uint32 position,uint32 stmtOriginalID)771 bool MIRModule::HasNotWarned(uint32 position, uint32 stmtOriginalID)
772 {
773     auto warnedOp = safetyWarningMap.find(position);
774     if (warnedOp == safetyWarningMap.end()) {
775         MapleSet<uint32> opSet(memPoolAllocator.Adapter());
776         opSet.emplace(stmtOriginalID);
777         safetyWarningMap.emplace(std::pair<uint32, MapleSet<uint32>>(position, std::move(opSet)));
778         return true;
779     }
780     if (warnedOp->second.find(stmtOriginalID) == warnedOp->second.end()) {
781         warnedOp->second.emplace(stmtOriginalID);
782         return true;
783     }
784     return false;
785 }
786 }  // namespace maple
787