• 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 "bin_mpl_import.h"
17 #include <sstream>
18 #include <vector>
19 #include <unordered_set>
20 #include <limits>
21 #include "bin_mplt.h"
22 #include "mir_function.h"
23 #include "namemangler.h"
24 #include "opcode_info.h"
25 #include "mir_pragma.h"
26 #include "mir_builder.h"
27 
28 namespace maple {
Read()29 uint8 BinaryMplImport::Read()
30 {
31     CHECK_FATAL(bufI < buf.size(), "Index out of bound in BinaryMplImport::Read()");
32     return buf[bufI++];
33 }
34 
35 // Little endian
ReadInt()36 int32 BinaryMplImport::ReadInt()
37 {
38     uint32 x0 = static_cast<uint32>(Read());
39     uint32 x1 = static_cast<uint32>(Read());
40     uint32 x2 = static_cast<uint32>(Read());
41     uint32 x3 = static_cast<uint32>(Read());
42     return (((((x3 << 8u) + x2) << 8u) + x1) << 8u) + x0;
43 }
44 
ReadInt64()45 int64 BinaryMplImport::ReadInt64()
46 {
47     // casts to avoid sign extension
48     uint32 x0 = static_cast<uint32>(ReadInt());
49     uint64 x1 = static_cast<uint32>(ReadInt());
50     return static_cast<int64>((x1 << 32) + x0); // x1 left shift 32 bit to join with x0
51 }
52 
53 // LEB128
ReadNum()54 int64 BinaryMplImport::ReadNum()
55 {
56     uint64 n = 0;
57     int64 y = 0;
58     uint64 b = static_cast<uint64>(Read());
59     while (b >= 0x80) {
60         y += ((b - 0x80) << n);
61         n += k7BitSize;
62         b = static_cast<uint64>(Read());
63     }
64     b = (b & 0x3F) - (b & 0x40);
65     return y + (b << n);
66 }
67 
ReadAsciiStr(std::string & str)68 void BinaryMplImport::ReadAsciiStr(std::string &str)
69 {
70     int64 n = ReadNum();
71     for (int64 i = 0; i < n; i++) {
72         uint8 ch = Read();
73         str.push_back(static_cast<char>(ch));
74     }
75 }
76 
ReadFileAt(const std::string & name,int32 offset)77 void BinaryMplImport::ReadFileAt(const std::string &name, int32 offset)
78 {
79     FILE *f = fopen(name.c_str(), "rb");
80     CHECK_FATAL(f != nullptr, "Error while reading the binary file: %s", name.c_str());
81 
82     int seekRet = fseek(f, 0, SEEK_END);
83     CHECK_FATAL(seekRet == 0, "call fseek failed");
84 
85     long size = ftell(f);
86     size -= offset;
87 
88     CHECK_FATAL(size >= 0, "should not be negative");
89 
90     seekRet = fseek(f, offset, SEEK_SET);
91     CHECK_FATAL(seekRet == 0, "call fseek failed");
92     buf.resize(size);
93 
94     size_t result = fread(&buf[0], sizeof(uint8), static_cast<size_t>(size), f);
95     fclose(f);
96     CHECK_FATAL(result == static_cast<size_t>(size), "Error while reading the binary file: %s", name.c_str());
97 }
98 
ImportStr()99 GStrIdx BinaryMplImport::ImportStr()
100 {
101     int64 tag = ReadNum();
102     if (tag == 0) {
103         return GStrIdx(0);
104     }
105     if (tag < 0) {
106         CHECK_FATAL(-tag < static_cast<int64>(gStrTab.size()), "index out of range in BinaryMplt::ImportStr");
107         return gStrTab[-tag];
108     }
109     CHECK_FATAL(tag == kBinString, "expecting kBinString");
110     std::string str;
111     ReadAsciiStr(str);
112     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(str);
113     gStrTab.push_back(strIdx);
114     return strIdx;
115 }
116 
ImportUsrStr()117 UStrIdx BinaryMplImport::ImportUsrStr()
118 {
119     int64 tag = ReadNum();
120     if (tag == 0) {
121         return UStrIdx(0);
122     }
123     if (tag < 0) {
124         CHECK_FATAL(-tag < static_cast<int64>(uStrTab.size()), "index out of range in BinaryMplt::InUsrStr");
125         return uStrTab[-tag];
126     }
127     CHECK_FATAL(tag == kBinUsrString, "expecting kBinUsrString");
128     std::string str;
129     ReadAsciiStr(str);
130     UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str);
131     uStrTab.push_back(strIdx);
132     return strIdx;
133 }
134 
ImportPragmaElement()135 MIRPragmaElement *BinaryMplImport::ImportPragmaElement()
136 {
137     MIRPragmaElement *element = mod.GetPragmaMemPool()->New<MIRPragmaElement>(mod);
138     element->SetNameStrIdx(ImportStr());
139     element->SetTypeStrIdx(ImportStr());
140     element->SetType(static_cast<PragmaValueType>(ReadNum()));
141     if (element->GetType() == kValueString || element->GetType() == kValueType || element->GetType() == kValueField ||
142         element->GetType() == kValueMethod || element->GetType() == kValueEnum) {
143         element->SetI32Val(static_cast<int32>(ImportStr()));
144     } else {
145         element->SetU64Val(static_cast<uint64>(ReadInt64()));
146     }
147     int64 size = ReadNum();
148     for (int64 i = 0; i < size; ++i) {
149         element->SubElemVecPushBack(ImportPragmaElement());
150     }
151     return element;
152 }
153 
ImportPragma()154 MIRPragma *BinaryMplImport::ImportPragma()
155 {
156     MIRPragma *p = mod.GetPragmaMemPool()->New<MIRPragma>(mod);
157     p->SetKind(static_cast<PragmaKind>(ReadNum()));
158     p->SetVisibility(ReadNum());
159     p->SetStrIdx(ImportStr());
160     p->SetParamNum(ReadNum());
161     int64 size = ReadNum();
162     for (int64 i = 0; i < size; ++i) {
163         p->PushElementVector(ImportPragmaElement());
164     }
165     return p;
166 }
167 
ImportFieldPair(FieldPair & fp)168 void BinaryMplImport::ImportFieldPair(FieldPair &fp)
169 {
170     fp.first = ImportStr();
171     fp.second.second.SetAttrFlag(ReadNum());
172     fp.second.second.SetAlignValue(ReadNum());
173 }
174 
ImportMethodPair(MethodPair & memPool)175 void BinaryMplImport::ImportMethodPair(MethodPair &memPool)
176 {
177     std::string funcName;
178     ReadAsciiStr(funcName);
179     TyIdx funcTyIdx = ImportJType();
180     int64 x = ReadNum();
181     CHECK_FATAL(x >= 0, "ReadNum error, x: %d", x);
182     auto attrFlag = static_cast<uint64>(x);
183 
184     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName);
185     MIRSymbol *prevFuncSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(strIdx);
186     MIRSymbol *funcSt = nullptr;
187     MIRFunction *fn = nullptr;
188 
189     if (prevFuncSt != nullptr && (prevFuncSt->GetStorageClass() == kScText && prevFuncSt->GetSKind() == kStFunc)) {
190         funcSt = prevFuncSt;
191         fn = funcSt->GetFunction();
192     } else {
193         funcSt = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
194         funcSt->SetNameStrIdx(strIdx);
195         GlobalTables::GetGsymTable().AddToStringSymbolMap(*funcSt);
196         funcSt->SetStorageClass(kScText);
197         funcSt->SetSKind(kStFunc);
198         funcSt->SetTyIdx(funcTyIdx);
199         funcSt->SetIsImported(imported);
200         funcSt->SetIsImportedDecl(imported);
201         methodSymbols.push_back(funcSt);
202 
203         fn = mod.GetMemPool()->New<MIRFunction>(&mod, funcSt->GetStIdx());
204         fn->SetPuidx(GlobalTables::GetFunctionTable().GetFuncTable().size());
205         GlobalTables::GetFunctionTable().GetFuncTable().push_back(fn);
206         funcSt->SetFunction(fn);
207         auto *funcType = static_cast<MIRFuncType *>(funcSt->GetType());
208         fn->SetMIRFuncType(funcType);
209         fn->SetFileIndex(0);
210         fn->SetBaseClassFuncNames(funcSt->GetNameStrIdx());
211         fn->SetFuncAttrs(attrFlag);
212     }
213     memPool.first.SetFullIdx(funcSt->GetStIdx().FullIdx());
214     memPool.second.first.reset(funcTyIdx);
215     memPool.second.second.SetAttrFlag(attrFlag);
216 }
217 
UpdateMethodSymbols()218 void BinaryMplImport::UpdateMethodSymbols()
219 {
220     for (auto sym : methodSymbols) {
221         MIRFunction *fn = sym->GetFunction();
222         CHECK_FATAL(fn != nullptr, "fn is null");
223         auto *funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(sym->GetTyIdx()));
224         fn->SetMIRFuncType(funcType);
225         fn->SetReturnStruct(*GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx()));
226         if (fn->GetFormalDefVec().size() != 0) {
227             continue;  // already updated in ImportFunction()
228         }
229         for (size_t i = 0; i < funcType->GetParamTypeList().size(); ++i) {
230             FormalDef formalDef(nullptr, funcType->GetParamTypeList()[i], funcType->GetParamAttrsList()[i]);
231             fn->GetFormalDefVec().push_back(formalDef);
232         }
233     }
234 }
235 
ImportFieldsOfStructType(FieldVector & fields,uint32 methodSize)236 void BinaryMplImport::ImportFieldsOfStructType(FieldVector &fields, uint32 methodSize)
237 {
238     int64 size = ReadNum();
239     int64 initSize = static_cast<int64>(fields.size() + methodSize);
240     for (int64 i = 0; i < size; ++i) {
241         FieldPair fp;
242         ImportFieldPair(fp);
243         if (initSize == 0) {
244             fields.push_back(fp);
245         }
246     }
247 }
248 
ImportMethodsOfStructType(MethodVector & methods)249 void BinaryMplImport::ImportMethodsOfStructType(MethodVector &methods)
250 {
251     int64 size = ReadNum();
252     bool isEmpty = methods.empty();
253     for (int64 i = 0; i < size; ++i) {
254         MethodPair memPool;
255         ImportMethodPair(memPool);
256         if (isEmpty) {
257             methods.push_back(memPool);
258         }
259     }
260 }
261 
ImportStructTypeData(MIRStructType & type)262 void BinaryMplImport::ImportStructTypeData(MIRStructType &type)
263 {
264     uint32 methodSize = type.GetMethods().size();
265     ImportFieldsOfStructType(type.GetFields(), methodSize);
266     ImportFieldsOfStructType(type.GetStaticFields(), methodSize);
267     ImportFieldsOfStructType(type.GetParentFields(), methodSize);
268     ImportMethodsOfStructType(type.GetMethods());
269     type.SetIsImported(imported);
270 }
271 
ImportInterfacesOfClassType(std::vector<TyIdx> & interfaces)272 void BinaryMplImport::ImportInterfacesOfClassType(std::vector<TyIdx> &interfaces)
273 {
274     int64 size = ReadNum();
275     bool isEmpty = interfaces.empty();
276     for (int64 i = 0; i < size; ++i) {
277         TyIdx idx = ImportJType();
278         if (isEmpty) {
279             interfaces.push_back(idx);
280         }
281     }
282 }
283 
ImportInfoIsStringOfStructType(MIRStructType & type)284 void BinaryMplImport::ImportInfoIsStringOfStructType(MIRStructType &type)
285 {
286     int64 size = ReadNum();
287     bool isEmpty = type.GetInfoIsString().empty();
288 
289     for (int64 i = 0; i < size; ++i) {
290         auto isString = static_cast<bool>(ReadNum());
291 
292         if (isEmpty) {
293             type.PushbackIsString(isString);
294         }
295     }
296 }
297 
ImportInfoOfStructType(MIRStructType & type)298 void BinaryMplImport::ImportInfoOfStructType(MIRStructType &type)
299 {
300     uint64 size = static_cast<uint64>(ReadNum());
301     bool isEmpty = type.GetInfo().empty();
302     for (size_t i = 0; i < size; ++i) {
303         GStrIdx idx = ImportStr();
304         int64 x = (type.GetInfoIsStringElemt(i)) ? static_cast<int64>(ImportStr()) : ReadNum();
305         CHECK_FATAL(x >= 0, "ReadNum nagative, x: %d", x);
306         CHECK_FATAL(x <= std::numeric_limits<uint32_t>::max(), "ReadNum too large, x: %d", x);
307         if (isEmpty) {
308             type.PushbackMIRInfo(MIRInfoPair(idx, static_cast<uint32>(x)));
309         }
310     }
311 }
312 
ImportPragmaOfStructType(MIRStructType & type)313 void BinaryMplImport::ImportPragmaOfStructType(MIRStructType &type)
314 {
315     int64 size = ReadNum();
316     bool isEmpty = type.GetPragmaVec().empty();
317     for (int64 i = 0; i < size; ++i) {
318         MIRPragma *pragma = ImportPragma();
319         if (isEmpty) {
320             type.PushbackPragma(pragma);
321         }
322     }
323 }
324 
SetClassTyidxOfMethods(MIRStructType & type)325 void BinaryMplImport::SetClassTyidxOfMethods(MIRStructType &type)
326 {
327     if (type.GetTypeIndex() != 0u) {
328         // set up classTyIdx for methods
329         for (size_t i = 0; i < type.GetMethods().size(); ++i) {
330             StIdx stidx = type.GetMethodsElement(i).first;
331             MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx());
332             CHECK_FATAL(st != nullptr, "st is null");
333             CHECK_FATAL(st->GetSKind() == kStFunc, "unexpected st->sKind");
334             st->GetFunction()->SetClassTyIdx(type.GetTypeIndex());
335         }
336     }
337 }
338 
ImportClassTypeData(MIRClassType & type)339 void BinaryMplImport::ImportClassTypeData(MIRClassType &type)
340 {
341     TyIdx tempType = ImportJType();
342     // Keep the parent_tyidx we first met.
343     if (type.GetParentTyIdx() == 0u) {
344         type.SetParentTyIdx(tempType);
345     }
346     ImportInterfacesOfClassType(type.GetInterfaceImplemented());
347     ImportInfoIsStringOfStructType(type);
348     if (!inIPA) {
349         ImportInfoOfStructType(type);
350         ImportPragmaOfStructType(type);
351     }
352     SetClassTyidxOfMethods(type);
353 }
354 
ImportInterfaceTypeData(MIRInterfaceType & type)355 void BinaryMplImport::ImportInterfaceTypeData(MIRInterfaceType &type)
356 {
357     ImportInterfacesOfClassType(type.GetParentsTyIdx());
358     ImportInfoIsStringOfStructType(type);
359     if (!inIPA) {
360         ImportInfoOfStructType(type);
361         ImportPragmaOfStructType(type);
362     }
363     SetClassTyidxOfMethods(type);
364 }
365 
Reset()366 void BinaryMplImport::Reset()
367 {
368     buf.clear();
369     bufI = 0;
370     gStrTab.clear();
371     uStrTab.clear();
372     typTab.clear();
373     funcTab.clear();
374     symTab.clear();
375     methodSymbols.clear();
376     definedLabels.clear();
377     gStrTab.push_back(GStrIdx(0));  // Dummy
378     uStrTab.push_back(UStrIdx(0));  // Dummy
379     symTab.push_back(nullptr);      // Dummy
380     funcTab.push_back(nullptr);     // Dummy
381     eaCgTab.push_back(nullptr);
382     for (int32 pti = static_cast<int32>(PTY_begin); pti < static_cast<int32>(PTY_end); ++pti) {
383         typTab.push_back(TyIdx(pti));
384     }
385 }
386 
ImportTypeAttrs()387 TypeAttrs BinaryMplImport::ImportTypeAttrs()
388 {
389     TypeAttrs ta;
390     ta.SetAttrFlag(static_cast<uint64>(ReadNum()));
391     ta.SetAlignValue(static_cast<uint8>(ReadNum()));
392     ta.SetPack(static_cast<uint32>(ReadNum()));
393     return ta;
394 }
395 
ImportTypePairs(std::vector<TypePair> & insVecType)396 void BinaryMplImport::ImportTypePairs(std::vector<TypePair> &insVecType)
397 {
398     int64 size = ReadNum();
399     for (int64 i = 0; i < size; ++i) {
400         TyIdx t0 = ImportJType();
401         TyIdx t1 = ImportJType();
402         TypePair tp(t0, t1);
403         insVecType.push_back(tp);
404     }
405 }
406 
CompleteAggInfo(TyIdx tyIdx)407 void BinaryMplImport::CompleteAggInfo(TyIdx tyIdx)
408 {
409     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
410     CHECK_FATAL(type != nullptr, "MIRType is null");
411     if (type->GetKind() == kTypeInterface) {
412         auto *interfaceType = static_cast<MIRInterfaceType *>(type);
413         ImportStructTypeData(*interfaceType);
414         ImportInterfaceTypeData(*interfaceType);
415     } else if (type->GetKind() == kTypeClass) {
416         auto *classType = static_cast<MIRClassType *>(type);
417         ImportStructTypeData(*classType);
418         ImportClassTypeData(*classType);
419     } else if (type->GetKind() == kTypeStruct || type->GetKind() == kTypeUnion) {
420         auto *structType = static_cast<MIRStructType *>(type);
421         ImportStructTypeData(*structType);
422     } else {
423         ERR(kLncErr, "in BinaryMplImport::CompleteAggInfo, MIRType error");
424     }
425 }
426 
ImportJType(bool forPointedType)427 TyIdx BinaryMplImport::ImportJType(bool forPointedType)
428 {
429     int64 tag = ReadNum();
430     if (tag == 0) {
431         return TyIdx(0);
432     }
433     if (tag < 0) {
434         CHECK_FATAL(static_cast<size_t>(-tag) < typTab.size(), "index out of bounds");
435         return typTab.at(static_cast<uint64>(-tag));
436     }
437     PrimType primType = static_cast<PrimType>(0);
438     GStrIdx strIdx(0);
439     bool nameIsLocal = false;
440     ImportTypeBase(primType, strIdx, nameIsLocal);
441 
442     switch (tag) {
443         case kBinKindTypeScalar:
444             return TyIdx(primType);
445         default:
446             CHECK_FATAL(false, "Unexpected binary kind");
447     }
448 }
449 
ImportTypeBase(PrimType & primType,GStrIdx & strIdx,bool & nameIsLocal)450 void BinaryMplImport::ImportTypeBase(PrimType &primType, GStrIdx &strIdx, bool &nameIsLocal)
451 {
452     primType = static_cast<PrimType>(ReadNum());
453     strIdx = ImportStr();
454     nameIsLocal = ReadNum();
455 }
456 
GetOrCreateSymbol(TyIdx tyIdx,GStrIdx strIdx,MIRSymKind mclass,MIRStorageClass sclass,MIRFunction * func,uint8 scpID)457 MIRSymbol *BinaryMplImport::GetOrCreateSymbol(TyIdx tyIdx, GStrIdx strIdx, MIRSymKind mclass, MIRStorageClass sclass,
458                                               MIRFunction *func, uint8 scpID)
459 {
460     MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(strIdx);
461     if (st != nullptr && st->GetStorageClass() == sclass && st->GetSKind() == mclass && scpID == kScopeGlobal) {
462         return st;
463     }
464     return mirBuilder.CreateSymbol(tyIdx, strIdx, mclass, sclass, func, scpID);
465 }
466 
SkipTotalSize()467 inline void BinaryMplImport::SkipTotalSize()
468 {
469     ReadInt();
470 }
471 
ReadStrField()472 void BinaryMplImport::ReadStrField()
473 {
474     SkipTotalSize();
475 
476     int32 size = ReadInt();
477     for (int64 i = 0; i < size; ++i) {
478         GStrIdx stridx = ImportStr();
479         GlobalTables::GetConstPool().PutLiteralNameAsImported(stridx);
480     }
481     int64 tag = 0;
482     tag = ReadNum();
483     CHECK_FATAL(tag == ~kBinStrStart, "pattern mismatch in Read STR");
484 }
485 
MergeDuplicated(PUIdx methodPuidx,std::vector<CallInfo * > & targetSet,std::vector<CallInfo * > & newSet)486 void BinaryMplImport::MergeDuplicated(PUIdx methodPuidx, std::vector<CallInfo *> &targetSet,
487                                       std::vector<CallInfo *> &newSet)
488 {
489     if (targetSet.empty()) {
490         (void)targetSet.insert(targetSet.begin(), newSet.begin(), newSet.end());
491         std::unordered_set<uint32> tmp;
492         mod.AddValueToMethod2TargetHash(methodPuidx, tmp);
493         for (size_t i = 0; i < newSet.size(); ++i) {
494             mod.InsertTargetHash(methodPuidx, newSet[i]->GetID());
495         }
496     } else {
497         for (size_t i = 0; i < newSet.size(); ++i) {
498             CallInfo *newItem = newSet[i];
499             if (!mod.HasTargetHash(methodPuidx, newItem->GetID())) {
500                 targetSet.push_back(newItem);
501                 mod.InsertTargetHash(methodPuidx, newItem->GetID());
502             }
503         }
504     }
505 }
506 
ReadEaField()507 void BinaryMplImport::ReadEaField()
508 {
509     ReadInt();
510     int size = ReadInt();
511     for (int i = 0; i < size; ++i) {
512         GStrIdx funcName = ImportStr();
513         int nodesSize = ReadInt();
514         EAConnectionGraph *newEaCg =
515             mod.GetMemPool()->New<EAConnectionGraph>(&mod, &mod.GetMPAllocator(), funcName, true);
516         newEaCg->ResizeNodes(nodesSize, nullptr);
517         InEaCgNode(*newEaCg);
518         int eaSize = ReadInt();
519         for (int j = 0; j < eaSize; ++j) {
520             EACGBaseNode *node = &InEaCgNode(*newEaCg);
521             newEaCg->funcArgNodes.push_back(node);
522         }
523         mod.SetEAConnectionGraph(funcName, newEaCg);
524     }
525     CHECK_FATAL(ReadNum() == ~kBinEaStart, "pattern mismatch in Read EA");
526 }
527 
ReadSeField()528 void BinaryMplImport::ReadSeField()
529 {
530     SkipTotalSize();
531 
532     int32 size = ReadInt();
533 #ifdef MPLT_DEBUG
534     LogInfo::MapleLogger() << "SE SIZE : " << size << '\n';
535 #endif
536     for (int32 i = 0; i < size; ++i) {
537         GStrIdx funcName = ImportStr();
538         uint8 specialEffect = Read();
539         TyIdx tyIdx = kInitTyIdx;
540         if ((specialEffect & kPureFunc) == kPureFunc) {
541             tyIdx = ImportJType();
542         }
543         const std::string &funcStr = GlobalTables::GetStrTable().GetStringFromStrIdx(funcName);
544         auto *funcSymbol =
545             GlobalTables::GetGsymTable().GetSymbolFromStrIdx(GlobalTables::GetStrTable().GetStrIdxFromName(funcStr));
546         MIRFunction *func = funcSymbol != nullptr ? mirBuilder.GetFunctionFromSymbol(*funcSymbol) : nullptr;
547         if (func != nullptr) {
548             func->SetAttrsFromSe(specialEffect);
549         } else if ((specialEffect & kPureFunc) == kPureFunc) {
550             func = mirBuilder.GetOrCreateFunction(funcStr, tyIdx);
551             func->SetAttrsFromSe(specialEffect);
552         }
553     }
554     int64 tag = ReadNum();
555     CHECK_FATAL(tag == ~kBinSeStart, "pattern mismatch in Read TYPE");
556 }
557 
InEaCgBaseNode(EACGBaseNode & base,EAConnectionGraph & newEaCg,bool firstPart)558 void BinaryMplImport::InEaCgBaseNode(EACGBaseNode &base, EAConnectionGraph &newEaCg, bool firstPart)
559 {
560     if (firstPart) {
561         base.SetEAStatus(static_cast<EAStatus>(ReadNum()));
562         base.SetID(ReadInt());
563     } else {
564         // start to in points to
565         int size = ReadInt();
566         for (int i = 0; i < size; ++i) {
567             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
568             CHECK_FATAL(point2Node->IsObjectNode(), "must be");
569             (void)base.pointsTo.insert(static_cast<EACGObjectNode *>(point2Node));
570         }
571         // start to in in
572         size = ReadInt();
573         for (int i = 0; i < size; ++i) {
574             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
575             base.InsertInSet(point2Node);
576         }
577         // start to in out
578         size = ReadInt();
579         for (int i = 0; i < size; ++i) {
580             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
581             base.InsertOutSet(point2Node);
582         }
583     }
584 }
585 
InEaCgActNode(EACGActualNode & actual)586 void BinaryMplImport::InEaCgActNode(EACGActualNode &actual)
587 {
588     actual.isPhantom = Read() == 1;
589     actual.isReturn = Read() == 1;
590     actual.argIdx = Read();
591     actual.callSiteInfo = static_cast<uint32>(ReadInt());
592 }
593 
InEaCgFieldNode(EACGFieldNode & field,EAConnectionGraph & newEaCg)594 void BinaryMplImport::InEaCgFieldNode(EACGFieldNode &field, EAConnectionGraph &newEaCg)
595 {
596     field.SetFieldID(ReadInt());
597     int size = ReadInt();
598     for (int i = 0; i < size; ++i) {
599         EACGBaseNode *node = &InEaCgNode(newEaCg);
600         CHECK_FATAL(node->IsObjectNode(), "must be");
601         (void)field.belongsTo.insert(static_cast<EACGObjectNode *>(node));
602     }
603     field.isPhantom = Read() == 1;
604 }
605 
InEaCgObjNode(EACGObjectNode & obj,EAConnectionGraph & newEaCg)606 void BinaryMplImport::InEaCgObjNode(EACGObjectNode &obj, EAConnectionGraph &newEaCg)
607 {
608     Read();
609     obj.isPhantom = true;
610     int size = ReadInt();
611     for (int i = 0; i < size; ++i) {
612         EACGBaseNode *node = &InEaCgNode(newEaCg);
613         CHECK_FATAL(node->IsFieldNode(), "must be");
614         auto *field = static_cast<EACGFieldNode *>(node);
615         obj.fieldNodes[static_cast<EACGFieldNode *>(field)->GetFieldID()] = field;
616     }
617     // start to in point by
618     size = ReadInt();
619     for (int i = 0; i < size; ++i) {
620         EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
621         (void)obj.pointsBy.insert(point2Node);
622     }
623 }
624 
InEaCgRefNode(EACGRefNode & ref)625 void BinaryMplImport::InEaCgRefNode(EACGRefNode &ref)
626 {
627     ref.isStaticField = Read() == 1 ? true : false;
628 }
629 
InEaCgNode(EAConnectionGraph & newEaCg)630 EACGBaseNode &BinaryMplImport::InEaCgNode(EAConnectionGraph &newEaCg)
631 {
632     int64 tag = ReadNum();
633     if (tag < 0) {
634         CHECK_FATAL(static_cast<uint64>(-tag) < eaCgTab.size(), "index out of bounds");
635         return *eaCgTab[-tag];
636     }
637     CHECK_FATAL(tag == kBinEaCgNode, "must be");
638     NodeKind kind = static_cast<NodeKind>(ReadNum());
639     EACGBaseNode *node = nullptr;
640     switch (kind) {
641         case kObejectNode:
642             node = new EACGObjectNode(&mod, &mod.GetMPAllocator(), &newEaCg);
643             break;
644         case kReferenceNode:
645             node = new EACGRefNode(&mod, &mod.GetMPAllocator(), &newEaCg);
646             break;
647         case kFieldNode:
648             node = new EACGFieldNode(&mod, &mod.GetMPAllocator(), &newEaCg);
649             break;
650         case kActualNode:
651             node = new EACGActualNode(&mod, &mod.GetMPAllocator(), &newEaCg);
652             break;
653         default:
654             CHECK_FATAL(false, "impossible");
655     }
656     node->SetEACG(&newEaCg);
657     eaCgTab.push_back(node);
658     InEaCgBaseNode(*node, newEaCg, true);
659     CHECK_FATAL(node->id > 0, "must not be zero");
660     newEaCg.SetNodeAt(node->id - 1, node);
661     if (node->IsActualNode()) {
662         CHECK_FATAL(ReadNum() == kBinEaCgActNode, "must be");
663         InEaCgActNode(static_cast<EACGActualNode &>(*node));
664     } else if (node->IsFieldNode()) {
665         CHECK_FATAL(ReadNum() == kBinEaCgFieldNode, "must be");
666         InEaCgFieldNode(static_cast<EACGFieldNode &>(*node), newEaCg);
667     } else if (node->IsObjectNode()) {
668         CHECK_FATAL(ReadNum() == kBinEaCgObjNode, "must be");
669         InEaCgObjNode(static_cast<EACGObjectNode &>(*node), newEaCg);
670     } else if (node->IsReferenceNode()) {
671         CHECK_FATAL(ReadNum() == kBinEaCgRefNode, "must be");
672         InEaCgRefNode(static_cast<EACGRefNode &>(*node));
673     }
674     InEaCgBaseNode(*node, newEaCg, false);
675     CHECK_FATAL(ReadNum() == ~kBinEaCgNode, "must be");
676     return *node;
677 }
678 
ReadEaCgField()679 EAConnectionGraph *BinaryMplImport::ReadEaCgField()
680 {
681     if (ReadNum() == ~kBinEaCgStart) {
682         return nullptr;
683     }
684     ReadInt();
685     GStrIdx funcStr = ImportStr();
686     int nodesSize = ReadInt();
687     EAConnectionGraph *newEaCg = mod.GetMemPool()->New<EAConnectionGraph>(&mod, &mod.GetMPAllocator(), funcStr, true);
688     newEaCg->ResizeNodes(nodesSize, nullptr);
689     InEaCgNode(*newEaCg);
690     CHECK_FATAL(newEaCg->GetNode(kFirstOpnd)->IsObjectNode(), "must be");
691     CHECK_FATAL(newEaCg->GetNode(kSecondOpnd)->IsReferenceNode(), "must be");
692     CHECK_FATAL(newEaCg->GetNode(kThirdOpnd)->IsFieldNode(), "must be");
693     newEaCg->globalField = static_cast<EACGFieldNode *>(newEaCg->GetNode(kThirdOpnd));
694     newEaCg->globalObj = static_cast<EACGObjectNode *>(newEaCg->GetNode(kFirstOpnd));
695     newEaCg->globalRef = static_cast<EACGRefNode *>(newEaCg->GetNode(kSecondOpnd));
696     CHECK_FATAL(newEaCg->globalField && newEaCg->globalObj && newEaCg->globalRef, "must be");
697     int32 nodeSize = ReadInt();
698     for (int j = 0; j < nodeSize; ++j) {
699         EACGBaseNode *node = &InEaCgNode(*newEaCg);
700         newEaCg->funcArgNodes.push_back(node);
701     }
702 
703     int32 callSitesize = ReadInt();
704     for (int i = 0; i < callSitesize; ++i) {
705         uint32 id = static_cast<uint32>(ReadInt());
706         newEaCg->callSite2Nodes[id] =
707             mod.GetMemPool()->New<MapleVector<EACGBaseNode *>>(mod.GetMPAllocator().Adapter());
708         int32 calleeArgSize = ReadInt();
709         for (int j = 0; j < calleeArgSize; ++j) {
710             EACGBaseNode *node = &InEaCgNode(*newEaCg);
711             newEaCg->callSite2Nodes[id]->push_back(node);
712         }
713     }
714 
715 #ifdef DEBUG
716     for (EACGBaseNode *node : newEaCg->GetNodes()) {
717         if (node == nullptr) {
718             continue;
719         }
720         node->CheckAllConnectionInNodes();
721     }
722 #endif
723     CHECK_FATAL(ReadNum() == ~kBinEaCgStart, "pattern mismatch in Read EACG");
724     return newEaCg;
725 }
726 
ReadSymTabField()727 void BinaryMplImport::ReadSymTabField()
728 {
729     SkipTotalSize();
730     int32 size = ReadInt();
731     for (int64 i = 0; i < size; i++) {
732         std::string str;
733         ReadAsciiStr(str);
734     }
735     int64 tag = ReadNum();
736     CHECK_FATAL(tag == ~kBinSymTabStart, "pattern mismatch in Read TYPE");
737     return;
738 }
739 
ReadContentField()740 void BinaryMplImport::ReadContentField()
741 {
742     SkipTotalSize();
743 
744     int32 size = ReadInt();
745     int64 item;
746     int32 offset;
747     for (int32 i = 0; i < size; ++i) {
748         item = ReadNum();
749         offset = ReadInt();
750         content[item] = offset;
751     }
752     CHECK_FATAL(ReadNum() == ~kBinContentStart, "pattern mismatch in Read CONTENT");
753 }
754 
Jump2NextField()755 void BinaryMplImport::Jump2NextField()
756 {
757     uint32 totalSize = static_cast<uint32>(ReadInt());
758     bufI += (totalSize - sizeof(uint32));
759     ReadNum();  // skip end tag for this field
760 }
761 
ImportForSrcLang(const std::string & fname,MIRSrcLang & srcLang)762 bool BinaryMplImport::ImportForSrcLang(const std::string &fname, MIRSrcLang &srcLang)
763 {
764     Reset();
765     ReadFileAt(fname, 0);
766     int32 magic = ReadInt();
767     if (kMpltMagicNumber != magic && (kMpltMagicNumber + 0x10) != magic) {
768         buf.clear();
769         return false;
770     }
771     importingFromMplt = kMpltMagicNumber == magic;
772     int64 fieldID = ReadNum();
773     while (fieldID != kBinFinish) {
774         switch (fieldID) {
775             case kBinHeaderStart: {
776                 SkipTotalSize();
777                 (void)ReadNum();  // skip flavor
778                 srcLang = static_cast<MIRSrcLang>(ReadNum());
779                 return true;
780             }
781             default: {
782                 Jump2NextField();
783                 break;
784             }
785         }
786         fieldID = ReadNum();
787     }
788     return false;
789 }
790 }  // namespace maple
791