• 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 
ImportConstBase(MIRConstKind & kind,MIRTypePtr & type)99 void BinaryMplImport::ImportConstBase(MIRConstKind &kind, MIRTypePtr &type)
100 {
101     kind = static_cast<MIRConstKind>(ReadNum());
102     TyIdx tyidx = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
103     type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyidx);
104 }
105 
ImportConst(MIRFunction * func)106 MIRConst *BinaryMplImport::ImportConst(MIRFunction *func)
107 {
108     int64 tag = ReadNum();
109     if (tag == 0) {
110         return nullptr;
111     }
112 
113     MIRConstKind kind;
114     MIRType *type = nullptr;
115     MemPool *memPool = mod.GetMemPool();
116 
117     ImportConstBase(kind, type);
118     switch (tag) {
119         case kBinKindConstInt:
120             return GlobalTables::GetIntConstTable().GetOrCreateIntConst(ReadNum(), *type);
121         case kBinKindConstAddrof: {
122             MIRSymbol *sym = InSymbol(func);
123             CHECK_FATAL(sym != nullptr, "null ptr check");
124             FieldID fi = ReadNum();
125             int32 ofst = static_cast<int32>(ReadNum());
126             // do not use "type"; instead, get exprTy from sym
127             TyIdx ptyIdx = sym->GetTyIdx();
128             MIRPtrType ptrType(ptyIdx, (mod.IsJavaModule() ? PTY_ref : GetExactPtrPrimType()));
129             ptyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&ptrType);
130             MIRType *exprTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptyIdx);
131             return memPool->New<MIRAddrofConst>(sym->GetStIdx(), fi, *exprTy, ofst);
132         }
133         case kBinKindConstAddrofLocal: {
134             MIRSymbol *sym = ImportLocalSymbol(func);
135             FieldID fi = static_cast<FieldID>(ReadNum());
136             int32 ofst = static_cast<int32>(ReadNum());
137             return memPool->New<MIRAddrofConst>(sym->GetStIdx(), fi, *type, ofst);
138         }
139         case kBinKindConstAddrofFunc: {
140             PUIdx puIdx = ImportFunction();
141             MIRFunction *f = GlobalTables::GetFunctionTable().GetFuncTable()[puIdx];
142             f->GetFuncSymbol()->SetAppearsInCode(true);
143             mod.SetCurFunction(func);
144             return memPool->New<MIRAddroffuncConst>(puIdx, *type);
145         }
146         case kBinKindConstAddrofLabel: {
147             LabelIdx lidx = ImportLabel(func);
148             PUIdx puIdx = func->GetPuidx();
149             MIRLblConst *lblConst = memPool->New<MIRLblConst>(lidx, puIdx, *type);
150             (void)func->GetLabelTab()->addrTakenLabels.insert(lidx);
151             return lblConst;
152         }
153         case kBinKindConstStr: {
154             UStrIdx ustr = ImportUsrStr();
155             return memPool->New<MIRStrConst>(ustr, *type);
156         }
157         case kBinKindConstStr16: {
158             Conststr16Node *cs;
159             cs = memPool->New<Conststr16Node>();
160             cs->SetPrimType(type->GetPrimType());
161             int64 len = ReadNum();
162             std::ostringstream ostr;
163             for (int64 i = 0; i < len; ++i) {
164                 ostr << Read();
165             }
166             std::u16string str16;
167             (void)namemangler::UTF8ToUTF16(str16, ostr.str());
168             cs->SetStrIdx(GlobalTables::GetU16StrTable().GetOrCreateStrIdxFromName(str16));
169             return memPool->New<MIRStr16Const>(cs->GetStrIdx(), *type);
170         }
171         case kBinKindConstFloat: {
172             union {
173                 float fvalue;
174                 int32 ivalue;
175             } value;
176 
177             value.ivalue = ReadNum();
178             return GlobalTables::GetFpConstTable().GetOrCreateFloatConst(value.fvalue);
179         }
180         case kBinKindConstDouble: {
181             union {
182                 double dvalue;
183                 int64 ivalue;
184             } value;
185 
186             value.ivalue = ReadNum();
187             return GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(value.dvalue);
188         }
189         case kBinKindConstAgg: {
190             MIRAggConst *aggConst = mod.GetMemPool()->New<MIRAggConst>(mod, *type);
191             int64 size = ReadNum();
192             for (int64 i = 0; i < size; ++i) {
193                 auto fieldId = static_cast<uint32>(ReadNum());
194                 auto fieldConst = ImportConst(func);
195                 aggConst->AddItem(fieldConst, fieldId);
196             }
197             return aggConst;
198         }
199         case kBinKindConstSt: {
200             MIRStConst *stConst = mod.GetMemPool()->New<MIRStConst>(mod, *type);
201             int64 size = ReadNum();
202             for (int64 i = 0; i < size; ++i) {
203                 stConst->PushbackSymbolToSt(InSymbol(func));
204             }
205             size = ReadNum();
206             for (int64 i = 0; i < size; ++i) {
207                 stConst->PushbackOffsetToSt(ReadNum());
208             }
209             return stConst;
210         }
211         default:
212             CHECK_FATAL(false, "Unhandled const type");
213     }
214 }
215 
ImportStr()216 GStrIdx BinaryMplImport::ImportStr()
217 {
218     int64 tag = ReadNum();
219     if (tag == 0) {
220         return GStrIdx(0);
221     }
222     if (tag < 0) {
223         CHECK_FATAL(-tag < static_cast<int64>(gStrTab.size()), "index out of range in BinaryMplt::ImportStr");
224         return gStrTab[-tag];
225     }
226     CHECK_FATAL(tag == kBinString, "expecting kBinString");
227     std::string str;
228     ReadAsciiStr(str);
229     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(str);
230     gStrTab.push_back(strIdx);
231     return strIdx;
232 }
233 
ImportUsrStr()234 UStrIdx BinaryMplImport::ImportUsrStr()
235 {
236     int64 tag = ReadNum();
237     if (tag == 0) {
238         return UStrIdx(0);
239     }
240     if (tag < 0) {
241         CHECK_FATAL(-tag < static_cast<int64>(uStrTab.size()), "index out of range in BinaryMplt::InUsrStr");
242         return uStrTab[-tag];
243     }
244     CHECK_FATAL(tag == kBinUsrString, "expecting kBinUsrString");
245     std::string str;
246     ReadAsciiStr(str);
247     UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str);
248     uStrTab.push_back(strIdx);
249     return strIdx;
250 }
251 
ImportPragmaElement()252 MIRPragmaElement *BinaryMplImport::ImportPragmaElement()
253 {
254     MIRPragmaElement *element = mod.GetPragmaMemPool()->New<MIRPragmaElement>(mod);
255     element->SetNameStrIdx(ImportStr());
256     element->SetTypeStrIdx(ImportStr());
257     element->SetType(static_cast<PragmaValueType>(ReadNum()));
258     if (element->GetType() == kValueString || element->GetType() == kValueType || element->GetType() == kValueField ||
259         element->GetType() == kValueMethod || element->GetType() == kValueEnum) {
260         element->SetI32Val(static_cast<int32>(ImportStr()));
261     } else {
262         element->SetU64Val(static_cast<uint64>(ReadInt64()));
263     }
264     int64 size = ReadNum();
265     for (int64 i = 0; i < size; ++i) {
266         element->SubElemVecPushBack(ImportPragmaElement());
267     }
268     return element;
269 }
270 
ImportPragma()271 MIRPragma *BinaryMplImport::ImportPragma()
272 {
273     MIRPragma *p = mod.GetPragmaMemPool()->New<MIRPragma>(mod);
274     p->SetKind(static_cast<PragmaKind>(ReadNum()));
275     p->SetVisibility(ReadNum());
276     p->SetStrIdx(ImportStr());
277     if (mod.IsJavaModule()) {
278         p->SetTyIdx(ImportType());
279         p->SetTyIdxEx(ImportType());
280     } else {
281         p->SetTyIdx(ImportTypeNonJava());
282         p->SetTyIdxEx(ImportTypeNonJava());
283     }
284     p->SetParamNum(ReadNum());
285     int64 size = ReadNum();
286     for (int64 i = 0; i < size; ++i) {
287         p->PushElementVector(ImportPragmaElement());
288     }
289     return p;
290 }
291 
ImportFieldPair(FieldPair & fp)292 void BinaryMplImport::ImportFieldPair(FieldPair &fp)
293 {
294     fp.first = ImportStr();
295     fp.second.first = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
296     fp.second.second.SetAttrFlag(ReadNum());
297     fp.second.second.SetAlignValue(ReadNum());
298     FieldAttrs fa = fp.second.second;
299     if (fa.GetAttr(FLDATTR_static) && fa.GetAttr(FLDATTR_final) &&
300         (fa.GetAttr(FLDATTR_public) || fa.GetAttr(FLDATTR_protected))) {
301         int64 tag = ReadNum();
302         if (tag == kBinInitConst) {
303             GlobalTables::GetConstPool().InsertConstPool(fp.first, ImportConst(nullptr));
304         }
305     }
306 }
307 
ImportMethodPair(MethodPair & memPool)308 void BinaryMplImport::ImportMethodPair(MethodPair &memPool)
309 {
310     std::string funcName;
311     ReadAsciiStr(funcName);
312     TyIdx funcTyIdx = ImportType();
313     int64 x = ReadNum();
314     CHECK_FATAL(x >= 0, "ReadNum error, x: %d", x);
315     auto attrFlag = static_cast<uint64>(x);
316 
317     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName);
318     MIRSymbol *prevFuncSt = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(strIdx);
319     MIRSymbol *funcSt = nullptr;
320     MIRFunction *fn = nullptr;
321 
322     if (prevFuncSt != nullptr && (prevFuncSt->GetStorageClass() == kScText && prevFuncSt->GetSKind() == kStFunc)) {
323         funcSt = prevFuncSt;
324         fn = funcSt->GetFunction();
325     } else {
326         funcSt = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
327         funcSt->SetNameStrIdx(strIdx);
328         GlobalTables::GetGsymTable().AddToStringSymbolMap(*funcSt);
329         funcSt->SetStorageClass(kScText);
330         funcSt->SetSKind(kStFunc);
331         funcSt->SetTyIdx(funcTyIdx);
332         funcSt->SetIsImported(imported);
333         funcSt->SetIsImportedDecl(imported);
334         methodSymbols.push_back(funcSt);
335 
336         fn = mod.GetMemPool()->New<MIRFunction>(&mod, funcSt->GetStIdx());
337         fn->SetPuidx(GlobalTables::GetFunctionTable().GetFuncTable().size());
338         GlobalTables::GetFunctionTable().GetFuncTable().push_back(fn);
339         funcSt->SetFunction(fn);
340         auto *funcType = static_cast<MIRFuncType *>(funcSt->GetType());
341         fn->SetMIRFuncType(funcType);
342         fn->SetFileIndex(0);
343         fn->SetBaseClassFuncNames(funcSt->GetNameStrIdx());
344         fn->SetFuncAttrs(attrFlag);
345     }
346     memPool.first.SetFullIdx(funcSt->GetStIdx().FullIdx());
347     memPool.second.first.reset(funcTyIdx);
348     memPool.second.second.SetAttrFlag(attrFlag);
349 }
350 
UpdateMethodSymbols()351 void BinaryMplImport::UpdateMethodSymbols()
352 {
353     for (auto sym : methodSymbols) {
354         MIRFunction *fn = sym->GetFunction();
355         CHECK_FATAL(fn != nullptr, "fn is null");
356         auto *funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(sym->GetTyIdx()));
357         fn->SetMIRFuncType(funcType);
358         fn->SetReturnStruct(*GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx()));
359         if (fn->GetFormalDefVec().size() != 0) {
360             continue;  // already updated in ImportFunction()
361         }
362         for (size_t i = 0; i < funcType->GetParamTypeList().size(); ++i) {
363             FormalDef formalDef(nullptr, funcType->GetParamTypeList()[i], funcType->GetParamAttrsList()[i]);
364             fn->GetFormalDefVec().push_back(formalDef);
365         }
366     }
367 }
368 
ImportFieldsOfStructType(FieldVector & fields,uint32 methodSize)369 void BinaryMplImport::ImportFieldsOfStructType(FieldVector &fields, uint32 methodSize)
370 {
371     int64 size = ReadNum();
372     int64 initSize = fields.size() + methodSize;
373     for (int64 i = 0; i < size; ++i) {
374         FieldPair fp;
375         ImportFieldPair(fp);
376         if (initSize == 0) {
377             fields.push_back(fp);
378         }
379     }
380 }
381 
ImportMethodsOfStructType(MethodVector & methods)382 void BinaryMplImport::ImportMethodsOfStructType(MethodVector &methods)
383 {
384     int64 size = ReadNum();
385     bool isEmpty = methods.empty();
386     for (int64 i = 0; i < size; ++i) {
387         MethodPair memPool;
388         ImportMethodPair(memPool);
389         if (isEmpty) {
390             methods.push_back(memPool);
391         }
392     }
393 }
394 
ImportStructTypeData(MIRStructType & type)395 void BinaryMplImport::ImportStructTypeData(MIRStructType &type)
396 {
397     uint32 methodSize = type.GetMethods().size();
398     ImportFieldsOfStructType(type.GetFields(), methodSize);
399     ImportFieldsOfStructType(type.GetStaticFields(), methodSize);
400     ImportFieldsOfStructType(type.GetParentFields(), methodSize);
401     ImportMethodsOfStructType(type.GetMethods());
402     type.SetIsImported(imported);
403 }
404 
ImportInterfacesOfClassType(std::vector<TyIdx> & interfaces)405 void BinaryMplImport::ImportInterfacesOfClassType(std::vector<TyIdx> &interfaces)
406 {
407     int64 size = ReadNum();
408     bool isEmpty = interfaces.empty();
409     for (int64 i = 0; i < size; ++i) {
410         TyIdx idx = ImportType();
411         if (isEmpty) {
412             interfaces.push_back(idx);
413         }
414     }
415 }
416 
ImportInfoIsStringOfStructType(MIRStructType & type)417 void BinaryMplImport::ImportInfoIsStringOfStructType(MIRStructType &type)
418 {
419     int64 size = ReadNum();
420     bool isEmpty = type.GetInfoIsString().empty();
421 
422     for (int64 i = 0; i < size; ++i) {
423         auto isString = static_cast<bool>(ReadNum());
424 
425         if (isEmpty) {
426             type.PushbackIsString(isString);
427         }
428     }
429 }
430 
ImportInfoOfStructType(MIRStructType & type)431 void BinaryMplImport::ImportInfoOfStructType(MIRStructType &type)
432 {
433     uint64 size = static_cast<uint64>(ReadNum());
434     bool isEmpty = type.GetInfo().empty();
435     for (size_t i = 0; i < size; ++i) {
436         GStrIdx idx = ImportStr();
437         int64 x = (type.GetInfoIsStringElemt(i)) ? static_cast<int64>(ImportStr()) : ReadNum();
438         CHECK_FATAL(x >= 0, "ReadNum nagative, x: %d", x);
439         CHECK_FATAL(x <= std::numeric_limits<uint32_t>::max(), "ReadNum too large, x: %d", x);
440         if (isEmpty) {
441             type.PushbackMIRInfo(MIRInfoPair(idx, static_cast<uint32>(x)));
442         }
443     }
444 }
445 
ImportPragmaOfStructType(MIRStructType & type)446 void BinaryMplImport::ImportPragmaOfStructType(MIRStructType &type)
447 {
448     int64 size = ReadNum();
449     bool isEmpty = type.GetPragmaVec().empty();
450     for (int64 i = 0; i < size; ++i) {
451         MIRPragma *pragma = ImportPragma();
452         if (isEmpty) {
453             type.PushbackPragma(pragma);
454         }
455     }
456 }
457 
SetClassTyidxOfMethods(MIRStructType & type)458 void BinaryMplImport::SetClassTyidxOfMethods(MIRStructType &type)
459 {
460     if (type.GetTypeIndex() != 0u) {
461         // set up classTyIdx for methods
462         for (size_t i = 0; i < type.GetMethods().size(); ++i) {
463             StIdx stidx = type.GetMethodsElement(i).first;
464             MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx());
465             CHECK_FATAL(st != nullptr, "st is null");
466             CHECK_FATAL(st->GetSKind() == kStFunc, "unexpected st->sKind");
467             st->GetFunction()->SetClassTyIdx(type.GetTypeIndex());
468         }
469     }
470 }
471 
ImportClassTypeData(MIRClassType & type)472 void BinaryMplImport::ImportClassTypeData(MIRClassType &type)
473 {
474     TyIdx tempType = ImportType();
475     // Keep the parent_tyidx we first met.
476     if (type.GetParentTyIdx() == 0u) {
477         type.SetParentTyIdx(tempType);
478     }
479     ImportInterfacesOfClassType(type.GetInterfaceImplemented());
480     ImportInfoIsStringOfStructType(type);
481     if (!inIPA) {
482         ImportInfoOfStructType(type);
483         ImportPragmaOfStructType(type);
484     }
485     SetClassTyidxOfMethods(type);
486 }
487 
ImportInterfaceTypeData(MIRInterfaceType & type)488 void BinaryMplImport::ImportInterfaceTypeData(MIRInterfaceType &type)
489 {
490     ImportInterfacesOfClassType(type.GetParentsTyIdx());
491     ImportInfoIsStringOfStructType(type);
492     if (!inIPA) {
493         ImportInfoOfStructType(type);
494         ImportPragmaOfStructType(type);
495     }
496     SetClassTyidxOfMethods(type);
497 }
498 
Reset()499 void BinaryMplImport::Reset()
500 {
501     buf.clear();
502     bufI = 0;
503     gStrTab.clear();
504     uStrTab.clear();
505     typTab.clear();
506     funcTab.clear();
507     symTab.clear();
508     methodSymbols.clear();
509     definedLabels.clear();
510     gStrTab.push_back(GStrIdx(0));  // Dummy
511     uStrTab.push_back(UStrIdx(0));  // Dummy
512     symTab.push_back(nullptr);      // Dummy
513     funcTab.push_back(nullptr);     // Dummy
514     eaCgTab.push_back(nullptr);
515     for (int32 pti = static_cast<int32>(PTY_begin); pti < static_cast<int32>(PTY_end); ++pti) {
516         typTab.push_back(TyIdx(pti));
517     }
518 }
519 
ImportTypeAttrs()520 TypeAttrs BinaryMplImport::ImportTypeAttrs()
521 {
522     TypeAttrs ta;
523     ta.SetAttrFlag(static_cast<uint64>(ReadNum()));
524     ta.SetAlignValue(static_cast<uint8>(ReadNum()));
525     ta.SetPack(static_cast<uint32>(ReadNum()));
526     return ta;
527 }
528 
ImportTypePairs(std::vector<TypePair> & insVecType)529 void BinaryMplImport::ImportTypePairs(std::vector<TypePair> &insVecType)
530 {
531     int64 size = ReadNum();
532     for (int64 i = 0; i < size; ++i) {
533         TyIdx t0 = ImportType();
534         TyIdx t1 = ImportType();
535         TypePair tp(t0, t1);
536         insVecType.push_back(tp);
537     }
538 }
539 
CompleteAggInfo(TyIdx tyIdx)540 void BinaryMplImport::CompleteAggInfo(TyIdx tyIdx)
541 {
542     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
543     CHECK_FATAL(type != nullptr, "MIRType is null");
544     if (type->GetKind() == kTypeInterface) {
545         auto *interfaceType = static_cast<MIRInterfaceType *>(type);
546         ImportStructTypeData(*interfaceType);
547         ImportInterfaceTypeData(*interfaceType);
548     } else if (type->GetKind() == kTypeClass) {
549         auto *classType = static_cast<MIRClassType *>(type);
550         ImportStructTypeData(*classType);
551         ImportClassTypeData(*classType);
552     } else if (type->GetKind() == kTypeStruct || type->GetKind() == kTypeUnion) {
553         auto *structType = static_cast<MIRStructType *>(type);
554         ImportStructTypeData(*structType);
555     } else {
556         ERR(kLncErr, "in BinaryMplImport::CompleteAggInfo, MIRType error");
557     }
558 }
559 
IsIncomplete(const MIRType & type)560 inline static bool IsIncomplete(const MIRType &type)
561 {
562     return (type.GetKind() == kTypeInterfaceIncomplete || type.GetKind() == kTypeClassIncomplete ||
563             type.GetKind() == kTypeStructIncomplete);
564 }
565 
ImportType(bool forPointedType)566 TyIdx BinaryMplImport::ImportType(bool forPointedType)
567 {
568     int64 tag = ReadNum();
569     static MIRType *typeNeedsComplete = nullptr;
570     static int ptrLev = 0;
571     if (tag == 0) {
572         return TyIdx(0);
573     }
574     if (tag < 0) {
575         CHECK_FATAL(static_cast<size_t>(-tag) < typTab.size(), "index out of bounds");
576         return typTab.at(static_cast<uint64>(-tag));
577     }
578     PrimType primType = static_cast<PrimType>(0);
579     GStrIdx strIdx(0);
580     bool nameIsLocal = false;
581     ImportTypeBase(primType, strIdx, nameIsLocal);
582 
583     switch (tag) {
584         case kBinKindTypeScalar:
585             return TyIdx(primType);
586         case kBinKindTypePointer: {
587             MIRPtrType type(primType, strIdx);
588             type.SetNameIsLocal(nameIsLocal);
589             size_t idx = typTab.size();
590             typTab.push_back(TyIdx(0));
591             type.SetTypeAttrs(ImportTypeAttrs());
592             ++ptrLev;
593             type.SetPointedTyIdx(ImportType(true));
594             --ptrLev;
595             MIRType *origType = &InsertInTypeTables(type);
596             typTab[idx] = origType->GetTypeIndex();
597             if (typeNeedsComplete != nullptr && ptrLev == 0) {
598                 TyIdx tyIdxNeedsComplete = typeNeedsComplete->GetTypeIndex();
599                 typeNeedsComplete = nullptr;
600                 CompleteAggInfo(tyIdxNeedsComplete);
601             }
602             return origType->GetTypeIndex();
603         }
604         case kBinKindTypeFArray: {
605             MIRFarrayType type(strIdx);
606             type.SetNameIsLocal(nameIsLocal);
607             size_t idx = typTab.size();
608             typTab.push_back(TyIdx(0));
609             type.SetElemtTyIdx(ImportType(forPointedType));
610             MIRType *origType = &InsertInTypeTables(type);
611             typTab[idx] = origType->GetTypeIndex();
612             return origType->GetTypeIndex();
613         }
614         case kBinKindTypeJarray: {
615             MIRJarrayType type(strIdx);
616             type.SetNameIsLocal(nameIsLocal);
617             size_t idx = typTab.size();
618             typTab.push_back(TyIdx(0));
619             type.SetElemtTyIdx(ImportType(forPointedType));
620             MIRType *origType = &InsertInTypeTables(type);
621             typTab[idx] = origType->GetTypeIndex();
622             return origType->GetTypeIndex();
623         }
624         case kBinKindTypeArray: {
625             MIRArrayType type(strIdx);
626             type.SetNameIsLocal(nameIsLocal);
627             type.SetDim(ReadNum());
628             CHECK_FATAL(type.GetDim() < kMaxArrayDim, "array index out of range");
629             for (uint16 i = 0; i < type.GetDim(); ++i) {
630                 type.SetSizeArrayItem(i, ReadNum());
631             }
632             size_t idx = typTab.size();
633             typTab.push_back(TyIdx(0));
634             type.SetElemTyIdx(ImportType(forPointedType));
635             type.SetTypeAttrs(ImportTypeAttrs());
636             MIRType *origType = &InsertInTypeTables(type);
637             typTab[idx] = origType->GetTypeIndex();
638             return origType->GetTypeIndex();
639         }
640         case kBinKindTypeFunction: {
641             MIRFuncType type(strIdx);
642             type.SetNameIsLocal(nameIsLocal);
643             size_t idx = typTab.size();
644             typTab.push_back(TyIdx(0));
645             type.SetRetTyIdx(ImportType());
646             type.funcAttrs.SetAttrFlag(ReadNum());
647             int64 size = ReadNum();
648             for (int64 i = 0; i < size; ++i) {
649                 type.GetParamTypeList().push_back(ImportType());
650             }
651             size = ReadNum();
652             for (int64 i = 0; i < size; ++i) {
653                 type.GetParamAttrsList().push_back(ImportTypeAttrs());
654             }
655             MIRType *origType = &InsertInTypeTables(type);
656             typTab[idx] = origType->GetTypeIndex();
657             return origType->GetTypeIndex();
658         }
659         case kBinKindTypeParam: {
660             MIRTypeParam type(strIdx);
661             type.SetNameIsLocal(nameIsLocal);
662             MIRType *origType = &InsertInTypeTables(type);
663             typTab.push_back(origType->GetTypeIndex());
664             return origType->GetTypeIndex();
665         }
666         case kBinKindTypeInstantVector: {
667             auto kind = static_cast<MIRTypeKind>(ReadNum());
668             MIRInstantVectorType type(kind, strIdx);
669             type.SetNameIsLocal(nameIsLocal);
670             auto *origType = static_cast<MIRInstantVectorType *>(&InsertInTypeTables(type));
671             typTab.push_back(origType->GetTypeIndex());
672             ImportTypePairs(origType->GetInstantVec());
673             return origType->GetTypeIndex();
674         }
675         case kBinKindTypeGenericInstant: {
676             MIRGenericInstantType type(strIdx);
677             type.SetNameIsLocal(nameIsLocal);
678             auto *origType = static_cast<MIRGenericInstantType *>(&InsertInTypeTables(type));
679             typTab.push_back(origType->GetTypeIndex());
680             ImportTypePairs(origType->GetInstantVec());
681             origType->SetGenericTyIdx(ImportType());
682             return origType->GetTypeIndex();
683         }
684         case kBinKindTypeBitField: {
685             uint8 fieldSize = ReadNum();
686             MIRBitFieldType type(fieldSize, primType, strIdx);
687             type.SetNameIsLocal(nameIsLocal);
688             MIRType *origType = &InsertInTypeTables(type);
689             typTab.push_back(origType->GetTypeIndex());
690             return origType->GetTypeIndex();
691         }
692         case kBinKindTypeStruct: {
693             auto kind = static_cast<MIRTypeKind>(ReadNum());
694             MIRStructType type(kind, strIdx);
695             type.SetNameIsLocal(nameIsLocal);
696             type.SetTypeAttrs(ImportTypeAttrs());
697             MIRStructType &origType = static_cast<MIRStructType &>(InsertInTypeTables(type));
698             typTab.push_back(origType.GetTypeIndex());
699             if (kind != kTypeStructIncomplete) {
700                 if (forPointedType) {
701                     typeNeedsComplete = &origType;
702                 } else {
703                     ImportStructTypeData(origType);
704                 }
705             }
706             return origType.GetTypeIndex();
707         }
708         case kBinKindTypeClass: {
709             auto kind = static_cast<MIRTypeKind>(ReadNum());
710             MIRClassType type(kind, strIdx);
711             type.SetNameIsLocal(nameIsLocal);
712             auto &origType = static_cast<MIRClassType &>(InsertInTypeTables(type));
713             typTab.push_back(origType.GetTypeIndex());
714             if (kind != kTypeClassIncomplete) {
715                 if (forPointedType) {
716                     typeNeedsComplete = &origType;
717                 } else {
718                     ImportStructTypeData(origType);
719                     ImportClassTypeData(origType);
720                 }
721             }
722             return origType.GetTypeIndex();
723         }
724         case kBinKindTypeInterface: {
725             auto kind = static_cast<MIRTypeKind>(ReadNum());
726             MIRInterfaceType type(kind, strIdx);
727             type.SetNameIsLocal(nameIsLocal);
728             auto &origType = static_cast<MIRInterfaceType &>(InsertInTypeTables(type));
729             typTab.push_back(origType.GetTypeIndex());
730             if (kind != kTypeInterfaceIncomplete) {
731                 if (forPointedType) {
732                     typeNeedsComplete = &origType;
733                 } else {
734                     ImportStructTypeData(origType);
735                     ImportInterfaceTypeData(origType);
736                 }
737             }
738             return origType.GetTypeIndex();
739         }
740         default:
741             CHECK_FATAL(false, "Unexpected binary kind");
742     }
743 }
744 
ImportTypeNonJava()745 TyIdx BinaryMplImport::ImportTypeNonJava()
746 {
747     int64 tag = ReadNum();
748     if (tag == 0) {
749         return TyIdx(0);
750     }
751     if (tag < 0) {
752         CHECK_FATAL(static_cast<size_t>(-tag) < typTab.size(), "index out of bounds");
753         return typTab[static_cast<uint64>(-tag)];
754     }
755     PrimType primType = static_cast<PrimType>(0);
756     GStrIdx strIdx(0);
757     bool nameIsLocal = false;
758     ImportTypeBase(primType, strIdx, nameIsLocal);
759     TyIdx tyIdxUsed(GlobalTables::GetTypeTable().GetTypeTableSize());
760     if (tag != kBinKindTypeScalar) {
761         GlobalTables::GetTypeTable().PushNull();
762         typTab.push_back(tyIdxUsed);
763     }
764 
765     switch (tag) {
766         case kBinKindTypeScalar:
767             return TyIdx(primType);
768         case kBinKindTypePointer: {
769             MIRPtrType type(primType, strIdx);
770             type.SetNameIsLocal(nameIsLocal);
771             type.SetTypeAttrs(ImportTypeAttrs());
772             type.SetPointedTyIdx(ImportTypeNonJava());
773             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
774             return tyIdxUsed;
775         }
776         case kBinKindTypeFArray: {
777             MIRFarrayType type(strIdx);
778             type.SetNameIsLocal(nameIsLocal);
779             type.SetElemtTyIdx(ImportTypeNonJava());
780             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
781             return tyIdxUsed;
782         }
783         case kBinKindTypeJarray: {
784             MIRJarrayType type(strIdx);
785             type.SetNameIsLocal(nameIsLocal);
786             type.SetElemtTyIdx(ImportTypeNonJava());
787             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
788             return tyIdxUsed;
789         }
790         case kBinKindTypeArray: {
791             MIRArrayType type(strIdx);
792             type.SetNameIsLocal(nameIsLocal);
793             type.SetDim(ReadNum());
794             CHECK_FATAL(type.GetDim() < kMaxArrayDim, "array index out of range");
795             for (uint16 i = 0; i < type.GetDim(); ++i) {
796                 type.SetSizeArrayItem(i, ReadNum());
797             }
798             type.SetElemTyIdx(ImportTypeNonJava());
799             type.SetTypeAttrs(ImportTypeAttrs());
800             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
801             return tyIdxUsed;
802         }
803         case kBinKindTypeFunction: {
804             MIRFuncType type(strIdx);
805             type.SetNameIsLocal(nameIsLocal);
806             type.SetRetTyIdx(ImportTypeNonJava());
807             type.funcAttrs.SetAttrFlag(ReadNum());
808             int64 size = ReadNum();
809             for (int64 i = 0; i < size; ++i) {
810                 type.GetParamTypeList().push_back(ImportTypeNonJava());
811             }
812             size = ReadNum();
813             for (int64 i = 0; i < size; ++i) {
814                 type.GetParamAttrsList().push_back(ImportTypeAttrs());
815             }
816             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
817             return tyIdxUsed;
818         }
819         case kBinKindTypeParam: {
820             MIRTypeParam type(strIdx);
821             type.SetNameIsLocal(nameIsLocal);
822             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
823             return tyIdxUsed;
824         }
825         case kBinKindTypeInstantVector: {
826             auto kind = static_cast<MIRTypeKind>(ReadNum());
827             MIRInstantVectorType type(kind, strIdx);
828             type.SetNameIsLocal(nameIsLocal);
829             ImportTypePairs(type.GetInstantVec());
830             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
831             return tyIdxUsed;
832         }
833         case kBinKindTypeGenericInstant: {
834             MIRGenericInstantType type(strIdx);
835             type.SetNameIsLocal(nameIsLocal);
836             ImportTypePairs(type.GetInstantVec());
837             type.SetGenericTyIdx(ImportTypeNonJava());
838             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
839             return tyIdxUsed;
840         }
841         case kBinKindTypeBitField: {
842             uint8 fieldSize = ReadNum();
843             MIRBitFieldType type(fieldSize, primType, strIdx);
844             type.SetNameIsLocal(nameIsLocal);
845             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false);
846             return tyIdxUsed;
847         }
848         case kBinKindTypeStruct: {
849             auto kind = static_cast<MIRTypeKind>(ReadNum());
850             MIRStructType type(kind, strIdx);
851             type.SetNameIsLocal(nameIsLocal);
852             type.SetTypeAttrs(ImportTypeAttrs());
853             if (kind != kTypeStructIncomplete) {
854                 ImportStructTypeData(type);
855             }
856             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, IsIncomplete(type));
857             return tyIdxUsed;
858         }
859         case kBinKindTypeClass: {
860             auto kind = static_cast<MIRTypeKind>(ReadNum());
861             MIRClassType type(kind, strIdx);
862             type.SetNameIsLocal(nameIsLocal);
863             if (kind != kTypeClassIncomplete) {
864                 ImportStructTypeData(type);
865                 ImportClassTypeData(type);
866             }
867             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, true, IsIncomplete(type));
868             return tyIdxUsed;
869         }
870         case kBinKindTypeInterface: {
871             auto kind = static_cast<MIRTypeKind>(ReadNum());
872             MIRInterfaceType type(kind, strIdx);
873             type.SetNameIsLocal(nameIsLocal);
874             if (kind != kTypeInterfaceIncomplete) {
875                 ImportStructTypeData(type);
876                 ImportInterfaceTypeData(type);
877             }
878             GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, true, IsIncomplete(type));
879             return tyIdxUsed;
880         }
881         default:
882             CHECK_FATAL(false, "Unexpected binary kind");
883     }
884 }
885 
ImportTypeBase(PrimType & primType,GStrIdx & strIdx,bool & nameIsLocal)886 void BinaryMplImport::ImportTypeBase(PrimType &primType, GStrIdx &strIdx, bool &nameIsLocal)
887 {
888     primType = static_cast<PrimType>(ReadNum());
889     strIdx = ImportStr();
890     nameIsLocal = ReadNum();
891 }
892 
IsObject(const MIRType & type)893 inline static bool IsObject(const MIRType &type)
894 {
895     return (type.GetKind() == kTypeClass || type.GetKind() == kTypeClassIncomplete ||
896             type.GetKind() == kTypeInterface || type.GetKind() == kTypeInterfaceIncomplete);
897 }
898 
InsertInTypeTables(MIRType & type)899 MIRType &BinaryMplImport::InsertInTypeTables(MIRType &type)
900 {
901     MIRType *resultTypePtr = &type;
902     TyIdx prevTyIdx = mod.GetTypeNameTab()->GetTyIdxFromGStrIdx(type.GetNameStrIdx());
903     if (prevTyIdx != 0u && !type.IsNameIsLocal()) {
904         MIRType *prevType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(prevTyIdx);
905         if (!prevType->IsMIRTypeByName() &&
906             ((IsIncomplete(*prevType) && IsIncomplete(type)) || (!IsIncomplete(*prevType) && !IsIncomplete(type)) ||
907              (!IsIncomplete(*prevType) && IsIncomplete(type)))) {
908             resultTypePtr = prevType->CopyMIRTypeNode();
909             if (resultTypePtr->GetKind() == kTypeStruct || resultTypePtr->GetKind() == kTypeUnion ||
910                 resultTypePtr->GetKind() == kTypeStructIncomplete) {
911                 tmpStruct.push_back(static_cast<MIRStructType *>(resultTypePtr));
912             } else if (resultTypePtr->GetKind() == kTypeClass || resultTypePtr->GetKind() == kTypeClassIncomplete) {
913                 tmpClass.push_back(static_cast<MIRClassType *>(resultTypePtr));
914             } else if (resultTypePtr->GetKind() == kTypeInterface ||
915                        resultTypePtr->GetKind() == kTypeInterfaceIncomplete) {
916                 tmpInterface.push_back(static_cast<MIRInterfaceType *>(resultTypePtr));
917             }
918         } else {
919             // New definition wins
920             type.SetTypeIndex(prevTyIdx);
921             CHECK_FATAL(GlobalTables::GetTypeTable().GetTypeTable().empty() == false, "container check");
922             GlobalTables::GetTypeTable().SetTypeWithTyIdx(prevTyIdx, *type.CopyMIRTypeNode());
923             resultTypePtr = GlobalTables::GetTypeTable().GetTypeFromTyIdx(prevTyIdx);
924             if (!IsIncomplete(*resultTypePtr)) {
925                 GlobalTables::GetTypeNameTable().SetGStrIdxToTyIdx(resultTypePtr->GetNameStrIdx(),
926                                                                    resultTypePtr->GetTypeIndex());
927             }
928         }
929     } else {
930         // New type, no previous definition or anonymous type
931         TyIdx tyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&type);
932         resultTypePtr = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
933         if (tyIdx + 1 == GlobalTables::GetTypeTable().GetTypeTable().size() && !resultTypePtr->IsNameIsLocal()) {
934             GStrIdx stridx = resultTypePtr->GetNameStrIdx();
935             if (stridx != 0u) {
936                 mod.GetTypeNameTab()->SetGStrIdxToTyIdx(stridx, tyIdx);
937                 mod.PushbackTypeDefOrder(stridx);
938                 if (IsObject(*resultTypePtr)) {
939                     mod.AddClass(tyIdx);
940                     if (!IsIncomplete(*resultTypePtr)) {
941                         GlobalTables::GetTypeNameTable().SetGStrIdxToTyIdx(stridx, tyIdx);
942                     }
943                 }
944             }
945         }
946     }
947     return *resultTypePtr;
948 }
949 
SetupEHRootType()950 void BinaryMplImport::SetupEHRootType()
951 {
952     // setup eh root type with most recent Ljava_2Flang_2FObject_3B
953     GStrIdx gStrIdx = GlobalTables::GetStrTable().GetStrIdxFromName(namemangler::kJavaLangObjectStr);
954     if (gStrIdx == 0u) {
955         return;
956     }
957 
958     TyIdx tyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(gStrIdx);
959     if (tyIdx != 0u) {
960         mod.SetThrowableTyIdx(tyIdx);
961     }
962 }
963 
GetOrCreateSymbol(TyIdx tyIdx,GStrIdx strIdx,MIRSymKind mclass,MIRStorageClass sclass,MIRFunction * func,uint8 scpID)964 MIRSymbol *BinaryMplImport::GetOrCreateSymbol(TyIdx tyIdx, GStrIdx strIdx, MIRSymKind mclass, MIRStorageClass sclass,
965                                               MIRFunction *func, uint8 scpID)
966 {
967     MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(strIdx);
968     if (st != nullptr && st->GetStorageClass() == sclass && st->GetSKind() == mclass && scpID == kScopeGlobal) {
969         return st;
970     }
971     return mirBuilder.CreateSymbol(tyIdx, strIdx, mclass, sclass, func, scpID);
972 }
973 
InSymbol(MIRFunction * func)974 MIRSymbol *BinaryMplImport::InSymbol(MIRFunction *func)
975 {
976     int64 tag = ReadNum();
977     if (tag == 0) {
978         return nullptr;
979     } else if (tag < 0) {
980         CHECK_FATAL(static_cast<size_t>(-tag) < symTab.size(), "index out of bounds");
981         return symTab.at(-tag);
982     } else {
983         CHECK_FATAL(tag == kBinSymbol, "expecting kBinSymbol");
984         int64 scope = ReadNum();
985         GStrIdx stridx = ImportStr();
986         UStrIdx secAttr = ImportUsrStr();
987         UStrIdx asmAttr = ImportUsrStr();
988         auto skind = static_cast<MIRSymKind>(ReadNum());
989         auto sclass = static_cast<MIRStorageClass>(ReadNum());
990         TyIdx tyTmp(0);
991         MIRSymbol *sym = GetOrCreateSymbol(tyTmp, stridx, skind, sclass, func, scope);
992         if (secAttr != 0u) {
993             sym->sectionAttr = secAttr;
994         }
995         if (asmAttr != 0u) {
996             sym->SetAsmAttr(asmAttr);
997         }
998         symTab.push_back(sym);
999         sym->SetAttrs(ImportTypeAttrs());
1000         sym->SetIsTmp(ReadNum() != 0);
1001         sym->SetIsImported(imported);
1002         uint32 thepregno = 0;
1003         if (skind == kStPreg) {
1004             CHECK_FATAL(scope == kScopeLocal && func != nullptr, "Expecting kScopeLocal");
1005             thepregno = static_cast<uint32>(ReadNum());
1006         } else if (skind == kStConst || skind == kStVar) {
1007             sym->SetKonst(ImportConst(func));
1008         } else if (skind == kStFunc) {
1009             PUIdx puidx = ImportFunction();
1010             mod.SetCurFunction(func);
1011             if (puidx != 0) {
1012                 sym->SetFunction(GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puidx));
1013             }
1014         }
1015         if (skind == kStVar || skind == kStFunc) {
1016             ImportSrcPos(sym->GetSrcPosition());
1017         }
1018         TyIdx tyIdx = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
1019         sym->SetTyIdx(tyIdx);
1020         if (skind == kStPreg) {
1021             MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(sym->GetTyIdx());
1022             PregIdx pregidx = func->GetPregTab()->EnterPregNo(thepregno, mirType->GetPrimType(), mirType);
1023             MIRPregTable *pregTab = func->GetPregTab();
1024             MIRPreg *preg = pregTab->PregFromPregIdx(pregidx);
1025             preg->SetPrimType(mirType->GetPrimType());
1026             sym->SetPreg(preg);
1027         }
1028         return sym;
1029     }
1030 }
1031 
ImportFunction()1032 PUIdx BinaryMplImport::ImportFunction()
1033 {
1034     int64 tag = ReadNum();
1035     if (tag == 0) {
1036         mod.SetCurFunction(nullptr);
1037         return 0;
1038     } else if (tag < 0) {
1039         CHECK_FATAL(static_cast<uint64>(-tag) <= funcTab.size(), "index out of bounds");
1040         if (static_cast<uint64>(-tag) == funcTab.size()) {  // function was exported before its symbol
1041             return static_cast<PUIdx>(0);
1042         }
1043         PUIdx puIdx = funcTab[static_cast<uint64>(-tag)]->GetPuidx();
1044         mod.SetCurFunction(GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx));
1045         return puIdx;
1046     }
1047     CHECK_FATAL(tag == kBinFunction, "expecting kBinFunction");
1048     MIRSymbol *funcSt = InSymbol(nullptr);
1049     CHECK_FATAL(funcSt != nullptr, "null ptr check");
1050     MIRFunction *func = nullptr;
1051     if (funcSt->GetFunction() == nullptr) {
1052         maple::MIRBuilder builder(&mod);
1053         func = builder.CreateFunction(funcSt->GetStIdx());
1054         funcTab.push_back(func);
1055     } else {
1056         func = funcSt->GetFunction();
1057         funcTab.push_back(func);
1058     }
1059     funcSt->SetFunction(func);
1060     methodSymbols.push_back(funcSt);
1061     if (mod.IsJavaModule()) {
1062         func->SetBaseClassFuncNames(funcSt->GetNameStrIdx());
1063     }
1064     TyIdx funcTyIdx = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
1065     func->SetMIRFuncType(static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcTyIdx)));
1066 
1067     func->SetStIdx(funcSt->GetStIdx());
1068     if (!inCG) {
1069         func->SetFuncAttrs(ReadNum());  // merge side effect
1070     } else {
1071         if (!func->IsDirty()) {
1072             func->SetDirty(true);
1073             func->SetFuncAttrs(ReadNum());  // merge side effect
1074         } else {
1075             FuncAttrs tmp;
1076             tmp.SetAttrFlag(ReadNum());
1077             if (func->IsNoDefArgEffect() != tmp.GetAttr(FUNCATTR_nodefargeffect)) {
1078                 tmp.SetAttr(FUNCATTR_nodefargeffect, true);
1079             }
1080             if (func->IsNoDefEffect() != tmp.GetAttr(FUNCATTR_nodefeffect)) {
1081                 tmp.SetAttr(FUNCATTR_nodefeffect, true);
1082             }
1083             if (func->IsNoRetGlobal() != tmp.GetAttr(FUNCATTR_noretglobal)) {
1084                 tmp.SetAttr(FUNCATTR_noretglobal, true);
1085             }
1086             if (func->IsNoThrowException() != tmp.GetAttr(FUNCATTR_nothrow_exception)) {
1087                 tmp.SetAttr(FUNCATTR_nothrow_exception, true);
1088             }
1089             if (func->IsIpaSeen() != tmp.GetAttr(FUNCATTR_ipaseen)) {
1090                 tmp.SetAttr(FUNCATTR_ipaseen);
1091             }
1092             if (func->IsPure() != tmp.GetAttr(FUNCATTR_pure)) {
1093                 tmp.SetAttr(FUNCATTR_pure, true);
1094             }
1095             if (func->IsNoRetArg() != tmp.GetAttr(FUNCATTR_noretarg)) {
1096                 tmp.SetAttr(FUNCATTR_noretarg, true);
1097             }
1098             if (func->IsNoPrivateDefEffect() != tmp.GetAttr(FUNCATTR_noprivate_defeffect)) {
1099                 tmp.SetAttr(FUNCATTR_noprivate_defeffect, true);
1100             }
1101             func->SetFuncAttrs(tmp);
1102         }
1103     }
1104 
1105     auto &attributes = func->GetFuncAttrs();
1106     if (attributes.GetAttr(FUNCATTR_constructor_priority)) {
1107         attributes.SetConstructorPriority(static_cast<int>(ReadNum()));
1108     }
1109     if (attributes.GetAttr(FUNCATTR_destructor_priority)) {
1110         attributes.SetDestructorPriority(static_cast<int>(ReadNum()));
1111     }
1112 
1113     func->SetFlag(ReadNum());
1114     if (mod.IsJavaModule()) {
1115         (void)ImportType();  // not set the field to mimic parser
1116     } else {
1117         (void)ImportTypeNonJava();  // not set the field to mimic parser
1118     }
1119     size_t size = static_cast<size_t>(ReadNum());
1120     if (func->GetFormalDefVec().size() == 0) {
1121         for (size_t i = 0; i < size; i++) {
1122             GStrIdx strIdx = ImportStr();
1123             TyIdx tyIdx = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
1124             FormalDef formalDef(strIdx, nullptr, tyIdx, TypeAttrs());
1125             formalDef.formalAttrs.SetAttrFlag(static_cast<uint64>(ReadNum()));
1126             func->GetFormalDefVec().push_back(formalDef);
1127         }
1128     } else {
1129         CHECK_FATAL(func->GetFormalDefVec().size() >= size, "ImportFunction: inconsistent number of formals");
1130         for (size_t i = 0; i < size; i++) {
1131             func->GetFormalDefVec()[i].formalStrIdx = ImportStr();
1132             func->GetFormalDefVec()[i].formalTyIdx = mod.IsJavaModule() ? ImportType() : ImportTypeNonJava();
1133             func->GetFormalDefVec()[i].formalAttrs.SetAttrFlag(static_cast<uint64>(ReadNum()));
1134         }
1135     }
1136 
1137     mod.SetCurFunction(func);
1138     return func->GetPuidx();
1139 }
1140 
SkipTotalSize()1141 inline void BinaryMplImport::SkipTotalSize()
1142 {
1143     ReadInt();
1144 }
1145 
ReadStrField()1146 void BinaryMplImport::ReadStrField()
1147 {
1148     SkipTotalSize();
1149 
1150     int32 size = ReadInt();
1151     for (int64 i = 0; i < size; ++i) {
1152         GStrIdx stridx = ImportStr();
1153         GlobalTables::GetConstPool().PutLiteralNameAsImported(stridx);
1154     }
1155     int64 tag = 0;
1156     tag = ReadNum();
1157     CHECK_FATAL(tag == ~kBinStrStart, "pattern mismatch in Read STR");
1158 }
1159 
ReadHeaderField()1160 void BinaryMplImport::ReadHeaderField()
1161 {
1162     SkipTotalSize();
1163     mod.SetFlavor(static_cast<MIRFlavor>(ReadNum()));
1164     mod.SetSrcLang(static_cast<MIRSrcLang>(ReadNum()));
1165     mod.SetID(static_cast<uint16>(ReadNum()));
1166     if (mod.GetFlavor() == kFlavorLmbc) {
1167         mod.SetGlobalMemSize(static_cast<uint32>(ReadNum()));
1168         mod.SetWithDbgInfo(static_cast<uint32>(ReadNum()));
1169     }
1170     mod.SetNumFuncs(static_cast<uint32>(ReadNum()));
1171     std::string inStr;
1172     ReadAsciiStr(inStr);
1173     mod.SetEntryFuncName(inStr);
1174     ImportInfoVector(mod.GetFileInfo(), mod.GetFileInfoIsString());
1175 
1176     int32 size = static_cast<int32>(ReadNum());
1177     MIRInfoPair infopair;
1178     for (int32 i = 0; i < size; i++) {
1179         infopair.first = ImportStr();
1180         infopair.second = static_cast<uint32>(ReadNum());
1181         mod.PushbackFileInfo(infopair);
1182     }
1183 
1184     size = static_cast<int32>(ReadNum());
1185     for (int32 i = 0; i < size; i++) {
1186         GStrIdx gStrIdx = ImportStr();
1187         mod.GetImportFiles().push_back(gStrIdx);
1188         std::string importfilename = GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx);
1189         // record the imported file for later reading summary info, if exists
1190         mod.PushbackImportedMplt(importfilename);
1191         BinaryMplt *binMplt = new BinaryMplt(mod);
1192         binMplt->GetBinImport().imported = true;
1193 
1194         INFO(kLncInfo, "importing %s", importfilename.c_str());
1195         if (!binMplt->GetBinImport().Import(importfilename, false)) {  // not a binary mplt
1196             FATAL(kLncFatal, "cannot open binary MPLT file: %s\n", importfilename.c_str());
1197         } else {
1198             INFO(kLncInfo, "finished import of %s", importfilename.c_str());
1199         }
1200         if (i == 0) {
1201             binMplt->SetImportFileName(importfilename);
1202             mod.SetBinMplt(binMplt);
1203         } else {
1204             delete binMplt;
1205         }
1206     }
1207 
1208     size = static_cast<int32>(ReadNum());
1209     for (int32 i = 0; i < size; i++) {
1210         std::string str;
1211         ReadAsciiStr(str);
1212         mod.GetAsmDecls().emplace_back(MapleString(str, mod.GetMemPool()));
1213     }
1214 
1215     int32 tag = static_cast<int32>(ReadNum());
1216     CHECK_FATAL(tag == ~kBinHeaderStart, "pattern mismatch in Read Import");
1217     return;
1218 }
1219 
ReadTypeField()1220 void BinaryMplImport::ReadTypeField()
1221 {
1222     SkipTotalSize();
1223 
1224     int32 size = ReadInt();
1225     if (mod.IsJavaModule()) {
1226         for (int64 i = 0; i < size; ++i) {
1227             ImportType();
1228         }
1229     } else {
1230         for (int64 i = 0; i < size; ++i) {
1231             (void)ImportTypeNonJava();
1232         }
1233     }
1234     int64 tag = 0;
1235     tag = ReadNum();
1236     CHECK_FATAL(tag == ~kBinTypeStart, "pattern mismatch in Read TYPE");
1237 }
1238 
ImportCallInfo()1239 CallInfo *BinaryMplImport::ImportCallInfo()
1240 {
1241     int64 tag = ReadNum();
1242     if (tag < 0) {
1243         CHECK_FATAL(static_cast<size_t>(-tag) < callInfoTab.size(), "index out of bounds");
1244         return callInfoTab.at(-tag);
1245     }
1246     CHECK_FATAL(tag == kBinCallinfo, "expecting kBinCallinfo");
1247     CallType ctype = static_cast<CallType>(ReadNum());  // call type
1248     uint32 loopDepth = static_cast<uint32>(ReadInt());
1249     uint32 id = static_cast<uint32>(ReadInt());
1250     bool argLocal = Read() == 1;
1251     MIRSymbol *funcSym = InSymbol(nullptr);
1252     CHECK_FATAL(funcSym != nullptr, "func_sym is null in BinaryMplImport::InCallInfo");
1253     CallInfo *ret = mod.GetMemPool()->New<CallInfo>(ctype, *funcSym->GetFunction(), static_cast<StmtNode *>(nullptr),
1254                                                     loopDepth, id, argLocal);
1255     callInfoTab.push_back(ret);
1256     return ret;
1257 }
1258 
MergeDuplicated(PUIdx methodPuidx,std::vector<CallInfo * > & targetSet,std::vector<CallInfo * > & newSet)1259 void BinaryMplImport::MergeDuplicated(PUIdx methodPuidx, std::vector<CallInfo *> &targetSet,
1260                                       std::vector<CallInfo *> &newSet)
1261 {
1262     if (targetSet.empty()) {
1263         (void)targetSet.insert(targetSet.begin(), newSet.begin(), newSet.end());
1264         std::unordered_set<uint32> tmp;
1265         mod.AddValueToMethod2TargetHash(methodPuidx, tmp);
1266         for (size_t i = 0; i < newSet.size(); ++i) {
1267             mod.InsertTargetHash(methodPuidx, newSet[i]->GetID());
1268         }
1269     } else {
1270         for (size_t i = 0; i < newSet.size(); ++i) {
1271             CallInfo *newItem = newSet[i];
1272             if (!mod.HasTargetHash(methodPuidx, newItem->GetID())) {
1273                 targetSet.push_back(newItem);
1274                 mod.InsertTargetHash(methodPuidx, newItem->GetID());
1275             }
1276         }
1277     }
1278 }
1279 
ReadCgField()1280 void BinaryMplImport::ReadCgField()
1281 {
1282     SkipTotalSize();
1283 
1284     int32 size = ReadInt();
1285     int64 tag = 0;
1286 
1287     for (int i = 0; i < size; ++i) {
1288         tag = ReadNum();
1289         CHECK_FATAL(tag == kStartMethod, " should be start point of method");
1290         MIRSymbol *tmpInSymbol = InSymbol(nullptr);
1291         CHECK_FATAL(tmpInSymbol != nullptr, "null ptr check");
1292         PUIdx methodPuidx = tmpInSymbol->GetFunction()->GetPuidx();
1293         CHECK_FATAL(methodPuidx, "should not be 0");
1294         if (mod.GetMethod2TargetMap().find(methodPuidx) == mod.GetMethod2TargetMap().end()) {
1295             std::vector<CallInfo *> targetSetTmp;
1296             mod.AddMemToMethod2TargetMap(methodPuidx, targetSetTmp);
1297         }
1298         int32 targSize = ReadInt();
1299         std::vector<CallInfo *> targetSet;
1300         callInfoTab.clear();
1301         callInfoTab.push_back(nullptr);
1302         for (int32 j = 0; j < targSize; ++j) {
1303             CallInfo *callInfo = ImportCallInfo();
1304             targetSet.push_back(callInfo);
1305         }
1306         MergeDuplicated(methodPuidx, mod.GetMemFromMethod2TargetMap(methodPuidx), targetSet);
1307         tag = ReadNum();
1308         CHECK_FATAL(tag == ~kStartMethod, " should be start point of method");
1309     }
1310     tag = ReadNum();
1311     CHECK_FATAL(tag == ~kBinCgStart, "pattern mismatch in Read CG");
1312 }
1313 
ReadEaField()1314 void BinaryMplImport::ReadEaField()
1315 {
1316     ReadInt();
1317     int size = ReadInt();
1318     for (int i = 0; i < size; ++i) {
1319         GStrIdx funcName = ImportStr();
1320         int nodesSize = ReadInt();
1321         EAConnectionGraph *newEaCg =
1322             mod.GetMemPool()->New<EAConnectionGraph>(&mod, &mod.GetMPAllocator(), funcName, true);
1323         newEaCg->ResizeNodes(nodesSize, nullptr);
1324         InEaCgNode(*newEaCg);
1325         int eaSize = ReadInt();
1326         for (int j = 0; j < eaSize; ++j) {
1327             EACGBaseNode *node = &InEaCgNode(*newEaCg);
1328             newEaCg->funcArgNodes.push_back(node);
1329         }
1330         mod.SetEAConnectionGraph(funcName, newEaCg);
1331     }
1332     CHECK_FATAL(ReadNum() == ~kBinEaStart, "pattern mismatch in Read EA");
1333 }
1334 
ReadSeField()1335 void BinaryMplImport::ReadSeField()
1336 {
1337     SkipTotalSize();
1338 
1339     int32 size = ReadInt();
1340 #ifdef MPLT_DEBUG
1341     LogInfo::MapleLogger() << "SE SIZE : " << size << '\n';
1342 #endif
1343     for (int32 i = 0; i < size; ++i) {
1344         GStrIdx funcName = ImportStr();
1345         uint8 specialEffect = Read();
1346         TyIdx tyIdx = kInitTyIdx;
1347         if ((specialEffect & kPureFunc) == kPureFunc) {
1348             tyIdx = ImportType();
1349         }
1350         const std::string &funcStr = GlobalTables::GetStrTable().GetStringFromStrIdx(funcName);
1351         if (funcStr == "Ljava_2Flang_2FObject_3B_7Cwait_7C_28_29V") {
1352             specialEffect = 0;
1353         }
1354         auto *funcSymbol =
1355             GlobalTables::GetGsymTable().GetSymbolFromStrIdx(GlobalTables::GetStrTable().GetStrIdxFromName(funcStr));
1356         MIRFunction *func = funcSymbol != nullptr ? mirBuilder.GetFunctionFromSymbol(*funcSymbol) : nullptr;
1357         if (func != nullptr) {
1358             func->SetAttrsFromSe(specialEffect);
1359         } else if ((specialEffect & kPureFunc) == kPureFunc) {
1360             func = mirBuilder.GetOrCreateFunction(funcStr, tyIdx);
1361             func->SetAttrsFromSe(specialEffect);
1362         }
1363     }
1364     int64 tag = ReadNum();
1365     CHECK_FATAL(tag == ~kBinSeStart, "pattern mismatch in Read TYPE");
1366 }
1367 
InEaCgBaseNode(EACGBaseNode & base,EAConnectionGraph & newEaCg,bool firstPart)1368 void BinaryMplImport::InEaCgBaseNode(EACGBaseNode &base, EAConnectionGraph &newEaCg, bool firstPart)
1369 {
1370     if (firstPart) {
1371         base.SetEAStatus(static_cast<EAStatus>(ReadNum()));
1372         base.SetID(ReadInt());
1373     } else {
1374         // start to in points to
1375         int size = ReadInt();
1376         for (int i = 0; i < size; ++i) {
1377             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
1378             CHECK_FATAL(point2Node->IsObjectNode(), "must be");
1379             (void)base.pointsTo.insert(static_cast<EACGObjectNode *>(point2Node));
1380         }
1381         // start to in in
1382         size = ReadInt();
1383         for (int i = 0; i < size; ++i) {
1384             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
1385             base.InsertInSet(point2Node);
1386         }
1387         // start to in out
1388         size = ReadInt();
1389         for (int i = 0; i < size; ++i) {
1390             EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
1391             base.InsertOutSet(point2Node);
1392         }
1393     }
1394 }
1395 
InEaCgActNode(EACGActualNode & actual)1396 void BinaryMplImport::InEaCgActNode(EACGActualNode &actual)
1397 {
1398     actual.isPhantom = Read() == 1;
1399     actual.isReturn = Read() == 1;
1400     actual.argIdx = Read();
1401     actual.callSiteInfo = static_cast<uint32>(ReadInt());
1402 }
1403 
InEaCgFieldNode(EACGFieldNode & field,EAConnectionGraph & newEaCg)1404 void BinaryMplImport::InEaCgFieldNode(EACGFieldNode &field, EAConnectionGraph &newEaCg)
1405 {
1406     field.SetFieldID(ReadInt());
1407     int size = ReadInt();
1408     for (int i = 0; i < size; ++i) {
1409         EACGBaseNode *node = &InEaCgNode(newEaCg);
1410         CHECK_FATAL(node->IsObjectNode(), "must be");
1411         (void)field.belongsTo.insert(static_cast<EACGObjectNode *>(node));
1412     }
1413     field.isPhantom = Read() == 1;
1414 }
1415 
InEaCgObjNode(EACGObjectNode & obj,EAConnectionGraph & newEaCg)1416 void BinaryMplImport::InEaCgObjNode(EACGObjectNode &obj, EAConnectionGraph &newEaCg)
1417 {
1418     Read();
1419     obj.isPhantom = true;
1420     int size = ReadInt();
1421     for (int i = 0; i < size; ++i) {
1422         EACGBaseNode *node = &InEaCgNode(newEaCg);
1423         CHECK_FATAL(node->IsFieldNode(), "must be");
1424         auto *field = static_cast<EACGFieldNode *>(node);
1425         obj.fieldNodes[static_cast<EACGFieldNode *>(field)->GetFieldID()] = field;
1426     }
1427     // start to in point by
1428     size = ReadInt();
1429     for (int i = 0; i < size; ++i) {
1430         EACGBaseNode *point2Node = &InEaCgNode(newEaCg);
1431         (void)obj.pointsBy.insert(point2Node);
1432     }
1433 }
1434 
InEaCgRefNode(EACGRefNode & ref)1435 void BinaryMplImport::InEaCgRefNode(EACGRefNode &ref)
1436 {
1437     ref.isStaticField = Read() == 1 ? true : false;
1438 }
1439 
InEaCgNode(EAConnectionGraph & newEaCg)1440 EACGBaseNode &BinaryMplImport::InEaCgNode(EAConnectionGraph &newEaCg)
1441 {
1442     int64 tag = ReadNum();
1443     if (tag < 0) {
1444         CHECK_FATAL(static_cast<uint64>(-tag) < eaCgTab.size(), "index out of bounds");
1445         return *eaCgTab[-tag];
1446     }
1447     CHECK_FATAL(tag == kBinEaCgNode, "must be");
1448     NodeKind kind = static_cast<NodeKind>(ReadNum());
1449     EACGBaseNode *node = nullptr;
1450     switch (kind) {
1451         case kObejectNode:
1452             node = new EACGObjectNode(&mod, &mod.GetMPAllocator(), &newEaCg);
1453             break;
1454         case kReferenceNode:
1455             node = new EACGRefNode(&mod, &mod.GetMPAllocator(), &newEaCg);
1456             break;
1457         case kFieldNode:
1458             node = new EACGFieldNode(&mod, &mod.GetMPAllocator(), &newEaCg);
1459             break;
1460         case kActualNode:
1461             node = new EACGActualNode(&mod, &mod.GetMPAllocator(), &newEaCg);
1462             break;
1463         default:
1464             CHECK_FATAL(false, "impossible");
1465     }
1466     node->SetEACG(&newEaCg);
1467     eaCgTab.push_back(node);
1468     InEaCgBaseNode(*node, newEaCg, true);
1469     newEaCg.SetNodeAt(node->id - 1, node);
1470     if (node->IsActualNode()) {
1471         CHECK_FATAL(ReadNum() == kBinEaCgActNode, "must be");
1472         InEaCgActNode(static_cast<EACGActualNode &>(*node));
1473     } else if (node->IsFieldNode()) {
1474         CHECK_FATAL(ReadNum() == kBinEaCgFieldNode, "must be");
1475         InEaCgFieldNode(static_cast<EACGFieldNode &>(*node), newEaCg);
1476     } else if (node->IsObjectNode()) {
1477         CHECK_FATAL(ReadNum() == kBinEaCgObjNode, "must be");
1478         InEaCgObjNode(static_cast<EACGObjectNode &>(*node), newEaCg);
1479     } else if (node->IsReferenceNode()) {
1480         CHECK_FATAL(ReadNum() == kBinEaCgRefNode, "must be");
1481         InEaCgRefNode(static_cast<EACGRefNode &>(*node));
1482     }
1483     InEaCgBaseNode(*node, newEaCg, false);
1484     CHECK_FATAL(ReadNum() == ~kBinEaCgNode, "must be");
1485     return *node;
1486 }
1487 
ReadEaCgField()1488 EAConnectionGraph *BinaryMplImport::ReadEaCgField()
1489 {
1490     if (ReadNum() == ~kBinEaCgStart) {
1491         return nullptr;
1492     }
1493     ReadInt();
1494     GStrIdx funcStr = ImportStr();
1495     int nodesSize = ReadInt();
1496     EAConnectionGraph *newEaCg = mod.GetMemPool()->New<EAConnectionGraph>(&mod, &mod.GetMPAllocator(), funcStr, true);
1497     newEaCg->ResizeNodes(nodesSize, nullptr);
1498     InEaCgNode(*newEaCg);
1499     CHECK_FATAL(newEaCg->GetNode(kFirstOpnd)->IsObjectNode(), "must be");
1500     CHECK_FATAL(newEaCg->GetNode(kSecondOpnd)->IsReferenceNode(), "must be");
1501     CHECK_FATAL(newEaCg->GetNode(kThirdOpnd)->IsFieldNode(), "must be");
1502     newEaCg->globalField = static_cast<EACGFieldNode *>(newEaCg->GetNode(kThirdOpnd));
1503     newEaCg->globalObj = static_cast<EACGObjectNode *>(newEaCg->GetNode(kFirstOpnd));
1504     newEaCg->globalRef = static_cast<EACGRefNode *>(newEaCg->GetNode(kSecondOpnd));
1505     CHECK_FATAL(newEaCg->globalField && newEaCg->globalObj && newEaCg->globalRef, "must be");
1506     int32 nodeSize = ReadInt();
1507     for (int j = 0; j < nodeSize; ++j) {
1508         EACGBaseNode *node = &InEaCgNode(*newEaCg);
1509         newEaCg->funcArgNodes.push_back(node);
1510     }
1511 
1512     int32 callSitesize = ReadInt();
1513     for (int i = 0; i < callSitesize; ++i) {
1514         uint32 id = static_cast<uint32>(ReadInt());
1515         newEaCg->callSite2Nodes[id] =
1516             mod.GetMemPool()->New<MapleVector<EACGBaseNode *>>(mod.GetMPAllocator().Adapter());
1517         int32 calleeArgSize = ReadInt();
1518         for (int j = 0; j < calleeArgSize; ++j) {
1519             EACGBaseNode *node = &InEaCgNode(*newEaCg);
1520             newEaCg->callSite2Nodes[id]->push_back(node);
1521         }
1522     }
1523 
1524 #ifdef DEBUG
1525     for (EACGBaseNode *node : newEaCg->GetNodes()) {
1526         if (node == nullptr) {
1527             continue;
1528         }
1529         node->CheckAllConnectionInNodes();
1530     }
1531 #endif
1532     CHECK_FATAL(ReadNum() == ~kBinEaCgStart, "pattern mismatch in Read EACG");
1533     return newEaCg;
1534 }
1535 
ReadSymField()1536 void BinaryMplImport::ReadSymField()
1537 {
1538     SkipTotalSize();
1539     int32 size = ReadInt();
1540     for (int64 i = 0; i < size; i++) {
1541         (void)InSymbol(nullptr);
1542     }
1543     int64 tag = ReadNum();
1544     CHECK_FATAL(tag == ~kBinSymStart, "pattern mismatch in Read SYM");
1545     return;
1546 }
1547 
ReadSymTabField()1548 void BinaryMplImport::ReadSymTabField()
1549 {
1550     SkipTotalSize();
1551     int32 size = ReadInt();
1552     for (int64 i = 0; i < size; i++) {
1553         std::string str;
1554         ReadAsciiStr(str);
1555     }
1556     int64 tag = ReadNum();
1557     CHECK_FATAL(tag == ~kBinSymTabStart, "pattern mismatch in Read TYPE");
1558     return;
1559 }
1560 
ReadContentField()1561 void BinaryMplImport::ReadContentField()
1562 {
1563     SkipTotalSize();
1564 
1565     int32 size = ReadInt();
1566     int64 item;
1567     int32 offset;
1568     for (int32 i = 0; i < size; ++i) {
1569         item = ReadNum();
1570         offset = ReadInt();
1571         content[item] = offset;
1572     }
1573     CHECK_FATAL(ReadNum() == ~kBinContentStart, "pattern mismatch in Read CONTENT");
1574 }
1575 
Jump2NextField()1576 void BinaryMplImport::Jump2NextField()
1577 {
1578     uint32 totalSize = static_cast<uint32>(ReadInt());
1579     bufI += (totalSize - sizeof(uint32));
1580     ReadNum();  // skip end tag for this field
1581 }
1582 
ImportForSrcLang(const std::string & fname,MIRSrcLang & srcLang)1583 bool BinaryMplImport::ImportForSrcLang(const std::string &fname, MIRSrcLang &srcLang)
1584 {
1585     Reset();
1586     ReadFileAt(fname, 0);
1587     int32 magic = ReadInt();
1588     if (kMpltMagicNumber != magic && (kMpltMagicNumber + 0x10) != magic) {
1589         buf.clear();
1590         return false;
1591     }
1592     importingFromMplt = kMpltMagicNumber == magic;
1593     int64 fieldID = ReadNum();
1594     while (fieldID != kBinFinish) {
1595         switch (fieldID) {
1596             case kBinHeaderStart: {
1597                 SkipTotalSize();
1598                 (void)ReadNum();  // skip flavor
1599                 srcLang = static_cast<MIRSrcLang>(ReadNum());
1600                 return true;
1601             }
1602             default: {
1603                 Jump2NextField();
1604                 break;
1605             }
1606         }
1607         fieldID = ReadNum();
1608     }
1609     return false;
1610 }
1611 
Import(const std::string & fname,bool readSymbols,bool readSe)1612 bool BinaryMplImport::Import(const std::string &fname, bool readSymbols, bool readSe)
1613 {
1614     Reset();
1615     ReadFileAt(fname, 0);
1616     int32 magic = ReadInt();
1617     if (kMpltMagicNumber != magic && (kMpltMagicNumber + 0x10) != magic) {
1618         buf.clear();
1619         return false;
1620     }
1621     importingFromMplt = kMpltMagicNumber == magic;
1622     int64 fieldID = ReadNum();
1623     if (readSe) {
1624         while (fieldID != kBinFinish) {
1625             if (fieldID == kBinSeStart) {
1626 #ifdef MPLT_DEBUG
1627                 LogInfo::MapleLogger() << "read SE of : " << fname << '\n';
1628 #endif
1629                 BinaryMplImport tmp(mod);
1630                 tmp.Reset();
1631                 tmp.buf = buf;
1632                 tmp.bufI = bufI;
1633                 tmp.importFileName = fname;
1634                 tmp.ReadSeField();
1635                 Jump2NextField();
1636             } else if (fieldID == kBinEaStart) {
1637                 BinaryMplImport tmp(mod);
1638                 tmp.Reset();
1639                 tmp.buf = buf;
1640                 tmp.bufI = bufI;
1641                 tmp.importFileName = fname;
1642                 tmp.ReadEaField();
1643                 Jump2NextField();
1644             } else {
1645                 Jump2NextField();
1646             }
1647             fieldID = ReadNum();
1648         }
1649         return true;
1650     }
1651     while (fieldID != kBinFinish) {
1652         switch (fieldID) {
1653             case kBinContentStart: {
1654                 ReadContentField();
1655                 break;
1656             }
1657             case kBinStrStart: {
1658                 ReadStrField();
1659                 break;
1660             }
1661             case kBinHeaderStart: {
1662                 ReadHeaderField();
1663                 break;
1664             }
1665             case kBinTypeStart: {
1666                 ReadTypeField();
1667                 break;
1668             }
1669             case kBinSymStart: {
1670                 if (readSymbols) {
1671                     ReadSymField();
1672                 } else {
1673                     Jump2NextField();
1674                 }
1675                 break;
1676             }
1677             case kBinSymTabStart: {
1678                 ReadSymTabField();
1679                 break;
1680             }
1681             case kBinCgStart: {
1682                 if (readSymbols) {
1683 #ifdef MPLT_DEBUG
1684                     LogInfo::MapleLogger() << "read CG of : " << fname << '\n';
1685 #endif
1686                     BinaryMplImport tmp(mod);
1687                     tmp.Reset();
1688                     tmp.inIPA = true;
1689                     tmp.buf = buf;
1690                     tmp.bufI = bufI;
1691                     tmp.importFileName = fname;
1692                     tmp.ReadCgField();
1693                     tmp.UpdateMethodSymbols();
1694                     Jump2NextField();
1695                 } else {
1696                     Jump2NextField();
1697                 }
1698                 break;
1699             }
1700             case kBinSeStart: {
1701                 Jump2NextField();
1702                 break;
1703             }
1704             case kBinEaStart: {
1705                 if (readSymbols) {
1706 #ifdef MPLT_DEBUG
1707                     LogInfo::MapleLogger() << "read EA of : " << fname << '\n';
1708 #endif
1709                     BinaryMplImport tmp(mod);
1710                     tmp.Reset();
1711                     tmp.buf = buf;
1712                     tmp.bufI = bufI;
1713                     tmp.importFileName = fname;
1714                     tmp.ReadEaField();
1715                     Jump2NextField();
1716                 } else {
1717                     Jump2NextField();
1718                 }
1719                 break;
1720             }
1721             case kBinFunctionBodyStart: {
1722                 ReadFunctionBodyField();
1723                 break;
1724             }
1725             default:
1726                 CHECK_FATAL(false, "should not run here");
1727         }
1728         fieldID = ReadNum();
1729     }
1730     UpdateMethodSymbols();
1731     SetupEHRootType();
1732     return true;
1733 }
1734 }  // namespace maple
1735