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