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