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