• 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 <fstream>
18 #include "mir_builder.h"
19 
20 namespace maple {
21 #if MIR_FEATURE_FULL  // to avoid compilation error when MIR_FEATURE_FULL=0
MIRModule(const std::string & fn)22 MIRModule::MIRModule(const std::string &fn)
23     : memPool(new ThreadShareMemPool(memPoolCtrler, "maple_ir mempool")),
24       pragmaMemPool(memPoolCtrler.NewMemPool("pragma mempool", false /* isLcalPool */)),
25       memPoolAllocator(memPool),
26       pragmaMemPoolAllocator(pragmaMemPool),
27       functionList(memPoolAllocator.Adapter()),
28       importedMplt(memPoolAllocator.Adapter()),
29       typeDefOrder(memPoolAllocator.Adapter()),
30       externStructTypeSet(std::less<TyIdx>(), memPoolAllocator.Adapter()),
31       symbolSet(std::less<StIdx>(), memPoolAllocator.Adapter()),
32       symbolDefOrder(memPoolAllocator.Adapter()),
33       out(LogInfo::MapleLogger()),
34       fileName(fn),
35       fileInfo(memPoolAllocator.Adapter()),
36       fileInfoIsString(memPoolAllocator.Adapter()),
37       fileData(memPoolAllocator.Adapter()),
38       srcFileInfo(memPoolAllocator.Adapter()),
39       importFiles(memPoolAllocator.Adapter()),
40       importPaths(memPoolAllocator.Adapter()),
41       asmDecls(memPoolAllocator.Adapter()),
42       classList(memPoolAllocator.Adapter()),
43       optimizedFuncs(memPoolAllocator.Adapter()),
44       optimizedFuncsType(memPoolAllocator.Adapter()),
45       puIdxFieldInitializedMap(std::less<PUIdx>(), memPoolAllocator.Adapter()),
46       inliningGlobals(memPoolAllocator.Adapter()),
47       partO2FuncList(memPoolAllocator.Adapter()),
48       safetyWarningMap(memPoolAllocator.Adapter())
49 {
50     GlobalTables::GetGsymTable().SetModule(this);
51     typeNameTab = memPool->New<MIRTypeNameTable>(memPoolAllocator);
52     mirBuilder = memPool->New<MIRBuilder>(this);
53     IntrinDesc::InitMIRModule(this);
54 }
55 
~MIRModule()56 MIRModule::~MIRModule()
57 {
58     for (MIRFunction *mirFunc : functionList) {
59         mirFunc->ReleaseCodeMemory();
60     }
61     ReleasePragmaMemPool();
62     delete memPool;
63 }
64 
CurFuncCodeMemPool() const65 MemPool *MIRModule::CurFuncCodeMemPool() const
66 {
67     DEBUG_ASSERT(CurFunction() != nullptr, "CurFunction() should not be nullptr");
68     if (useFuncCodeMemPoolTmp) {
69         return CurFunction()->GetCodeMemPoolTmp();
70     }
71     return CurFunction()->GetCodeMemPool();
72 }
73 
CurFuncCodeMemPoolAllocator() const74 MapleAllocator *MIRModule::CurFuncCodeMemPoolAllocator() const
75 {
76     MIRFunction *curFunc = CurFunction();
77     CHECK_FATAL(curFunc != nullptr, "curFunction is null");
78     return &curFunc->GetCodeMempoolAllocator();
79 }
80 
GetCurFuncCodeMPAllocator() const81 MapleAllocator &MIRModule::GetCurFuncCodeMPAllocator() const
82 {
83     MIRFunction *curFunc = CurFunction();
84     CHECK_FATAL(curFunc != nullptr, "curFunction is null");
85     return curFunc->GetCodeMPAllocator();
86 }
87 
AddExternStructType(TyIdx tyIdx)88 void MIRModule::AddExternStructType(TyIdx tyIdx)
89 {
90     (void)externStructTypeSet.insert(tyIdx);
91 }
92 
AddExternStructType(const MIRType * t)93 void MIRModule::AddExternStructType(const MIRType *t)
94 {
95     DEBUG_ASSERT(t != nullptr, "MIRType is null");
96     (void)externStructTypeSet.insert(t->GetTypeIndex());
97 }
98 
AddSymbol(StIdx stIdx)99 void MIRModule::AddSymbol(StIdx stIdx)
100 {
101     auto it = symbolSet.find(stIdx);
102     if (it == symbolSet.end()) {
103         symbolDefOrder.push_back(stIdx);
104     }
105     (void)symbolSet.insert(stIdx);
106 }
107 
AddSymbol(const MIRSymbol * s)108 void MIRModule::AddSymbol(const MIRSymbol *s)
109 {
110     DEBUG_ASSERT(s != nullptr, "s is null");
111     AddSymbol(s->GetStIdx());
112 }
113 
114 #ifdef ARK_LITECG_DEBUG
DumpGlobals(bool emitStructureType) const115 void MIRModule::DumpGlobals(bool emitStructureType) const
116 {
117     if (flavor != kFlavorUnknown) {
118         LogInfo::MapleLogger() << "flavor " << flavor << '\n';
119     }
120     if (srcLang != kSrcLangUnknown) {
121         LogInfo::MapleLogger() << "srclang " << srcLang << '\n';
122     }
123     LogInfo::MapleLogger() << "id " << id << '\n';
124     if (globalMemSize != 0) {
125         LogInfo::MapleLogger() << "globalmemsize " << globalMemSize << '\n';
126     }
127     if (globalBlkMap != nullptr) {
128         LogInfo::MapleLogger() << "globalmemmap = [ ";
129         auto *p = reinterpret_cast<uint32 *>(globalBlkMap);
130         LogInfo::MapleLogger() << std::hex;
131         while (p < reinterpret_cast<uint32 *>(globalBlkMap + globalMemSize)) {
132             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
133             p++;
134         }
135         LogInfo::MapleLogger() << std::dec << "]\n";
136     }
137     if (globalWordsTypeTagged != nullptr) {
138         LogInfo::MapleLogger() << "globalwordstypetagged = [ ";
139         auto *p = reinterpret_cast<uint32 *>(globalWordsTypeTagged);
140         LogInfo::MapleLogger() << std::hex;
141         while (p < reinterpret_cast<uint32 *>(globalWordsTypeTagged + BlockSize2BitVectorSize(globalMemSize))) {
142             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
143             ++p;
144         }
145         LogInfo::MapleLogger() << std::dec << "]\n";
146     }
147     if (globalWordsRefCounted != nullptr) {
148         LogInfo::MapleLogger() << "globalwordsrefcounted = [ ";
149         auto *p = reinterpret_cast<uint32 *>(globalWordsRefCounted);
150         LogInfo::MapleLogger() << std::hex;
151         while (p < reinterpret_cast<uint32 *>(globalWordsRefCounted + BlockSize2BitVectorSize(globalMemSize))) {
152             LogInfo::MapleLogger() << std::hex << "0x" << *p << " ";
153             ++p;
154         }
155         LogInfo::MapleLogger() << std::dec << "]\n";
156     }
157     LogInfo::MapleLogger() << "numfuncs " << numFuncs << '\n';
158     if (!importFiles.empty()) {
159         // Output current module's mplt on top, imported ones at below
160         for (auto it = importFiles.rbegin(); it != importFiles.rend(); ++it) {
161             LogInfo::MapleLogger() << "import \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(*it) << "\"\n";
162         }
163     }
164     if (!importPaths.empty()) {
165         size_t size = importPaths.size();
166         for (size_t i = 0; i < size; ++i) {
167             LogInfo::MapleLogger() << "importpath \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(importPaths[i])
168                                    << "\"\n";
169         }
170     }
171     if (!asmDecls.empty()) {
172         size_t size = asmDecls.size();
173         for (size_t i = 0; i < size; ++i) {
174             LogInfo::MapleLogger() << "asmdecl ";
175             EmitStr(asmDecls[i]);
176         }
177     }
178     if (entryFuncName.length()) {
179         LogInfo::MapleLogger() << "entryfunc &" << entryFuncName << '\n';
180     }
181     if (!fileInfo.empty()) {
182         LogInfo::MapleLogger() << "fileinfo {\n";
183         size_t size = fileInfo.size();
184         for (size_t i = 0; i < size; ++i) {
185             LogInfo::MapleLogger() << "  @" << GlobalTables::GetStrTable().GetStringFromStrIdx(fileInfo[i].first)
186                                    << " ";
187             if (!fileInfoIsString[i]) {
188                 LogInfo::MapleLogger() << "0x" << std::hex << fileInfo[i].second;
189             } else {
190                 LogInfo::MapleLogger() << "\""
191                                        << GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(fileInfo[i].second))
192                                        << "\"";
193             }
194             if (i < size - 1) {
195                 LogInfo::MapleLogger() << ",\n";
196             } else {
197                 LogInfo::MapleLogger() << "}\n";
198             }
199         }
200         LogInfo::MapleLogger() << std::dec;
201     }
202     if (!srcFileInfo.empty()) {
203         LogInfo::MapleLogger() << "srcfileinfo {\n";
204         size_t size = srcFileInfo.size();
205         size_t i = 0;
206         for (auto infoElem : srcFileInfo) {
207             LogInfo::MapleLogger() << "  " << infoElem.second;
208             LogInfo::MapleLogger() << " \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(infoElem.first) << "\"";
209             DEBUG_ASSERT(size > 0, "must not be zero");
210             if (i++ < size - 1) {
211                 LogInfo::MapleLogger() << ",\n";
212             } else {
213                 LogInfo::MapleLogger() << "}\n";
214             }
215         }
216     }
217     if (!fileData.empty()) {
218         LogInfo::MapleLogger() << "filedata {\n";
219         size_t size = fileData.size();
220         for (size_t i = 0; i < size; ++i) {
221             LogInfo::MapleLogger() << "  @" << GlobalTables::GetStrTable().GetStringFromStrIdx(fileData[i].first)
222                                    << " ";
223             size_t dataSize = fileData[i].second.size();
224             for (size_t j = 0; j < dataSize; ++j) {
225                 uint8 data = fileData[i].second[j];
226                 LogInfo::MapleLogger() << "0x" << std::hex << static_cast<uint32>(data);
227                 if (j < dataSize - 1) {
228                     LogInfo::MapleLogger() << ' ';
229                 }
230             }
231             if (i < size - 1) {
232                 LogInfo::MapleLogger() << ",\n";
233             } else {
234                 LogInfo::MapleLogger() << "}\n";
235             }
236         }
237         LogInfo::MapleLogger() << std::dec;
238     }
239     if (flavor < kMmpl || flavor == kFlavorLmbc) {
240         for (auto it = typeDefOrder.begin(); it != typeDefOrder.end(); ++it) {
241             TyIdx tyIdx = typeNameTab->GetTyIdxFromGStrIdx(*it);
242             const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(*it);
243             MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
244             DEBUG_ASSERT(type != nullptr, "type should not be nullptr here");
245 
246             LogInfo::MapleLogger() << "type $" << name << " ";
247             if (type->GetKind() == kTypeByName) {
248                 LogInfo::MapleLogger() << "void";
249             } else if (type->GetNameStrIdx() == *it) {
250                 type->Dump(1, true);
251             } else {
252                 type->Dump(1);
253             }
254             LogInfo::MapleLogger() << '\n';
255         }
256         if (someSymbolNeedForwDecl) {
257             // an extra pass thru the global symbol table to print forward decl
258             for (auto sit = symbolSet.begin(); sit != symbolSet.end(); ++sit) {
259                 MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx((*sit).Idx());
260                 DEBUG_ASSERT(s != nullptr, "nullptr check");
261                 if (s->IsNeedForwDecl()) {
262                     s->Dump(false, 0, true);
263                 }
264             }
265         }
266         for (auto sit = symbolDefOrder.begin(); sit != symbolDefOrder.end(); ++sit) {
267             MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx((*sit).Idx());
268             CHECK_FATAL(s != nullptr, "nullptr check");
269             if (!s->IsDeleted() && !s->GetIsImported() && !s->GetIsImportedDecl()) {
270                 s->Dump(false, 0);
271             }
272         }
273     }
274 }
275 
Dump(bool emitStructureType,const std::unordered_set<std::string> * dumpFuncSet) const276 void MIRModule::Dump(bool emitStructureType, const std::unordered_set<std::string> *dumpFuncSet) const
277 {
278     DumpGlobals(emitStructureType);
279     DumpFunctionList(dumpFuncSet);
280 }
281 
DumpGlobalArraySymbol() const282 void MIRModule::DumpGlobalArraySymbol() const
283 {
284     for (StIdx stIdx : symbolSet) {
285         MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx());
286         DEBUG_ASSERT(symbol != nullptr, "null ptr check");
287         MIRType *symbolType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(symbol->GetTyIdx());
288         DEBUG_ASSERT(symbolType != nullptr, "null ptr check");
289         if (symbolType == nullptr || symbolType->GetKind() != kTypeArray) {
290             continue;
291         }
292         symbol->Dump(false, 0);
293     }
294 }
295 
Emit(const std::string & outFileName) const296 void MIRModule::Emit(const std::string &outFileName) const
297 {
298     std::ofstream file;
299     // Change cout's buffer to file.
300     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
301     LogInfo::MapleLogger().rdbuf(file.rdbuf());
302     file.open(outFileName, std::ios::trunc);
303     DumpGlobals();
304     for (MIRFunction *mirFunc : functionList) {
305         mirFunc->Dump();
306     }
307     // Restore cout's buffer.
308     LogInfo::MapleLogger().rdbuf(backup);
309     file.close();
310 }
311 
DumpFunctionList(const std::unordered_set<std::string> * dumpFuncSet) const312 void MIRModule::DumpFunctionList(const std::unordered_set<std::string> *dumpFuncSet) const
313 {
314     for (MIRFunction *mirFunc : functionList) {
315         if (dumpFuncSet == nullptr || dumpFuncSet->empty()) {
316             mirFunc->Dump();
317         } else {  // dump only if this func matches any name in *dumpFuncSet
318             const std::string &name = mirFunc->GetName();
319             bool matched = false;
320             for (std::string elem : *dumpFuncSet) {
321                 if (name.find(elem.c_str()) != std::string::npos) {
322                     matched = true;
323                     break;
324                 }
325             }
326             if (matched) {
327                 mirFunc->Dump();
328             }
329         }
330     }
331 }
332 
OutputFunctionListAsciiMpl(const std::string & phaseName)333 void MIRModule::OutputFunctionListAsciiMpl(const std::string &phaseName)
334 {
335     std::string fileStem;
336     std::string::size_type lastDot = fileName.find_last_of('.');
337     if (lastDot == std::string::npos) {
338         fileStem = fileName.append(phaseName);
339     } else {
340         fileStem = fileName.substr(0, lastDot).append(phaseName);
341     }
342     std::string outfileName;
343     if (flavor >= kMmpl) {
344         outfileName = fileStem.append(".mmpl");
345     } else {
346         outfileName = fileStem.append(".mpl");
347     }
348     std::ofstream mplFile;
349     mplFile.open(outfileName, std::ios::app);
350     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
351     LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());  // change cout's buffer to that of file
352     DumpGlobalArraySymbol();
353     DumpFunctionList(nullptr);
354     LogInfo::MapleLogger().rdbuf(backup);  // restore cout's buffer
355     mplFile.close();
356 }
357 
DumpToFile(const std::string & fileNameStr,bool emitStructureType) const358 void MIRModule::DumpToFile(const std::string &fileNameStr, bool emitStructureType) const
359 {
360     std::ofstream file;
361     file.open(fileNameStr, std::ios::trunc);
362     if (!file.is_open()) {
363         ERR(kLncErr, "Cannot open %s", fileNameStr.c_str());
364         return;
365     }
366     // Change cout's buffer to file.
367     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
368     LogInfo::MapleLogger().rdbuf(file.rdbuf());
369     Dump(emitStructureType);
370     // Restore cout's buffer.
371     LogInfo::MapleLogger().rdbuf(backup);
372     file.close();
373 }
374 
DumpDefType()375 void MIRModule::DumpDefType()
376 {
377     for (auto it = typeDefOrder.begin(); it != typeDefOrder.end(); ++it) {
378         TyIdx tyIdx = typeNameTab->GetTyIdxFromGStrIdx(*it);
379         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(*it);
380         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
381         DEBUG_ASSERT(type != nullptr, "type should not be nullptr here");
382         LogInfo::MapleLogger() << "type $" << name << " ";
383         if (type->GetKind() == kTypeByName) {
384             LogInfo::MapleLogger() << "void";
385         } else if (type->GetNameStrIdx() == *it) {
386             type->Dump(1, true);
387         } else {
388             type->Dump(1);
389         }
390         LogInfo::MapleLogger() << '\n';
391     }
392 }
393 
DumpInlineCandidateToFile(const std::string & fileNameStr)394 void MIRModule::DumpInlineCandidateToFile(const std::string &fileNameStr)
395 {
396     if (optimizedFuncs.empty()) {
397         return;
398     }
399     std::ofstream file;
400     // Change cout's buffer to file.
401     std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
402     LogInfo::MapleLogger().rdbuf(file.rdbuf());
403     file.open(fileNameStr, std::ios::trunc);
404     // dump global variables needed for inlining file
405     for (auto symbolIdx : inliningGlobals) {
406         MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolIdx);
407         DEBUG_ASSERT(s != nullptr, "null ptr check");
408         if (s->GetStorageClass() == kScFstatic) {
409             if (s->IsNeedForwDecl()) {
410                 // const string, including initialization
411                 s->Dump(false, 0, false);
412             }
413         }
414     }
415     for (auto symbolIdx : inliningGlobals) {
416         MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolIdx);
417         DEBUG_ASSERT(s != nullptr, "null ptr check");
418         MIRStorageClass sc = s->GetStorageClass();
419         if (s->GetStorageClass() == kScFstatic) {
420             if (!s->IsNeedForwDecl()) {
421                 // const string, including initialization
422                 s->Dump(false, 0, false);
423             }
424         } else if (s->GetSKind() == kStFunc) {
425             s->GetFunction()->Dump(true);
426         } else {
427             // static fields as extern
428             s->SetStorageClass(kScExtern);
429             s->Dump(false, 0, true);
430         }
431         s->SetStorageClass(sc);
432     }
433     for (auto *func : optimizedFuncs) {
434         func->SetWithLocInfo(false);
435         func->Dump();
436     }
437     // Restore cout's buffer.
438     LogInfo::MapleLogger().rdbuf(backup);
439     file.close();
440 }
441 #endif
442 
443 #ifdef ARK_LITECG_DEBUG
DumpClassToFile(const std::string & path) const444 void MIRModule::DumpClassToFile(const std::string &path) const
445 {
446     std::string strPath(path);
447     strPath.append("/");
448     for (auto it : typeNameTab->GetGStrIdxToTyIdxMap()) {
449         const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(it.first);
450         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(it.second);
451         std::string outClassFile(name);
452         /* replace class name / with - */
453         std::replace(outClassFile.begin(), outClassFile.end(), '/', '-');
454         (void)outClassFile.insert(0, strPath);
455         outClassFile.append(".mpl");
456         std::ofstream mplFile;
457         mplFile.open(outClassFile, std::ios::trunc);
458         std::streambuf *backup = LogInfo::MapleLogger().rdbuf();
459         LogInfo::MapleLogger().rdbuf(mplFile.rdbuf());
460         /* dump class type */
461         LogInfo::MapleLogger() << "type $" << name << " ";
462         if (type->GetNameStrIdx() == it.first && type->GetKind() != kTypeByName) {
463             type->Dump(1, true);
464         } else {
465             type->Dump(1);
466         }
467         LogInfo::MapleLogger() << '\n';
468         /* restore cout */
469         LogInfo::MapleLogger().rdbuf(backup);
470         mplFile.close();
471         ;
472     }
473 }
474 #endif
475 
GetFileinfo(GStrIdx strIdx) const476 uint32 MIRModule::GetFileinfo(GStrIdx strIdx) const
477 {
478     for (auto &infoElem : fileInfo) {
479         if (infoElem.first == strIdx) {
480             return infoElem.second;
481         }
482     }
483     DEBUG_ASSERT(false, "should not be here");
484     return 0;
485 }
486 
487 #ifdef ARK_LITECG_DEBUG
GetFileNameAsPostfix() const488 std::string MIRModule::GetFileNameAsPostfix() const
489 {
490     std::string fileNameStr = namemangler::kFileNameSplitterStr;
491     if (!fileInfo.empty()) {
492         // option 1: file name in INFO
493         uint32 fileNameIdx = GetFileinfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("INFO_filename"));
494         fileNameStr += GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(fileNameIdx));
495     } else {
496         // option 2: src file name removing ext name.
497         if (GetSrcFileInfo().size() != 0) {
498             GStrIdx idx = GetSrcFileInfo()[0].first;
499             const std::string kStr = GlobalTables::GetStrTable().GetStringFromStrIdx(idx);
500             DEBUG_ASSERT(kStr.find_last_of('.') != kStr.npos, "not found .");
501             fileNameStr += kStr.substr(0, kStr.find_last_of('.'));
502         } else {
503             DEBUG_ASSERT(0, "No fileinfo and no srcfileinfo in mpl file");
504         }
505     }
506     for (char &c : fileNameStr) {
507         if (!isalpha(c) && !isdigit(c) && c != '_' && c != '$') {
508             c = '_';
509         }
510     }
511     return fileNameStr;
512 }
513 #endif
514 
515 #endif  // MIR_FEATURE_FULL
516 }  // namespace maple
517