• 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_export.h"
17 #include <sstream>
18 #include <vector>
19 #include "mir_function.h"
20 #include "namemangler.h"
21 #include "opcode_info.h"
22 #include "mir_pragma.h"
23 #include "bin_mplt.h"
24 #include "factory.h"
25 
26 namespace {
27 using namespace maple;
28 /* Storage location of field  */
29 constexpr uint32 kFirstField = 0;
30 constexpr uint32 kSecondField = 1;
31 constexpr uint32 kThirdField = 2;
32 constexpr uint32 kFourthField = 3;
33 constexpr int32 kFourthFieldInt = 3;
34 constexpr uint32 kFifthField = 4;
35 constexpr int32 kSixthFieldInt = 5;
36 
37 using OutputConstFactory = FunctionFactory<MIRConstKind, void, MIRConst &, BinaryMplExport &>;
38 using OutputTypeFactory = FunctionFactory<MIRTypeKind, void, MIRType &, BinaryMplExport &>;
39 
OutputConstInt(const MIRConst & constVal,BinaryMplExport & mplExport)40 void OutputConstInt(const MIRConst &constVal, BinaryMplExport &mplExport)
41 {
42     mplExport.WriteNum(kBinKindConstInt);
43     mplExport.OutputConstBase(constVal);
44     mplExport.WriteNum(static_cast<const MIRIntConst &>(constVal).GetExtValue());
45 }
46 
OutputConstAddrof(const MIRConst & constVal,BinaryMplExport & mplExport)47 void OutputConstAddrof(const MIRConst &constVal, BinaryMplExport &mplExport)
48 {
49     const MIRAddrofConst &addrof = static_cast<const MIRAddrofConst &>(constVal);
50     if (addrof.GetSymbolIndex().IsGlobal()) {
51         mplExport.WriteNum(kBinKindConstAddrof);
52     } else {
53         mplExport.WriteNum(kBinKindConstAddrofLocal);
54     }
55     mplExport.OutputConstBase(constVal);
56     if (addrof.GetSymbolIndex().IsGlobal()) {
57         mplExport.OutputSymbol(mplExport.GetMIRModule().CurFunction()->GetLocalOrGlobalSymbol(addrof.GetSymbolIndex()));
58     } else {
59         mplExport.OutputLocalSymbol(mplExport.curFunc->GetLocalOrGlobalSymbol(addrof.GetSymbolIndex()));
60     }
61     mplExport.WriteNum(addrof.GetFieldID());
62     mplExport.WriteNum(addrof.GetOffset());
63 }
64 
OutputConstAddrofFunc(const MIRConst & constVal,BinaryMplExport & mplExport)65 void OutputConstAddrofFunc(const MIRConst &constVal, BinaryMplExport &mplExport)
66 {
67     mplExport.WriteNum(kBinKindConstAddrofFunc);
68     mplExport.OutputConstBase(constVal);
69     const auto &newConst = static_cast<const MIRAddroffuncConst &>(constVal);
70     mplExport.OutputFunction(newConst.GetValue());
71 }
72 
OutputConstLbl(const MIRConst & constVal,BinaryMplExport & mplExport)73 void OutputConstLbl(const MIRConst &constVal, BinaryMplExport &mplExport)
74 {
75     mplExport.WriteNum(kBinKindConstAddrofLabel);
76     mplExport.OutputConstBase(constVal);
77     const MIRLblConst &lblConst = static_cast<const MIRLblConst &>(constVal);
78     mplExport.OutputLabel(lblConst.GetValue());
79 }
80 
OutputConstStr(const MIRConst & constVal,BinaryMplExport & mplExport)81 void OutputConstStr(const MIRConst &constVal, BinaryMplExport &mplExport)
82 {
83     mplExport.WriteNum(kBinKindConstStr);
84     mplExport.OutputConstBase(constVal);
85     const auto &newConst = static_cast<const MIRStrConst &>(constVal);
86     mplExport.OutputUsrStr(newConst.GetValue());
87 }
88 
OutputConstStr16(const MIRConst & constVal,BinaryMplExport & mplExport)89 void OutputConstStr16(const MIRConst &constVal, BinaryMplExport &mplExport)
90 {
91     mplExport.WriteNum(kBinKindConstStr16);
92     mplExport.OutputConstBase(constVal);
93     const auto &mirStr16 = static_cast<const MIRStr16Const &>(constVal);
94     std::u16string str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(mirStr16.GetValue());
95     std::string str;
96     (void)namemangler::UTF16ToUTF8(str, str16);
97     mplExport.WriteNum(str.length());
98     for (char c : str) {
99         mplExport.Write(static_cast<uint8>(c));
100     }
101 }
102 
OutputConstFloat(const MIRConst & constVal,BinaryMplExport & mplExport)103 void OutputConstFloat(const MIRConst &constVal, BinaryMplExport &mplExport)
104 {
105     mplExport.WriteNum(kBinKindConstFloat);
106     mplExport.OutputConstBase(constVal);
107     const auto &newConst = static_cast<const MIRFloatConst &>(constVal);
108     mplExport.WriteNum(newConst.GetIntValue());
109 }
110 
OutputConstDouble(const MIRConst & constVal,BinaryMplExport & mplExport)111 void OutputConstDouble(const MIRConst &constVal, BinaryMplExport &mplExport)
112 {
113     mplExport.WriteNum(kBinKindConstDouble);
114     mplExport.OutputConstBase(constVal);
115     const auto &newConst = static_cast<const MIRDoubleConst &>(constVal);
116     mplExport.WriteNum(newConst.GetIntValue());
117 }
118 
OutputConstAgg(const MIRConst & constVal,BinaryMplExport & mplExport)119 void OutputConstAgg(const MIRConst &constVal, BinaryMplExport &mplExport)
120 {
121     mplExport.WriteNum(kBinKindConstAgg);
122     mplExport.OutputConstBase(constVal);
123     const auto &aggConst = static_cast<const MIRAggConst &>(constVal);
124     size_t size = aggConst.GetConstVec().size();
125     mplExport.WriteNum(size);
126     for (size_t i = 0; i < size; ++i) {
127         mplExport.WriteNum(aggConst.GetFieldIdItem(i));
128         mplExport.OutputConst(aggConst.GetConstVecItem(i));
129     }
130 }
131 
OutputConstSt(MIRConst & constVal,BinaryMplExport & mplExport)132 void OutputConstSt(MIRConst &constVal, BinaryMplExport &mplExport)
133 {
134     mplExport.WriteNum(kBinKindConstSt);
135     mplExport.OutputConstBase(constVal);
136     auto &stConst = static_cast<MIRStConst &>(constVal);
137     size_t size = stConst.GetStVec().size();
138     mplExport.WriteNum(size);
139     for (size_t i = 0; i < size; ++i) {
140         mplExport.OutputSymbol(stConst.GetStVecItem(i));
141     }
142     size = stConst.GetStOffsetVec().size();
143     mplExport.WriteNum(size);
144     for (size_t i = 0; i < size; ++i) {
145         mplExport.WriteNum(stConst.GetStOffsetVecItem(i));
146     }
147 }
148 
InitOutputConstFactory()149 static bool InitOutputConstFactory()
150 {
151     RegisterFactoryFunction<OutputConstFactory>(kConstInt, OutputConstInt);
152     RegisterFactoryFunction<OutputConstFactory>(kConstAddrof, OutputConstAddrof);
153     RegisterFactoryFunction<OutputConstFactory>(kConstAddrofFunc, OutputConstAddrofFunc);
154     RegisterFactoryFunction<OutputConstFactory>(kConstLblConst, OutputConstLbl);
155     RegisterFactoryFunction<OutputConstFactory>(kConstStrConst, OutputConstStr);
156     RegisterFactoryFunction<OutputConstFactory>(kConstStr16Const, OutputConstStr16);
157     RegisterFactoryFunction<OutputConstFactory>(kConstFloatConst, OutputConstFloat);
158     RegisterFactoryFunction<OutputConstFactory>(kConstDoubleConst, OutputConstDouble);
159     RegisterFactoryFunction<OutputConstFactory>(kConstAggConst, OutputConstAgg);
160     RegisterFactoryFunction<OutputConstFactory>(kConstStConst, OutputConstSt);
161     return true;
162 }
163 
OutputTypeScalar(const MIRType & ty,BinaryMplExport & mplExport)164 void OutputTypeScalar(const MIRType &ty, BinaryMplExport &mplExport)
165 {
166     mplExport.WriteNum(kBinKindTypeScalar);
167     mplExport.OutputTypeBase(ty);
168 }
169 
OutputTypePointer(const MIRType & ty,BinaryMplExport & mplExport)170 void OutputTypePointer(const MIRType &ty, BinaryMplExport &mplExport)
171 {
172     const auto &type = static_cast<const MIRPtrType &>(ty);
173     mplExport.WriteNum(kBinKindTypePointer);
174     mplExport.OutputTypeBase(type);
175     mplExport.OutputTypeAttrs(type.GetTypeAttrs());
176     mplExport.OutputType(type.GetPointedTyIdx());
177 }
178 
OutputTypeByName(const MIRType & ty,BinaryMplExport & mplExport)179 void OutputTypeByName(const MIRType &ty, BinaryMplExport &mplExport)
180 {
181     mplExport.WriteNum(kBinKindTypeByName);
182     mplExport.OutputTypeBase(ty);
183 }
184 
OutputTypeFArray(const MIRType & ty,BinaryMplExport & mplExport)185 void OutputTypeFArray(const MIRType &ty, BinaryMplExport &mplExport)
186 {
187     const auto &type = static_cast<const MIRFarrayType &>(ty);
188     mplExport.WriteNum(kBinKindTypeFArray);
189     mplExport.OutputTypeBase(type);
190     mplExport.OutputType(type.GetElemTyIdx());
191 }
192 
OutputTypeJArray(const MIRType & ty,BinaryMplExport & mplExport)193 void OutputTypeJArray(const MIRType &ty, BinaryMplExport &mplExport)
194 {
195     const auto &type = static_cast<const MIRJarrayType &>(ty);
196     mplExport.WriteNum(kBinKindTypeJarray);
197     mplExport.OutputTypeBase(type);
198     mplExport.OutputType(type.GetElemTyIdx());
199 }
200 
OutputTypeArray(const MIRType & ty,BinaryMplExport & mplExport)201 void OutputTypeArray(const MIRType &ty, BinaryMplExport &mplExport)
202 {
203     const auto &type = static_cast<const MIRArrayType &>(ty);
204     mplExport.WriteNum(kBinKindTypeArray);
205     mplExport.OutputTypeBase(type);
206     mplExport.WriteNum(type.GetDim());
207     for (uint16 i = 0; i < type.GetDim(); ++i) {
208         mplExport.WriteNum(type.GetSizeArrayItem(i));
209     }
210     mplExport.OutputType(type.GetElemTyIdx());
211     mplExport.OutputTypeAttrs(type.GetTypeAttrs());
212 }
213 
OutputTypeFunction(const MIRType & ty,BinaryMplExport & mplExport)214 void OutputTypeFunction(const MIRType &ty, BinaryMplExport &mplExport)
215 {
216     const auto &type = static_cast<const MIRFuncType &>(ty);
217     mplExport.WriteNum(kBinKindTypeFunction);
218     mplExport.OutputTypeBase(type);
219     mplExport.OutputType(type.GetRetTyIdx());
220     mplExport.WriteNum(type.funcAttrs.GetAttrFlag());
221     size_t size = type.GetParamTypeList().size();
222     mplExport.WriteNum(size);
223     for (size_t i = 0; i < size; ++i) {
224         mplExport.OutputType(type.GetNthParamType(i));
225     }
226     size = type.GetParamAttrsList().size();
227     mplExport.WriteNum(size);
228     for (size_t i = 0; i < size; ++i) {
229         mplExport.OutputTypeAttrs(type.GetNthParamAttrs(i));
230     }
231 }
232 
OutputTypeParam(const MIRType & ty,BinaryMplExport & mplExport)233 void OutputTypeParam(const MIRType &ty, BinaryMplExport &mplExport)
234 {
235     const auto &type = static_cast<const MIRTypeParam &>(ty);
236     mplExport.WriteNum(kBinKindTypeParam);
237     mplExport.OutputTypeBase(type);
238 }
239 
OutputTypeInstantVector(const MIRType & ty,BinaryMplExport & mplExport)240 void OutputTypeInstantVector(const MIRType &ty, BinaryMplExport &mplExport)
241 {
242     const auto &type = static_cast<const MIRInstantVectorType &>(ty);
243     mplExport.WriteNum(kBinKindTypeInstantVector);
244     mplExport.OutputTypeBase(type);
245     mplExport.WriteNum(ty.GetKind());
246     mplExport.OutputTypePairs(type);
247 }
248 
OutputTypeGenericInstant(const MIRType & ty,BinaryMplExport & mplExport)249 void OutputTypeGenericInstant(const MIRType &ty, BinaryMplExport &mplExport)
250 {
251     const auto &type = static_cast<const MIRGenericInstantType &>(ty);
252     mplExport.WriteNum(kBinKindTypeGenericInstant);
253     mplExport.OutputTypeBase(type);
254     mplExport.OutputTypePairs(type);
255     mplExport.OutputType(type.GetGenericTyIdx());
256 }
257 
OutputTypeBitField(const MIRType & ty,BinaryMplExport & mplExport)258 void OutputTypeBitField(const MIRType &ty, BinaryMplExport &mplExport)
259 {
260     const auto &type = static_cast<const MIRBitFieldType &>(ty);
261     mplExport.WriteNum(kBinKindTypeBitField);
262     mplExport.OutputTypeBase(type);
263     mplExport.WriteNum(type.GetFieldSize());
264 }
265 
266 // for Struct/StructIncomplete/Union
OutputTypeStruct(const MIRType & ty,BinaryMplExport & mplExport)267 void OutputTypeStruct(const MIRType &ty, BinaryMplExport &mplExport)
268 {
269     const auto &type = static_cast<const MIRStructType &>(ty);
270     mplExport.WriteNum(kBinKindTypeStruct);
271     mplExport.OutputTypeBase(type);
272     MIRTypeKind kind = ty.GetKind();
273     if (type.IsImported()) {
274         CHECK_FATAL(ty.GetKind() != kTypeUnion, "Must be.");
275         kind = kTypeStructIncomplete;
276     }
277     mplExport.WriteNum(kind);
278     mplExport.OutputTypeAttrs(type.GetTypeAttrs());
279     if (kind != kTypeStructIncomplete) {
280         mplExport.OutputStructTypeData(type);
281     }
282 }
283 
OutputTypeClass(const MIRType & ty,BinaryMplExport & mplExport)284 void OutputTypeClass(const MIRType &ty, BinaryMplExport &mplExport)
285 {
286     const auto &type = static_cast<const MIRClassType &>(ty);
287     mplExport.WriteNum(kBinKindTypeClass);
288     mplExport.OutputTypeBase(type);
289     MIRTypeKind kind = ty.GetKind();
290     if (type.IsImported()) {
291         kind = kTypeClassIncomplete;
292     }
293     mplExport.WriteNum(kind);
294     if (kind != kTypeClassIncomplete) {
295         mplExport.OutputStructTypeData(type);
296         mplExport.OutputClassTypeData(type);
297     }
298 }
299 
OutputTypeInterface(const MIRType & ty,BinaryMplExport & mplExport)300 void OutputTypeInterface(const MIRType &ty, BinaryMplExport &mplExport)
301 {
302     const auto &type = static_cast<const MIRInterfaceType &>(ty);
303     mplExport.WriteNum(kBinKindTypeInterface);
304     mplExport.OutputTypeBase(type);
305     MIRTypeKind kind = ty.GetKind();
306     if (type.IsImported()) {
307         kind = kTypeInterfaceIncomplete;
308     }
309     mplExport.WriteNum(kind);
310     if (kind != kTypeInterfaceIncomplete) {
311         mplExport.OutputStructTypeData(type);
312         mplExport.OutputInterfaceTypeData(type);
313     }
314 }
315 
OutputTypeConstString(const MIRType & ty,BinaryMplExport &)316 void OutputTypeConstString(const MIRType &ty, BinaryMplExport &)
317 {
318     DEBUG_ASSERT(false, "Type's kind not yet implemented: %d", ty.GetKind());
319     (void)ty;
320 }
321 
InitOutputTypeFactory()322 static bool InitOutputTypeFactory()
323 {
324     RegisterFactoryFunction<OutputTypeFactory>(kTypeScalar, OutputTypeScalar);
325     RegisterFactoryFunction<OutputTypeFactory>(kTypePointer, OutputTypePointer);
326     RegisterFactoryFunction<OutputTypeFactory>(kTypeByName, OutputTypeByName);
327     RegisterFactoryFunction<OutputTypeFactory>(kTypeFArray, OutputTypeFArray);
328     RegisterFactoryFunction<OutputTypeFactory>(kTypeJArray, OutputTypeJArray);
329     RegisterFactoryFunction<OutputTypeFactory>(kTypeArray, OutputTypeArray);
330     RegisterFactoryFunction<OutputTypeFactory>(kTypeFunction, OutputTypeFunction);
331     RegisterFactoryFunction<OutputTypeFactory>(kTypeParam, OutputTypeParam);
332     RegisterFactoryFunction<OutputTypeFactory>(kTypeInstantVector, OutputTypeInstantVector);
333     RegisterFactoryFunction<OutputTypeFactory>(kTypeGenericInstant, OutputTypeGenericInstant);
334     RegisterFactoryFunction<OutputTypeFactory>(kTypeBitField, OutputTypeBitField);
335     RegisterFactoryFunction<OutputTypeFactory>(kTypeStruct, OutputTypeStruct);
336     RegisterFactoryFunction<OutputTypeFactory>(kTypeStructIncomplete, OutputTypeStruct);
337     RegisterFactoryFunction<OutputTypeFactory>(kTypeUnion, OutputTypeStruct);
338     RegisterFactoryFunction<OutputTypeFactory>(kTypeClass, OutputTypeClass);
339     RegisterFactoryFunction<OutputTypeFactory>(kTypeClassIncomplete, OutputTypeClass);
340     RegisterFactoryFunction<OutputTypeFactory>(kTypeInterface, OutputTypeInterface);
341     RegisterFactoryFunction<OutputTypeFactory>(kTypeInterfaceIncomplete, OutputTypeInterface);
342     RegisterFactoryFunction<OutputTypeFactory>(kTypeConstString, OutputTypeConstString);
343     return true;
344 }
345 };  // namespace
346 
347 namespace maple {
348 int BinaryMplExport::typeMarkOffset = 0;
349 
BinaryMplExport(MIRModule & md)350 BinaryMplExport::BinaryMplExport(MIRModule &md) : mod(md)
351 {
352     bufI = 0;
353     Init();
354     (void)InitOutputConstFactory();
355     (void)InitOutputTypeFactory();
356     not2mplt = false;
357 }
358 
Read()359 uint8 BinaryMplExport::Read()
360 {
361     CHECK_FATAL(bufI < buf.size(), "Index out of bound in BinaryMplImport::Read()");
362     return buf[bufI++];
363 }
364 
365 // Little endian
ReadInt()366 int32 BinaryMplExport::ReadInt()
367 {
368     uint32 x0 = static_cast<uint32>(Read());
369     uint32 x1 = static_cast<uint32>(Read());
370     uint32 x2 = static_cast<uint32>(Read());
371     uint32 x3 = static_cast<uint32>(Read());
372     int32 x = static_cast<int32>((((((x3 << 8) + x2) << 8) + x1) << 8) + x0);
373     return x;
374 }
375 
Write(uint8 b)376 void BinaryMplExport::Write(uint8 b)
377 {
378     buf.push_back(b);
379 }
380 
381 // Little endian
WriteInt(int32 x)382 void BinaryMplExport::WriteInt(int32 x)
383 {
384     Write(static_cast<uint8>(static_cast<uint32>(x) & 0xFF));
385     Write(static_cast<uint8>((static_cast<uint32>(x) >> 8) & 0xFF));  // shift 8 to get 9th-16th bits
386     Write(static_cast<uint8>((static_cast<uint32>(x) >> 16) & 0xFF)); // shift 16 to get 17th-24th bits
387     Write(static_cast<uint8>((static_cast<uint32>(x) >> 24) & 0xFF)); // shift 24 to get high 8 bits
388 }
389 
ExpandFourBuffSize()390 void BinaryMplExport::ExpandFourBuffSize()
391 {
392     WriteInt(0);
393 }
394 
Fixup(size_t i,int32 x)395 void BinaryMplExport::Fixup(size_t i, int32 x)
396 {
397     constexpr int fixupCount = 4;
398     CHECK(i <= buf.size() - fixupCount, "Index out of bound in BinaryMplImport::Fixup()");
399     buf[i + kFirstField] = static_cast<uint8>(static_cast<uint32>(x) & 0xFF);
400     buf[i + kSecondField] = static_cast<uint8>((static_cast<uint32>(x) >> 8) & 0xFF);  // shift 8 to get 9th-16th bits
401     buf[i + kThirdField] = static_cast<uint8>((static_cast<uint32>(x) >> 16) & 0xFF);  // shift 16 to get 17th-24th bits
402     buf[i + kFourthField] = static_cast<uint8>((static_cast<uint32>(x) >> 24) & 0xFF); // shift 24 to get high 8 bits
403 }
404 
WriteInt64(int64 x)405 void BinaryMplExport::WriteInt64(int64 x)
406 {
407     WriteInt(static_cast<int32>(static_cast<uint64>(x) & 0xFFFFFFFF));
408     WriteInt(static_cast<int32>((static_cast<uint64>(x) >> k32BitSize) & 0xFFFFFFFF));
409 }
410 
411 // LEB128
WriteNum(int64 x)412 void BinaryMplExport::WriteNum(int64 x)
413 {
414     while (x < -0x40 || x >= 0x40) {
415         Write(static_cast<uint8>((static_cast<uint64>(x) & 0x7F) + 0x80));
416         x = x >> 7; // LEB128 is a compress algorithm, save 1 bit subsequent falg and 7 bits data in 1 byte.
417                     // Do not cast int64 to uint64. If do so, small negtivate number like
418                     // -3 will occupy 9 bits and we will not get the compressed benefit.
419     }
420     Write(static_cast<uint8>(static_cast<uint64>(x) & 0x7F));
421 }
422 
WriteAsciiStr(const std::string & str)423 void BinaryMplExport::WriteAsciiStr(const std::string &str)
424 {
425     WriteNum(static_cast<int64>(str.size()));
426     for (size_t i = 0; i < str.size(); ++i) {
427         Write(static_cast<uint8>(str[i]));
428     }
429 }
430 
DumpBuf(const std::string & name)431 void BinaryMplExport::DumpBuf(const std::string &name)
432 {
433     FILE *f = fopen(name.c_str(), "wb");
434     if (f == nullptr) {
435         LogInfo::MapleLogger(kLlErr) << "Error while creating the binary file: " << name << '\n';
436         FATAL(kLncFatal, "Error while creating the binary file: %s\n", name.c_str());
437     }
438     size_t size = buf.size();
439     size_t k = fwrite(&buf[0], sizeof(uint8), size, f);
440     fclose(f);
441     if (k != size) {
442         LogInfo::MapleLogger(kLlErr) << "Error while writing the binary file: " << name << '\n';
443     }
444 }
445 
OutputConstBase(const MIRConst & constVal)446 void BinaryMplExport::OutputConstBase(const MIRConst &constVal)
447 {
448     WriteNum(constVal.GetKind());
449     OutputType(constVal.GetType().GetTypeIndex());
450 }
451 
OutputConst(MIRConst * constVal)452 void BinaryMplExport::OutputConst(MIRConst *constVal)
453 {
454     if (constVal == nullptr) {
455         WriteNum(0);
456     } else {
457         auto func = CreateProductFunction<OutputConstFactory>(constVal->GetKind());
458         if (func != nullptr) {
459             func(*constVal, *this);
460         }
461     }
462 }
463 
OutputStr(const GStrIdx & gstr)464 void BinaryMplExport::OutputStr(const GStrIdx &gstr)
465 {
466     if (gstr == 0u) {
467         WriteNum(0);
468         return;
469     }
470 
471     auto it = gStrMark.find(gstr);
472     if (it != gStrMark.end()) {
473         WriteNum(-(it->second));
474         return;
475     }
476 
477     size_t mark = gStrMark.size();
478     gStrMark[gstr] = mark;
479     WriteNum(kBinString);
480     DEBUG_ASSERT(GlobalTables::GetStrTable().StringTableSize() != 0, "Container check");
481     WriteAsciiStr(GlobalTables::GetStrTable().GetStringFromStrIdx(gstr));
482 }
483 
OutputUsrStr(UStrIdx ustr)484 void BinaryMplExport::OutputUsrStr(UStrIdx ustr)
485 {
486     if (ustr == 0u) {
487         WriteNum(0);
488         return;
489     }
490 
491     auto it = uStrMark.find(ustr);
492     if (it != uStrMark.end()) {
493         WriteNum(-(it->second));
494         return;
495     }
496 
497     size_t mark = uStrMark.size();
498     uStrMark[ustr] = mark;
499     WriteNum(kBinUsrString);
500     WriteAsciiStr(GlobalTables::GetUStrTable().GetStringFromStrIdx(ustr));
501 }
502 
OutputPragmaElement(const MIRPragmaElement & e)503 void BinaryMplExport::OutputPragmaElement(const MIRPragmaElement &e)
504 {
505     OutputStr(e.GetNameStrIdx());
506     OutputStr(e.GetTypeStrIdx());
507     WriteNum(e.GetType());
508 
509     if (e.GetType() == kValueString || e.GetType() == kValueType || e.GetType() == kValueField ||
510         e.GetType() == kValueMethod || e.GetType() == kValueEnum) {
511         OutputStr(GStrIdx(e.GetI32Val()));
512     } else {
513         WriteInt64(e.GetU64Val());
514     }
515     size_t size = e.GetSubElemVec().size();
516     WriteNum(size);
517     for (size_t i = 0; i < size; ++i) {
518         OutputPragmaElement(*(e.GetSubElement(i)));
519     }
520 }
521 
OutputPragma(const MIRPragma & p)522 void BinaryMplExport::OutputPragma(const MIRPragma &p)
523 {
524     WriteNum(p.GetKind());
525     WriteNum(p.GetVisibility());
526     OutputStr(p.GetStrIdx());
527     OutputType(p.GetTyIdx());
528     OutputType(p.GetTyIdxEx());
529     WriteNum(p.GetParamNum());
530     size_t size = p.GetElementVector().size();
531     WriteNum(size);
532     for (size_t i = 0; i < size; ++i) {
533         OutputPragmaElement(*(p.GetNthElement(i)));
534     }
535 }
536 
OutputTypeBase(const MIRType & type)537 void BinaryMplExport::OutputTypeBase(const MIRType &type)
538 {
539     WriteNum(type.GetPrimType());
540     OutputStr(type.GetNameStrIdx());
541     WriteNum(type.IsNameIsLocal());
542 }
543 
OutputFieldPair(const FieldPair & fp)544 void BinaryMplExport::OutputFieldPair(const FieldPair &fp)
545 {
546     OutputStr(fp.first);          // GStrIdx
547     OutputType(fp.second.first);  // TyIdx
548     FieldAttrs fa = fp.second.second;
549     WriteNum(fa.GetAttrFlag());
550     WriteNum(fa.GetAlignValue());
551     if (fa.GetAttr(FLDATTR_static) && fa.GetAttr(FLDATTR_final) &&
552         (fa.GetAttr(FLDATTR_public) || fa.GetAttr(FLDATTR_protected))) {
553         const std::string &fieldName = GlobalTables::GetStrTable().GetStringFromStrIdx(fp.first);
554         MIRSymbol *fieldVar = mod.GetMIRBuilder()->GetGlobalDecl(fieldName);
555         if ((fieldVar != nullptr) && (fieldVar->GetKonst() != nullptr) &&
556             (fieldVar->GetKonst()->GetKind() == kConstStr16Const)) {
557             WriteNum(kBinInitConst);
558             OutputConst(fieldVar->GetKonst());
559         } else {
560             WriteNum(0);
561         }
562     }
563 }
564 
OutputMethodPair(const MethodPair & memPool)565 void BinaryMplExport::OutputMethodPair(const MethodPair &memPool)
566 {
567     // use GStrIdx instead, StIdx will be created by ImportMethodPair
568     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(memPool.first.Idx());
569     CHECK_FATAL(funcSt != nullptr, "Pointer funcSt is nullptr, can't get symbol! Check it!");
570     WriteAsciiStr(GlobalTables::GetStrTable().GetStringFromStrIdx(funcSt->GetNameStrIdx()));
571     OutputType(memPool.second.first);               // TyIdx
572     WriteNum(memPool.second.second.GetAttrFlag());  // FuncAttrs
573 }
574 
OutputFieldsOfStruct(const FieldVector & fields)575 void BinaryMplExport::OutputFieldsOfStruct(const FieldVector &fields)
576 {
577     WriteNum(fields.size());
578     for (const FieldPair &fp : fields) {
579         OutputFieldPair(fp);
580     }
581 }
582 
OutputMethodsOfStruct(const MethodVector & methods)583 void BinaryMplExport::OutputMethodsOfStruct(const MethodVector &methods)
584 {
585     WriteNum(methods.size());
586     for (const MethodPair &memPool : methods) {
587         OutputMethodPair(memPool);
588     }
589 }
590 
OutputStructTypeData(const MIRStructType & type)591 void BinaryMplExport::OutputStructTypeData(const MIRStructType &type)
592 {
593     OutputFieldsOfStruct(type.GetFields());
594     OutputFieldsOfStruct(type.GetStaticFields());
595     OutputFieldsOfStruct(type.GetParentFields());
596     OutputMethodsOfStruct(type.GetMethods());
597 }
598 
OutputImplementedInterfaces(const std::vector<TyIdx> & interfaces)599 void BinaryMplExport::OutputImplementedInterfaces(const std::vector<TyIdx> &interfaces)
600 {
601     WriteNum(interfaces.size());
602     for (const TyIdx &tyIdx : interfaces) {
603         OutputType(tyIdx);
604     }
605 }
606 
OutputInfoIsString(const std::vector<bool> & infoIsString)607 void BinaryMplExport::OutputInfoIsString(const std::vector<bool> &infoIsString)
608 {
609     WriteNum(infoIsString.size());
610     for (bool isString : infoIsString) {
611         WriteNum(static_cast<int64>(isString));
612     }
613 }
614 
OutputInfo(const std::vector<MIRInfoPair> & info,const std::vector<bool> & infoIsString)615 void BinaryMplExport::OutputInfo(const std::vector<MIRInfoPair> &info, const std::vector<bool> &infoIsString)
616 {
617     size_t size = info.size();
618     WriteNum(size);
619     for (size_t i = 0; i < size; ++i) {
620         OutputStr(info[i].first);  // GStrIdx
621         if (infoIsString[i]) {
622             OutputStr(GStrIdx(info[i].second));
623         } else {
624             WriteNum(info[i].second);
625         }
626     }
627 }
628 
OutputPragmaVec(const std::vector<MIRPragma * > & pragmaVec)629 void BinaryMplExport::OutputPragmaVec(const std::vector<MIRPragma *> &pragmaVec)
630 {
631     WriteNum(pragmaVec.size());
632     for (MIRPragma *pragma : pragmaVec) {
633         OutputPragma(*pragma);
634     }
635 }
636 
OutputClassTypeData(const MIRClassType & type)637 void BinaryMplExport::OutputClassTypeData(const MIRClassType &type)
638 {
639     OutputType(type.GetParentTyIdx());
640     OutputImplementedInterfaces(type.GetInterfaceImplemented());
641     OutputInfoIsString(type.GetInfoIsString());
642     if (!inIPA) {
643         OutputInfo(type.GetInfo(), type.GetInfoIsString());
644         OutputPragmaVec(type.GetPragmaVec());
645     }
646 }
647 
OutputInterfaceTypeData(const MIRInterfaceType & type)648 void BinaryMplExport::OutputInterfaceTypeData(const MIRInterfaceType &type)
649 {
650     OutputImplementedInterfaces(type.GetParentsTyIdx());
651     OutputInfoIsString(type.GetInfoIsString());
652     if (!inIPA) {
653         OutputInfo(type.GetInfo(), type.GetInfoIsString());
654         OutputPragmaVec(type.GetPragmaVec());
655     }
656 }
657 
Init()658 void BinaryMplExport::Init()
659 {
660     BinaryMplExport::typeMarkOffset = 0;
661     gStrMark.clear();
662     uStrMark.clear();
663     symMark.clear();
664     funcMark.clear();
665     typMark.clear();
666     gStrMark[GStrIdx(0)] = 0;
667     uStrMark[UStrIdx(0)] = 0;
668     symMark[nullptr] = 0;
669     funcMark[nullptr] = 0;
670     eaNodeMark[nullptr] = 0;
671     curFunc = nullptr;
672     for (uint32 pti = static_cast<int32>(PTY_begin); pti < static_cast<uint32>(PTY_end); ++pti) {
673         typMark[GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(pti))] = pti;
674     }
675 }
676 
OutputSymbol(MIRSymbol * sym)677 void BinaryMplExport::OutputSymbol(MIRSymbol *sym)
678 {
679     if (sym == nullptr) {
680         WriteNum(0);
681         return;
682     }
683 
684     std::unordered_map<const MIRSymbol *, int64>::iterator it = symMark.find(sym);
685     if (it != symMark.end()) {
686         WriteNum(-(it->second));
687         return;
688     }
689 
690     WriteNum(kBinSymbol);
691     WriteNum(sym->GetScopeIdx());
692     OutputStr(sym->GetNameStrIdx());
693     OutputUsrStr(sym->sectionAttr);
694     OutputUsrStr(sym->GetAsmAttr());
695     WriteNum(sym->GetSKind());
696     WriteNum(sym->GetStorageClass());
697     size_t mark = symMark.size();
698     symMark[sym] = mark;
699     OutputTypeAttrs(sym->GetAttrs());
700     WriteNum(sym->GetIsTmp() ? 1 : 0);
701     if (sym->GetSKind() == kStPreg) {
702         WriteNum(sym->GetPreg()->GetPregNo());
703     } else if (sym->GetSKind() == kStConst || sym->GetSKind() == kStVar) {
704         if (sym->GetKonst() != nullptr) {
705             sym->GetKonst()->SetType(*sym->GetType());
706         }
707         OutputConst(sym->GetKonst());
708     } else if (sym->GetSKind() == kStFunc) {
709         OutputFunction(sym->GetFunction()->GetPuidx());
710     } else if (sym->GetSKind() == kStJavaClass || sym->GetSKind() == kStJavaInterface) {
711     } else {
712         CHECK_FATAL(false, "should not used");
713     }
714     if (sym->GetSKind() == kStVar || sym->GetSKind() == kStFunc) {
715         OutputSrcPos(sym->GetSrcPosition());
716     }
717     OutputType(sym->GetTyIdx());
718 }
719 
OutputFunction(PUIdx puIdx)720 void BinaryMplExport::OutputFunction(PUIdx puIdx)
721 {
722     if (puIdx == 0) {
723         WriteNum(0);
724         mod.SetCurFunction(nullptr);
725         return;
726     }
727     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
728     CHECK_FATAL(func != nullptr, "Cannot get MIRFunction.");
729     auto it = funcMark.find(func);
730     if (it != funcMark.end()) {
731         WriteNum(-it->second);
732         mod.SetCurFunction(func);
733         return;
734     }
735     size_t mark = funcMark.size();
736     funcMark[func] = mark;
737     MIRFunction *savedFunc = mod.CurFunction();
738     mod.SetCurFunction(func);
739 
740     WriteNum(kBinFunction);
741     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx());
742     CHECK_FATAL(funcSt != nullptr, "Pointer funcSt is nullptr, cannot get symbol! Check it!");
743     OutputSymbol(funcSt);
744     OutputType(func->GetMIRFuncType()->GetTypeIndex());
745     WriteNum(func->GetFuncAttrs().GetAttrFlag());
746 
747     auto &attributes = func->GetFuncAttrs();
748     if (attributes.GetAttr(FUNCATTR_constructor_priority)) {
749         WriteNum(attributes.GetConstructorPriority());
750     }
751 
752     if (attributes.GetAttr(FUNCATTR_destructor_priority)) {
753         WriteNum(attributes.GetDestructorPriority());
754     }
755 
756     WriteNum(func->GetFlag());
757     OutputType(func->GetClassTyIdx());
758     // output formal parameter information
759     WriteNum(static_cast<int64>(func->GetFormalDefVec().size()));
760     for (FormalDef formalDef : func->GetFormalDefVec()) {
761         OutputStr(formalDef.formalStrIdx);
762         OutputType(formalDef.formalTyIdx);
763         WriteNum(static_cast<int64>(formalDef.formalAttrs.GetAttrFlag()));
764     }
765     //  store Side Effect for each func
766     if (func2SEMap) {
767         uint32 isSee = func->IsIpaSeen() == true ? 1 : 0;
768         uint32 isPure = func->IsPure() == true ? 1 : 0;
769         uint32 noDefArg = func->IsNoDefArgEffect() == true ? 1 : 0;
770         uint32 noDef = func->IsNoDefEffect() == true ? 1 : 0;
771         uint32 noRetGlobal = func->IsNoRetGlobal() == true ? 1 : 0;
772         uint32 noThr = func->IsNoThrowException() == true ? 1 : 0;
773         uint32 noRetArg = func->IsNoRetArg() == true ? 1 : 0;
774         uint32 noPriDef = func->IsNoPrivateDefEffect() == true ? 1 : 0;
775         uint32 i = 0;
776         uint8 se = noThr << i++;
777         se |= noRetGlobal << i++;
778         se |= noDef << i++;
779         se |= noDefArg << i++;
780         se |= isPure << i++;
781         se |= isSee << i++;
782         se |= noRetArg << i++;
783         se |= noPriDef << i;
784         if ((*func2SEMap).find(func->GetNameStrIdx()) == (*func2SEMap).end()) {
785             (*func2SEMap)[func->GetNameStrIdx()] = se;
786         } else if ((*func2SEMap)[func->GetNameStrIdx()] != se) {
787             FATAL(kLncFatal, "It is a bug.");
788         }
789     }
790     mod.SetCurFunction(savedFunc);
791 }
792 
WriteStrField(uint64 contentIdx)793 void BinaryMplExport::WriteStrField(uint64 contentIdx)
794 {
795     Fixup(contentIdx, buf.size());
796     WriteNum(kBinStrStart);
797     size_t totalSizeIdx = buf.size();
798     ExpandFourBuffSize();  // total size of this field to ~BIN_STR_START
799     size_t outStrSizeIdx = buf.size();
800     ExpandFourBuffSize();  // size of OutputStr
801 
802     int32 size = 0;
803     for (const auto &entity : GlobalTables::GetConstPool().GetConstU16StringPool()) {
804         MIRSymbol *sym = entity.second;
805         if (sym->IsLiteral()) {
806             OutputStr(sym->GetNameStrIdx());
807             ++size;
808         }
809     }
810     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
811     Fixup(outStrSizeIdx, size);
812     WriteNum(~kBinStrStart);
813 }
814 
WriteHeaderField(uint64 contentIdx)815 void BinaryMplExport::WriteHeaderField(uint64 contentIdx)
816 {
817     Fixup(contentIdx, buf.size());
818     WriteNum(kBinHeaderStart);
819     size_t totalSizeIdx = buf.size();
820     ExpandFourBuffSize();  // total size of this field to ~BIN_IMPORT_START
821     WriteNum(mod.GetFlavor());
822     WriteNum(mod.GetSrcLang());
823     WriteNum(mod.GetID());
824     if (mod.GetFlavor() == kFlavorLmbc) {
825         WriteNum(mod.GetGlobalMemSize());
826         WriteNum(mod.IsWithDbgInfo());
827     }
828     WriteNum(mod.GetNumFuncs());
829     WriteAsciiStr(mod.GetEntryFuncName());
830     OutputInfoVector(mod.GetFileInfo(), mod.GetFileInfoIsString());
831 
832     if (mod.IsWithDbgInfo()) {
833         WriteNum(static_cast<int64>(mod.GetSrcFileInfo().size()));
834         for (uint32 i = 0; i < mod.GetSrcFileInfo().size(); i++) {
835             OutputStr(mod.GetSrcFileInfo()[i].first);
836             WriteNum(mod.GetSrcFileInfo()[i].second);
837         }
838     } else {
839         Write(0);
840     }
841 
842     WriteNum(static_cast<int64>(mod.GetImportFiles().size()));
843     for (GStrIdx strIdx : mod.GetImportFiles()) {
844         OutputStr(strIdx);
845     }
846 
847     WriteNum(static_cast<int64>(mod.GetAsmDecls().size()));
848     for (MapleString mapleStr : mod.GetAsmDecls()) {
849         std::string str(mapleStr.c_str());
850         WriteAsciiStr(str);
851     }
852 
853     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
854     WriteNum(~kBinHeaderStart);
855     return;
856 }
857 
WriteTypeField(uint64 contentIdx,bool useClassList)858 void BinaryMplExport::WriteTypeField(uint64 contentIdx, bool useClassList)
859 {
860     Fixup(contentIdx, buf.size());
861     WriteNum(kBinTypeStart);
862     size_t totalSizeIdx = buf.size();
863     ExpandFourBuffSize();  // total size of this field to ~BIN_TYPE_START
864     size_t outTypeSizeIdx = buf.size();
865     ExpandFourBuffSize();  // size of OutputType
866     int32 size = 0;
867     if (useClassList) {
868         for (uint32 tyIdx : mod.GetClassList()) {
869             TyIdx curTyidx(tyIdx);
870             MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curTyidx);
871             CHECK_FATAL(type != nullptr, "Pointer type is nullptr, cannot get type, check it!");
872             if (type->GetKind() == kTypeClass || type->GetKind() == kTypeInterface) {
873                 auto *structType = static_cast<MIRStructType *>(type);
874                 // skip imported class/interface and incomplete types
875                 if (!structType->IsImported() && !structType->IsIncomplete()) {
876                     OutputType(curTyidx);
877                     ++size;
878                 }
879             }
880         }
881     } else {
882         uint32 idx = GlobalTables::GetTypeTable().lastDefaultTyIdx.GetIdx();
883         for (idx = idx + 1; idx < GlobalTables::GetTypeTable().GetTypeTableSize(); idx++) {
884             OutputType(TyIdx(idx));
885             size++;
886         }
887     }
888     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
889     Fixup(outTypeSizeIdx, size);
890     WriteNum(~kBinTypeStart);
891 }
892 
OutputCallInfo(CallInfo & callInfo)893 void BinaryMplExport::OutputCallInfo(CallInfo &callInfo)
894 {
895     auto it = callInfoMark.find(callInfo.GetID());
896     if (it != callInfoMark.end()) {
897         WriteNum(-(it->second));
898         return;
899     }
900     WriteNum(kBinCallinfo);
901     size_t mark = callInfoMark.size();
902     callInfoMark[callInfo.GetID()] = mark;
903     WriteNum(callInfo.GetCallType());  // call type
904     WriteInt(callInfo.GetLoopDepth());
905     WriteInt(callInfo.GetID());
906     callInfo.AreAllArgsLocal() ? Write(1) : Write(0);  // All args are local variables or not.
907     OutputSymbol(callInfo.GetFunc()->GetFuncSymbol());
908 }
909 
WriteCgField(uint64 contentIdx,const CallGraph * cg)910 void BinaryMplExport::WriteCgField(uint64 contentIdx, const CallGraph *cg)
911 {
912     if (contentIdx != 0) {
913         Fixup(contentIdx, buf.size());
914     }
915     WriteNum(kBinCgStart);
916     size_t totalSizeIdx = buf.size();
917     ExpandFourBuffSize();  // total size of this field to ~BIN_CG_START
918     size_t outcgSizeIdx = buf.size();
919     ExpandFourBuffSize();  // size of OutCG
920     int32 size = 0;
921     if (cg != nullptr) {
922         for (auto entry : cg->GetNodesMap()) {
923             MIRSymbol *methodSym = entry.first->GetFuncSymbol();
924             WriteNum(kStartMethod);
925             OutputSymbol(methodSym);
926             size_t targetTyIdx = buf.size();
927             ExpandFourBuffSize();
928             int32 targSize = 0;
929             callInfoMark.clear();
930             callInfoMark[0xffffffff] = 0;
931             for (const auto &callSite : entry.second->GetCallee()) {
932                 OutputCallInfo(*(callSite.first));
933                 ++targSize;
934             }
935             Fixup(targetTyIdx, targSize);
936             WriteNum(~kStartMethod);
937             ++size;
938         }
939     }
940 
941     DEBUG_ASSERT((buf.size() - totalSizeIdx) <= 0xffffffff, "Integer overflow.");
942     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
943     Fixup(outcgSizeIdx, size);
944     WriteNum(~kBinCgStart);
945 }
946 
WriteSeField()947 void BinaryMplExport::WriteSeField()
948 {
949     DEBUG_ASSERT(func2SEMap != nullptr, "Expecting a func2SE map");
950     WriteNum(kBinSeStart);
951     size_t totalSizeIdx = buf.size();
952     ExpandFourBuffSize();  // total size of this field to ~BIN_SYM_START
953     size_t outseSizeIdx = buf.size();
954     ExpandFourBuffSize();  // size of OutSym
955     int32 size = 0;
956 
957     for (const auto &func2SE : *func2SEMap) {
958         uint8 se = func2SE.second;
959         if (static_cast<int32>(se)) {
960             OutputStr(func2SE.first);
961             Write(se);
962             if ((se & kPureFunc) == kPureFunc) {
963                 const std::string &funcStr = GlobalTables::GetStrTable().GetStringFromStrIdx(func2SE.first);
964                 auto *funcSymbol = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(
965                     GlobalTables::GetStrTable().GetStrIdxFromName(funcStr));
966                 MIRFunction *func = (funcSymbol != nullptr)
967                                         ? GetMIRModule().GetMIRBuilder()->GetFunctionFromSymbol(*funcSymbol)
968                                         : nullptr;
969                 OutputType(func->GetReturnTyIdx());
970             }
971             ++size;
972         }
973     }
974     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
975     Fixup(outseSizeIdx, size);
976     WriteNum(~kBinSeStart);
977 }
978 
OutEaCgBaseNode(const EACGBaseNode & node,bool firstPart)979 void BinaryMplExport::OutEaCgBaseNode(const EACGBaseNode &node, bool firstPart)
980 {
981     if (firstPart) {
982         WriteNum(node.eaStatus);
983         WriteInt(static_cast<int32>(node.id));
984     } else {
985         // in and out set in base node is not necessary to be outed
986         // start to out point-to set
987         size_t outP2SizeIdx = buf.size();
988         WriteInt(0);
989         uint32 size = 0;
990         for (EACGBaseNode *outNode : node.GetPointsToSet()) {
991             OutEaCgNode(*outNode);
992             ++size;
993         }
994         Fixup(outP2SizeIdx, size);
995         // start to out in set
996         outP2SizeIdx = buf.size();
997         WriteInt(0);
998         size = 0;
999         for (EACGBaseNode *outNode : node.GetInSet()) {
1000             OutEaCgNode(*outNode);
1001             ++size;
1002         }
1003         Fixup(outP2SizeIdx, size);
1004         // start to out out set
1005         outP2SizeIdx = buf.size();
1006         WriteInt(0);
1007         size = 0;
1008         for (EACGBaseNode *outNode : node.GetOutSet()) {
1009             OutEaCgNode(*outNode);
1010             ++size;
1011         }
1012         Fixup(outP2SizeIdx, size);
1013     }
1014 }
1015 
OutEaCgObjNode(EACGObjectNode & obj)1016 void BinaryMplExport::OutEaCgObjNode(EACGObjectNode &obj)
1017 {
1018     Write(uint8(obj.isPhantom));
1019     size_t outFieldSizeIdx = buf.size();
1020     WriteInt(0);
1021     uint32 size = 0;
1022     for (const auto &fieldNodePair : obj.fieldNodes) {
1023         EACGBaseNode *fieldNode = fieldNodePair.second;
1024         DEBUG_ASSERT(fieldNodePair.first == static_cast<EACGFieldNode *>(fieldNode)->GetFieldID(), "Must be.");
1025         OutEaCgNode(*fieldNode);
1026         ++size;
1027     }
1028     Fixup(outFieldSizeIdx, size);
1029     // start to out point by
1030     outFieldSizeIdx = buf.size();
1031     WriteInt(0);
1032     size = 0;
1033     for (EACGBaseNode *node : obj.pointsBy) {
1034         OutEaCgNode(*node);
1035         ++size;
1036     }
1037     Fixup(outFieldSizeIdx, size);
1038 }
1039 
OutEaCgRefNode(const EACGRefNode & ref)1040 void BinaryMplExport::OutEaCgRefNode(const EACGRefNode &ref)
1041 {
1042     Write(uint8(ref.isStaticField));
1043 }
1044 
OutEaCgFieldNode(EACGFieldNode & field)1045 void BinaryMplExport::OutEaCgFieldNode(EACGFieldNode &field)
1046 {
1047     WriteInt(field.GetFieldID());
1048     int32 size = 0;
1049     size_t outFieldSizeIdx = buf.size();
1050     WriteInt(0);
1051     for (EACGBaseNode *obj : field.belongsTo) {
1052         OutEaCgNode(*obj);
1053         ++size;
1054     }
1055     Fixup(outFieldSizeIdx, size);
1056     Write(uint8(field.isPhantom));
1057 }
1058 
OutEaCgActNode(const EACGActualNode & act)1059 void BinaryMplExport::OutEaCgActNode(const EACGActualNode &act)
1060 {
1061     Write(uint8(act.isPhantom));
1062     Write(uint8(act.isReturn));
1063     Write(act.argIdx);
1064     WriteInt(act.callSiteInfo);
1065 }
1066 
OutEaCgNode(EACGBaseNode & node)1067 void BinaryMplExport::OutEaCgNode(EACGBaseNode &node)
1068 {
1069     auto it = eaNodeMark.find(&node);
1070     if (it != eaNodeMark.end()) {
1071         WriteNum(-it->second);
1072         return;
1073     }
1074     size_t mark = eaNodeMark.size();
1075     eaNodeMark[&node] = mark;
1076     WriteNum(kBinEaCgNode);
1077     WriteNum(node.kind);
1078     OutEaCgBaseNode(node, true);
1079     if (node.IsActualNode()) {
1080         WriteNum(kBinEaCgActNode);
1081         OutEaCgActNode(static_cast<EACGActualNode &>(node));
1082     } else if (node.IsFieldNode()) {
1083         WriteNum(kBinEaCgFieldNode);
1084         OutEaCgFieldNode(static_cast<EACGFieldNode &>(node));
1085     } else if (node.IsObjectNode()) {
1086         WriteNum(kBinEaCgObjNode);
1087         OutEaCgObjNode(static_cast<EACGObjectNode &>(node));
1088     } else if (node.IsReferenceNode()) {
1089         WriteNum(kBinEaCgRefNode);
1090         OutEaCgRefNode(static_cast<EACGRefNode &>(node));
1091     } else {
1092         DEBUG_ASSERT(false, "Must be.");
1093     }
1094     OutEaCgBaseNode(node, false);
1095     WriteNum(~kBinEaCgNode);
1096 }
1097 
WriteEaField(const CallGraph & cg)1098 void BinaryMplExport::WriteEaField(const CallGraph &cg)
1099 {
1100     WriteNum(kBinEaStart);
1101     uint64 totalSizeIdx = buf.size();
1102     WriteInt(0);
1103     uint64 outeaSizeIdx = buf.size();
1104     WriteInt(0);
1105     int32 size = 0;
1106     for (auto cgNodePair : cg.GetNodesMap()) {
1107         MIRFunction *func = cgNodePair.first;
1108         if (func->GetEACG() == nullptr) {
1109             continue;
1110         }
1111         EAConnectionGraph *eacg = func->GetEACG();
1112         DEBUG_ASSERT(eacg != nullptr, "Must be.");
1113         OutputStr(eacg->GetFuncNameStrIdx());
1114         WriteInt(eacg->GetNodes().size());
1115         OutEaCgNode(*eacg->GetGlobalObject());
1116         uint64 outFunceaIdx = buf.size();
1117         WriteInt(0);
1118         size_t funceaSize = 0;
1119         for (EACGBaseNode *node : eacg->GetFuncArgNodes()) {
1120             OutEaCgNode(*node);
1121             ++funceaSize;
1122         }
1123         Fixup(outFunceaIdx, funceaSize);
1124         ++size;
1125     }
1126     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1127     Fixup(outeaSizeIdx, size);
1128     WriteNum(~kBinEaStart);
1129 }
1130 
WriteEaCgField(EAConnectionGraph * eaCg)1131 void BinaryMplExport::WriteEaCgField(EAConnectionGraph *eaCg)
1132 {
1133     if (eaCg == nullptr) {
1134         WriteNum(~kBinEaCgStart);
1135         return;
1136     }
1137     WriteNum(kBinEaCgStart);
1138     size_t totalSizeIdx = buf.size();
1139     WriteInt(0);
1140     // out this function's arg list
1141     OutputStr(eaCg->GetFuncNameStrIdx());
1142     WriteInt(eaCg->GetNodes().size());
1143     OutEaCgNode(*eaCg->GetGlobalObject());
1144     size_t outNodeSizeIdx = buf.size();
1145     WriteInt(0);
1146     size_t argNodeSize = 0;
1147     for (EACGBaseNode *node : eaCg->GetFuncArgNodes()) {
1148         OutEaCgNode(*node);
1149         ++argNodeSize;
1150     }
1151     Fixup(outNodeSizeIdx, argNodeSize);
1152     // out this function's call site's arg list
1153     outNodeSizeIdx = buf.size();
1154     WriteInt(0);
1155     size_t callSiteSize = 0;
1156     for (auto nodePair : eaCg->GetCallSite2Nodes()) {
1157         uint32 id = nodePair.first;
1158         MapleVector<EACGBaseNode *> *calleeArgNode = nodePair.second;
1159         WriteInt(id);
1160         size_t outCalleeArgSizeIdx = buf.size();
1161         WriteInt(0);
1162         size_t calleeArgSize = 0;
1163         for (EACGBaseNode *node : *calleeArgNode) {
1164             OutEaCgNode(*node);
1165             ++calleeArgSize;
1166         }
1167         Fixup(outCalleeArgSizeIdx, calleeArgSize);
1168         ++callSiteSize;
1169     }
1170     Fixup(outNodeSizeIdx, callSiteSize);
1171 
1172     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1173     WriteNum(~kBinEaCgStart);
1174 }
1175 
WriteSymField(uint64 contentIdx)1176 void BinaryMplExport::WriteSymField(uint64 contentIdx)
1177 {
1178     Fixup(contentIdx, buf.size());
1179     WriteNum(kBinSymStart);
1180     uint64 totalSizeIdx = buf.size();
1181     ExpandFourBuffSize();  // total size of this field to ~BIN_SYM_START
1182     uint64 outsymSizeIdx = buf.size();
1183     ExpandFourBuffSize();  // size of OutSym
1184     int32 size = 0;
1185 
1186     if (not2mplt) {
1187         for (auto sit = GetMIRModule().GetSymbolDefOrder().begin(); sit != GetMIRModule().GetSymbolDefOrder().end();
1188              ++sit) {
1189             MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(sit->Idx());
1190             DEBUG_ASSERT(s != nullptr, "null ptr check");
1191             // Verify: all wpofake variables should have been deleted from globaltable
1192             DEBUG_ASSERT(!(s->IsWpoFakeParm() || s->IsWpoFakeRet()) || s->IsDeleted(), "wpofake var not deleted");
1193             MIRStorageClass storageClass = s->GetStorageClass();
1194             MIRSymKind sKind = s->GetSKind();
1195             if (s->IsDeleted() || storageClass == kScUnused || (s->GetIsImported() && !s->GetAppearsInCode()) ||
1196                 (sKind == kStFunc && (storageClass == kScExtern || !s->GetAppearsInCode()))) {
1197                 continue;
1198             }
1199             OutputSymbol(s);
1200             size++;
1201         }
1202     }
1203     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1204     Fixup(outsymSizeIdx, size);
1205     WriteNum(~kBinSymStart);
1206     return;
1207 }
1208 
WriteContentField4mplt(int fieldNum,uint64 * fieldStartP)1209 void BinaryMplExport::WriteContentField4mplt(int fieldNum, uint64 *fieldStartP)
1210 {
1211     WriteNum(kBinContentStart);
1212     size_t totalSizeIdx = buf.size();
1213     ExpandFourBuffSize();  // total size of this field to ~BIN_SYM_START
1214 
1215     WriteInt(fieldNum);  // size of Content item
1216 
1217     WriteNum(kBinStrStart);
1218     fieldStartP[kFirstField] = buf.size();
1219     ExpandFourBuffSize();
1220 
1221     WriteNum(kBinTypeStart);
1222     fieldStartP[kSecondField] = buf.size();
1223     ExpandFourBuffSize();
1224 
1225     WriteNum(kBinCgStart);
1226     fieldStartP[kThirdField] = buf.size();
1227     ExpandFourBuffSize();
1228 
1229     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1230     WriteNum(~kBinContentStart);
1231 }
1232 
WriteContentField4nonmplt(int fieldNum,uint64 * fieldStartP)1233 void BinaryMplExport::WriteContentField4nonmplt(int fieldNum, uint64 *fieldStartP)
1234 {
1235     CHECK_FATAL(fieldStartP != nullptr, "fieldStartP is null.");
1236     WriteNum(kBinContentStart);
1237     size_t totalSizeIdx = buf.size();
1238     ExpandFourBuffSize();  // total size of this field to ~BIN_SYM_START
1239 
1240     WriteInt(fieldNum);  // size of Content item
1241 
1242     WriteNum(kBinHeaderStart);
1243     fieldStartP[kFirstField] = buf.size();
1244     ExpandFourBuffSize();
1245 
1246     WriteNum(kBinSymStart);
1247     fieldStartP[kSecondField] = buf.size();
1248     ExpandFourBuffSize();
1249 
1250     WriteNum(kBinFunctionBodyStart);
1251     fieldStartP[kThirdField] = buf.size();
1252     ExpandFourBuffSize();
1253 
1254     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1255     WriteNum(~kBinContentStart);
1256 }
1257 
WriteContentField4nonJava(int fieldNum,uint64 * fieldStartP)1258 void BinaryMplExport::WriteContentField4nonJava(int fieldNum, uint64 *fieldStartP)
1259 {
1260     CHECK_FATAL(fieldStartP != nullptr, "fieldStartP is null.");
1261     WriteNum(kBinContentStart);
1262     size_t totalSizeIdx = buf.size();
1263     ExpandFourBuffSize();  // total size of this field to ~BIN_SYM_START
1264 
1265     WriteInt(fieldNum);  // size of Content item
1266 
1267     WriteNum(kBinHeaderStart);
1268     fieldStartP[kFirstField] = buf.size();
1269     ExpandFourBuffSize();
1270 
1271     WriteNum(kBinStrStart);
1272     fieldStartP[kSecondField] = buf.size();
1273     ExpandFourBuffSize();
1274 
1275     WriteNum(kBinTypeStart);
1276     fieldStartP[kThirdField] = buf.size();
1277     ExpandFourBuffSize();
1278 
1279     WriteNum(kBinSymStart);
1280     fieldStartP[kFourthField] = buf.size();
1281     ExpandFourBuffSize();
1282 
1283     WriteNum(kBinFunctionBodyStart);
1284     fieldStartP[kFifthField] = buf.size();
1285     ExpandFourBuffSize();
1286 
1287     Fixup(totalSizeIdx, buf.size() - totalSizeIdx);
1288     WriteNum(~kBinContentStart);
1289 }
1290 
Export(const std::string & fname,std::unordered_set<std::string> * dumpFuncSet)1291 void BinaryMplExport::Export(const std::string &fname, std::unordered_set<std::string> *dumpFuncSet)
1292 {
1293     uint64 fieldStartPoint[5];
1294     if (!not2mplt) {
1295         WriteInt(kMpltMagicNumber);
1296         WriteContentField4mplt(kFourthFieldInt, fieldStartPoint);
1297         WriteStrField(fieldStartPoint[kFirstField]);
1298         WriteTypeField(fieldStartPoint[kSecondField]);
1299         WriteCgField(fieldStartPoint[kThirdField], nullptr);
1300         importFileName = fname;
1301     } else {
1302         WriteInt(kMpltMagicNumber + 0x10);
1303         if (mod.IsJavaModule()) {
1304             WriteContentField4nonmplt(kFourthFieldInt, fieldStartPoint);
1305             WriteHeaderField(fieldStartPoint[kFirstField]);
1306             WriteSymField(fieldStartPoint[kSecondField]);
1307             WriteFunctionBodyField(fieldStartPoint[kThirdField], dumpFuncSet);
1308         } else {
1309             WriteContentField4nonJava(kSixthFieldInt, fieldStartPoint);
1310             WriteHeaderField(fieldStartPoint[kFirstField]);
1311             WriteSymField(fieldStartPoint[kFourthField]);
1312             WriteFunctionBodyField(fieldStartPoint[kFifthField], dumpFuncSet);
1313         }
1314     }
1315     WriteNum(kBinFinish);
1316     DumpBuf(fname);
1317 }
1318 
AppendAt(const std::string & name,int32 offset)1319 void BinaryMplExport::AppendAt(const std::string &name, int32 offset)
1320 {
1321     FILE *f = fopen(name.c_str(), "r+b");
1322     if (f == nullptr) {
1323         LogInfo::MapleLogger(kLlErr) << "Error while opening the binary file: " << name << '\n';
1324         FATAL(kLncFatal, "Error while creating the binary file: %s\n", name.c_str());
1325     }
1326     int seekRet = fseek(f, static_cast<long int>(offset), SEEK_SET);
1327     CHECK_FATAL(seekRet == 0, "Call fseek failed.");
1328     size_t size = buf.size();
1329     size_t k = fwrite(&buf[0], sizeof(uint8), size, f);
1330     fclose(f);
1331     if (k != size) {
1332         LogInfo::MapleLogger(kLlErr) << "Error while writing the binary file: " << name << '\n';
1333     }
1334 }
1335 
OutputTypePairs(const MIRInstantVectorType & type)1336 void BinaryMplExport::OutputTypePairs(const MIRInstantVectorType &type)
1337 {
1338     size_t size = type.GetInstantVec().size();
1339     WriteNum(size);
1340     for (const TypePair &typePair : type.GetInstantVec()) {
1341         OutputType(typePair.first);
1342         OutputType(typePair.second);
1343     }
1344 }
1345 
OutputTypeAttrs(const TypeAttrs & ta)1346 void BinaryMplExport::OutputTypeAttrs(const TypeAttrs &ta)
1347 {
1348     WriteNum(ta.GetAttrFlag());
1349     WriteNum(ta.GetAlignValue());
1350     WriteNum(ta.GetPack());
1351 }
1352 
OutputType(TyIdx tyIdx)1353 void BinaryMplExport::OutputType(TyIdx tyIdx)
1354 {
1355     if (tyIdx == 0u) {
1356         WriteNum(0);
1357         return;
1358     }
1359     MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1360     CHECK_FATAL(ty != nullptr, "If gets nulltype, should have been returned!");
1361     auto it = typMark.find(ty);
1362     if (it != typMark.end()) {
1363         if (ty->GetKind() != kTypeFunction) {
1364             WriteNum(-(it->second));
1365             return;
1366         }
1367         ++BinaryMplExport::typeMarkOffset;
1368     } else {
1369         size_t mark = typMark.size() + BinaryMplExport::typeMarkOffset;
1370         typMark[ty] = mark;
1371     }
1372 
1373     auto func = CreateProductFunction<OutputTypeFactory>(ty->GetKind());
1374     if (func != nullptr) {
1375         func(*ty, *this);
1376     } else {
1377         DEBUG_ASSERT(false, "Type's kind not yet implemented: %d", ty->GetKind());
1378     }
1379 }
1380 
UpdateCgField(BinaryMplt & binMplt,const CallGraph & cg)1381 void UpdateMplt::UpdateCgField(BinaryMplt &binMplt, const CallGraph &cg)
1382 {
1383     BinaryMplImport &binImport = binMplt.GetBinImport();
1384     BinaryMplExport &binExport = binMplt.GetBinExport();
1385     binImport.SetBufI(0);
1386     if (binImport.IsBufEmpty() || binImport.ReadInt() != kMpltMagicNumber) {
1387         INFO(kLncInfo, " This Module depends on nothing");
1388         return;
1389     }
1390     int64 cgStart = binImport.GetContent(kBinCgStart);
1391     DEBUG_ASSERT(cgStart != 0, "Should be updated in import processing.");
1392     binImport.SetBufI(cgStart);
1393     [[maybe_unused]] int64 checkReadNum = binImport.ReadNum();
1394     DEBUG_ASSERT(checkReadNum == kBinCgStart, "Should be cg start point.");
1395     int32 totalSize = binImport.ReadInt();
1396     constexpr int32 headLen = 4;
1397     binImport.SetBufI(binImport.GetBufI() + totalSize - headLen);
1398     checkReadNum = binImport.ReadNum();
1399     DEBUG_ASSERT(checkReadNum == ~kBinCgStart, "Should be end of cg.");
1400     binExport.Init();
1401     std::map<GStrIdx, uint8> tmp;
1402     binExport.func2SEMap = &tmp;
1403     binExport.inIPA = true;
1404     binExport.WriteCgField(0, &cg);
1405     binExport.Init();
1406     binExport.WriteSeField();
1407     binExport.eaNodeMark.clear();
1408     binExport.eaNodeMark[nullptr] = 0;
1409     binExport.gStrMark.clear();
1410     binExport.gStrMark[GStrIdx(0)] = 0;
1411     binExport.WriteEaField(cg);
1412     binExport.WriteNum(kBinFinish);
1413     std::string filename(binMplt.GetImportFileName());
1414     binExport.AppendAt(filename, cgStart);
1415 }
1416 
1417 }  // namespace maple
1418