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