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