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 #ifndef MAPLEIPA_INCLUDE_ESCAPEANALYSIS_H
17 #define MAPLEIPA_INCLUDE_ESCAPEANALYSIS_H
18 #include <fstream>
19 #include <iostream>
20 #include <stdlib.h>
21 #include "call_graph.h"
22 #include "me_ir.h"
23 #include "irmap.h"
24
25 namespace maple {
26 enum NodeKind { kObejectNode, kReferenceNode, kActualNode, kFieldNode, kPointerNode };
27
28 enum EAStatus { kNoEscape, kReturnEscape, kArgumentEscape, kGlobalEscape };
29
EscapeName(EAStatus esc)30 const inline std::string EscapeName(EAStatus esc)
31 {
32 switch (esc) {
33 case kNoEscape:
34 return "NoEsc";
35 case kReturnEscape:
36 return "RetEsc";
37 case kArgumentEscape:
38 return "ArgEsc";
39 case kGlobalEscape:
40 return "GlobalEsc";
41 default:
42 return "";
43 }
44 }
45
46 class Location {
47 public:
Location(const std::string & modName,uint32 fileId,uint32 lineId)48 Location(const std::string &modName, uint32 fileId, uint32 lineId)
49 : modName(modName), fileId(fileId), lineId(lineId) {};
50 ~Location() = default;
51
GetModName()52 const std::string &GetModName() const
53 {
54 return modName;
55 }
56
GetFileId()57 uint32 GetFileId() const
58 {
59 return fileId;
60 }
61
GetLineId()62 uint32 GetLineId() const
63 {
64 return lineId;
65 }
66
67 private:
68 std::string modName;
69 uint32 fileId;
70 uint32 lineId;
71 };
72
73 class EACGBaseNode;
74 class EACGObjectNode;
75 class EACGFieldNode;
76 class EACGRefNode;
77 class EACGActualNode;
78 class EACGPointerNode;
79
80 class EAConnectionGraph {
81 public:
82 friend class BinaryMplExport;
83 friend class BinaryMplImport;
84 friend class EACGBaseNode;
85 friend class EACGObjectNode;
86 friend class EACGFieldNode;
87 friend class EACGRefNode;
88 friend class EACGPointerNode;
89 // If import is false, need init globalNode.
90 EAConnectionGraph(MIRModule *m, MapleAllocator *allocator, const GStrIdx &funcName, bool import = false)
mirModule(m)91 : mirModule(m),
92 alloc(allocator),
93 nodes(allocator->Adapter()),
94 expr2Nodes(allocator->Adapter()),
95 funcArgNodes(allocator->Adapter()),
96 callSite2Nodes(allocator->Adapter()),
97 funcStIdx(funcName),
98 hasUpdated(false),
99 needConv(false),
100 imported(import),
101 exprIdMax(0),
102 globalObj(nullptr),
103 globalRef(nullptr),
104 globalField(nullptr) {};
105 ~EAConnectionGraph() = default;
106
107 EACGObjectNode *CreateObjectNode(MeExpr *expr, EAStatus initialEas, bool isPh, TyIdx tyIdx);
108 EACGRefNode *CreateReferenceNode(MeExpr *expr, EAStatus initialEas, bool isStatic);
109 EACGActualNode *CreateActualNode(EAStatus initialEas, bool isReurtn, bool isPh, uint8 argIdx, uint32 callSiteInfo);
110 EACGFieldNode *CreateFieldNode(MeExpr *expr, EAStatus initialEas, FieldID fId, EACGObjectNode *belongTo, bool isPh);
111 EACGPointerNode *CreatePointerNode(MeExpr *expr, EAStatus initialEas, int inderictL);
112 EACGBaseNode *GetCGNodeFromExpr(MeExpr *me);
113 EACGFieldNode *GetOrCreateFieldNodeFromIdx(EACGObjectNode &obj, int32 fieldID);
114 EACGActualNode *GetReturnNode() const;
115 const MapleVector<EACGBaseNode *> *GetFuncArgNodeVector() const;
116 void TouchCallSite(uint32 callSiteInfo);
117 MapleVector<EACGBaseNode *> *GetCallSiteArgNodeVector(uint32 callSite);
118 bool ExprCanBeOptimized(MeExpr &expr);
119
CGHasUpdated()120 bool CGHasUpdated() const
121 {
122 return hasUpdated;
123 }
124
UnSetCGUpdateFlag()125 void UnSetCGUpdateFlag()
126 {
127 hasUpdated = false;
128 }
129
SetCGHasUpdated()130 void SetCGHasUpdated()
131 {
132 hasUpdated = true;
133 }
134
SetExprIdMax(int max)135 void SetExprIdMax(int max)
136 {
137 exprIdMax = max;
138 }
139
SetNeedConservation()140 void SetNeedConservation()
141 {
142 needConv = true;
143 }
144
GetNeedConservation()145 bool GetNeedConservation() const
146 {
147 return needConv;
148 }
149
GetFuncNameStrIdx()150 GStrIdx GetFuncNameStrIdx() const
151 {
152 return funcStIdx;
153 }
154
GetGlobalObject()155 EACGObjectNode *GetGlobalObject()
156 {
157 return globalObj;
158 }
159
GetGlobalObject()160 const EACGObjectNode *GetGlobalObject() const
161 {
162 return globalObj;
163 }
164
GetGlobalReference()165 EACGRefNode *GetGlobalReference()
166 {
167 return globalRef;
168 }
169
GetGlobalReference()170 const EACGRefNode *GetGlobalReference() const
171 {
172 return globalRef;
173 }
174
GetNodes()175 const MapleVector<EACGBaseNode *> &GetNodes() const
176 {
177 return nodes;
178 }
179
ResizeNodes(size_t size,EACGBaseNode * val)180 void ResizeNodes(size_t size, EACGBaseNode *val)
181 {
182 nodes.resize(size, val);
183 }
184
GetNode(uint32 idx)185 EACGBaseNode *GetNode(uint32 idx) const
186 {
187 CHECK_FATAL(idx < nodes.size(), "array check fail");
188 return nodes[idx];
189 }
190
SetNodeAt(size_t index,EACGBaseNode * val)191 void SetNodeAt(size_t index, EACGBaseNode *val)
192 {
193 nodes[index] = val;
194 }
195
GetFuncArgNodes()196 const MapleVector<EACGBaseNode *> &GetFuncArgNodes() const
197 {
198 return funcArgNodes;
199 }
200
GetCallSite2Nodes()201 const MapleMap<uint32, MapleVector<EACGBaseNode *> *> &GetCallSite2Nodes() const
202 {
203 return callSite2Nodes;
204 }
205
206 void InitGlobalNode();
207 void AddMaps2Object(EACGObjectNode *caller, EACGObjectNode *callee);
208 void UpdateExprOfNode(EACGBaseNode &node, MeExpr *me);
209 void UpdateExprOfGlobalRef(MeExpr *me);
210 void PropogateEAStatus();
211 bool MergeCG(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> *callee);
212 void TrimGlobalNode() const;
213 void UpdateEACGFromCaller(const MapleVector<EACGBaseNode *> &callerCallSiteArg,
214 const MapleVector<EACGBaseNode *> &calleeFuncArg);
215 void DumpDotFile(const IRMap *irMap, bool dumpPt, MapleVector<EACGBaseNode *> *dumpVec = nullptr);
216 void DeleteEACG() const;
217 void RestoreStatus(bool old);
218 void CountObjEAStatus() const;
219
GetFunctionName()220 const std::string &GetFunctionName() const
221 {
222 return GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx);
223 }
224
225 private:
226 MIRModule *mirModule;
227 MapleAllocator *alloc;
228 MapleVector<EACGBaseNode *> nodes;
229 MapleMap<MeExpr *, MapleSet<EACGBaseNode *> *> expr2Nodes;
230 // this vector contain func arg nodes first in declaration order and the last is return node
231 MapleVector<EACGBaseNode *> funcArgNodes;
232 MapleMap<uint32, MapleVector<EACGBaseNode *> *> callSite2Nodes;
233 GStrIdx funcStIdx;
234 bool hasUpdated;
235 bool needConv;
236 bool imported;
237 int exprIdMax;
238 EACGObjectNode *globalObj;
239 EACGRefNode *globalRef;
240 EACGFieldNode *globalField;
241 // this is used as a tmp varible for merge cg
242 std::map<EACGObjectNode *, std::set<EACGObjectNode *>> callee2Caller;
243 void CheckArgNodeOrder(MapleVector<EACGBaseNode *> &funcArgV);
244 void UpdateCallerNodes(const MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> &callee);
245 void UpdateCallerRetNode(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> &callee);
246 void UpdateCallerEdges();
247 void UpdateCallerEdgesInternal(EACGObjectNode *node1, int32 fieldID, EACGObjectNode *node2);
248 void UpdateNodes(const EACGBaseNode &actualInCallee, EACGBaseNode &actualInCaller, bool firstTime);
249 void UpdateCallerWithCallee(EACGObjectNode &objInCaller, const EACGObjectNode &objInCallee, bool firstTime);
250
SetCGUpdateFlag()251 void SetCGUpdateFlag()
252 {
253 hasUpdated = true;
254 }
255 };
256
257 class EACGBaseNode {
258 public:
259 friend class BinaryMplExport;
260 friend class BinaryMplImport;
261 friend class EACGObjectNode;
262 friend class EACGFieldNode;
263 friend class EACGActualNode;
264 friend class EACGRefNode;
265 friend class EACGPointerNode;
266 friend class EAConnectionGraph;
267
EACGBaseNode(MIRModule * m,MapleAllocator * a,NodeKind nk,EAConnectionGraph * ec)268 EACGBaseNode(MIRModule *m, MapleAllocator *a, NodeKind nk, EAConnectionGraph *ec)
269 : locInfo(nullptr), mirModule(m), alloc(a), kind(nk), meExpr(nullptr), eaStatus(kNoEscape), id(0), eaCG(ec)
270 {
271 }
272
EACGBaseNode(MIRModule * m,MapleAllocator * a,NodeKind nk,EAConnectionGraph & ec,MeExpr * expr,EAStatus initialEas,int i)273 EACGBaseNode(MIRModule *m, MapleAllocator *a, NodeKind nk, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas,
274 int i)
275 : locInfo(nullptr), mirModule(m), alloc(a), kind(nk), meExpr(expr), eaStatus(initialEas), id(i), eaCG(&ec)
276 {
277 ec.SetCGUpdateFlag();
278 }
279
280 virtual ~EACGBaseNode() = default;
281
IsFieldNode()282 virtual bool IsFieldNode() const
283 {
284 return kind == kFieldNode;
285 }
286
IsObjectNode()287 virtual bool IsObjectNode() const
288 {
289 return kind == kObejectNode;
290 }
291
IsReferenceNode()292 virtual bool IsReferenceNode() const
293 {
294 return kind == kReferenceNode;
295 }
296
IsActualNode()297 virtual bool IsActualNode() const
298 {
299 return kind == kActualNode;
300 }
301
IsPointerNode()302 virtual bool IsPointerNode() const
303 {
304 return kind == kPointerNode;
305 }
306
GetMeExpr()307 virtual const MeExpr *GetMeExpr() const
308 {
309 return meExpr;
310 }
311
SetMeExpr(MeExpr & newExpr)312 virtual void SetMeExpr(MeExpr &newExpr)
313 {
314 if (IsFieldNode() && newExpr.GetMeOp() != kMeOpIvar && newExpr.GetMeOp() != kMeOpOp) {
315 CHECK_FATAL(false, "must be kMeOpIvar or kMeOpOp");
316 } else if (IsReferenceNode() == true && newExpr.GetMeOp() != kMeOpVar && newExpr.GetMeOp() != kMeOpReg &&
317 newExpr.GetMeOp() != kMeOpAddrof && newExpr.GetMeOp() != kMeOpConststr) {
318 CHECK_FATAL(false, "must be kMeOpVar, kMeOpReg, kMeOpAddrof or kMeOpConststr");
319 }
320 meExpr = &newExpr;
321 }
322
GetPointsToSet()323 const std::set<EACGObjectNode *> &GetPointsToSet() const
324 {
325 CHECK_FATAL(!IsPointerNode(), "must be pointer node");
326 return pointsTo;
327 };
328
329 virtual bool AddOutNode(EACGBaseNode &newOut);
330
GetEAStatus()331 virtual EAStatus GetEAStatus() const
332 {
333 return eaStatus;
334 }
335
GetInSet()336 virtual const std::set<EACGBaseNode *> &GetInSet() const
337 {
338 return in;
339 }
340
InsertInSet(EACGBaseNode * val)341 virtual void InsertInSet(EACGBaseNode *val)
342 {
343 (void)in.insert(val);
344 }
345
GetOutSet()346 virtual const std::set<EACGBaseNode *> &GetOutSet() const
347 {
348 CHECK_FATAL(IsActualNode(), "must be actual node");
349 return out;
350 }
351
InsertOutSet(EACGBaseNode * val)352 virtual void InsertOutSet(EACGBaseNode *val)
353 {
354 (void)out.insert(val);
355 }
356
UpdateEAStatus(EAStatus newEas)357 virtual bool UpdateEAStatus(EAStatus newEas)
358 {
359 if (newEas > eaStatus) {
360 eaStatus = newEas;
361 PropagateEAStatusForNode(this);
362 eaCG->SetCGUpdateFlag();
363 return true;
364 }
365 return false;
366 }
367
IsBelongTo(const EAConnectionGraph * cg)368 bool IsBelongTo(const EAConnectionGraph *cg) const
369 {
370 return this->eaCG == cg;
371 }
372
GetEACG()373 const EAConnectionGraph *GetEACG() const
374 {
375 return eaCG;
376 }
377
GetEACG()378 EAConnectionGraph *GetEACG()
379 {
380 return eaCG;
381 }
382
SetEACG(EAConnectionGraph * cg)383 void SetEACG(EAConnectionGraph *cg)
384 {
385 this->eaCG = cg;
386 }
387
SetID(int setId)388 void SetID(int setId)
389 {
390 this->id = static_cast<size_t>(setId);
391 }
392
393 bool CanIgnoreRC() const;
394
395 protected:
396 Location *locInfo;
397 MIRModule *mirModule;
398 MapleAllocator *alloc;
399 NodeKind kind;
400 MeExpr *meExpr;
401 EAStatus eaStatus;
402 size_t id;
403 // OBJ<->Field will not in following Set
404 std::set<EACGBaseNode *> in;
405 std::set<EACGBaseNode *> out;
406 std::set<EACGObjectNode *> pointsTo;
407 EAConnectionGraph *eaCG;
408
409 virtual void CheckAllConnectionInNodes();
410 virtual std::string GetName(const IRMap *irMap) const;
411 virtual void DumpDotFile(std::ostream &, std::map<EACGBaseNode *, bool> &, bool, const IRMap *irMap = nullptr) = 0;
412 virtual void PropagateEAStatusForNode(const EACGBaseNode *subRoot) const;
413 virtual void GetNodeFormatInDot(std::string &label, std::string &color) const;
414 virtual bool UpdatePointsTo(const std::set<EACGObjectNode *> &cPointsTo);
415
SetEAStatus(EAStatus status)416 virtual void SetEAStatus(EAStatus status)
417 {
418 this->eaStatus = status;
419 }
420
GetNodeKind()421 virtual NodeKind GetNodeKind() const
422 {
423 return kind;
424 }
425
426 private:
ReplaceByGlobalNode()427 virtual bool ReplaceByGlobalNode()
428 {
429 CHECK_FATAL(false, "impossible");
430 return false;
431 }
432 };
433
434 class EACGPointerNode : public EACGBaseNode {
435 public:
436 friend class BinaryMplExport;
437 friend class BinaryMplImport;
EACGPointerNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph * ec)438 EACGPointerNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph *ec)
439 : EACGBaseNode(md, alloc, kPointerNode, ec), indirectLevel(0)
440 {
441 }
442
EACGPointerNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph & ec,MeExpr * expr,EAStatus initialEas,int i,int indirectL)443 EACGPointerNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas,
444 int i, int indirectL)
445 : EACGBaseNode(md, alloc, kPointerNode, ec, expr, initialEas, i), indirectLevel(indirectL) {};
446 ~EACGPointerNode() = default;
447
SetLocation(Location * loc)448 void SetLocation(Location *loc)
449 {
450 this->locInfo = loc;
451 }
452
GetIndirectLevel()453 int GetIndirectLevel() const
454 {
455 return indirectLevel;
456 }
457
AddOutNode(EACGBaseNode & newOut)458 bool AddOutNode(EACGBaseNode &newOut) override
459 {
460 if (indirectLevel == 1) {
461 CHECK_FATAL(!newOut.IsPointerNode(), "must be pointer node");
462 (void)pointingTo.insert(&newOut);
463 (void)out.insert(&newOut);
464 (void)newOut.in.insert(this);
465 } else {
466 pointingTo.insert(&newOut);
467 CHECK_FATAL(pointingTo.size() == 1, "the size must be one");
468 CHECK_FATAL(newOut.IsPointerNode(), "must be pointer node");
469 CHECK_FATAL((indirectLevel - static_cast<EACGPointerNode &>(newOut).GetIndirectLevel()) == 1,
470 "must be one");
471 (void)out.insert(&newOut);
472 (void)newOut.in.insert(this);
473 }
474 return false;
475 }
476
GetPointingTo()477 const std::set<EACGBaseNode *> &GetPointingTo() const
478 {
479 return pointingTo;
480 }
481
UpdatePointsTo(const std::set<EACGObjectNode * > &)482 bool UpdatePointsTo(const std::set<EACGObjectNode *> &) override
483 {
484 CHECK_FATAL(false, "impossible to update PointsTo");
485 return true;
486 };
487
PropagateEAStatusForNode(const EACGBaseNode *)488 void PropagateEAStatusForNode(const EACGBaseNode *) const override
489 {
490 CHECK_FATAL(false, "impossible to propagate EA status for node");
491 }
492
493 void DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
494 const IRMap *irMap = nullptr) override;
CheckAllConnectionInNodes()495 void CheckAllConnectionInNodes() override {}
496
497 private:
498 int indirectLevel;
499 std::set<EACGBaseNode *> pointingTo;
ReplaceByGlobalNode()500 bool ReplaceByGlobalNode() override
501 {
502 CHECK_FATAL(false, "impossible to replace by global node");
503 return true;
504 }
505 };
506
507 class EACGObjectNode : public EACGBaseNode {
508 public:
509 friend class EACGFieldNode;
510 friend class BinaryMplExport;
511 friend class BinaryMplImport;
EACGObjectNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph * ec)512 EACGObjectNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph *ec)
513 : EACGBaseNode(md, alloc, kObejectNode, ec), rcOperations(0), ignorRC(false), isPhantom(false)
514 {
515 }
516
EACGObjectNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph & ec,MeExpr * expr,EAStatus initialEas,int i,bool isPh)517 EACGObjectNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas,
518 int i, bool isPh)
519 : EACGBaseNode(md, alloc, kObejectNode, ec, expr, initialEas, i),
520 rcOperations(0),
521 ignorRC(false),
522 isPhantom(isPh)
523 {
524 (void)pointsBy.insert(this);
525 (void)pointsTo.insert(this);
526 };
527 ~EACGObjectNode() = default;
IsPhantom()528 bool IsPhantom() const
529 {
530 return isPhantom == true;
531 };
532
SetLocation(Location * loc)533 void SetLocation(Location *loc)
534 {
535 this->locInfo = loc;
536 }
537
GetFieldNodeMap()538 const std::map<FieldID, EACGFieldNode *> &GetFieldNodeMap() const
539 {
540 return fieldNodes;
541 }
542
GetFieldNodeFromIdx(FieldID fId)543 EACGFieldNode *GetFieldNodeFromIdx(FieldID fId)
544 {
545 if (fieldNodes.find(-1) != fieldNodes.end()) { // -1 expresses global
546 return fieldNodes[-1];
547 }
548 if (fieldNodes.find(fId) == fieldNodes.end()) {
549 return nullptr;
550 }
551 return fieldNodes[fId];
552 }
553
554 bool AddOutNode(EACGBaseNode &newOut) override;
UpdatePointsTo(const std::set<EACGObjectNode * > &)555 bool UpdatePointsTo(const std::set<EACGObjectNode *> &) override
556 {
557 CHECK_FATAL(false, "impossible");
558 return true;
559 };
560
561 bool IsPointedByFieldNode() const;
562 void PropagateEAStatusForNode(const EACGBaseNode *subRoot) const override;
563 void DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
564 const IRMap *irMap = nullptr) override;
565 void CheckAllConnectionInNodes() override;
566
Insert2PointsBy(EACGBaseNode * node)567 void Insert2PointsBy(EACGBaseNode *node)
568 {
569 (void)pointsBy.insert(node);
570 }
571
EraseNodeFromPointsBy(EACGBaseNode * node)572 void EraseNodeFromPointsBy(EACGBaseNode *node)
573 {
574 pointsBy.erase(node);
575 }
576
IncresRCOperations()577 void IncresRCOperations()
578 {
579 ++rcOperations;
580 }
581
IncresRCOperations(int num)582 void IncresRCOperations(int num)
583 {
584 rcOperations += num;
585 }
586
GetRCOperations()587 int GetRCOperations() const
588 {
589 return rcOperations;
590 }
591
GetIgnorRC()592 bool GetIgnorRC() const
593 {
594 return ignorRC;
595 }
596
SetIgnorRC(bool ignore)597 void SetIgnorRC(bool ignore)
598 {
599 ignorRC = ignore;
600 }
601
602 private:
603 std::set<EACGBaseNode *> pointsBy;
604 int rcOperations;
605 bool ignorRC;
606 bool isPhantom;
607 std::map<FieldID, EACGFieldNode *> fieldNodes;
608 bool ReplaceByGlobalNode() override;
609 };
610
611 class EACGRefNode : public EACGBaseNode {
612 public:
613 friend class BinaryMplExport;
614 friend class BinaryMplImport;
EACGRefNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph * ec)615 EACGRefNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph *ec)
616 : EACGBaseNode(md, alloc, kReferenceNode, ec), isStaticField(false), sym(nullptr), version(0)
617 {
618 }
619
620 EACGRefNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas, int i,
621 bool isS = false)
EACGBaseNode(md,alloc,kReferenceNode,ec,expr,initialEas,i)622 : EACGBaseNode(md, alloc, kReferenceNode, ec, expr, initialEas, i),
623 isStaticField(isS),
624 sym(nullptr),
625 version(0) {};
626 ~EACGRefNode() = default;
IsStaticRef()627 bool IsStaticRef() const
628 {
629 return isStaticField;
630 };
SetSymbolAndVersion(MIRSymbol * mirSym,int versionIdx)631 void SetSymbolAndVersion(MIRSymbol *mirSym, int versionIdx)
632 {
633 if (sym != nullptr) {
634 CHECK_FATAL(sym == mirSym, "must be sym");
635 CHECK_FATAL(versionIdx == version, "must be version ");
636 }
637 sym = mirSym;
638 version = versionIdx;
639 };
640
641 void DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
642 const IRMap *irMap = nullptr);
643
644 private:
645 bool isStaticField;
646 MIRSymbol *sym;
647 int version;
648 bool ReplaceByGlobalNode();
649 };
650 class EACGFieldNode : public EACGBaseNode {
651 public:
652 friend class BinaryMplExport;
653 friend class BinaryMplImport;
654 friend class EACGObjectNode;
EACGFieldNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph * ec)655 EACGFieldNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph *ec)
656 : EACGBaseNode(md, alloc, kFieldNode, ec), fieldID(0), isPhantom(false), sym(nullptr), version(0), mirFieldId(0)
657 {
658 }
659
EACGFieldNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph & ec,MeExpr * expr,EAStatus initialEas,int i,FieldID fId,EACGObjectNode * bt,bool isPh)660 EACGFieldNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas, int i,
661 FieldID fId, EACGObjectNode *bt, bool isPh)
662 : EACGBaseNode(md, alloc, kFieldNode, ec, expr, initialEas, i),
663 fieldID(fId),
664 isPhantom(isPh),
665 sym(nullptr),
666 version(0),
667 mirFieldId(0)
668 {
669 bt->fieldNodes[fieldID] = this;
670 (void)belongsTo.insert(bt);
671 };
672
673 ~EACGFieldNode() = default;
674
GetFieldID()675 FieldID GetFieldID() const
676 {
677 return fieldID;
678 };
679
SetFieldID(FieldID id)680 void SetFieldID(FieldID id)
681 {
682 fieldID = id;
683 }
684
IsPhantom()685 bool IsPhantom() const
686 {
687 return isPhantom;
688 }
689
GetBelongsToObj()690 const std::set<EACGObjectNode *> &GetBelongsToObj() const
691 {
692 return belongsTo;
693 }
694
AddBelongTo(EACGObjectNode * newObj)695 void AddBelongTo(EACGObjectNode *newObj)
696 {
697 (void)belongsTo.insert(newObj);
698 }
699
SetSymbolAndVersion(MIRSymbol * mirSym,int versionIdx,FieldID fID)700 void SetSymbolAndVersion(MIRSymbol *mirSym, int versionIdx, FieldID fID)
701 {
702 if (sym != nullptr) {
703 CHECK_FATAL(sym == mirSym, "must be mirSym");
704 CHECK_FATAL(version == versionIdx, "must be version");
705 CHECK_FATAL(mirFieldId == fID, "must be mir FieldId");
706 }
707 sym = mirSym;
708 version = versionIdx;
709 mirFieldId = fID;
710 };
711
712 void DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
713 const IRMap *irMap = nullptr);
714
715 private:
716 FieldID fieldID;
717 std::set<EACGObjectNode *> belongsTo;
718 bool isPhantom;
719 MIRSymbol *sym;
720 int version;
721 FieldID mirFieldId;
722 bool ReplaceByGlobalNode();
723 };
724
725 class EACGActualNode : public EACGBaseNode {
726 public:
727 friend class BinaryMplExport;
728 friend class BinaryMplImport;
EACGActualNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph * ec)729 EACGActualNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph *ec)
730 : EACGBaseNode(md, alloc, kActualNode, ec), isReturn(false), isPhantom(false), argIdx(0), callSiteInfo(0) {};
EACGActualNode(MIRModule * md,MapleAllocator * alloc,EAConnectionGraph & ec,MeExpr * expr,EAStatus initialEas,int i,bool isR,bool isPh,uint8 aI,uint32 callSite)731 EACGActualNode(MIRModule *md, MapleAllocator *alloc, EAConnectionGraph &ec, MeExpr *expr, EAStatus initialEas,
732 int i, bool isR, bool isPh, uint8 aI, uint32 callSite)
733 : EACGBaseNode(md, alloc, kActualNode, ec, expr, initialEas, i),
734 isReturn(isR),
735 isPhantom(isPh),
736 argIdx(aI),
737 callSiteInfo(callSite) {};
738 ~EACGActualNode() = default;
739
IsReturn()740 bool IsReturn() const
741 {
742 return isReturn;
743 };
744
IsPhantom()745 bool IsPhantom() const
746 {
747 return isPhantom;
748 };
749
GetArgIndex()750 uint32 GetArgIndex() const
751 {
752 return argIdx;
753 };
754
GetCallSite()755 uint32 GetCallSite() const
756 {
757 return callSiteInfo;
758 }
759
760 void DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
761 const IRMap *irMap = nullptr);
762
763 private:
764 bool isReturn;
765 bool isPhantom;
766 uint8 argIdx;
767 uint32 callSiteInfo;
768 bool ReplaceByGlobalNode();
769 };
770 } // namespace maple
771 #endif
772