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