• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mir_function.h"
17 #include "opcode_info.h"
18 #include "mir_pragma.h"
19 #include "mir_builder.h"
20 #include "bin_mplt.h"
21 #include <sstream>
22 #include <vector>
23 
24 using namespace std;
25 namespace maple {
OutputInfoVector(const MIRInfoVector & infoVector,const MapleVector<bool> & infoVectorIsString)26 void BinaryMplExport::OutputInfoVector(const MIRInfoVector &infoVector, const MapleVector<bool> &infoVectorIsString)
27 {
28     if (!mod.IsWithDbgInfo()) {
29         Write(0);
30         return;
31     }
32     WriteNum(infoVector.size());
33     for (uint32 i = 0; i < infoVector.size(); i++) {
34         OutputStr(infoVector[i].first);
35         WriteNum(infoVectorIsString[i] ? 1 : 0);
36         if (!infoVectorIsString[i]) {
37             WriteNum(infoVector[i].second);
38         } else {
39             OutputStr(GStrIdx(infoVector[i].second));
40         }
41     }
42 }
43 
OutputFuncIdInfo(MIRFunction * func)44 void BinaryMplExport::OutputFuncIdInfo(MIRFunction *func)
45 {
46     WriteNum(kBinFuncIdInfoStart);
47     WriteNum(func->GetPuidxOrigin());  // the funcid
48     OutputInfoVector(func->GetInfoVector(), func->InfoIsString());
49     if (mod.GetFlavor() == kFlavorLmbc) {
50         WriteNum(func->GetFrameSize());
51     }
52 }
53 
OutputBaseNode(const BaseNode * b)54 void BinaryMplExport::OutputBaseNode(const BaseNode *b)
55 {
56     Write(static_cast<uint8>(b->GetOpCode()));
57     Write(static_cast<uint8>(b->GetPrimType()));
58 }
59 
OutputLocalSymbol(MIRSymbol * sym)60 void BinaryMplExport::OutputLocalSymbol(MIRSymbol *sym)
61 {
62     std::unordered_map<const MIRSymbol *, int64>::iterator it = localSymMark.find(sym);
63     if (it != localSymMark.end()) {
64         WriteNum(-(it->second));
65         return;
66     }
67 
68     WriteNum(kBinSymbol);
69     OutputStr(sym->GetNameStrIdx());
70     WriteNum(sym->GetSKind());
71     WriteNum(sym->GetStorageClass());
72     size_t mark = localSymMark.size();
73     localSymMark[sym] = mark;
74     OutputTypeAttrs(sym->GetAttrs());
75     WriteNum(static_cast<int64>(sym->GetIsTmp()));
76     if (sym->GetSKind() == kStVar || sym->GetSKind() == kStFunc) {
77         OutputSrcPos(sym->GetSrcPosition());
78     }
79     OutputType(sym->GetTyIdx());
80     if (sym->GetSKind() == kStPreg) {
81         OutputPreg(sym->GetPreg());
82     } else if (sym->GetSKind() == kStConst || sym->GetSKind() == kStVar) {
83         OutputConst(sym->GetKonst());
84     } else if (sym->GetSKind() == kStFunc) {
85         OutputFuncViaSym(sym->GetFunction()->GetPuidx());
86     } else {
87         CHECK_FATAL(false, "should not used");
88     }
89 }
90 
OutputPreg(MIRPreg * preg)91 void BinaryMplExport::OutputPreg(MIRPreg *preg)
92 {
93     if (preg->GetPregNo() < 0) {
94         WriteNum(kBinSpecialReg);
95         Write(static_cast<uint8>(-preg->GetPregNo()));
96         return;
97     }
98     std::unordered_map<const MIRPreg *, int64>::iterator it = localPregMark.find(preg);
99     if (it != localPregMark.end()) {
100         WriteNum(-(it->second));
101         return;
102     }
103 
104     WriteNum(kBinPreg);
105     Write(static_cast<uint8>(preg->GetPrimType()));
106     size_t mark = localPregMark.size();
107     localPregMark[preg] = mark;
108 }
109 
OutputLabel(LabelIdx lidx)110 void BinaryMplExport::OutputLabel(LabelIdx lidx)
111 {
112     std::unordered_map<LabelIdx, int64>::iterator it = labelMark.find(lidx);
113     if (it != labelMark.end()) {
114         WriteNum(-(it->second));
115         return;
116     }
117 
118     WriteNum(kBinLabel);
119     size_t mark = labelMark.size();
120     labelMark[lidx] = mark;
121 }
122 
OutputLocalTypeNameTab(const MIRTypeNameTable * typeNameTab)123 void BinaryMplExport::OutputLocalTypeNameTab(const MIRTypeNameTable *typeNameTab)
124 {
125     WriteNum(kBinTypenameStart);
126     WriteNum(static_cast<int64>(typeNameTab->Size()));
127     for (std::pair<GStrIdx, TyIdx> it : typeNameTab->GetGStrIdxToTyIdxMap()) {
128         OutputStr(it.first);
129         OutputType(it.second);
130     }
131 }
132 
OutputFormalsStIdx(MIRFunction * func)133 void BinaryMplExport::OutputFormalsStIdx(MIRFunction *func)
134 {
135     WriteNum(kBinFormalStart);
136     WriteNum(func->GetFormalDefVec().size());
137     for (FormalDef formalDef : func->GetFormalDefVec()) {
138         OutputLocalSymbol(formalDef.formalSym);
139     }
140 }
141 
OutputAliasMap(MapleMap<GStrIdx,MIRAliasVars> & aliasVarMap)142 void BinaryMplExport::OutputAliasMap(MapleMap<GStrIdx, MIRAliasVars> &aliasVarMap)
143 {
144     WriteNum(kBinAliasMapStart);
145     WriteInt(static_cast<int32>(aliasVarMap.size()));
146     for (std::pair<GStrIdx, MIRAliasVars> it : aliasVarMap) {
147         OutputStr(it.first);
148         OutputStr(it.second.mplStrIdx);
149         OutputType(it.second.tyIdx);
150         OutputStr(it.second.sigStrIdx);
151     }
152 }
153 
OutputFuncViaSym(PUIdx puIdx)154 void BinaryMplExport::OutputFuncViaSym(PUIdx puIdx)
155 {
156     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
157     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx());
158     OutputSymbol(funcSt);
159 }
160 
OutputExpression(BaseNode * e)161 void BinaryMplExport::OutputExpression(BaseNode *e)
162 {
163     OutputBaseNode(e);
164     switch (e->GetOpCode()) {
165         // leaf
166         case OP_constval: {
167             MIRConst *constVal = static_cast<ConstvalNode *>(e)->GetConstVal();
168             OutputConst(constVal);
169             return;
170         }
171         case OP_conststr: {
172             UStrIdx strIdx = static_cast<ConststrNode *>(e)->GetStrIdx();
173             OutputUsrStr(strIdx);
174             return;
175         }
176         case OP_addroflabel: {
177             AddroflabelNode *lNode = static_cast<AddroflabelNode *>(e);
178             OutputLabel(lNode->GetOffset());
179             return;
180         }
181         case OP_addroffunc: {
182             AddroffuncNode *addrNode = static_cast<AddroffuncNode *>(e);
183             OutputFuncViaSym(addrNode->GetPUIdx());
184             return;
185         }
186         case OP_sizeoftype: {
187             SizeoftypeNode *sot = static_cast<SizeoftypeNode *>(e);
188             OutputType(sot->GetTyIdx());
189             return;
190         }
191         case OP_addrof:
192         case OP_addrofoff:
193         case OP_dread:
194         case OP_dreadoff: {
195             StIdx stIdx;
196             if (e->GetOpCode() == OP_addrof || e->GetOpCode() == OP_dread) {
197                 AddrofNode *drNode = static_cast<AddrofNode *>(e);
198                 WriteNum(drNode->GetFieldID());
199                 stIdx = drNode->GetStIdx();
200             } else {
201                 DreadoffNode *droff = static_cast<DreadoffNode *>(e);
202                 WriteNum(droff->offset);
203                 stIdx = droff->stIdx;
204             }
205             WriteNum(stIdx.Scope());
206             if (stIdx.Islocal()) {
207                 OutputLocalSymbol(curFunc->GetLocalOrGlobalSymbol(stIdx));
208             } else {
209                 OutputSymbol(curFunc->GetLocalOrGlobalSymbol(stIdx));
210             }
211             return;
212         }
213         case OP_regread: {
214             RegreadNode *regreadNode = static_cast<RegreadNode *>(e);
215             MIRPreg *preg = curFunc->GetPregTab()->PregFromPregIdx(regreadNode->GetRegIdx());
216             OutputPreg(preg);
217             return;
218         }
219         case OP_gcmalloc:
220         case OP_gcpermalloc:
221         case OP_stackmalloc: {
222             GCMallocNode *gcNode = static_cast<GCMallocNode *>(e);
223             OutputType(gcNode->GetTyIdx());
224             return;
225         }
226         // unary
227         case OP_ceil:
228         case OP_cvt:
229         case OP_floor:
230         case OP_trunc: {
231             TypeCvtNode *typecvtNode = static_cast<TypeCvtNode *>(e);
232             Write(static_cast<uint8>(typecvtNode->FromType()));
233             break;
234         }
235         case OP_retype: {
236             RetypeNode *retypeNode = static_cast<RetypeNode *>(e);
237             OutputType(retypeNode->GetTyIdx());
238             break;
239         }
240         case OP_iread:
241         case OP_iaddrof: {
242             IreadNode *irNode = static_cast<IreadNode *>(e);
243             OutputType(irNode->GetTyIdx());
244             WriteNum(irNode->GetFieldID());
245             break;
246         }
247         case OP_ireadoff: {
248             IreadoffNode *irNode = static_cast<IreadoffNode *>(e);
249             WriteNum(irNode->GetOffset());
250             break;
251         }
252         case OP_ireadfpoff: {
253             IreadFPoffNode *irNode = static_cast<IreadFPoffNode *>(e);
254             WriteNum(irNode->GetOffset());
255             break;
256         }
257         case OP_sext:
258         case OP_zext:
259         case OP_extractbits: {
260             ExtractbitsNode *extNode = static_cast<ExtractbitsNode *>(e);
261             Write(extNode->GetBitsOffset());
262             Write(extNode->GetBitsSize());
263             break;
264         }
265         case OP_depositbits: {
266             DepositbitsNode *dbNode = static_cast<DepositbitsNode *>(e);
267             Write(dbNode->GetBitsOffset());
268             Write(dbNode->GetBitsSize());
269             break;
270         }
271         case OP_gcmallocjarray:
272         case OP_gcpermallocjarray: {
273             JarrayMallocNode *gcNode = static_cast<JarrayMallocNode *>(e);
274             OutputType(gcNode->GetTyIdx());
275             break;
276         }
277         // binary
278         case OP_sub:
279         case OP_mul:
280         case OP_div:
281         case OP_rem:
282         case OP_ashr:
283         case OP_lshr:
284         case OP_shl:
285         case OP_max:
286         case OP_min:
287         case OP_band:
288         case OP_bior:
289         case OP_bxor:
290         case OP_cand:
291         case OP_cior:
292         case OP_land:
293         case OP_lior:
294         case OP_add: {
295             break;
296         }
297         case OP_eq:
298         case OP_ne:
299         case OP_lt:
300         case OP_gt:
301         case OP_le:
302         case OP_ge:
303         case OP_cmpg:
304         case OP_cmpl:
305         case OP_cmp: {
306             CompareNode *cmpNode = static_cast<CompareNode *>(e);
307             Write(static_cast<uint8>(cmpNode->GetOpndType()));
308             break;
309         }
310         case OP_resolveinterfacefunc:
311         case OP_resolvevirtualfunc: {
312             ResolveFuncNode *rsNode = static_cast<ResolveFuncNode *>(e);
313             OutputFuncViaSym(rsNode->GetPuIdx());
314             break;
315         }
316         // ternary
317         case OP_select: {
318             break;
319         }
320         // nary
321         case OP_array: {
322             ArrayNode *arrNode = static_cast<ArrayNode *>(e);
323             OutputType(arrNode->GetTyIdx());
324             Write(static_cast<int8>(arrNode->GetBoundsCheck()));
325             WriteNum(static_cast<int64>(arrNode->NumOpnds()));
326             break;
327         }
328         case OP_intrinsicop: {
329             IntrinsicopNode *intrnNode = static_cast<IntrinsicopNode *>(e);
330             WriteNum(intrnNode->GetIntrinsic());
331             WriteNum(static_cast<int64>(intrnNode->NumOpnds()));
332             break;
333         }
334         case OP_intrinsicopwithtype: {
335             IntrinsicopNode *intrnNode = static_cast<IntrinsicopNode *>(e);
336             WriteNum(intrnNode->GetIntrinsic());
337             OutputType(intrnNode->GetTyIdx());
338             WriteNum(static_cast<int64>(intrnNode->NumOpnds()));
339             break;
340         }
341         default:
342             break;
343     }
344     for (uint32 i = 0; i < e->NumOpnds(); ++i) {
345         OutputExpression(e->Opnd(i));
346     }
347 }
348 
349 static SrcPosition lastOutputSrcPosition;
350 
OutputSrcPos(const SrcPosition & pos)351 void BinaryMplExport::OutputSrcPos(const SrcPosition &pos)
352 {
353     if (!mod.IsWithDbgInfo()) {
354         return;
355     }
356     if (pos.FileNum() == 0 || pos.LineNum() == 0) {  // error case, so output 0
357         WriteNum(lastOutputSrcPosition.RawData());
358         WriteNum(lastOutputSrcPosition.LineNum());
359         return;
360     }
361     WriteNum(pos.RawData());
362     WriteNum(pos.LineNum());
363     lastOutputSrcPosition = pos;
364 }
365 
OutputReturnValues(const CallReturnVector * retv)366 void BinaryMplExport::OutputReturnValues(const CallReturnVector *retv)
367 {
368     WriteNum(kBinReturnvals);
369     WriteNum(static_cast<int64>(retv->size()));
370     for (uint32 i = 0; i < retv->size(); i++) {
371         RegFieldPair rfp = (*retv)[i].second;
372         if (rfp.IsReg()) {
373             MIRPreg *preg = curFunc->GetPregTab()->PregFromPregIdx(rfp.GetPregIdx());
374             OutputPreg(preg);
375         } else {
376             WriteNum(0);
377             WriteNum((rfp.GetFieldID()));
378             OutputLocalSymbol(curFunc->GetLocalOrGlobalSymbol((*retv)[i].first));
379         }
380     }
381 }
382 
OutputBlockNode(BlockNode * block)383 void BinaryMplExport::OutputBlockNode(BlockNode *block)
384 {
385     WriteNum(kBinNodeBlock);
386     if (!block->GetStmtNodes().empty()) {
387         OutputSrcPos(block->GetSrcPos());
388     } else {
389         OutputSrcPos(SrcPosition());  // output 0
390     }
391     int32 num = 0;
392     uint64 idx = buf.size();
393     ExpandFourBuffSize();  // place holder, Fixup later
394     for (StmtNode *s = block->GetFirst(); s; s = s->GetNext()) {
395         bool doneWithOpnds = false;
396         OutputSrcPos(s->GetSrcPos());
397         WriteNum(s->GetOpCode());
398         switch (s->GetOpCode()) {
399             case OP_dassign:
400             case OP_dassignoff: {
401                 StIdx stIdx;
402                 if (s->GetOpCode() == OP_dassign) {
403                     DassignNode *dass = static_cast<DassignNode *>(s);
404                     WriteNum(dass->GetFieldID());
405                     stIdx = dass->GetStIdx();
406                 } else {
407                     DassignoffNode *dassoff = static_cast<DassignoffNode *>(s);
408                     WriteNum(dassoff->GetPrimType());
409                     WriteNum(dassoff->offset);
410                     stIdx = dassoff->stIdx;
411                 }
412                 WriteNum(stIdx.Scope());
413                 if (stIdx.Islocal()) {
414                     OutputLocalSymbol(curFunc->GetLocalOrGlobalSymbol(stIdx));
415                 } else {
416                     OutputSymbol(curFunc->GetLocalOrGlobalSymbol(stIdx));
417                 }
418                 break;
419             }
420             case OP_regassign: {
421                 RegassignNode *rass = static_cast<RegassignNode *>(s);
422                 Write(static_cast<uint8>(rass->GetPrimType()));
423                 MIRPreg *preg = curFunc->GetPregTab()->PregFromPregIdx(rass->GetRegIdx());
424                 OutputPreg(preg);
425                 break;
426             }
427             case OP_iassign: {
428                 IassignNode *iass = static_cast<IassignNode *>(s);
429                 OutputType(iass->GetTyIdx());
430                 WriteNum(iass->GetFieldID());
431                 break;
432             }
433             case OP_iassignoff: {
434                 IassignoffNode *iassoff = static_cast<IassignoffNode *>(s);
435                 Write(static_cast<uint8>(iassoff->GetPrimType()));
436                 WriteNum(iassoff->GetOffset());
437                 break;
438             }
439             case OP_iassignspoff:
440             case OP_iassignfpoff: {
441                 IassignFPoffNode *iassfpoff = static_cast<IassignFPoffNode *>(s);
442                 Write(static_cast<uint8>(iassfpoff->GetPrimType()));
443                 WriteNum(iassfpoff->GetOffset());
444                 break;
445             }
446             case OP_blkassignoff: {
447                 BlkassignoffNode *bass = static_cast<BlkassignoffNode *>(s);
448                 int32 offsetAlign = (bass->offset << 4) | bass->alignLog2;
449                 WriteNum(offsetAlign);
450                 WriteNum(bass->blockSize);
451                 break;
452             }
453             case OP_call:
454             case OP_virtualcall:
455             case OP_virtualicall:
456             case OP_superclasscall:
457             case OP_interfacecall:
458             case OP_interfaceicall:
459             case OP_customcall:
460             case OP_polymorphiccall: {
461                 CallNode *callnode = static_cast<CallNode *>(s);
462                 OutputFuncViaSym(callnode->GetPUIdx());
463                 if (s->GetOpCode() == OP_polymorphiccall) {
464                     OutputType(static_cast<CallNode *>(callnode)->GetTyIdx());
465                 }
466                 WriteNum(static_cast<int64>(s->NumOpnds()));
467                 break;
468             }
469             case OP_callassigned:
470             case OP_virtualcallassigned:
471             case OP_virtualicallassigned:
472             case OP_superclasscallassigned:
473             case OP_interfacecallassigned:
474             case OP_interfaceicallassigned:
475             case OP_customcallassigned: {
476                 CallNode *callnode = static_cast<CallNode *>(s);
477                 OutputFuncViaSym(callnode->GetPUIdx());
478                 OutputReturnValues(&callnode->GetReturnVec());
479                 WriteNum(static_cast<int64>(s->NumOpnds()));
480                 break;
481             }
482             case OP_polymorphiccallassigned: {
483                 CallNode *callnode = static_cast<CallNode *>(s);
484                 OutputFuncViaSym(callnode->GetPUIdx());
485                 OutputType(callnode->GetTyIdx());
486                 OutputReturnValues(&callnode->GetReturnVec());
487                 WriteNum(static_cast<int64>(s->NumOpnds()));
488                 break;
489             }
490             case OP_icallproto:
491             case OP_icall: {
492                 IcallNode *icallnode = static_cast<IcallNode *>(s);
493                 OutputType(icallnode->GetRetTyIdx());
494                 WriteNum(static_cast<int64>(s->NumOpnds()));
495                 break;
496             }
497             case OP_icallprotoassigned:
498             case OP_icallassigned: {
499                 IcallNode *icallnode = static_cast<IcallNode *>(s);
500                 OutputType(icallnode->GetRetTyIdx());
501                 OutputReturnValues(&icallnode->GetReturnVec());
502                 WriteNum(static_cast<int64>(s->NumOpnds()));
503                 break;
504             }
505             case OP_intrinsiccall:
506             case OP_xintrinsiccall: {
507                 IntrinsiccallNode *intrnNode = static_cast<IntrinsiccallNode *>(s);
508                 WriteNum(intrnNode->GetIntrinsic());
509                 WriteNum(static_cast<int64>(s->NumOpnds()));
510                 break;
511             }
512             case OP_intrinsiccallassigned:
513             case OP_xintrinsiccallassigned: {
514                 IntrinsiccallNode *intrnNode = static_cast<IntrinsiccallNode *>(s);
515                 WriteNum(intrnNode->GetIntrinsic());
516                 OutputReturnValues(&intrnNode->GetReturnVec());
517                 WriteNum(static_cast<int64>(s->NumOpnds()));
518                 break;
519             }
520             case OP_intrinsiccallwithtype: {
521                 IntrinsiccallNode *intrnNode = static_cast<IntrinsiccallNode *>(s);
522                 WriteNum(intrnNode->GetIntrinsic());
523                 OutputType(intrnNode->GetTyIdx());
524                 WriteNum(static_cast<int64>(s->NumOpnds()));
525                 break;
526             }
527             case OP_intrinsiccallwithtypeassigned: {
528                 IntrinsiccallNode *intrnNode = static_cast<IntrinsiccallNode *>(s);
529                 WriteNum(intrnNode->GetIntrinsic());
530                 OutputType(intrnNode->GetTyIdx());
531                 OutputReturnValues(&intrnNode->GetReturnVec());
532                 WriteNum(static_cast<int64>(s->NumOpnds()));
533                 break;
534             }
535             case OP_syncenter:
536             case OP_syncexit:
537             case OP_return: {
538                 WriteNum(static_cast<int64>(s->NumOpnds()));
539                 break;
540             }
541             case OP_jscatch:
542             case OP_cppcatch:
543             case OP_finally:
544             case OP_endtry:
545             case OP_cleanuptry:
546             case OP_retsub:
547             case OP_membaracquire:
548             case OP_membarrelease:
549             case OP_membarstorestore:
550             case OP_membarstoreload: {
551                 break;
552             }
553             case OP_eval:
554             case OP_throw:
555             case OP_free:
556             case OP_decref:
557             case OP_incref:
558             case OP_decrefreset:
559                 CASE_OP_ASSERT_NONNULL
560             case OP_igoto: {
561                 break;
562             }
563             case OP_label: {
564                 LabelNode *lNode = static_cast<LabelNode *>(s);
565                 OutputLabel(lNode->GetLabelIdx());
566                 break;
567             }
568             case OP_goto:
569             case OP_gosub: {
570                 GotoNode *gtoNode = static_cast<GotoNode *>(s);
571                 OutputLabel(gtoNode->GetOffset());
572                 break;
573             }
574             case OP_brfalse:
575             case OP_brtrue: {
576                 CondGotoNode *cgotoNode = static_cast<CondGotoNode *>(s);
577                 OutputLabel(cgotoNode->GetOffset());
578                 break;
579             }
580             case OP_switch: {
581                 SwitchNode *swNode = static_cast<SwitchNode *>(s);
582                 OutputLabel(swNode->GetDefaultLabel());
583                 WriteNum(static_cast<int64>(swNode->GetSwitchTable().size()));
584                 for (CasePair cpair : swNode->GetSwitchTable()) {
585                     WriteNum(cpair.first);
586                     OutputLabel(cpair.second);
587                 }
588                 break;
589             }
590             case OP_rangegoto: {
591                 RangeGotoNode *rgoto = static_cast<RangeGotoNode *>(s);
592                 WriteNum(rgoto->GetTagOffset());
593                 WriteNum(static_cast<int64>(rgoto->GetRangeGotoTable().size()));
594                 for (SmallCasePair cpair : rgoto->GetRangeGotoTable()) {
595                     WriteNum(cpair.first);
596                     OutputLabel(cpair.second);
597                 }
598                 break;
599             }
600             case OP_jstry: {
601                 JsTryNode *tryNode = static_cast<JsTryNode *>(s);
602                 OutputLabel(tryNode->GetCatchOffset());
603                 OutputLabel(tryNode->GetFinallyOffset());
604                 break;
605             }
606             case OP_cpptry:
607             case OP_try: {
608                 TryNode *tryNode = static_cast<TryNode *>(s);
609                 WriteNum(static_cast<int64>(tryNode->GetOffsetsCount()));
610                 for (LabelIdx lidx : tryNode->GetOffsets()) {
611                     OutputLabel(lidx);
612                 }
613                 break;
614             }
615             case OP_catch: {
616                 CatchNode *catchNode = static_cast<CatchNode *>(s);
617                 WriteNum(static_cast<int64>(catchNode->GetExceptionTyIdxVec().size()));
618                 for (TyIdx tidx : catchNode->GetExceptionTyIdxVec()) {
619                     OutputType(tidx);
620                 }
621                 break;
622             }
623             case OP_comment: {
624                 string str(static_cast<CommentNode *>(s)->GetComment().c_str());
625                 WriteAsciiStr(str);
626                 break;
627             }
628             case OP_dowhile:
629             case OP_while: {
630                 WhileStmtNode *whileNode = static_cast<WhileStmtNode *>(s);
631                 OutputBlockNode(whileNode->GetBody());
632                 OutputExpression(whileNode->Opnd());
633                 doneWithOpnds = true;
634                 break;
635             }
636             case OP_if: {
637                 IfStmtNode *ifNode = static_cast<IfStmtNode *>(s);
638                 bool hasElsePart = ifNode->GetElsePart() != nullptr;
639                 WriteNum(static_cast<int64>(hasElsePart));
640                 OutputBlockNode(ifNode->GetThenPart());
641                 if (hasElsePart) {
642                     OutputBlockNode(ifNode->GetElsePart());
643                 }
644                 OutputExpression(ifNode->Opnd());
645                 doneWithOpnds = true;
646                 break;
647             }
648             case OP_block: {
649                 BlockNode *blockNode = static_cast<BlockNode *>(s);
650                 OutputBlockNode(blockNode);
651                 doneWithOpnds = true;
652                 break;
653             }
654             case OP_asm: {
655                 AsmNode *asmNode = static_cast<AsmNode *>(s);
656                 WriteNum(asmNode->qualifiers);
657                 string str(asmNode->asmString.c_str());
658                 WriteAsciiStr(str);
659                 // the outputs
660                 size_t count = asmNode->asmOutputs.size();
661                 WriteNum(static_cast<int64>(count));
662                 for (size_t i = 0; i < count; ++i) {
663                     OutputUsrStr(asmNode->outputConstraints[i]);
664                 }
665                 OutputReturnValues(&asmNode->asmOutputs);
666                 // the clobber list
667                 count = asmNode->clobberList.size();
668                 WriteNum(static_cast<int64>(count));
669                 for (size_t i = 0; i < count; ++i) {
670                     OutputUsrStr(asmNode->clobberList[i]);
671                 }
672                 // the labels
673                 count = asmNode->gotoLabels.size();
674                 WriteNum(static_cast<int64>(count));
675                 for (size_t i = 0; i < count; ++i) {
676                     OutputLabel(asmNode->gotoLabels[i]);
677                 }
678                 // the inputs
679                 WriteNum(asmNode->NumOpnds());
680                 for (uint8 i = 0; i < asmNode->numOpnds; ++i) {
681                     OutputUsrStr(asmNode->inputConstraints[i]);
682                 }
683                 break;
684             }
685             default:
686                 CHECK_FATAL(false, "Unhandled opcode %d", s->GetOpCode());
687                 break;
688         }
689         num++;
690         if (!doneWithOpnds) {
691             for (uint32 i = 0; i < s->NumOpnds(); ++i) {
692                 OutputExpression(s->Opnd(i));
693             }
694         }
695     }
696     Fixup(idx, num);
697 }
698 
WriteFunctionBodyField(uint64 contentIdx,std::unordered_set<std::string> * dumpFuncSet)699 void BinaryMplExport::WriteFunctionBodyField(uint64 contentIdx, std::unordered_set<std::string> *dumpFuncSet)
700 {
701     Fixup(contentIdx, static_cast<int32>(buf.size()));
702     WriteNum(kBinFunctionBodyStart);
703     uint64 totalSizeIdx = buf.size();
704     ExpandFourBuffSize();  /// total size of this field to ~BIN_FUNCTIONBODY_START
705     uint64 outFunctionBodySizeIdx = buf.size();
706     ExpandFourBuffSize();  /// size of outFunctionBody
707     int32 size = 0;
708 
709     if (not2mplt) {
710         for (MIRFunction *func : GetMIRModule().GetFunctionList()) {
711             curFunc = func;
712             if (func->GetAttr(FUNCATTR_optimized)) {
713                 continue;
714             }
715             if (func->GetCodeMemPool() == nullptr || func->GetBody() == nullptr) {
716                 continue;
717             }
718             if (dumpFuncSet != nullptr && !dumpFuncSet->empty()) {
719                 // output only if this func matches any name in *dumpFuncSet
720                 const std::string &name = func->GetName();
721                 bool matched = false;
722                 for (std::string elem : *dumpFuncSet) {
723                     if (name.find(elem.c_str()) != string::npos) {
724                         matched = true;
725                         break;
726                     }
727                 }
728                 if (!matched) {
729                     continue;
730                 }
731             }
732             localSymMark.clear();
733             localSymMark[nullptr] = 0;
734             localPregMark.clear();
735             localPregMark[nullptr] = 0;
736             labelMark.clear();
737             labelMark[0] = 0;
738             OutputFunction(func->GetPuidx());
739             CHECK_FATAL(func->GetBody() != nullptr, "WriteFunctionBodyField: no function body");
740             OutputFuncIdInfo(func);
741             OutputLocalTypeNameTab(func->GetTypeNameTab());
742             OutputFormalsStIdx(func);
743             if (mod.GetFlavor() < kMmpl) {
744                 OutputAliasMap(func->GetAliasVarMap());
745             }
746             lastOutputSrcPosition = SrcPosition();
747             OutputBlockNode(func->GetBody());
748             size++;
749         }
750     }
751 
752     Fixup(totalSizeIdx, static_cast<int32>(buf.size() - totalSizeIdx));
753     Fixup(outFunctionBodySizeIdx, size);
754     return;
755 }
756 }  // namespace maple
757