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