• 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_nodes.h"
17 
18 #include <algorithm>
19 #include <stack>
20 
21 #include "maple_string.h"
22 #include "mir_function.h"
23 #include "namemangler.h"
24 #include "opcode_info.h"
25 #include "printing.h"
26 #include "utils.h"
27 #include "verification.h"
28 
29 namespace maple {
30 MIRModule *theMIRModule = nullptr;
31 std::atomic<uint32> StmtNode::stmtIDNext(1);  // 0 is reserved
32 uint32 StmtNode::lastPrintedLineNum = 0;
33 uint16 StmtNode::lastPrintedColumnNum = 0;
34 const int32 CondGotoNode::probAll = 10000;
35 
GetIntrinsicName(MIRIntrinsicID intrn)36 const char *GetIntrinsicName(MIRIntrinsicID intrn)
37 {
38     switch (intrn) {
39         default:
40 #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) \
41     case INTRN_##STR:                                               \
42         return #STR;
43 #include "intrinsics.def"
44 #undef DEF_MIR_INTRINSIC
45     }
46 }
47 
GetOpName() const48 const char *BaseNode::GetOpName() const
49 {
50     return kOpcodeInfo.GetTableItemAt(GetOpCode()).name.c_str();
51 }
52 
MayThrowException()53 bool BaseNode::MayThrowException()
54 {
55     if (kOpcodeInfo.MayThrowException(GetOpCode())) {
56         if (GetOpCode() != OP_array) {
57             return true;
58         }
59         auto *arry = static_cast<ArrayNode *>(this);
60         if (arry->GetBoundsCheck()) {
61             return true;
62         }
63     }
64     for (size_t i = 0; i < NumOpnds(); ++i) {
65         if (Opnd(i)->MayThrowException()) {
66             return true;
67         }
68     }
69     return false;
70 }
71 
CheckNode(const MIRModule & mod) const72 bool AddrofNode::CheckNode(const MIRModule &mod) const
73 {
74     const MIRSymbol *st = mod.CurFunction()->GetLocalOrGlobalSymbol(GetStIdx());
75     DEBUG_ASSERT(st != nullptr, "null ptr check");
76     MIRType *ty = st->GetType();
77     switch (ty->GetKind()) {
78         case kTypeScalar: {
79 #ifdef DYNAMICLANG
80             if (GetPrimType() == PTY_dynany) {
81                 return true;
82             }
83             return IsPrimitiveScalar(GetPrimType());
84 #else
85             return IsPrimitiveScalar(GetPrimType());
86 #endif
87         }
88         case kTypeArray: {
89             return GetPrimType() == PTY_agg;
90         }
91         case kTypeUnion:
92         case kTypeStruct:
93         case kTypeStructIncomplete: {
94             if (GetFieldID() == 0) {
95                 return GetPrimType() == PTY_agg;
96             }
97             auto *structType = static_cast<MIRStructType *>(ty);
98             TyIdx fTyIdx = structType->GetFieldTyIdx(fieldID);
99             MIRType *subType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fTyIdx);
100             MIRTypeKind subKind = subType->GetKind();
101             return (subKind == kTypeBitField && VerifyPrimType(subType->GetPrimType(), GetPrimType())) ||
102                    (subKind == kTypeScalar && IsPrimitiveScalar(GetPrimType())) ||
103                    (subKind == kTypePointer && IsPrimitivePoint(GetPrimType())) ||
104                    (subKind == kTypeStruct && GetPrimType() == PTY_agg) || (fTyIdx != 0u && GetPrimType() == PTY_agg);
105         }
106         case kTypeClass:
107         case kTypeClassIncomplete: {
108             if (fieldID == 0) {
109                 return GetPrimType() == PTY_agg;
110             }
111             auto *classType = static_cast<MIRClassType *>(ty);
112             MIRType *subType = classType->GetFieldType(fieldID);
113             MIRTypeKind subKind = subType->GetKind();
114             return (subKind == kTypeBitField && VerifyPrimType(subType->GetPrimType(), GetPrimType())) ||
115                    (subKind == kTypeScalar && IsPrimitiveScalar(GetPrimType())) ||
116                    (subKind == kTypePointer && IsPrimitivePoint(GetPrimType())) ||
117                    (subKind == kTypeStruct && GetPrimType() == PTY_agg);
118         }
119         case kTypeInterface:
120         case kTypeInterfaceIncomplete: {
121             if (fieldID == 0) {
122                 return GetPrimType() == PTY_agg;
123             }
124             auto *interfaceType = static_cast<MIRInterfaceType *>(ty);
125             MIRType *subType = interfaceType->GetFieldType(fieldID);
126             MIRTypeKind subKind = subType->GetKind();
127             return (subKind == kTypeBitField && VerifyPrimType(subType->GetPrimType(), GetPrimType())) ||
128                    (subKind == kTypeScalar && IsPrimitiveScalar(GetPrimType())) ||
129                    (subKind == kTypePointer && IsPrimitivePoint(GetPrimType())) ||
130                    (subKind == kTypeStruct && GetPrimType() == PTY_agg);
131         }
132         case kTypePointer:
133             return IsPrimitivePoint(GetPrimType());
134         case kTypeParam:
135         case kTypeGenericInstant:
136             return true;
137         default:
138             return false;
139     }
140 }
141 
GetType() const142 MIRType *IreadNode::GetType() const
143 {
144     MIRPtrType *ptrtype = static_cast<MIRPtrType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx));
145     if (fieldID == 0) {
146         return ptrtype->GetPointedType();
147     }
148     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrtype->GetPointedTyIdxWithFieldID(fieldID));
149 }
150 
IsVolatile() const151 bool IreadNode::IsVolatile() const
152 {
153     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
154     DEBUG_ASSERT(type != nullptr, "null ptr check");
155     DEBUG_ASSERT(type->IsMIRPtrType(), "type of iread should be pointer type");
156     return static_cast<MIRPtrType *>(type)->IsPointedTypeVolatile(fieldID);
157 }
158 
IsVolatile(const MIRModule & mod) const159 bool AddrofNode::IsVolatile(const MIRModule &mod) const
160 {
161     DEBUG_ASSERT(mod.CurFunction() != nullptr, "mod.CurFunction() should not be nullptr");
162     auto *symbol = mod.CurFunction()->GetLocalOrGlobalSymbol(stIdx);
163     DEBUG_ASSERT(symbol != nullptr, "null ptr check on symbol");
164     return symbol->IsVolatile();
165 }
166 
IsVolatile(const MIRModule & mod) const167 bool DreadoffNode::IsVolatile(const MIRModule &mod) const
168 {
169     auto *symbol = mod.CurFunction()->GetLocalOrGlobalSymbol(stIdx);
170     DEBUG_ASSERT(symbol != nullptr, "null ptr check on symbol");
171     return symbol->IsVolatile();
172 }
173 
AssigningVolatile(const MIRModule & mod) const174 bool DassignNode::AssigningVolatile(const MIRModule &mod) const
175 {
176     auto *symbol = mod.CurFunction()->GetLocalOrGlobalSymbol(stIdx);
177     DEBUG_ASSERT(symbol != nullptr, "null ptr check on symbol");
178     return symbol->IsVolatile();
179 }
180 
AssigningVolatile() const181 bool IassignNode::AssigningVolatile() const
182 {
183     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
184     DEBUG_ASSERT(type != nullptr, "null ptr check");
185     DEBUG_ASSERT(type->IsMIRPtrType(), "type of iassign should be pointer type");
186     return static_cast<MIRPtrType *>(type)->IsPointedTypeVolatile(fieldID);
187 }
188 
AddStatement(StmtNode * stmt)189 void BlockNode::AddStatement(StmtNode *stmt)
190 {
191     DEBUG_ASSERT(stmt != nullptr, "null ptr check");
192     stmtNodeList.push_back(stmt);
193 }
194 
AppendStatementsFromBlock(BlockNode & blk)195 void BlockNode::AppendStatementsFromBlock(BlockNode &blk)
196 {
197     if (blk.GetStmtNodes().empty()) {
198         return;
199     }
200     stmtNodeList.splice(stmtNodeList.end(), blk.GetStmtNodes());
201 }
202 
203 /// Insert stmt as the first
InsertFirst(StmtNode * stmt)204 void BlockNode::InsertFirst(StmtNode *stmt)
205 {
206     DEBUG_ASSERT(stmt != nullptr, "stmt is null");
207     stmtNodeList.push_front(stmt);
208 }
209 
210 /// Insert stmt as the last
InsertLast(StmtNode * stmt)211 void BlockNode::InsertLast(StmtNode *stmt)
212 {
213     DEBUG_ASSERT(stmt != nullptr, "stmt is null");
214     stmtNodeList.push_back(stmt);
215 }
216 
ReplaceStmtWithBlock(StmtNode & stmtNode,BlockNode & blk)217 void BlockNode::ReplaceStmtWithBlock(StmtNode &stmtNode, BlockNode &blk)
218 {
219     stmtNodeList.splice(&stmtNode, blk.GetStmtNodes());
220     stmtNodeList.erase(&stmtNode);
221     stmtNode.SetNext(blk.GetLast()->GetNext());
222 }
223 
ReplaceStmt1WithStmt2(const StmtNode * stmtNode1,StmtNode * stmtNode2)224 void BlockNode::ReplaceStmt1WithStmt2(const StmtNode *stmtNode1, StmtNode *stmtNode2)
225 {
226     if (stmtNode2 == stmtNode1) {
227         // do nothing
228     } else if (stmtNode2 == nullptr) {
229         // delete stmtNode1
230         stmtNodeList.erase(stmtNode1);
231     } else {
232         // replace stmtNode1 with stmtNode2
233         stmtNodeList.insert(stmtNode1, stmtNode2);
234         (void)stmtNodeList.erase(stmtNode1);
235     }
236 }
237 
238 // remove sstmtNode1 from block
RemoveStmt(const StmtNode * stmtNode1)239 void BlockNode::RemoveStmt(const StmtNode *stmtNode1)
240 {
241     DEBUG_ASSERT(stmtNode1 != nullptr, "delete a null stmtment");
242     (void)stmtNodeList.erase(stmtNode1);
243 }
244 
245 /// Insert stmtNode2 before stmtNode1 in current block.
InsertBefore(const StmtNode * stmtNode1,StmtNode * stmtNode2)246 void BlockNode::InsertBefore(const StmtNode *stmtNode1, StmtNode *stmtNode2)
247 {
248     stmtNodeList.insert(stmtNode1, stmtNode2);
249 }
250 
251 /// Insert stmtNode2 after stmtNode1 in current block.
InsertAfter(const StmtNode * stmtNode1,StmtNode * stmtNode2)252 void BlockNode::InsertAfter(const StmtNode *stmtNode1, StmtNode *stmtNode2)
253 {
254     stmtNodeList.insertAfter(stmtNode1, stmtNode2);
255 }
256 
257 // insert all the stmts in inblock to the current block after stmt1
InsertBlockAfter(BlockNode & inblock,const StmtNode * stmt1)258 void BlockNode::InsertBlockAfter(BlockNode &inblock, const StmtNode *stmt1)
259 {
260     DEBUG_ASSERT(stmt1 != nullptr, "null ptr check");
261     DEBUG_ASSERT(!inblock.IsEmpty(), "NYI");
262     stmtNodeList.splice(stmt1, inblock.GetStmtNodes());
263 }
264 
CloneTreeWithFreqs(MapleAllocator & allocator,std::unordered_map<uint32_t,uint64_t> & toFreqs,std::unordered_map<uint32_t,uint64_t> & fromFreqs,uint64_t numer,uint64_t denom,uint32_t updateOp)265 BlockNode *BlockNode::CloneTreeWithFreqs(MapleAllocator &allocator, std::unordered_map<uint32_t, uint64_t> &toFreqs,
266                                          std::unordered_map<uint32_t, uint64_t> &fromFreqs, uint64_t numer,
267                                          uint64_t denom, uint32_t updateOp)
268 {
269     auto *nnode = allocator.GetMemPool()->New<BlockNode>();
270     nnode->SetStmtID(stmtIDNext++);
271     if (fromFreqs.count(GetStmtID()) > 0) {
272         uint64_t oldFreq = fromFreqs[GetStmtID()];
273         uint64_t newFreq;
274         if (updateOp & kUpdateUnrollRemainderFreq) {
275             newFreq = denom > 0 ? (oldFreq * numer % denom) : oldFreq;
276         } else {
277             newFreq = numer == 0 ? 0 : (denom > 0 ? (oldFreq * numer / denom) : oldFreq);
278         }
279         toFreqs[nnode->GetStmtID()] = (newFreq > 0 || (numer == 0)) ? newFreq : 1;
280         if (updateOp & kUpdateOrigFreq) {  // upateOp & 1 : update from
281             int64_t left = ((oldFreq - newFreq) > 0 || (oldFreq == 0)) ? static_cast<int64_t>(oldFreq - newFreq) : 1;
282             fromFreqs[GetStmtID()] = static_cast<uint64_t>(left);
283         }
284     }
285     for (auto &stmt : stmtNodeList) {
286         StmtNode *newStmt;
287         if (stmt.GetOpCode() == OP_block) {
288             newStmt = static_cast<StmtNode *>(
289                 (static_cast<BlockNode *>(&stmt))
290                     ->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp));
291         } else if (stmt.GetOpCode() == OP_if) {
292             newStmt = static_cast<StmtNode *>(
293                 (static_cast<IfStmtNode *>(&stmt))
294                     ->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp));
295         } else if (stmt.GetOpCode() == OP_while) {
296             newStmt = static_cast<StmtNode *>(
297                 (static_cast<WhileStmtNode *>(&stmt))
298                     ->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp));
299         } else if (stmt.GetOpCode() == OP_doloop) {
300             newStmt = static_cast<StmtNode *>(
301                 (static_cast<DoloopNode *>(&stmt))
302                     ->CloneTreeWithFreqs(allocator, toFreqs, fromFreqs, numer, denom, updateOp));
303         } else {
304             newStmt = static_cast<StmtNode *>(stmt.CloneTree(allocator));
305             if (fromFreqs.count(stmt.GetStmtID()) > 0) {
306                 uint64_t oldFreq = fromFreqs[stmt.GetStmtID()];
307                 uint64_t newFreq;
308                 if (updateOp & kUpdateUnrollRemainderFreq) {
309                     newFreq = denom > 0 ? (oldFreq * numer % denom) : oldFreq;
310                 } else {
311                     newFreq = numer == 0 ? 0 : (denom > 0 ? (oldFreq * numer / denom) : oldFreq);
312                 }
313                 toFreqs[newStmt->GetStmtID()] =
314                     (newFreq > 0 || oldFreq == 0 || numer == 0) ? static_cast<uint64_t>(newFreq) : 1;
315                 if (updateOp & kUpdateOrigFreq) {
316                     int64_t left = ((oldFreq - newFreq) > 0 || oldFreq == 0) ?
317                         static_cast<int64_t>(oldFreq - newFreq) : 1;
318                     fromFreqs[stmt.GetStmtID()] = static_cast<uint64_t>(left);
319                 }
320             }
321         }
322         DEBUG_ASSERT(newStmt != nullptr, "null ptr check");
323         newStmt->SetSrcPos(stmt.GetSrcPos());
324         newStmt->SetPrev(nullptr);
325         newStmt->SetNext(nullptr);
326         nnode->AddStatement(newStmt);
327     }
328     return nnode;
329 }
330 
DumpBase(int32 indent) const331 void BaseNode::DumpBase(int32 indent) const
332 {
333     PrintIndentation(indent);
334     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
335 }
336 
Dump(int32 indent) const337 void CatchNode::Dump(int32 indent) const
338 {
339     PrintIndentation(indent);
340     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " {";
341     size_t size = exceptionTyIdxVec.size();
342     for (size_t i = 0; i < size; ++i) {
343         LogInfo::MapleLogger() << " ";
344         GlobalTables::GetTypeTable().GetTypeFromTyIdx(exceptionTyIdxVec[i])->Dump(indent + 1);
345     }
346     LogInfo::MapleLogger() << " }\n";
347 }
348 
Dump(int32 indent) const349 void CppCatchNode::Dump(int32 indent) const
350 {
351     PrintIndentation(indent);
352     LogInfo::MapleLogger() << kOpcodeInfo.GetName(op);
353     if (exceptionTyIdx.GetIdx() != 0) {
354         LogInfo::MapleLogger() << " { ";
355         GlobalTables::GetTypeTable().GetTypeFromTyIdx(exceptionTyIdx)->Dump(indent + 1);
356         LogInfo::MapleLogger() << " }";
357     }
358     LogInfo::MapleLogger() << std::endl;
359 }
360 
DumpOpnd(const MIRModule &,int32 indent) const361 void UnaryNode::DumpOpnd(const MIRModule &, int32 indent) const
362 {
363     DumpOpnd(indent);
364 }
365 
DumpOpnd(int32 indent) const366 void UnaryNode::DumpOpnd(int32 indent) const
367 {
368     LogInfo::MapleLogger() << " (";
369     if (uOpnd != nullptr) {
370         uOpnd->Dump(indent);
371     }
372     LogInfo::MapleLogger() << ")";
373 }
374 
Dump(int32 indent) const375 void UnaryNode::Dump(int32 indent) const
376 {
377     BaseNode::DumpBase(0);
378     DumpOpnd(*theMIRModule, indent);
379 }
380 
Dump(int32 indent) const381 void TypeCvtNode::Dump(int32 indent) const
382 {
383     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " ";
384     LogInfo::MapleLogger() << GetPrimTypeName(GetPrimType()) << " " << GetPrimTypeName(FromType());
385     DumpOpnd(*theMIRModule, indent);
386 }
387 
Dump(int32 indent) const388 void RetypeNode::Dump(int32 indent) const
389 {
390     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " ";
391     LogInfo::MapleLogger() << GetPrimTypeName(GetPrimType()) << " ";
392     MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
393     if (ty->GetKind() == kTypeScalar) {
394         LogInfo::MapleLogger() << "<";
395         ty->Dump(indent + 1);
396         LogInfo::MapleLogger() << ">";
397     } else {
398         ty->Dump(indent + 1);
399     }
400     DumpOpnd(*theMIRModule, indent);
401 }
402 
Dump(int32 indent) const403 void ExtractbitsNode::Dump(int32 indent) const
404 {
405     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
406     if (GetOpCode() == OP_extractbits) {
407         LogInfo::MapleLogger() << " " << static_cast<int32>(bitsOffset) << " " << static_cast<int32>(bitsSize);
408     } else {
409         LogInfo::MapleLogger() << " " << static_cast<int32>(bitsSize);
410     }
411     DumpOpnd(*theMIRModule, indent);
412 }
413 
Dump(int32 indent) const414 void IreadNode::Dump(int32 indent) const
415 {
416     BaseNode::DumpBase(0);
417     LogInfo::MapleLogger() << " ";
418     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
419     LogInfo::MapleLogger() << " " << fieldID;
420     DumpOpnd(*theMIRModule, indent);
421 }
422 
Dump(int32 indent) const423 void IreadoffNode::Dump(int32 indent) const
424 {
425     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
426     LogInfo::MapleLogger() << " " << offset;
427     DumpOpnd(*theMIRModule, indent);
428 }
429 
Dump(int32) const430 void IreadFPoffNode::Dump(int32) const
431 {
432     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
433     LogInfo::MapleLogger() << " " << offset;
434 }
435 
Dump(int32 indent) const436 void BinaryNode::Dump(int32 indent) const
437 {
438     BaseNode::DumpBase(0);
439     BinaryOpnds::Dump(indent);
440 }
441 
Dump(int32 indent) const442 void BinaryOpnds::Dump(int32 indent) const
443 {
444     LogInfo::MapleLogger() << " (";
445     if (bOpnd[0]->IsLeaf() && bOpnd[1]->IsLeaf()) {
446         bOpnd[0]->Dump(0);
447         LogInfo::MapleLogger() << ", ";
448         bOpnd[1]->Dump(0);
449     } else {
450         LogInfo::MapleLogger() << '\n';
451         PrintIndentation(indent + 1);
452         bOpnd[0]->Dump(indent + 1);
453         LogInfo::MapleLogger() << ",\n";
454         PrintIndentation(indent + 1);
455         bOpnd[1]->Dump(indent + 1);
456     }
457     LogInfo::MapleLogger() << ")";
458 }
459 
Dump(int32 indent) const460 void ResolveFuncNode::Dump(int32 indent) const
461 {
462     BaseNode::DumpBase(0);
463     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
464     LogInfo::MapleLogger() << " &" << func->GetName();
465     BinaryOpnds::Dump(indent);
466 }
467 
Dump(int32 indent) const468 void CompareNode::Dump(int32 indent) const
469 {
470     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
471     LogInfo::MapleLogger() << " " << GetPrimTypeName(opndType);
472     BinaryOpnds::Dump(indent);
473 }
474 
Dump(int32 indent) const475 void DepositbitsNode::Dump(int32 indent) const
476 {
477     BaseNode::DumpBase(0);
478     LogInfo::MapleLogger() << " " << static_cast<int32>(bitsOffset) << " " << static_cast<int32>(bitsSize) << " (";
479     if (GetBOpnd(0)->IsLeaf() && GetBOpnd(1)->IsLeaf()) {
480         GetBOpnd(0)->Dump(0);
481         LogInfo::MapleLogger() << ", ";
482         GetBOpnd(1)->Dump(0);
483     } else {
484         LogInfo::MapleLogger() << '\n';
485         PrintIndentation(indent + 1);
486         GetBOpnd(0)->Dump(indent + 1);
487         LogInfo::MapleLogger() << ",\n";
488         PrintIndentation(indent + 1);
489         GetBOpnd(1)->Dump(indent + 1);
490     }
491     LogInfo::MapleLogger() << ")";
492 }
493 
Dump(int32 indent) const494 void TernaryNode::Dump(int32 indent) const
495 {
496     BaseNode::DumpBase(0);
497     LogInfo::MapleLogger() << " (";
498     if (topnd[kFirstOpnd]->IsLeaf() && topnd[kSecondOpnd]->IsLeaf() && topnd[kThirdOpnd]->IsLeaf()) {
499         topnd[kFirstOpnd]->Dump(0);
500         LogInfo::MapleLogger() << ", ";
501         topnd[kSecondOpnd]->Dump(0);
502         LogInfo::MapleLogger() << ", ";
503         topnd[kThirdOpnd]->Dump(0);
504     } else {
505         LogInfo::MapleLogger() << '\n';
506         PrintIndentation(indent + 1);
507         topnd[kFirstOpnd]->Dump(indent + 1);
508         LogInfo::MapleLogger() << ",\n";
509         PrintIndentation(indent + 1);
510         topnd[kSecondOpnd]->Dump(indent + 1);
511         LogInfo::MapleLogger() << ",\n";
512         PrintIndentation(indent + 1);
513         topnd[kThirdOpnd]->Dump(indent + 1);
514     }
515     LogInfo::MapleLogger() << ")";
516 }
517 
Dump(int32 indent) const518 void NaryOpnds::Dump(int32 indent) const
519 {
520     LogInfo::MapleLogger() << " (";
521     if (GetNopndSize() == 0) {
522         LogInfo::MapleLogger() << ")";
523         return;
524     }
525     if (GetNopndSize() == 1) {
526         GetNopndAt(0)->Dump(indent);
527     } else {
528         bool allisLeaf = true;
529         for (size_t i = 0; i < GetNopndSize(); ++i)
530             if (!GetNopndAt(i)->IsLeaf()) {
531                 allisLeaf = false;
532                 break;
533             }
534         if (allisLeaf) {
535             GetNopndAt(0)->Dump(0);
536             for (size_t i = 1; i < GetNopndSize(); ++i) {
537                 LogInfo::MapleLogger() << ", ";
538                 GetNopndAt(i)->Dump(0);
539             }
540         } else {
541             LogInfo::MapleLogger() << '\n';
542             PrintIndentation(indent + 1);
543             GetNopndAt(0)->Dump(indent + 1);
544             for (size_t i = 1; i < GetNopndSize(); ++i) {
545                 LogInfo::MapleLogger() << ",\n";
546                 PrintIndentation(indent + 1);
547                 GetNopndAt(i)->Dump(indent + 1);
548             }
549         }
550     }
551     LogInfo::MapleLogger() << ")";
552 }
553 
Dump(int32 indent) const554 void DeoptBundleInfo::Dump(int32 indent) const
555 {
556     size_t deoptBundleSize = deoptBundleInfo.size();
557     if (deoptBundleSize == 0) {
558         return;
559     }
560     LogInfo::MapleLogger() << " deopt: (";
561     bool isFirstItem = true;
562     for (const auto &elem : deoptBundleInfo) {
563         if (!isFirstItem) {
564             LogInfo::MapleLogger() << ", ";
565         } else {
566             isFirstItem = false;
567         }
568         LogInfo::MapleLogger() << elem.first << ": ";
569         auto valueKind = elem.second.GetMapleValueKind();
570         if (valueKind == MapleValue::kPregKind) {
571             LogInfo::MapleLogger() << "%" << elem.second.GetPregIdx() << " ";
572         } else if (valueKind == MapleValue::kConstKind) {
573             if (elem.second.GetConstValue().GetKind() != kConstInt) {
574                 CHECK_FATAL(false, "not supported currently");
575             }
576             LogInfo::MapleLogger() << static_cast<const MIRIntConst &>(elem.second.GetConstValue()).GetValue() << " ";
577         }
578     }
579     LogInfo::MapleLogger() << ")";
580 }
581 
VerifyOpnds() const582 bool NaryOpnds::VerifyOpnds() const
583 {
584     bool nOpndsVerify = true;
585     for (size_t i = 0; i < GetNopndSize(); ++i) {
586         if (!GetNopndAt(i)->Verify()) {
587             nOpndsVerify = false;
588             break;
589         }
590     }
591     return nOpndsVerify;
592 }
593 
Dump(int32 indent) const594 void NaryNode::Dump(int32 indent) const
595 {
596     BaseNode::DumpBase(0);
597     NaryOpnds::Dump(indent);
598 }
599 
GetArrayType(const TypeTable & tt) const600 const MIRType *ArrayNode::GetArrayType(const TypeTable &tt) const
601 {
602     const MIRType *type = tt.GetTypeFromTyIdx(tyIdx);
603     CHECK_FATAL(type->GetKind() == kTypePointer, "expect array type pointer");
604     const auto *pointType = static_cast<const MIRPtrType *>(type);
605     return tt.GetTypeFromTyIdx(pointType->GetPointedTyIdx());
606 }
GetArrayType(const TypeTable & tt)607 MIRType *ArrayNode::GetArrayType(const TypeTable &tt)
608 {
609     return const_cast<MIRType *>(const_cast<const ArrayNode *>(this)->GetArrayType(tt));
610 }
611 
GetDim(const MIRModule & mod,TypeTable & tt,int i) const612 const BaseNode *ArrayNode::GetDim(const MIRModule &mod, TypeTable &tt, int i) const
613 {
614     const auto *arrayType = static_cast<const MIRArrayType *>(GetArrayType(tt));
615     auto *mirConst =
616         GlobalTables::GetIntConstTable().GetOrCreateIntConst(i, *tt.GetTypeFromTyIdx(arrayType->GetElemTyIdx()));
617     return mod.CurFuncCodeMemPool()->New<ConstvalNode>(mirConst);
618 }
GetDim(const MIRModule & mod,TypeTable & tt,int i)619 BaseNode *ArrayNode::GetDim(const MIRModule &mod, TypeTable &tt, int i)
620 {
621     return const_cast<BaseNode *>(const_cast<const ArrayNode *>(this)->GetDim(mod, tt, i));
622 }
623 
Dump(int32 indent) const624 void ArrayNode::Dump(int32 indent) const
625 {
626     PrintIndentation(0);
627     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " ";
628     if (boundsCheck) {
629         LogInfo::MapleLogger() << "1 ";
630     } else {
631         LogInfo::MapleLogger() << "0 ";
632     }
633     LogInfo::MapleLogger() << GetPrimTypeName(GetPrimType());
634     LogInfo::MapleLogger() << " ";
635     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
636     NaryOpnds::Dump(indent);
637 }
638 
IsSameBase(ArrayNode * arry)639 bool ArrayNode::IsSameBase(ArrayNode *arry)
640 {
641     DEBUG_ASSERT(arry != nullptr, "null ptr check");
642     if (arry == this) {
643         return true;
644     }
645     BaseNode *curBase = this->GetBase();
646     BaseNode *otherBase = arry->GetBase();
647     if (curBase->GetOpCode() != OP_addrof || otherBase->GetOpCode() != OP_addrof) {
648         return false;
649     }
650     return static_cast<AddrofNode *>(curBase)->GetStIdx() == static_cast<AddrofNode *>(otherBase)->GetStIdx();
651 }
652 
Dump(int32 indent) const653 void IntrinsicopNode::Dump(int32 indent) const
654 {
655     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
656     if (GetOpCode() == OP_intrinsicopwithtype) {
657         LogInfo::MapleLogger() << " ";
658         GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(indent + 1);
659     }
660     LogInfo::MapleLogger() << " " << GetIntrinsicName(GetIntrinsic());
661     NaryOpnds::Dump(indent);
662 }
663 
Dump(int32) const664 void ConstvalNode::Dump(int32) const
665 {
666     if (GetConstVal()->GetType().GetKind() != kTypePointer) {
667         BaseNode::DumpBase(0);
668         LogInfo::MapleLogger() << " ";
669     }
670     GetConstVal()->Dump();
671 }
672 
Dump(int32) const673 void ConststrNode::Dump(int32) const
674 {
675     BaseNode::DumpBase(0);
676     const std::string kStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(UStrIdx(strIdx));
677     PrintString(kStr);
678 }
679 
Dump(int32) const680 void Conststr16Node::Dump(int32) const
681 {
682     BaseNode::DumpBase(0);
683     const std::u16string kStr16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(U16StrIdx(strIdx));
684     // UTF-16 string are dumped as UTF-8 string in mpl to keep the printable chars in ascii form
685     std::string str;
686     (void)namemangler::UTF16ToUTF8(str, kStr16);
687     PrintString(str);
688 }
689 
Dump(int32) const690 void SizeoftypeNode::Dump(int32) const
691 {
692     BaseNode::DumpBase(0);
693     LogInfo::MapleLogger() << " ";
694     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
695 }
696 
Dump(int32) const697 void FieldsDistNode::Dump(int32) const
698 {
699     BaseNode::DumpBase(0);
700     LogInfo::MapleLogger() << " ";
701     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
702     LogInfo::MapleLogger() << " " << fieldID1 << " " << fieldID2;
703 }
704 
Dump(int32) const705 void AddrofNode::Dump(int32) const
706 {
707     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
708     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
709     const MIRSymbol *st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(GetStIdx());
710     LogInfo::MapleLogger() << (GetStIdx().Islocal() ? " %" : " $");
711     DEBUG_ASSERT(st != nullptr, "null ptr check");
712     LogInfo::MapleLogger() << st->GetName();
713     if (fieldID != 0) {
714         LogInfo::MapleLogger() << " " << fieldID;
715     }
716 }
717 
Dump(int32) const718 void DreadoffNode::Dump(int32) const
719 {
720     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
721     const MIRSymbol *st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(stIdx);
722     LogInfo::MapleLogger() << (stIdx.Islocal() ? " %" : " $");
723     DEBUG_ASSERT(st != nullptr, "null ptr check");
724     LogInfo::MapleLogger() << st->GetName();
725     LogInfo::MapleLogger() << " " << offset;
726 }
727 
Dump(int32) const728 void RegreadNode::Dump(int32) const
729 {
730     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
731     if (regIdx >= 0) {
732         LogInfo::MapleLogger() << " %"
733                                << theMIRModule->CurFunction()->GetPregTab()->PregFromPregIdx(regIdx)->GetPregNo();
734         return;
735     }
736     LogInfo::MapleLogger() << " %%";
737     switch (regIdx) {
738         case -kSregSp:
739             LogInfo::MapleLogger() << "SP";
740             break;
741         case -kSregFp:
742             LogInfo::MapleLogger() << "FP";
743             break;
744         case -kSregGp:
745             LogInfo::MapleLogger() << "GP";
746             break;
747         case -kSregThrownval:
748             LogInfo::MapleLogger() << "thrownval";
749             break;
750         case -kSregMethodhdl:
751             LogInfo::MapleLogger() << "methodhdl";
752             break;
753         default:
754             int32 retValIdx = (-regIdx) - kSregRetval0;
755             LogInfo::MapleLogger() << "retval" << retValIdx;
756             break;
757     }
758 }
759 
Dump(int32) const760 void AddroffuncNode::Dump(int32) const
761 {
762     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
763     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
764     CHECK_FATAL(func != nullptr, "null ptr");
765     MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx());
766     if (symbol != nullptr) {
767         LogInfo::MapleLogger() << " &" << symbol->GetName();
768     }
769 }
770 
Dump(int32) const771 void AddroflabelNode::Dump(int32) const
772 {
773     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
774     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name << " " << GetPrimTypeName(GetPrimType());
775     LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(static_cast<LabelIdx>(offset));
776 }
777 
DumpBase(int32 indent) const778 void StmtNode::DumpBase(int32 indent) const
779 {
780     srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
781     // dump stmtFreqs
782     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
783     if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData() &&
784         theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) >= 0) {
785         LogInfo::MapleLogger() << "stmtID " << GetStmtID() << "  freq "
786                                << theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n";
787     }
788     PrintIndentation(indent);
789     LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name;
790 }
791 
Dump(int32 indent) const792 void StmtNode::Dump(int32 indent) const
793 {
794     StmtNode::DumpBase(indent);
795     LogInfo::MapleLogger() << '\n';
796 }
797 
798 // Get the next stmt skip the comment stmt.
GetRealNext() const799 StmtNode *StmtNode::GetRealNext() const
800 {
801     StmtNode *stmt = this->GetNext();
802     while (stmt != nullptr) {
803         if (stmt->GetOpCode() != OP_comment) {
804             break;
805         }
806         stmt = stmt->GetNext();
807     }
808     return stmt;
809 }
810 
811 // insert this before pos
InsertAfterThis(StmtNode & pos)812 void StmtNode::InsertAfterThis(StmtNode &pos)
813 {
814     this->SetNext(&pos);
815     if (pos.GetPrev()) {
816         this->SetPrev(pos.GetPrev());
817         pos.GetPrev()->SetNext(this);
818     }
819     pos.SetPrev(this);
820 }
821 
822 // insert stmtnode after pos
InsertBeforeThis(StmtNode & pos)823 void StmtNode::InsertBeforeThis(StmtNode &pos)
824 {
825     this->SetPrev(&pos);
826     if (pos.GetNext()) {
827         this->SetNext(pos.GetNext());
828         pos.GetNext()->SetPrev(this);
829     }
830     pos.SetNext(this);
831 }
832 
Dump(int32 indent) const833 void DassignNode::Dump(int32 indent) const
834 {
835     StmtNode::DumpBase(indent);
836     const MIRSymbol *st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(stIdx);
837     DEBUG_ASSERT(st != nullptr, "null ptr check");
838     LogInfo::MapleLogger() << (st->IsLocal() ? " %" : " $");
839     LogInfo::MapleLogger() << st->GetName() << " " << fieldID;
840     LogInfo::MapleLogger() << " (";
841     if (GetRHS() != nullptr) {
842         GetRHS()->Dump(indent + 1);
843     } else {
844         LogInfo::MapleLogger() << "/*empty-rhs*/";
845     }
846     LogInfo::MapleLogger() << ")\n";
847 }
848 
Dump(int32 indent) const849 void DassignoffNode::Dump(int32 indent) const
850 {
851     StmtNode::DumpBase(indent);
852     LogInfo::MapleLogger() << " " << GetPrimTypeName(GetPrimType());
853     const MIRSymbol *st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(stIdx);
854     DEBUG_ASSERT(st != nullptr, "null ptr check");
855     LogInfo::MapleLogger() << (st->IsLocal() ? " %" : " $");
856     LogInfo::MapleLogger() << st->GetName() << " " << offset;
857     LogInfo::MapleLogger() << " (";
858     if (GetRHS() != nullptr) {
859         GetRHS()->Dump(indent + 1);
860     } else {
861         LogInfo::MapleLogger() << "/*empty-rhs*/";
862     }
863     LogInfo::MapleLogger() << ")\n";
864 }
865 
Dump(int32 indent) const866 void RegassignNode::Dump(int32 indent) const
867 {
868     StmtNode::DumpBase(indent);
869     LogInfo::MapleLogger() << " " << GetPrimTypeName(GetPrimType());
870     if (regIdx >= 0) {
871         LogInfo::MapleLogger() << " %"
872                                << theMIRModule->CurFunction()->GetPregTab()->PregFromPregIdx(regIdx)->GetPregNo();
873     } else {
874         LogInfo::MapleLogger() << " %%";
875         switch (regIdx) {
876             case -kSregSp:
877                 LogInfo::MapleLogger() << "SP";
878                 break;
879             case -kSregFp:
880                 LogInfo::MapleLogger() << "FP";
881                 break;
882             case -kSregGp:
883                 LogInfo::MapleLogger() << "GP";
884                 break;
885             case -kSregThrownval:
886                 LogInfo::MapleLogger() << "thrownval";
887                 break;
888             case -kSregMethodhdl:
889                 LogInfo::MapleLogger() << "methodhdl";
890                 break;
891             case -kSregRetval0:
892                 LogInfo::MapleLogger() << "retval0";
893                 break;
894             // no default
895             default:
896                 break;
897         }
898     }
899     LogInfo::MapleLogger() << " (";
900     UnaryStmtNode::Opnd(0)->Dump(indent + 1);
901     LogInfo::MapleLogger() << ")\n";
902 }
903 
Dump(int32 indent) const904 void IassignNode::Dump(int32 indent) const
905 {
906     StmtNode::DumpBase(indent);
907     LogInfo::MapleLogger() << " ";
908     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
909     LogInfo::MapleLogger() << " " << fieldID;
910     LogInfo::MapleLogger() << " (";
911     if (addrExpr->IsLeaf() && rhs->IsLeaf()) {
912         addrExpr->Dump(0);
913         LogInfo::MapleLogger() << ", ";
914         rhs->Dump(0);
915     } else {
916         LogInfo::MapleLogger() << '\n';
917         PrintIndentation(indent + 1);
918         addrExpr->Dump(indent + 1);
919         LogInfo::MapleLogger() << ", \n";
920         PrintIndentation(indent + 1);
921         rhs->Dump(indent + 1);
922     }
923     LogInfo::MapleLogger() << ")\n";
924 }
925 
Dump(int32 indent) const926 void IassignoffNode::Dump(int32 indent) const
927 {
928     StmtNode::DumpBase(indent);
929     LogInfo::MapleLogger() << " " << GetPrimTypeName(GetPrimType()) << " " << offset;
930     BinaryOpnds::Dump(indent);
931     LogInfo::MapleLogger() << '\n';
932 }
933 
Dump(int32 indent) const934 void IassignFPoffNode::Dump(int32 indent) const
935 {
936     StmtNode::DumpBase(indent);
937     LogInfo::MapleLogger() << " " << GetPrimTypeName(GetPrimType()) << " " << offset;
938     DumpOpnd(*theMIRModule, indent);
939     LogInfo::MapleLogger() << '\n';
940 }
941 
Dump(int32 indent) const942 void BlkassignoffNode::Dump(int32 indent) const
943 {
944     StmtNode::DumpBase(indent);
945     LogInfo::MapleLogger() << " " << offset << " " << GetAlign() << " " << blockSize;
946     BinaryOpnds::Dump(indent);
947     LogInfo::MapleLogger() << '\n';
948 }
949 
Dump(int32 indent) const950 void GotoNode::Dump(int32 indent) const
951 {
952     StmtNode::DumpBase(indent);
953     if (offset == 0) {
954         LogInfo::MapleLogger() << '\n';
955     } else {
956         LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(static_cast<LabelIdx>(offset))
957                                << '\n';
958     }
959 }
960 
Dump(int32 indent) const961 void JsTryNode::Dump(int32 indent) const
962 {
963     StmtNode::DumpBase(indent);
964     if (catchOffset == 0) {
965         LogInfo::MapleLogger() << " 0";
966     } else {
967         LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(static_cast<LabelIdx>(catchOffset));
968     }
969     if (finallyOffset == 0) {
970         LogInfo::MapleLogger() << " 0\n";
971     } else {
972         LogInfo::MapleLogger() << " @"
973                                << theMIRModule->CurFunction()->GetLabelName(static_cast<LabelIdx>(finallyOffset))
974                                << '\n';
975     }
976 }
977 
Dump(int32 indent) const978 void TryNode::Dump(int32 indent) const
979 {
980     StmtNode::DumpBase(indent);
981     LogInfo::MapleLogger() << " {";
982     for (size_t i = 0; i < offsets.size(); ++i) {
983         uint32 offset = offsets[i];
984         LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName((LabelIdx)offset);
985     }
986     LogInfo::MapleLogger() << " }\n";
987 }
988 
Dump(int32 indent) const989 void CondGotoNode::Dump(int32 indent) const
990 {
991     StmtNode::DumpBase(indent);
992     LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(static_cast<LabelIdx>(offset));
993     LogInfo::MapleLogger() << " (";
994     Opnd(0)->Dump(indent);
995     LogInfo::MapleLogger() << ")\n";
996 }
997 
Dump(int32 indent) const998 void SwitchNode::Dump(int32 indent) const
999 {
1000     StmtNode::DumpBase(indent);
1001     LogInfo::MapleLogger() << " (";
1002     switchOpnd->Dump(indent);
1003     if (defaultLabel == 0) {
1004         LogInfo::MapleLogger() << ") 0 {";
1005     } else {
1006         LogInfo::MapleLogger() << ") @" << theMIRModule->CurFunction()->GetLabelName(defaultLabel) << " {";
1007     }
1008     for (auto it = switchTable.begin(); it != switchTable.end(); it++) {
1009         LogInfo::MapleLogger() << '\n';
1010         PrintIndentation(indent + 1);
1011         LogInfo::MapleLogger() << std::hex << "0x" << it->first << std::dec;
1012         LogInfo::MapleLogger() << ": goto @" << theMIRModule->CurFunction()->GetLabelName(it->second);
1013     }
1014     LogInfo::MapleLogger() << " }\n";
1015 }
1016 
Dump(int32 indent) const1017 void RangeGotoNode::Dump(int32 indent) const
1018 {
1019     StmtNode::DumpBase(indent);
1020     LogInfo::MapleLogger() << " (";
1021     Opnd(0)->Dump(indent);
1022     LogInfo::MapleLogger() << ") " << tagOffset << " {";
1023     for (auto it = rangegotoTable.begin(); it != rangegotoTable.end(); it++) {
1024         LogInfo::MapleLogger() << '\n';
1025         PrintIndentation(indent + 1);
1026         LogInfo::MapleLogger() << std::hex << "0x" << it->first << std::dec;
1027         LogInfo::MapleLogger() << ": goto @" << theMIRModule->CurFunction()->GetLabelName(it->second);
1028     }
1029     LogInfo::MapleLogger() << " }\n";
1030 }
1031 
Dump(int32 indent) const1032 void MultiwayNode::Dump(int32 indent) const
1033 {
1034     StmtNode::DumpBase(indent);
1035     LogInfo::MapleLogger() << " (";
1036     multiWayOpnd->Dump(indent);
1037     if (defaultLabel == 0) {
1038         LogInfo::MapleLogger() << ") 0 {";
1039     } else {
1040         LogInfo::MapleLogger() << ") @" << theMIRModule->CurFunction()->GetLabelName(defaultLabel) << " {";
1041     }
1042     for (auto it = multiWayTable.begin(); it != multiWayTable.end(); it++) {
1043         LogInfo::MapleLogger() << '\n';
1044         PrintIndentation(indent);
1045         LogInfo::MapleLogger() << " (";
1046         it->first->Dump(indent + 1);
1047         LogInfo::MapleLogger() << "): goto @" << theMIRModule->CurFunction()->GetLabelName(it->second);
1048     }
1049     LogInfo::MapleLogger() << " }\n";
1050 }
1051 
DumpOpnd(const MIRModule &,int32 indent) const1052 void UnaryStmtNode::DumpOpnd(const MIRModule &, int32 indent) const
1053 {
1054     DumpOpnd(indent);
1055 }
1056 
DumpOpnd(int32 indent) const1057 void UnaryStmtNode::DumpOpnd(int32 indent) const
1058 {
1059     LogInfo::MapleLogger() << " (";
1060     if (uOpnd != nullptr) {
1061         uOpnd->Dump(indent);
1062     }
1063     LogInfo::MapleLogger() << ")\n";
1064 }
1065 
Dump(int32 indent) const1066 void UnaryStmtNode::Dump(int32 indent) const
1067 {
1068     StmtNode::DumpBase(indent);
1069     DumpOpnd(indent);
1070 }
1071 
Dump(int32) const1072 void GCMallocNode::Dump(int32) const
1073 {
1074     BaseNode::DumpBase(0);
1075     LogInfo::MapleLogger() << " ";
1076     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0);
1077 }
1078 
Dump(int32 indent) const1079 void JarrayMallocNode::Dump(int32 indent) const
1080 {
1081     BaseNode::DumpBase(0);
1082     LogInfo::MapleLogger() << " ";
1083     GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(0, false);
1084     DumpOpnd(*theMIRModule, indent);
1085 }
1086 
Dump(int32 indent) const1087 void IfStmtNode::Dump(int32 indent) const
1088 {
1089     StmtNode::DumpBase(indent);
1090     LogInfo::MapleLogger() << " (";
1091     Opnd()->Dump(indent);
1092     LogInfo::MapleLogger() << ")";
1093     thenPart->Dump(indent);
1094     if (elsePart) {
1095         PrintIndentation(indent);
1096         LogInfo::MapleLogger() << "else {\n";
1097         for (auto &stmt : elsePart->GetStmtNodes()) {
1098             stmt.Dump(indent + 1);
1099         }
1100         PrintIndentation(indent);
1101         LogInfo::MapleLogger() << "}\n";
1102     }
1103 }
1104 
Dump(int32 indent) const1105 void WhileStmtNode::Dump(int32 indent) const
1106 {
1107     StmtNode::DumpBase(indent);
1108     if (GetOpCode() == OP_while) {
1109         LogInfo::MapleLogger() << " (";
1110         Opnd(0)->Dump(indent);
1111         LogInfo::MapleLogger() << ")";
1112         body->Dump(indent);
1113     } else {  // OP_dowhile
1114         LogInfo::MapleLogger() << " {\n";
1115         for (auto &stmt : body->GetStmtNodes()) {
1116             stmt.Dump(indent + 1);
1117         }
1118         PrintIndentation(indent);
1119         LogInfo::MapleLogger() << "} (";
1120         Opnd(0)->Dump(indent);
1121         LogInfo::MapleLogger() << ")\n";
1122     }
1123 }
1124 
DumpDoVar(const MIRModule & mod) const1125 void DoloopNode::DumpDoVar(const MIRModule &mod) const
1126 {
1127     DEBUG_ASSERT(mod.CurFunction() != nullptr, "mod.CurFunction() should not be nullptr");
1128     if (isPreg) {
1129         LogInfo::MapleLogger() << " %"
1130                                << mod.CurFunction()->GetPregTab()->PregFromPregIdx(doVarStIdx.FullIdx())->GetPregNo()
1131                                << " (\n";
1132     } else {
1133         const MIRSymbol *st = mod.CurFunction()->GetLocalOrGlobalSymbol(doVarStIdx);
1134         CHECK_FATAL(st != nullptr, "null ptr");
1135         LogInfo::MapleLogger() << " %" << st->GetName() << " (\n";
1136     }
1137 }
1138 
Dump(int32 indent) const1139 void DoloopNode::Dump(int32 indent) const
1140 {
1141     StmtNode::DumpBase(indent);
1142     DumpDoVar(*theMIRModule);
1143     PrintIndentation(indent + 1);
1144     startExpr->Dump(indent + 1);
1145     LogInfo::MapleLogger() << ",\n";
1146     PrintIndentation(indent + 1);
1147     condExpr->Dump(indent + 1);
1148     LogInfo::MapleLogger() << ",\n";
1149     PrintIndentation(indent + 1);
1150     incrExpr->Dump(indent + 1);
1151     LogInfo::MapleLogger() << ")";
1152     doBody->Dump(indent + 1);
1153 }
1154 
Dump(int32 indent) const1155 void ForeachelemNode::Dump(int32 indent) const
1156 {
1157     StmtNode::DumpBase(indent);
1158     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
1159     const MIRSymbol *st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(elemStIdx);
1160     DEBUG_ASSERT(st != nullptr, "null ptr check");
1161     LogInfo::MapleLogger() << " %" << st->GetName();
1162     st = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(arrayStIdx);
1163     DEBUG_ASSERT(st != nullptr, "null ptr check");
1164     LogInfo::MapleLogger() << (arrayStIdx.Islocal() ? " %" : " $");
1165     LogInfo::MapleLogger() << st->GetName();
1166     loopBody->Dump(indent + 1);
1167 }
1168 
Dump(int32 indent) const1169 void BinaryStmtNode::Dump(int32 indent) const
1170 {
1171     StmtNode::DumpBase(indent);
1172     BinaryOpnds::Dump(indent);
1173     LogInfo::MapleLogger() << '\n';
1174 }
1175 
Dump(int32 indent) const1176 void NaryStmtNode::Dump(int32 indent) const
1177 {
1178     StmtNode::DumpBase(indent);
1179     NaryOpnds::Dump(indent);
1180     LogInfo::MapleLogger() << '\n';
1181 }
1182 
Dump(int32 indent) const1183 void CallAssertNonnullStmtNode::Dump(int32 indent) const
1184 {
1185     StmtNode::DumpBase(indent);
1186     SafetyCallCheckStmtNode::Dump();
1187     UnaryStmtNode::DumpOpnd(indent);
1188 }
1189 
Dump(int32 indent) const1190 void AssertNonnullStmtNode::Dump(int32 indent) const
1191 {
1192     StmtNode::DumpBase(indent);
1193     if (theMIRModule->IsCModule()) {
1194         SafetyCheckStmtNode::Dump();
1195     }
1196     UnaryStmtNode::DumpOpnd(indent);
1197 }
1198 
Dump(int32 indent) const1199 void AssertBoundaryStmtNode::Dump(int32 indent) const
1200 {
1201     StmtNode::DumpBase(indent);
1202     SafetyCheckStmtNode::Dump();
1203     NaryOpnds::Dump(indent);
1204     LogInfo::MapleLogger() << '\n';
1205 }
1206 
Dump(int32 indent) const1207 void CallAssertBoundaryStmtNode::Dump(int32 indent) const
1208 {
1209     StmtNode::DumpBase(indent);
1210     SafetyCallCheckStmtNode::Dump();
1211     NaryOpnds::Dump(indent);
1212     LogInfo::MapleLogger() << '\n';
1213 }
1214 
DumpCallReturns(const MIRModule & mod,CallReturnVector nrets,int32 indent)1215 void DumpCallReturns(const MIRModule &mod, CallReturnVector nrets, int32 indent)
1216 {
1217     const MIRFunction *mirFunc = mod.CurFunction();
1218     if (nrets.empty()) {
1219         LogInfo::MapleLogger() << " {}\n";
1220         return;
1221     } else if (nrets.size() == 1) {
1222         StIdx stIdx = nrets.begin()->first;
1223         RegFieldPair regFieldPair = nrets.begin()->second;
1224         if (!regFieldPair.IsReg()) {
1225             const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx);
1226             DEBUG_ASSERT(st != nullptr, "st is null");
1227             FieldID fieldID = regFieldPair.GetFieldID();
1228             LogInfo::MapleLogger() << " { dassign ";
1229             LogInfo::MapleLogger() << (stIdx.Islocal() ? "%" : "$");
1230             LogInfo::MapleLogger() << st->GetName() << " " << fieldID << " }\n";
1231             return;
1232         } else {
1233             PregIdx regIdx = regFieldPair.GetPregIdx();
1234             const MIRPreg *mirPreg = mirFunc->GetPregItem(static_cast<PregIdx>(regIdx));
1235             DEBUG_ASSERT(mirPreg != nullptr, "mirPreg is null");
1236             LogInfo::MapleLogger() << " { regassign";
1237             LogInfo::MapleLogger() << " " << GetPrimTypeName(mirPreg->GetPrimType());
1238             LogInfo::MapleLogger() << " %" << mirPreg->GetPregNo() << "}\n";
1239             return;
1240         }
1241     }
1242     LogInfo::MapleLogger() << " {\n";
1243     constexpr int32 spaceNum = 2;
1244     for (auto it = nrets.begin(); it != nrets.end(); it++) {
1245         PrintIndentation(indent + spaceNum);
1246         StIdx stIdx = (it)->first;
1247         RegFieldPair regFieldPair = it->second;
1248         if (!regFieldPair.IsReg()) {
1249             FieldID fieldID = regFieldPair.GetFieldID();
1250             LogInfo::MapleLogger() << "dassign";
1251             const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx);
1252             DEBUG_ASSERT(st != nullptr, "st is null");
1253             LogInfo::MapleLogger() << (stIdx.Islocal() ? " %" : " $");
1254             LogInfo::MapleLogger() << st->GetName() << " " << fieldID << '\n';
1255         } else {
1256             PregIdx regIdx = regFieldPair.GetPregIdx();
1257             const MIRPreg *mirPreg = mirFunc->GetPregItem(static_cast<PregIdx>(regIdx));
1258             DEBUG_ASSERT(mirPreg != nullptr, "mirPreg is null");
1259             LogInfo::MapleLogger() << "regassign"
1260                                    << " " << GetPrimTypeName(mirPreg->GetPrimType());
1261             LogInfo::MapleLogger() << " %" << mirPreg->GetPregNo() << '\n';
1262         }
1263     }
1264     PrintIndentation(indent + 1);
1265     LogInfo::MapleLogger() << "}\n";
1266 }
1267 
1268 // iread expr has sideeffect, may cause derefference error
HasIreadExpr(const BaseNode * expr)1269 bool HasIreadExpr(const BaseNode *expr)
1270 {
1271     if (expr->GetOpCode() == OP_iread) {
1272         return true;
1273     }
1274     for (size_t i = 0; i < expr->GetNumOpnds(); ++i) {
1275         if (HasIreadExpr(expr->Opnd(i))) {
1276             return true;
1277         }
1278     }
1279     return false;
1280 }
1281 
1282 // layer to leaf node
MaxDepth(const BaseNode * expr)1283 size_t MaxDepth(const BaseNode *expr)
1284 {
1285     if (expr->IsLeaf()) {
1286         return 1;
1287     }
1288     size_t maxSubDepth = 0;
1289     for (size_t i = 0; i < expr->GetNumOpnds(); ++i) {
1290         size_t depth = MaxDepth(expr->Opnd(i));
1291         maxSubDepth = (depth > maxSubDepth) ? depth : maxSubDepth;
1292     }
1293     return maxSubDepth + 1;  // expr itself
1294 }
1295 
GetCallReturnType()1296 MIRType *CallNode::GetCallReturnType()
1297 {
1298     if (!kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1299         return nullptr;
1300     }
1301     DEBUG_ASSERT(GlobalTables::GetFunctionTable().GetFuncTable().empty() == false, "container check");
1302     MIRFunction *mirFunc = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
1303     return mirFunc->GetReturnType();
1304 }
1305 
GetCallReturnSymbol(const MIRModule & mod) const1306 const MIRSymbol *CallNode::GetCallReturnSymbol(const MIRModule &mod) const
1307 {
1308     if (!kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1309         return nullptr;
1310     }
1311     const CallReturnVector &nRets = this->GetReturnVec();
1312     if (nRets.size() == 1) {
1313         StIdx stIdx = nRets.begin()->first;
1314         RegFieldPair regFieldPair = nRets.begin()->second;
1315         if (!regFieldPair.IsReg()) {
1316             const MIRFunction *mirFunc = mod.CurFunction();
1317             const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx);
1318             return st;
1319         }
1320     }
1321     return nullptr;
1322 }
1323 
Dump(int32 indent,bool newline) const1324 void CallNode::Dump(int32 indent, bool newline) const
1325 {
1326     StmtNode::DumpBase(indent);
1327     if (tyIdx != 0u) {
1328         LogInfo::MapleLogger() << " ";
1329         GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(indent + 1);
1330     }
1331     CHECK(puIdx < GlobalTables::GetFunctionTable().GetFuncTable().size(), "index out of range in CallNode::Dump");
1332     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
1333     DumpCallConvInfo();
1334     LogInfo::MapleLogger() << " &" << func->GetName();
1335     NaryOpnds::Dump(indent);
1336     DeoptBundleInfo::Dump(indent);
1337     if (kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1338         DumpCallReturns(*theMIRModule, this->GetReturnVec(), indent);
1339     } else if (newline) {
1340         LogInfo::MapleLogger() << '\n';
1341     }
1342 }
1343 
GetCallReturnType()1344 MIRType *IcallNode::GetCallReturnType()
1345 {
1346     if (op == OP_icall || op == OP_icallassigned) {
1347         return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx);
1348     }
1349     // icallproto or icallprotoassigned
1350     MIRFuncType *funcType = static_cast<MIRFuncType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx));
1351     return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx());
1352 }
1353 
GetCallReturnSymbol(const MIRModule & mod) const1354 const MIRSymbol *IcallNode::GetCallReturnSymbol(const MIRModule &mod) const
1355 {
1356     if (!kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1357         return nullptr;
1358     }
1359     const CallReturnVector &nRets = this->GetReturnVec();
1360     if (nRets.size() == 1) {
1361         StIdx stIdx = nRets.begin()->first;
1362         RegFieldPair regFieldPair = nRets.begin()->second;
1363         if (!regFieldPair.IsReg()) {
1364             const MIRFunction *mirFunc = mod.CurFunction();
1365             const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx);
1366             return st;
1367         }
1368     }
1369     return nullptr;
1370 }
1371 
Dump(int32 indent,bool newline) const1372 void IcallNode::Dump(int32 indent, bool newline) const
1373 {
1374     StmtNode::DumpBase(indent);
1375     DumpCallConvInfo();
1376     if (op == OP_icallproto || op == OP_icallprotoassigned) {
1377         LogInfo::MapleLogger() << " ";
1378         GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx)->Dump(indent + 1);
1379     }
1380     NaryOpnds::Dump(indent);
1381     DeoptBundleInfo::Dump(indent);
1382     if (kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1383         DumpCallReturns(*theMIRModule, this->returnValues, indent);
1384     } else if (newline) {
1385         LogInfo::MapleLogger() << '\n';
1386     }
1387 }
1388 
GetCallReturnType()1389 MIRType *IntrinsiccallNode::GetCallReturnType()
1390 {
1391     CHECK_FATAL(intrinsic < INTRN_LAST, "Index out of bound in IntrinsiccallNode::GetCallReturnType");
1392     IntrinDesc *intrinDesc = &IntrinDesc::intrinTable[intrinsic];
1393     return intrinDesc->GetReturnType();
1394 }
1395 
Dump(int32 indent,bool newline) const1396 void IntrinsiccallNode::Dump(int32 indent, bool newline) const
1397 {
1398     StmtNode::DumpBase(indent);
1399     if (tyIdx != 0u) {
1400         LogInfo::MapleLogger() << " ";
1401         GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->Dump(indent + 1);
1402     }
1403     if (GetOpCode() == OP_intrinsiccall || GetOpCode() == OP_intrinsiccallassigned ||
1404         GetOpCode() == OP_intrinsiccallwithtype || GetOpCode() == OP_intrinsiccallwithtypeassigned) {
1405         LogInfo::MapleLogger() << " " << GetIntrinsicName(intrinsic);
1406     } else {
1407         LogInfo::MapleLogger() << " " << intrinsic;
1408     }
1409     NaryOpnds::Dump(indent);
1410     if (kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1411         DumpCallReturns(*theMIRModule, this->GetReturnVec(), indent);
1412     } else if (newline) {
1413         LogInfo::MapleLogger() << '\n';
1414     }
1415 }
1416 
Dump(int32 indent,bool newline) const1417 void CallinstantNode::Dump(int32 indent, bool newline) const
1418 {
1419     StmtNode::DumpBase(indent);
1420     MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(GetPUIdx());
1421     LogInfo::MapleLogger() << " &" << func->GetName();
1422     MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(instVecTyIdx);
1423     LogInfo::MapleLogger() << "<";
1424     auto *instVecType = static_cast<MIRInstantVectorType *>(ty);
1425     instVecType->Dump(indent);
1426     LogInfo::MapleLogger() << ">";
1427     NaryOpnds::Dump(indent);
1428     if (kOpcodeInfo.IsCallAssigned(GetOpCode())) {
1429         DumpCallReturns(*theMIRModule, this->GetReturnVec(), indent);
1430     } else if (newline) {
1431         LogInfo::MapleLogger() << '\n';
1432     }
1433 }
1434 
Dump(int32 indent,const MIRSymbolTable * theSymTab,MIRPregTable * thePregTab,bool withInfo,bool isFuncbody,MIRFlavor flavor) const1435 void BlockNode::Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable *thePregTab, bool withInfo,
1436                      bool isFuncbody, MIRFlavor flavor) const
1437 {
1438     if (!withInfo) {
1439         LogInfo::MapleLogger() << " {\n";
1440     }
1441     // output puid for debugging purpose
1442     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
1443     if (isFuncbody) {
1444         theMIRModule->CurFunction()->DumpFuncBody(indent);
1445         if (theSymTab != nullptr || thePregTab != nullptr) {
1446             // print the locally declared type names
1447             if (theMIRModule->CurFunction()->HaveTypeNameTab()) {
1448                 constexpr int32 spaceNum = 2;
1449                 for (auto it : theMIRModule->CurFunction()->GetGStrIdxToTyIdxMap()) {
1450                     const std::string &name = GlobalTables::GetStrTable().GetStringFromStrIdx(it.first);
1451                     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(it.second);
1452                     PrintIndentation(indent + 1);
1453                     LogInfo::MapleLogger() << "type %" << name << " ";
1454                     if (type->GetKind() != kTypeByName) {
1455                         type->Dump(indent + spaceNum, true);
1456                     } else {
1457                         type->Dump(indent + spaceNum);
1458                     }
1459                     LogInfo::MapleLogger() << '\n';
1460                 }
1461             }
1462             // print the locally declared variables
1463 	    DEBUG_ASSERT(theSymTab != nullptr, "theSymTab should not be nullptr");
1464             theSymTab->Dump(true, indent + 1, false, flavor); /* first:isLocal, third:printDeleted */
1465             if (thePregTab != nullptr) {
1466                 thePregTab->DumpPregsWithTypes(indent + 1);
1467             }
1468         }
1469         LogInfo::MapleLogger() << '\n';
1470         if (theMIRModule->CurFunction()->NeedEmitAliasInfo()) {
1471             theMIRModule->CurFunction()->DumpScope();
1472         }
1473     }
1474     srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
1475     // dump stmtFreqs
1476     if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) {
1477         LogInfo::MapleLogger() << "stmtID " << GetStmtID() << "  freq "
1478                                << theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n";
1479     }
1480     for (auto &stmt : GetStmtNodes()) {
1481         stmt.Dump(indent + 1);
1482     }
1483     PrintIndentation(indent);
1484     LogInfo::MapleLogger() << "}\n";
1485 }
1486 
Dump(int32) const1487 void LabelNode::Dump(int32) const
1488 {
1489     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
1490     if (theMIRModule->CurFunction()->WithLocInfo()) {
1491         srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
1492     }
1493     // dump stmtFreqs
1494     if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) {
1495         LogInfo::MapleLogger() << "stmtID " << GetStmtID() << "  freq "
1496                                << theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n";
1497     }
1498     LogInfo::MapleLogger() << "@" << theMIRModule->CurFunction()->GetLabelName(labelIdx) << "\n";
1499 }
1500 
Dump(int32 indent) const1501 void CommentNode::Dump(int32 indent) const
1502 {
1503     srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
1504     PrintIndentation(indent);
1505     LogInfo::MapleLogger() << "#" << comment << '\n';
1506 }
1507 
EmitStr(const MapleString & mplStr)1508 void EmitStr(const MapleString &mplStr)
1509 {
1510     const char *str = mplStr.c_str();
1511     size_t len = mplStr.length();
1512     LogInfo::MapleLogger() << "\"";
1513 
1514     // don't expand special character; convert all \s to \\s in string
1515     for (size_t i = 0; i < len; ++i) {
1516         /* Referred to GNU AS: 3.6.1.1 Strings */
1517         constexpr int kBufSize = 5;
1518         constexpr int kFirstChar = 0;
1519         constexpr int kSecondChar = 1;
1520         constexpr int kThirdChar = 2;
1521         constexpr int kLastChar = 4;
1522         char buf[kBufSize];
1523         if (isprint(*str)) {
1524             buf[kFirstChar] = *str;
1525             buf[kSecondChar] = 0;
1526             if (*str == '\\' || *str == '\"') {
1527                 buf[kFirstChar] = '\\';
1528                 buf[kSecondChar] = *str;
1529                 buf[kThirdChar] = 0;
1530             }
1531             LogInfo::MapleLogger() << buf;
1532         } else if (*str == '\b') {
1533             LogInfo::MapleLogger() << "\\b";
1534         } else if (*str == '\n') {
1535             LogInfo::MapleLogger() << "\\n";
1536         } else if (*str == '\r') {
1537             LogInfo::MapleLogger() << "\\r";
1538         } else if (*str == '\t') {
1539             LogInfo::MapleLogger() << "\\t";
1540         } else if (*str == '\0') {
1541             buf[kFirstChar] = '\\';
1542             buf[kSecondChar] = '0';
1543             buf[kThirdChar] = 0;
1544             LogInfo::MapleLogger() << buf;
1545         } else {
1546             /* all others, print as number */
1547             int ret = snprintf_s(buf, sizeof(buf), kBufSize - 1, "\\%03o", static_cast<unsigned char>(*str) & 0xFF);
1548             if (ret < 0) {
1549                 FATAL(kLncFatal, "snprintf_s failed");
1550             }
1551             buf[kLastChar] = '\0';
1552             LogInfo::MapleLogger() << buf;
1553         }
1554         str++;
1555     }
1556 
1557     LogInfo::MapleLogger() << "\"\n";
1558 }
1559 
CloneTree(MapleAllocator & allocator) const1560 AsmNode *AsmNode::CloneTree(MapleAllocator &allocator) const
1561 {
1562     auto *node = allocator.GetMemPool()->New<AsmNode>(allocator, *this);
1563     for (size_t i = 0; i < GetNopndSize(); ++i) {
1564         node->GetNopnd().push_back(GetNopndAt(i)->CloneTree(allocator));
1565     }
1566     for (size_t i = 0; i < inputConstraints.size(); ++i) {
1567         node->inputConstraints.push_back(inputConstraints[i]);
1568     }
1569     for (size_t i = 0; i < asmOutputs.size(); ++i) {
1570         node->asmOutputs.push_back(asmOutputs[i]);
1571     }
1572     for (size_t i = 0; i < outputConstraints.size(); ++i) {
1573         node->outputConstraints.push_back(outputConstraints[i]);
1574     }
1575     for (size_t i = 0; i < clobberList.size(); ++i) {
1576         node->clobberList.push_back(clobberList[i]);
1577     }
1578     for (size_t i = 0; i < gotoLabels.size(); ++i) {
1579         node->gotoLabels.push_back(gotoLabels[i]);
1580     }
1581     node->SetNumOpnds(static_cast<uint8>(GetNopndSize()));
1582     return node;
1583 }
1584 
DumpOutputs(int32 indent,std::string & uStr) const1585 void AsmNode::DumpOutputs(int32 indent, std::string &uStr) const
1586 {
1587     PrintIndentation(indent + 1);
1588     LogInfo::MapleLogger() << " :";
1589     size_t numOutputs = asmOutputs.size();
1590 
1591     const MIRFunction *mirFunc = theMIRModule->CurFunction();
1592     if (numOutputs == 0) {
1593         LogInfo::MapleLogger() << '\n';
1594     } else {
1595         for (size_t i = 0; i < numOutputs; i++) {
1596             if (i != 0) {
1597                 PrintIndentation(indent + 2);  // Increase the indent by 2 bytes.
1598             }
1599             uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(outputConstraints[i]);
1600             PrintString(uStr);
1601             LogInfo::MapleLogger() << " ";
1602             StIdx stIdx = asmOutputs[i].first;
1603             RegFieldPair regFieldPair = asmOutputs[i].second;
1604             if (!regFieldPair.IsReg()) {
1605                 FieldID fieldID = regFieldPair.GetFieldID();
1606                 LogInfo::MapleLogger() << "dassign";
1607                 const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx);
1608                 DEBUG_ASSERT(st != nullptr, "st is null");
1609                 LogInfo::MapleLogger() << (stIdx.Islocal() ? " %" : " $");
1610                 LogInfo::MapleLogger() << st->GetName() << " " << fieldID;
1611             } else {
1612                 PregIdx regIdx = regFieldPair.GetPregIdx();
1613                 const MIRPreg *mirPreg = mirFunc->GetPregItem(static_cast<PregIdx>(regIdx));
1614                 DEBUG_ASSERT(mirPreg != nullptr, "mirPreg is null");
1615                 LogInfo::MapleLogger() << "regassign"
1616                                        << " " << GetPrimTypeName(mirPreg->GetPrimType());
1617                 LogInfo::MapleLogger() << " %" << mirPreg->GetPregNo();
1618             }
1619             if (i != numOutputs - 1) {
1620                 LogInfo::MapleLogger() << ',';
1621             }
1622             LogInfo::MapleLogger() << '\n';
1623         }
1624     }
1625 }
1626 
DumpInputOperands(int32 indent,std::string & uStr) const1627 void AsmNode::DumpInputOperands(int32 indent, std::string &uStr) const
1628 {
1629     PrintIndentation(indent + 1);
1630     LogInfo::MapleLogger() << " :";
1631     if (numOpnds == 0) {
1632         LogInfo::MapleLogger() << '\n';
1633     } else {
1634         for (size_t i = 0; i < numOpnds; i++) {
1635             if (i != 0) {
1636                 PrintIndentation(indent + 2);  // Increase the indent by 2 bytes.
1637             }
1638             uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(inputConstraints[i]);
1639             PrintString(uStr);
1640             LogInfo::MapleLogger() << " (";
1641             GetNopndAt(i)->Dump(indent + 4);  // Increase the indent by 4 bytes.
1642             LogInfo::MapleLogger() << ")";
1643             if (i != static_cast<size_t>(static_cast<int64>(numOpnds - 1))) {
1644                 LogInfo::MapleLogger() << ',';
1645             }
1646             LogInfo::MapleLogger() << "\n";
1647         }
1648     }
1649 }
1650 
Dump(int32 indent) const1651 void AsmNode::Dump(int32 indent) const
1652 {
1653     srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
1654     PrintIndentation(indent);
1655     LogInfo::MapleLogger() << kOpcodeInfo.GetName(op);
1656     if (GetQualifier(kASMvolatile)) {
1657         LogInfo::MapleLogger() << " volatile";
1658     }
1659     if (GetQualifier(kASMinline)) {
1660         LogInfo::MapleLogger() << " inline";
1661     }
1662     if (GetQualifier(kASMgoto)) {
1663         LogInfo::MapleLogger() << " goto";
1664     }
1665     LogInfo::MapleLogger() << " { ";
1666     EmitStr(asmString);
1667     // print outputs
1668     std::string uStr;
1669     DumpOutputs(indent, uStr);
1670     // print input operands
1671     DumpInputOperands(indent, uStr);
1672     // print clobber list
1673     PrintIndentation(indent + 1);
1674     LogInfo::MapleLogger() << " :";
1675     for (size_t i = 0; i < clobberList.size(); i++) {
1676         uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(clobberList[i]);
1677         PrintString(uStr);
1678         DEBUG_ASSERT(clobberList.size() > 0, "must not be zero");
1679         if (i != clobberList.size() - 1) {
1680             LogInfo::MapleLogger() << ',';
1681         }
1682     }
1683     LogInfo::MapleLogger() << '\n';
1684     // print labels
1685     PrintIndentation(indent + 1);
1686     LogInfo::MapleLogger() << " :";
1687     size_t labelSize = gotoLabels.size();
1688     DEBUG_ASSERT(theMIRModule->CurFunction() != nullptr, "theMIRModule->CurFunction() should not be nullptr");
1689     for (size_t i = 0; i < labelSize; i++) {
1690         LabelIdx offset = gotoLabels[i];
1691         LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(offset);
1692         if (i != labelSize - 1) {
1693             LogInfo::MapleLogger() << ',';
1694         }
1695     }
1696     LogInfo::MapleLogger() << " }\n";
1697 }
1698 
IntTypeVerify(PrimType pTyp)1699 inline bool IntTypeVerify(PrimType pTyp)
1700 {
1701     return pTyp == PTY_i32 || pTyp == PTY_u32 || pTyp == PTY_i64 || pTyp == PTY_u64;
1702 }
1703 
UnaryTypeVerify0(PrimType pTyp)1704 inline bool UnaryTypeVerify0(PrimType pTyp)
1705 {
1706     bool verifyResult = IntTypeVerify(pTyp);
1707     if (!verifyResult) {
1708         LogInfo::MapleLogger() << "\n#Error:result type of bnot,extractbits,sext,zext must be in [i32,u32,i64,u64]\n";
1709     }
1710     return verifyResult;
1711 }
1712 
ArithResTypeVerify(PrimType pTyp)1713 bool ArithResTypeVerify(PrimType pTyp)
1714 {
1715     switch (pTyp) {
1716         case PTY_i32:
1717         case PTY_u32:
1718         case PTY_i64:
1719         case PTY_u64:
1720         case PTY_f32:
1721         case PTY_f64:
1722             return true;
1723         case PTY_a32:
1724         case PTY_a64:
1725         case PTY_ptr:
1726             return theMIRModule->IsCModule();
1727         default:
1728             break;
1729     }
1730 
1731     // Arithmetic operations on all vector types are allowed
1732     PrimitiveType pt(pTyp);
1733     return pt.IsVector();
1734 }
1735 
UnaryTypeVerify1(PrimType pType)1736 inline bool UnaryTypeVerify1(PrimType pType)
1737 {
1738     bool verifyResult = ArithResTypeVerify(pType);
1739     if (!verifyResult) {
1740         LogInfo::MapleLogger() << "\n#Error:result type of abs,neg must be in [i32,u32,i64,u64,f32,f64]\n";
1741     }
1742     return verifyResult;
1743 }
1744 
UnaryTypeVerify2(PrimType pType)1745 inline bool UnaryTypeVerify2(PrimType pType)
1746 {
1747     bool verifyResult = IsPrimitiveFloat(pType);
1748     if (!verifyResult) {
1749         LogInfo::MapleLogger() << "\n#Error:result-type of recip,sqrt must be in [f32,f64]\n";
1750     }
1751     return verifyResult;
1752 }
1753 
BinaryTypeVerify(PrimType pType)1754 inline bool BinaryTypeVerify(PrimType pType)
1755 {
1756     return ArithResTypeVerify(pType) || IsPrimitiveDynType(pType);
1757 }
1758 
BinaryGenericVerify(const BaseNode & bOpnd0,const BaseNode & bOpnd1)1759 inline bool BinaryGenericVerify(const BaseNode &bOpnd0, const BaseNode &bOpnd1)
1760 {
1761     return bOpnd0.Verify() && bOpnd1.Verify();
1762 }
1763 
CompareTypeVerify(PrimType pType)1764 inline bool CompareTypeVerify(PrimType pType)
1765 {
1766     bool verifyResult = IsPrimitiveInteger(pType);
1767     if (!verifyResult) {
1768         LogInfo::MapleLogger() << "\n#Error:result type of eq,ge,gt,le,lt,ne must be primitive integer\n";
1769     }
1770     return verifyResult;
1771 }
1772 
1773 enum PTYGroup {
1774     kPTYGi32u32a32,
1775     kPTYGi32u32a32PtrRef,
1776     kPTYGi64u64a64,
1777     kPTYGPtrRef,
1778     kPTYGDynall,
1779     kPTYGu1,
1780     kPTYGSimpleObj,
1781     kPTYGSimpleStr,
1782     kPTYGOthers
1783 };
1784 
GetPTYGroup(PrimType primType)1785 uint8 GetPTYGroup(PrimType primType)
1786 {
1787     switch (primType) {
1788         case PTY_i32:
1789         case PTY_u32:
1790         case PTY_a32:
1791             return kPTYGi32u32a32;
1792         case PTY_i64:
1793         case PTY_u64:
1794         case PTY_a64:
1795             return kPTYGi64u64a64;
1796         case PTY_ref:
1797         case PTY_ptr:
1798             return kPTYGPtrRef;
1799         case PTY_dynany:
1800         case PTY_dyni32:
1801         case PTY_dynf64:
1802         case PTY_dynstr:
1803         case PTY_dynobj:
1804         case PTY_dynundef:
1805         case PTY_dynbool:
1806         case PTY_dynf32:
1807         case PTY_dynnone:
1808         case PTY_dynnull:
1809             return kPTYGDynall;
1810         case PTY_u1:
1811             return kPTYGu1;
1812         case PTY_simpleobj:
1813             return kPTYGSimpleObj;
1814         case PTY_simplestr:
1815             return kPTYGSimpleStr;
1816         default:
1817             return kPTYGOthers;
1818     }
1819 }
1820 
GetCompGroupID(const BaseNode & opnd)1821 uint8 GetCompGroupID(const BaseNode &opnd)
1822 {
1823     return GetPTYGroup(opnd.GetPrimType());
1824 }
1825 
1826 /*
1827   Refer to C11 Language Specification.
1828   $ 6.3.1.8 Usual arithmetic conversions
1829  */
CompatibleTypeVerify(const BaseNode & opnd1,const BaseNode & opnd2)1830 bool CompatibleTypeVerify(const BaseNode &opnd1, const BaseNode &opnd2)
1831 {
1832     uint8 groupID1 = GetCompGroupID(opnd1);
1833     uint8 groupID2 = GetCompGroupID(opnd2);
1834     Opcode opCode2 = opnd2.GetOpCode();
1835     bool verifyResult = (groupID1 == groupID2);
1836     if (opCode2 == OP_gcmallocjarray || opCode2 == OP_gcpermallocjarray) {
1837         verifyResult = (groupID1 == kPTYGi32u32a32);
1838     }
1839     if (!verifyResult) {
1840         LogInfo::MapleLogger() << "\n#Error:incompatible operand types :\n";
1841         opnd1.Dump();
1842         opnd2.Dump();
1843     }
1844     return verifyResult;
1845 }
1846 
FloatIntCvtTypeVerify(PrimType resPType,PrimType opndPType)1847 bool FloatIntCvtTypeVerify(PrimType resPType, PrimType opndPType)
1848 {
1849     bool resTypeVerf = resPType == PTY_i32 || resPType == PTY_u32 || resPType == PTY_i64 || resPType == PTY_u64;
1850     if (!resTypeVerf) {
1851         LogInfo::MapleLogger() << "\n#Error:result-type of ceil,floor,round,trunc must be in [i32,u32,i64,u64]\n";
1852     }
1853     bool opndTypeVerf = opndPType == PTY_f32 || opndPType == PTY_f64;
1854     if (!opndTypeVerf) {
1855         LogInfo::MapleLogger() << "\n#Error:oerand-type of ceil,floor,round,trunc must be in [f32,f64]\n";
1856     }
1857     return resTypeVerf && opndTypeVerf;
1858 }
1859 
GetTypeKind(StIdx stIdx)1860 inline MIRTypeKind GetTypeKind(StIdx stIdx)
1861 {
1862     const MIRSymbol *var = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(stIdx);
1863     DEBUG_ASSERT(var != nullptr, "null ptr check");
1864     MIRType *type = var->GetType();
1865     DEBUG_ASSERT(type != nullptr, "null ptr check");
1866     return type->GetKind();
1867 }
1868 
GetTypeKind(TyIdx tyIdx)1869 inline MIRTypeKind GetTypeKind(TyIdx tyIdx)
1870 {
1871     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1872     DEBUG_ASSERT(type != nullptr, "null ptr check");
1873     return type->GetKind();
1874 }
1875 
GetPointedMIRType(TyIdx tyIdx)1876 inline MIRType *GetPointedMIRType(TyIdx tyIdx)
1877 {
1878     MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
1879     CHECK_FATAL(type->GetKind() == kTypePointer, "TyIdx: %d is not pointer type", static_cast<uint32>(tyIdx));
1880     auto *ptrType = static_cast<MIRPtrType *>(type);
1881     return ptrType->GetPointedType();
1882 }
1883 
GetPointedTypeKind(TyIdx tyIdx)1884 inline MIRTypeKind GetPointedTypeKind(TyIdx tyIdx)
1885 {
1886     MIRType *pointedType = GetPointedMIRType(tyIdx);
1887     DEBUG_ASSERT(pointedType != nullptr, "null ptr check");
1888     return pointedType->GetKind();
1889 }
1890 
GetFieldTypeKind(MIRStructType * structType,FieldID fieldId)1891 MIRTypeKind GetFieldTypeKind(MIRStructType *structType, FieldID fieldId)
1892 {
1893     TyIdx fieldTyIdx;
1894     if (fieldId > 0) {
1895         MIRType *mirType = structType->GetFieldType(fieldId);
1896         fieldTyIdx = mirType->GetTypeIndex();
1897     } else {
1898         DEBUG_ASSERT(static_cast<unsigned>(-fieldId) < structType->GetParentFieldsSize() + 1,
1899                      "array index out of range");
1900         fieldTyIdx = structType->GetParentFieldsElemt(-fieldId - 1).second.first;
1901     }
1902     return GetTypeKind(fieldTyIdx);
1903 }
1904 
IsStructureTypeKind(MIRTypeKind kind)1905 inline bool IsStructureTypeKind(MIRTypeKind kind)
1906 {
1907     return kind == kTypeStruct || kind == kTypeStructIncomplete || kind == kTypeUnion || kind == kTypeClass ||
1908            kind == kTypeClassIncomplete || kind == kTypeInterface || kind == kTypeInterfaceIncomplete;
1909 }
1910 
IsStructureVerify(FieldID fieldID,StIdx stIdx)1911 inline bool IsStructureVerify(FieldID fieldID, StIdx stIdx)
1912 {
1913     if ((fieldID != 0) && (!IsStructureTypeKind(GetTypeKind(stIdx)))) {
1914         LogInfo::MapleLogger() << "\n#Error:if fieldID is not 0, the variable must be a structure\n";
1915         return false;
1916     }
1917     return true;
1918 }
1919 
IsStructureVerify(FieldID fieldID,TyIdx tyIdx)1920 inline bool IsStructureVerify(FieldID fieldID, TyIdx tyIdx)
1921 {
1922     if ((fieldID != 0) && (!IsStructureTypeKind(GetTypeKind(tyIdx)))) {
1923         LogInfo::MapleLogger() << "\n#Error:if fieldID is not 0, the variable must be a structure\n";
1924         return false;
1925     }
1926     return true;
1927 }
1928 
IsSignedType(const BaseNode * opnd)1929 bool IsSignedType(const BaseNode *opnd)
1930 {
1931     switch (opnd->GetPrimType()) {
1932         case PTY_i32:
1933         case PTY_i64:
1934         case PTY_f32:
1935         case PTY_f64:
1936         case PTY_dyni32:
1937         case PTY_dynf32:
1938         case PTY_dynf64:
1939             return true;
1940         default:
1941             break;
1942     }
1943     return false;
1944 }
1945 
BinaryStrictSignVerify0(const BaseNode * bOpnd0,const BaseNode * bOpnd1)1946 inline bool BinaryStrictSignVerify0(const BaseNode *bOpnd0, const BaseNode *bOpnd1)
1947 {
1948     DEBUG_ASSERT(bOpnd0 != nullptr, "bOpnd0 is null");
1949     DEBUG_ASSERT(bOpnd1 != nullptr, "bOpnd1 is null");
1950     bool isDynany = (bOpnd0->GetPrimType() == PTY_dynany || bOpnd1->GetPrimType() == PTY_dynany);
1951     return isDynany || (IsSignedType(bOpnd0) && IsSignedType(bOpnd1)) ||
1952            (!IsSignedType(bOpnd0) && !IsSignedType(bOpnd1));
1953 }
1954 
BinaryStrictSignVerify1(const BaseNode * bOpnd0,const BaseNode * bOpnd1,const BaseNode * res)1955 bool BinaryStrictSignVerify1(const BaseNode *bOpnd0, const BaseNode *bOpnd1, const BaseNode *res)
1956 {
1957     if (GetCompGroupID(*res) == kPTYGDynall) {
1958         return BinaryStrictSignVerify0(bOpnd0, res) && BinaryStrictSignVerify0(bOpnd1, res) &&
1959                BinaryStrictSignVerify0(bOpnd0, bOpnd1);
1960     }
1961     return (IsSignedType(bOpnd0) && IsSignedType(bOpnd1) && IsSignedType(res)) ||
1962            (!IsSignedType(bOpnd0) && !IsSignedType(bOpnd1) && !IsSignedType(res));
1963 }
1964 
Verify() const1965 bool UnaryNode::Verify() const
1966 {
1967     bool resTypeVerf = true;
1968     if (GetOpCode() == OP_bnot) {
1969         resTypeVerf = UnaryTypeVerify0(GetPrimType());
1970     } else if (GetOpCode() == OP_lnot) {
1971         if (!IsPrimitiveInteger(GetPrimType())) {
1972             resTypeVerf = false;
1973             LogInfo::MapleLogger() << "\n#Error:result-type of lnot must be primitive integer\n";
1974         }
1975     } else if (GetOpCode() == OP_abs || GetOpCode() == OP_neg) {
1976         resTypeVerf = UnaryTypeVerify1(GetPrimType());
1977     } else if (GetOpCode() == OP_recip || GetOpCode() == OP_sqrt) {
1978         resTypeVerf = UnaryTypeVerify2(GetPrimType());
1979     }
1980 
1981     // When an opcode only specifies one type, check for compatibility
1982     // between the operands and the result-type.
1983     bool compVerf = true;
1984     // op_alloca : return type is not compatible with operand, skip
1985     if (GetOpCode() != OP_alloca) {
1986         compVerf = CompatibleTypeVerify(*uOpnd, *this);
1987     }
1988     bool opndExprVerf = uOpnd->Verify();
1989     return resTypeVerf && compVerf && opndExprVerf;
1990 }
1991 
Verify() const1992 bool TypeCvtNode::Verify() const
1993 {
1994     bool opndTypeVerf = true;
1995     bool opndSizeVerf = true;
1996     if (GetOpCode() == OP_ceil || GetOpCode() == OP_floor || GetOpCode() == OP_round || GetOpCode() == OP_trunc) {
1997         opndTypeVerf = FloatIntCvtTypeVerify(GetPrimType(), Opnd(0)->GetPrimType());
1998     } else if (GetOpCode() == OP_retype) {
1999         if (GetPrimTypeSize(GetPrimType()) != GetPrimTypeSize(Opnd(0)->GetPrimType())) {
2000             opndSizeVerf = false;
2001             LogInfo::MapleLogger() << "\n#Error:The size of opnd0 and prim-type must be the same\n";
2002         }
2003     }
2004     bool opndExprVerf = Opnd(0)->Verify();
2005     return opndTypeVerf && opndSizeVerf && opndExprVerf;
2006 }
2007 
AddRuntimeVerifyError(std::string errMsg,VerifyResult & verifyResult)2008 void AddRuntimeVerifyError(std::string errMsg, VerifyResult &verifyResult)
2009 {
2010     LogInfo::MapleLogger() << "\n#Error: " << errMsg << '\n';
2011     // Throw Verify Error
2012     verifyResult.AddPragmaVerifyError(verifyResult.GetCurrentClassName(), std::move(errMsg));
2013 }
2014 
VerifyPrimTypesAndOpnd() const2015 bool RetypeNode::VerifyPrimTypesAndOpnd() const
2016 {
2017     PrimType toPrimType = GetPrimType();
2018     PrimType fromPrimType = Opnd(0)->GetPrimType();
2019     if (GetPrimTypeSize(toPrimType) != GetPrimTypeSize(fromPrimType)) {
2020         LogInfo::MapleLogger() << "\n#Error: The size of opnd0 and prim-type must be the same\n";
2021         return false;
2022     }
2023 
2024     if (!IsPrimitivePoint(toPrimType) || !IsPrimitivePoint(fromPrimType)) {
2025         LogInfo::MapleLogger() << "\n#Error: Wrong prim-type in retype node, should be ref or ptr\n";
2026         return false;
2027     }
2028     return Opnd(0)->Verify();
2029 }
2030 
CheckFromJarray(const MIRType & from,const MIRType & to,VerifyResult & verifyResult) const2031 bool RetypeNode::CheckFromJarray(const MIRType &from, const MIRType &to, VerifyResult &verifyResult) const
2032 {
2033     // Array types are subtypes of Object.
2034     AddRuntimeVerifyError("J array " + from.GetName() + " is not assignable to " + to.GetName(), verifyResult);
2035     return false;
2036 }
2037 
VerifyCompleteMIRType(const MIRType & from,const MIRType & to,bool isJRefType,VerifyResult & verifyResult) const2038 bool RetypeNode::VerifyCompleteMIRType(const MIRType &from, const MIRType &to, bool isJRefType,
2039                                        VerifyResult &verifyResult) const
2040 {
2041     if (from.IsScalarType() && to.IsScalarType() && !isJRefType) {
2042         if (GetPTYGroup(from.GetPrimType()) == GetPTYGroup(to.GetPrimType())) {
2043             return true;
2044         }
2045         LogInfo::MapleLogger() << "\n#Error: retype scalar type failed\n";
2046         return false;
2047     }
2048     return true;
2049 }
2050 
VerifyJarrayDimention(const MIRJarrayType & from,const MIRJarrayType & to,VerifyResult & verifyResult) const2051 bool RetypeNode::VerifyJarrayDimention(const MIRJarrayType &from, const MIRJarrayType &to,
2052                                        VerifyResult &verifyResult) const
2053 {
2054     int fromDim = const_cast<MIRJarrayType &>(from).GetDim();
2055     int toDim = const_cast<MIRJarrayType &>(to).GetDim();
2056     if (fromDim == toDim) {
2057         return true;
2058     } else if (fromDim > toDim) {
2059         const MIRType *toElemType = to.GetElemType();
2060         while (toElemType != nullptr && (toElemType->IsMIRJarrayType() || toElemType->IsMIRPtrType())) {
2061             toElemType = toElemType->IsMIRJarrayType() ? static_cast<const MIRJarrayType *>(toElemType)->GetElemType()
2062                                                        : static_cast<const MIRPtrType *>(toElemType)->GetPointedType();
2063         }
2064         if (toElemType != nullptr && CheckFromJarray(from, *toElemType, verifyResult)) {
2065             return true;
2066         }
2067     }
2068     Dump(0);
2069     std::string errorMsg =
2070         "Arrays have different dimentions: from " + std::to_string(fromDim) + " to " + std::to_string(toDim);
2071     AddRuntimeVerifyError(std::move(errorMsg), verifyResult);
2072     return false;
2073 }
2074 
Verify(VerifyResult & verifyResult) const2075 bool RetypeNode::Verify(VerifyResult &verifyResult) const
2076 {
2077     // If RetypeNode::Verify return false, Dump this node to show the wrong IR
2078     if (!VerifyPrimTypesAndOpnd()) {
2079         Dump(0);
2080         LogInfo::MapleLogger() << "\n#Error: Verify PrimTypes and Opnd failed in retype node\n";
2081         return false;
2082     }
2083     bool isJRefType = false;
2084     const MIRType *fromMIRType = verifyResult.GetCurrentFunction()->GetNodeType(*Opnd(0));
2085     const MIRType *toMIRType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
2086     while (fromMIRType != nullptr && toMIRType != nullptr && BothPointerOrJarray(*fromMIRType, *toMIRType)) {
2087         if (fromMIRType->IsMIRJarrayType()) {
2088             isJRefType = true;
2089             if (!VerifyJarrayDimention(static_cast<const MIRJarrayType &>(*fromMIRType),
2090                                        static_cast<const MIRJarrayType &>(*toMIRType), verifyResult)) {
2091                 return false;
2092             }
2093             fromMIRType = static_cast<const MIRJarrayType *>(fromMIRType)->GetElemType();
2094             toMIRType = static_cast<const MIRJarrayType *>(toMIRType)->GetElemType();
2095         } else {
2096             fromMIRType = static_cast<const MIRPtrType *>(fromMIRType)->GetPointedType();
2097             toMIRType = static_cast<const MIRPtrType *>(toMIRType)->GetPointedType();
2098         }
2099     }
2100     if (fromMIRType == nullptr || toMIRType == nullptr) {
2101         Dump(0);
2102         LogInfo::MapleLogger() << "\n#Error: MIRType is nullptr in retype node\n";
2103         return false;
2104     }
2105 
2106     if (fromMIRType->IsIncomplete() || toMIRType->IsIncomplete()) {
2107         // Add Deferred Check
2108         const std::string &currentClassName = verifyResult.GetCurrentClassName();
2109         LogInfo::MapleLogger(kLlDbg) << "Add AssignableCheck from " << fromMIRType->GetName() << " to "
2110                                      << toMIRType->GetName() << " in class " << currentClassName << '\n';
2111         verifyResult.AddPragmaAssignableCheck(currentClassName, fromMIRType->GetName(), toMIRType->GetName());
2112         // Deferred Assignable Check returns true because we should collect all the deferred checks for runtime
2113         return true;
2114     }
2115 
2116     if (VerifyCompleteMIRType(*fromMIRType, *toMIRType, isJRefType, verifyResult)) {
2117         return true;
2118     }
2119     Dump(0);
2120     LogInfo::MapleLogger() << "\n#Error: Verify Complete MIRType failed in retype node\n";
2121     return false;
2122 }
2123 
VerifyThrowable(VerifyResult & verifyResult) const2124 bool UnaryStmtNode::VerifyThrowable(VerifyResult &verifyResult) const
2125 {
2126     const BaseNode *rhs = GetRHS();
2127     if (rhs == nullptr) {
2128         return true;
2129     }
2130 
2131     const MIRType *mirType = verifyResult.GetCurrentFunction()->GetNodeType(*rhs);
2132     if (mirType != nullptr && mirType->IsMIRPtrType()) {
2133         mirType = static_cast<const MIRPtrType *>(mirType)->GetPointedType();
2134     }
2135     if (mirType != nullptr) {
2136         if (mirType->GetPrimType() == PTY_void) {
2137             return true;
2138         }
2139         if (mirType->IsIncomplete()) {
2140             // Add Deferred Check
2141             const std::string &currentClassName = verifyResult.GetCurrentClassName();
2142             std::string throwableName = "Lj_2Flang_2FThrowable_3B";
2143             LogInfo::MapleLogger(kLlDbg) << "Add AssignableCheck from " << mirType->GetName() << " to " << throwableName
2144                                          << " in class " << currentClassName << '\n';
2145             verifyResult.AddPragmaAssignableCheck(currentClassName, mirType->GetName(), std::move(throwableName));
2146             // Deferred Assignable Check returns true because we should collect all the deferred checks for runtime
2147             return true;
2148         }
2149     }
2150     Dump(0);
2151     std::string errMsg = (mirType == nullptr ? "nullptr" : mirType->GetName());
2152     errMsg += " is NOT throwable.";
2153     AddRuntimeVerifyError(std::move(errMsg), verifyResult);
2154     return false;
2155 }
2156 
Verify(VerifyResult & verifyResult) const2157 bool IntrinsicopNode::Verify(VerifyResult &verifyResult) const
2158 {
2159     return VerifyOpnds();
2160 }
2161 
VerifyJArrayLength(VerifyResult & verifyResult) const2162 bool IntrinsicopNode::VerifyJArrayLength(VerifyResult &verifyResult) const
2163 {
2164     BaseNode &val = utils::ToRef(Opnd(0));
2165     const MIRType *valType = verifyResult.GetCurrentFunction()->GetNodeType(val);
2166     if (valType != nullptr && valType->IsMIRPtrType()) {
2167         valType = static_cast<const MIRPtrType *>(valType)->GetPointedType();
2168         if (valType != nullptr && !valType->IsMIRJarrayType()) {
2169             Dump(0);
2170             AddRuntimeVerifyError("Operand of array length is not array", verifyResult);
2171             return false;
2172         }
2173     }
2174     return true;
2175 }
2176 
Verify() const2177 bool IreadNode::Verify() const
2178 {
2179     bool addrExprVerf = Opnd(0)->Verify();
2180     bool pTypeVerf = true;
2181     bool structVerf = true;
2182     if (GetTypeKind(tyIdx) != kTypePointer) {
2183         LogInfo::MapleLogger() << "\n#Error:<type> must be a pointer type\n";
2184         return false;
2185     }
2186     if (GetOpCode() == OP_iaddrof) {
2187         pTypeVerf = IsAddress(GetPrimType());
2188         if (!pTypeVerf) {
2189             LogInfo::MapleLogger() << "\n#Error:prim-type must be either ptr, ref, a32 or a64\n";
2190         }
2191     } else {
2192         if (fieldID == 0 && IsStructureTypeKind(GetPointedTypeKind(tyIdx))) {
2193             if (GetPrimType() != PTY_agg) {
2194                 pTypeVerf = false;
2195                 LogInfo::MapleLogger()
2196                     << "\n#Error:If the content dereferenced is a structure, then <prim-type> should specify agg\n";
2197             }
2198         }
2199     }
2200     if (fieldID != 0) {
2201         if (!IsStructureTypeKind(GetPointedTypeKind(tyIdx))) {
2202             structVerf = false;
2203             LogInfo::MapleLogger() << "\n#Error:If field-id is not 0, then type must specify pointer to a structure\n";
2204         } else {
2205             MIRType *type = GetPointedMIRType(tyIdx);
2206             auto *stTy = static_cast<MIRStructType *>(type);
2207             if (GetOpCode() == OP_iread && stTy->GetFieldsSize() != 0) {
2208                 if (IsStructureTypeKind(GetFieldTypeKind(stTy, fieldID))) {
2209                     if (GetPrimType() != PTY_agg) {
2210                         pTypeVerf = false;
2211                         LogInfo::MapleLogger()
2212                             << "\n#Error:If the field itself is a structure, prim-type should specify agg\n";
2213                     }
2214                 }
2215             }
2216         }
2217     }
2218     return addrExprVerf && pTypeVerf && structVerf;
2219 }
2220 
Verify() const2221 bool RegreadNode::Verify() const
2222 {
2223     return true;
2224 }
2225 
Verify() const2226 bool IreadoffNode::Verify() const
2227 {
2228     return true;
2229 }
2230 
Verify() const2231 bool IreadFPoffNode::Verify() const
2232 {
2233     return true;
2234 }
2235 
Verify() const2236 bool ExtractbitsNode::Verify() const
2237 {
2238     bool opndExprVerf = Opnd(0)->Verify();
2239     bool compVerf = CompatibleTypeVerify(*Opnd(0), *this);
2240     bool resTypeVerf = UnaryTypeVerify0(GetPrimType());
2241     constexpr int numBitsInByte = 8;
2242     bool opnd0SizeVerf = (numBitsInByte * GetPrimTypeSize(Opnd(0)->GetPrimType()) >= bitsSize);
2243     if (!opnd0SizeVerf) {
2244         LogInfo::MapleLogger()
2245             << "\n#Error: The operand of extractbits must be large enough to contain the specified bitfield\n";
2246     }
2247     return opndExprVerf && compVerf && resTypeVerf && opnd0SizeVerf;
2248 }
2249 
Verify() const2250 bool BinaryNode::Verify() const
2251 {
2252     bool opndsVerf = BinaryGenericVerify(*GetBOpnd(0), *GetBOpnd(1));
2253     bool resTypeVerf = BinaryTypeVerify(GetPrimType());
2254     if (!resTypeVerf && theMIRModule->IsCModule()) {
2255         if ((IsAddress(GetBOpnd(0)->GetPrimType()) && !IsAddress(GetBOpnd(1)->GetPrimType())) ||
2256             (!IsAddress(GetBOpnd(0)->GetPrimType()) && IsAddress(GetBOpnd(1)->GetPrimType()))) {
2257             resTypeVerf = true;  // don't print the same kind of error message twice
2258             if (GetOpCode() != OP_add && GetOpCode() != OP_sub && GetOpCode() != OP_CG_array_elem_add) {
2259                 LogInfo::MapleLogger() << "\n#Error: Only add and sub are allowed for pointer arithemetic\n";
2260                 this->Dump();
2261             } else if (!IsAddress(GetPrimType())) {
2262                 LogInfo::MapleLogger() << "\n#Error: Adding an offset to a pointer or subtracting one from a pointer "
2263                                           "should result in a pointer "
2264                                           "value\n";
2265                 this->Dump();
2266             }
2267         }
2268     }
2269     if (!resTypeVerf) {
2270         LogInfo::MapleLogger() << "\n#Error:result type of [add,div,sub,mul,max,min] and "
2271                                   "[ashr,band,bior,bxor,land,lior,lshr,shl,rem] must "
2272                                   "be in [i32,u32,i64,u64,f32,f64,dynamic-type]\n";
2273         this->Dump();
2274     }
2275     bool comp0Verf = CompatibleTypeVerify(*GetBOpnd(0), *this);
2276     bool comp1Verf = true;
2277     // Shift operations do not require same-type operands
2278     if (GetOpCode() < OP_ashr || GetOpCode() > OP_shl) {
2279         comp1Verf = CompatibleTypeVerify(*GetBOpnd(1), *this);
2280     }
2281     bool signVerf = true;
2282     bool typeVerf = resTypeVerf && comp0Verf && comp1Verf;
2283     if (typeVerf) {
2284         if (GetOpCode() == OP_div || GetOpCode() == OP_mul || GetOpCode() == OP_rem || GetOpCode() == OP_max ||
2285             GetOpCode() == OP_min) {
2286             signVerf = BinaryStrictSignVerify1(GetBOpnd(0), GetBOpnd(1), this);
2287             if (!signVerf) {
2288                 LogInfo::MapleLogger()
2289                     << "\n#Error:the result and operands of [div,mul,rem,max,min] must be of the same sign\n";
2290             }
2291         }
2292     }
2293     return opndsVerf && typeVerf && signVerf;
2294 }
2295 
Verify() const2296 bool CompareNode::Verify() const
2297 {
2298     bool opndsVerf = BinaryGenericVerify(*GetBOpnd(0), *GetBOpnd(1));
2299     bool compVerf = CompatibleTypeVerify(*GetBOpnd(0), *GetBOpnd(1));
2300     bool resTypeVerf = CompareTypeVerify(GetPrimType());
2301     if (!resTypeVerf) {
2302         this->Dump();
2303     }
2304     bool signVerf = true;
2305     bool typeVerf = compVerf && resTypeVerf;
2306     if (typeVerf && GetOpCode() != OP_eq && GetOpCode() != OP_ne) {
2307         signVerf = BinaryStrictSignVerify0(GetBOpnd(0), GetBOpnd(1));
2308         if (!signVerf) {
2309             LogInfo::MapleLogger() << "\n#Error:the operands of [ge,gt,le,lt] must be of the same sign\n";
2310         }
2311     }
2312     return opndsVerf && typeVerf && signVerf;
2313 }
2314 
Verify() const2315 bool DepositbitsNode::Verify() const
2316 {
2317     bool opndsVerf = BinaryGenericVerify(*GetBOpnd(0), *GetBOpnd(1));
2318     bool resTypeVerf = IntTypeVerify(GetPrimType());
2319     constexpr int numBitsInByte = 8;
2320     bool opnd0SizeVerf = (numBitsInByte * GetPrimTypeSize(GetBOpnd(0)->GetPrimType()) >= bitsSize);
2321     if (!opnd0SizeVerf) {
2322         LogInfo::MapleLogger()
2323             << "\n#Error:opnd0 of depositbits must be large enough to contain the specified bitfield\n";
2324     }
2325     return opndsVerf && resTypeVerf && opnd0SizeVerf;
2326 }
2327 
Verify() const2328 bool IntrinsicopNode::Verify() const
2329 {
2330     return VerifyOpnds();
2331 }
2332 
Verify() const2333 bool TernaryNode::Verify() const
2334 {
2335     bool comp1Verf = CompatibleTypeVerify(*topnd[kSecondOpnd], *this);
2336     bool comp2Verf = CompatibleTypeVerify(*topnd[kThirdOpnd], *this);
2337     bool opnd0TypeVerf = IsPrimitiveInteger(topnd[kFirstOpnd]->GetPrimType());
2338     if (!opnd0TypeVerf) {
2339         LogInfo::MapleLogger() << "\n#Error:select-opnd0 must be of integer type\n";
2340     }
2341     return comp1Verf && comp2Verf && opnd0TypeVerf;
2342 }
2343 
Verify() const2344 bool SizeoftypeNode::Verify() const
2345 {
2346     return true;
2347 }
2348 
Verify() const2349 bool ArrayNode::Verify() const
2350 {
2351     bool opndsVerf = VerifyOpnds();
2352     bool resTypeVerf = IsAddress(GetPrimType());
2353     bool opndsTypeVerf = true;
2354     if (!resTypeVerf) {
2355         LogInfo::MapleLogger() << "\n#Error:result-type of array must be in [ptr,ref,a32,a64]\n";
2356     }
2357     bool opnd0TypeVerf = IsAddress(GetNopndAt(0)->GetPrimType());
2358     if (!opnd0TypeVerf) {
2359         LogInfo::MapleLogger() << "\n#Error:result-type of array-opnd0 must be in [ptr,ref,a32,a64]\n";
2360     }
2361     for (size_t i = 1; i < NumOpnds(); ++i) {
2362         if (!IntTypeVerify(GetNopndAt(i)->GetPrimType())) {
2363             opndsTypeVerf = false;
2364             LogInfo::MapleLogger() << "\n#Error:result of the array index operands must be in [i32,u32,i64,u64]\n";
2365         }
2366     }
2367     return opndsVerf && resTypeVerf && opnd0TypeVerf && opndsTypeVerf;
2368 }
2369 
Verify() const2370 bool DassignNode::Verify() const
2371 {
2372     bool structVerf = IsStructureVerify(fieldID, stIdx);
2373     bool rhsVerf = GetRHS()->Verify();
2374     return structVerf && rhsVerf;
2375 }
2376 
Verify() const2377 bool AddrofNode::Verify() const
2378 {
2379     bool pTypeVerf = true;
2380     bool structVerf = IsStructureVerify(fieldID, GetStIdx());
2381     if (GetOpCode() == OP_dread) {
2382         if (fieldID == 0 && IsStructureTypeKind(GetTypeKind(GetStIdx()))) {
2383             if (GetPrimType() != PTY_agg) {
2384                 pTypeVerf = false;
2385                 LogInfo::MapleLogger() << "\n#Error:if variable is a structure, prim-type should specify agg\n";
2386             }
2387         }
2388         if (fieldID != 0 && structVerf) {
2389             const MIRSymbol *var = theMIRModule->CurFunction()->GetLocalOrGlobalSymbol(GetStIdx());
2390             DEBUG_ASSERT(var != nullptr, "null ptr check");
2391             MIRType *type = var->GetType();
2392             auto *stTy = static_cast<MIRStructType *>(type);
2393             if (IsStructureTypeKind(GetFieldTypeKind(stTy, fieldID))) {
2394                 if (GetPrimType() != PTY_agg) {
2395                     pTypeVerf = false;
2396                     LogInfo::MapleLogger()
2397                         << "\n#Error:if the field itself is a structure, prim-type should specify agg\n";
2398                 }
2399             }
2400         }
2401     } else {
2402         pTypeVerf = IsAddress(GetPrimType());
2403         if (!pTypeVerf) {
2404             LogInfo::MapleLogger()
2405                 << "\n#Error:result-type of addrof,addroflabel,addroffunc,iaddrof must be in [ptr,ref,a32,a64]\n";
2406         }
2407     }
2408     return pTypeVerf && structVerf;
2409 }
2410 
Verify() const2411 bool AddroffuncNode::Verify() const
2412 {
2413     bool addrTypeVerf = IsAddress(GetPrimType());
2414     if (!addrTypeVerf) {
2415         LogInfo::MapleLogger()
2416             << "\n#Error:result-type of addrof,addroflabel,addroffunc,iaddrof must be in [ptr,ref,a32,a64]\n";
2417     }
2418     return addrTypeVerf;
2419 }
2420 
Verify() const2421 bool AddroflabelNode::Verify() const
2422 {
2423     bool addrTypeVerf = IsAddress(GetPrimType());
2424     if (!addrTypeVerf) {
2425         LogInfo::MapleLogger()
2426             << "\n#Error:result-type of addrof,addroflabel,addroffunc,iaddrof must be in [ptr,ref,a32,a64]\n";
2427     }
2428     return addrTypeVerf;
2429 }
2430 
Verify() const2431 bool IassignNode::Verify() const
2432 {
2433     bool addrExpVerf = addrExpr->Verify();
2434     bool rhsVerf = rhs->Verify();
2435     bool structVerf = true;
2436     if (GetTypeKind(tyIdx) != kTypePointer) {
2437         LogInfo::MapleLogger() << "\n#Error:<type> must be a pointer type\n";
2438         return false;
2439     }
2440     if (fieldID != 0) {
2441         if (!IsStructureTypeKind(GetPointedTypeKind(tyIdx))) {
2442             structVerf = false;
2443             LogInfo::MapleLogger()
2444                 << "\n#Error:If field-id is not 0, the computed address must correspond to a structure\n";
2445         }
2446     }
2447     return addrExpVerf && rhsVerf && structVerf;
2448 }
2449 
Verify() const2450 bool IassignoffNode::Verify() const
2451 {
2452     bool addrVerf = GetBOpnd(0)->Verify();
2453     bool rhsVerf = GetBOpnd(1)->Verify();
2454     bool compVerf = CompatibleTypeVerify(*this, *GetBOpnd(1));
2455     return addrVerf && rhsVerf && compVerf;
2456 }
2457 
Verify() const2458 bool IassignFPoffNode::Verify() const
2459 {
2460     bool rhsVerf = Opnd(0)->Verify();
2461     bool compVerf = CompatibleTypeVerify(*this, *Opnd(0));
2462     return rhsVerf && compVerf;
2463 }
2464 
Verify() const2465 bool RegassignNode::Verify() const
2466 {
2467     bool rhsVerf = Opnd(0)->Verify();
2468     bool compVerf = CompatibleTypeVerify(*this, *Opnd(0));
2469     return rhsVerf && compVerf;
2470 }
2471 
Verify() const2472 bool CondGotoNode::Verify() const
2473 {
2474     bool opndExprVerf = UnaryStmtNode::Opnd(0)->Verify();
2475     bool opndTypeVerf = true;
2476     if (!IsPrimitiveInteger(UnaryStmtNode::Opnd(0)->GetPrimType())) {
2477         opndTypeVerf = false;
2478         LogInfo::MapleLogger() << "\n#Error:the operand of brfalse and trfalse must be primitive integer\n";
2479     }
2480     return opndExprVerf && opndTypeVerf;
2481 }
2482 
Verify() const2483 bool SwitchNode::Verify() const
2484 {
2485     bool opndExprVerf = switchOpnd->Verify();
2486     bool opndTypeVerf = IntTypeVerify(switchOpnd->GetPrimType());
2487     if (!opndTypeVerf) {
2488         LogInfo::MapleLogger() << "\n#Error: the operand of switch must be in [i32,u32,i64,u64]\n";
2489     }
2490     return opndExprVerf && opndTypeVerf;
2491 }
2492 
Verify() const2493 bool BinaryStmtNode::Verify() const
2494 {
2495     return GetBOpnd(0)->Verify() && GetBOpnd(1)->Verify() && CompatibleTypeVerify(*GetBOpnd(0), *GetBOpnd(1)) &&
2496            BinaryStrictSignVerify0(GetBOpnd(0), GetBOpnd(1));
2497 }
2498 
Verify() const2499 bool RangeGotoNode::Verify() const
2500 {
2501     bool opndExprVerf = Opnd(0)->Verify();
2502     bool opndTypeVerf = IntTypeVerify(Opnd(0)->GetPrimType());
2503     if (!opndTypeVerf) {
2504         LogInfo::MapleLogger() << "\n#Error: the operand of rangegoto must be in [i32,u32,i64,u64]\n";
2505     }
2506     return opndExprVerf && opndTypeVerf;
2507 }
2508 
Verify() const2509 bool BlockNode::Verify() const
2510 {
2511     for (auto &stmt : GetStmtNodes()) {
2512         if (!stmt.Verify()) {
2513             return false;
2514         }
2515     }
2516     return true;
2517 }
2518 
Verify(VerifyResult & verifyResult) const2519 bool BlockNode::Verify(VerifyResult &verifyResult) const
2520 {
2521     auto &nodes = GetStmtNodes();
2522     return !std::any_of(nodes.begin(), nodes.end(), [&verifyResult](auto &stmt) { return !stmt.Verify(verifyResult); });
2523 }
2524 
Verify() const2525 bool DoloopNode::Verify() const
2526 {
2527     bool startVerf = startExpr->Verify();
2528     bool contVerf = condExpr->Verify();
2529     bool incrVerf = incrExpr->Verify();
2530     bool doBodyVerf = true;
2531     if (doBody) {
2532         doBodyVerf = doBody->Verify();
2533     }
2534     return startVerf && contVerf && incrVerf && doBodyVerf;
2535 }
2536 
Verify() const2537 bool IfStmtNode::Verify() const
2538 {
2539     bool condVerf = Opnd()->Verify();
2540     bool thenVerf = true;
2541     bool elseVerf = true;
2542     if (thenPart != nullptr) {
2543         thenVerf = thenPart->Verify();
2544     }
2545     if (elsePart != nullptr) {
2546         elseVerf = elsePart->Verify();
2547     }
2548     return condVerf && thenVerf && elseVerf;
2549 }
2550 
Verify() const2551 bool WhileStmtNode::Verify() const
2552 {
2553     bool condVerf = Opnd(0)->Verify();
2554     bool bodyVerf = true;
2555     if (body != nullptr) {
2556         bodyVerf = body->Verify();
2557     }
2558     return condVerf && bodyVerf;
2559 }
2560 
Verify() const2561 bool NaryStmtNode::Verify() const
2562 {
2563     return VerifyOpnds();
2564 }
2565 
Verify() const2566 bool CallNode::Verify() const
2567 {
2568     return VerifyOpnds();
2569 }
2570 
Verify() const2571 bool IcallNode::Verify() const
2572 {
2573     bool nOpndsVerf = true;
2574     for (size_t i = 0; i < NumOpnds(); ++i) {
2575         if (!GetNopndAt(i)->Verify()) {
2576             nOpndsVerf = false;
2577             break;
2578         }
2579     }
2580     return nOpndsVerf;
2581 }
2582 
Verify() const2583 bool IntrinsiccallNode::Verify() const
2584 {
2585     return VerifyOpnds();
2586 }
2587 
GetFuncName() const2588 std::string SafetyCallCheckStmtNode::GetFuncName() const
2589 {
2590     return GlobalTables::GetStrTable().GetStringFromStrIdx(callFuncNameIdx);
2591 }
2592 
GetStmtFuncName() const2593 std::string SafetyCallCheckStmtNode::GetStmtFuncName() const
2594 {
2595     return GlobalTables::GetStrTable().GetStringFromStrIdx(stmtFuncNameIdx);
2596 }
2597 
GetFuncName() const2598 std::string SafetyCheckStmtNode::GetFuncName() const
2599 {
2600     return GlobalTables::GetStrTable().GetStringFromStrIdx(funcNameIdx);
2601 }
2602 
IsSameContent(const BaseNode * node) const2603 bool UnaryNode::IsSameContent(const BaseNode *node) const
2604 {
2605     auto *unaryNode = dynamic_cast<const UnaryNode *>(node);
2606     if ((this == unaryNode) || (unaryNode != nullptr && (GetOpCode() == unaryNode->GetOpCode()) &&
2607                                 (GetPrimType() == unaryNode->GetPrimType()) &&
2608                                 (uOpnd && unaryNode->Opnd(0) && uOpnd->IsSameContent(unaryNode->Opnd(0))))) {
2609         return true;
2610     } else {
2611         return false;
2612     }
2613 }
2614 
IsSameContent(const BaseNode * node) const2615 bool TypeCvtNode::IsSameContent(const BaseNode *node) const
2616 {
2617     auto *tyCvtNode = dynamic_cast<const TypeCvtNode *>(node);
2618     if ((this == tyCvtNode) ||
2619         (tyCvtNode != nullptr && (fromPrimType == tyCvtNode->FromType()) && UnaryNode::IsSameContent(tyCvtNode))) {
2620         return true;
2621     } else {
2622         return false;
2623     }
2624 }
2625 
IsSameContent(const BaseNode * node) const2626 bool IreadNode::IsSameContent(const BaseNode *node) const
2627 {
2628     auto *ireadNode = dynamic_cast<const IreadNode *>(node);
2629     if ((this == ireadNode) || (ireadNode != nullptr && (tyIdx == ireadNode->GetTyIdx()) &&
2630                                 (fieldID == ireadNode->GetFieldID()) && UnaryNode::IsSameContent(ireadNode))) {
2631         return true;
2632     } else {
2633         return false;
2634     }
2635 }
2636 
IsSameContent(const BaseNode * node) const2637 bool IreadoffNode::IsSameContent(const BaseNode *node) const
2638 {
2639     auto *ireadoffNode = dynamic_cast<const IreadoffNode *>(node);
2640     if ((this == ireadoffNode) || (ireadoffNode != nullptr && (GetOffset() == ireadoffNode->GetOffset()) &&
2641                                    UnaryNode::IsSameContent(ireadoffNode))) {
2642         return true;
2643     } else {
2644         return false;
2645     }
2646 }
2647 
IsSameContent(const BaseNode * node) const2648 bool IreadFPoffNode::IsSameContent(const BaseNode *node) const
2649 {
2650     auto *ireadFPoffNode = dynamic_cast<const IreadFPoffNode *>(node);
2651     if ((this == ireadFPoffNode) ||
2652         (ireadFPoffNode != nullptr && (GetOpCode() == ireadFPoffNode->GetOpCode()) &&
2653          (GetPrimType() == ireadFPoffNode->GetPrimType()) && (GetOffset() == ireadFPoffNode->GetOffset()))) {
2654         return true;
2655     } else {
2656         return false;
2657     }
2658 }
2659 
IsSameContent(const BaseNode * node) const2660 bool BinaryOpnds::IsSameContent(const BaseNode *node) const
2661 {
2662     auto *binaryOpnds = dynamic_cast<const BinaryOpnds *>(node);
2663     if ((this == binaryOpnds) || (binaryOpnds != nullptr && GetBOpnd(0)->IsSameContent(binaryOpnds->GetBOpnd(0)) &&
2664                                   GetBOpnd(1)->IsSameContent(binaryOpnds->GetBOpnd(1)))) {
2665         return true;
2666     } else {
2667         return false;
2668     }
2669 }
2670 
IsSameContent(const BaseNode * node) const2671 bool BinaryNode::IsSameContent(const BaseNode *node) const
2672 {
2673     auto *binaryNode = dynamic_cast<const BinaryNode *>(node);
2674     if ((this == binaryNode) ||
2675         (binaryNode != nullptr && (GetOpCode() == binaryNode->GetOpCode()) &&
2676          (GetPrimType() == binaryNode->GetPrimType()) && BinaryOpnds::IsSameContent(binaryNode))) {
2677         return true;
2678     } else {
2679         return false;
2680     }
2681 }
2682 
IsSameContent(const BaseNode * node) const2683 bool ConstvalNode::IsSameContent(const BaseNode *node) const
2684 {
2685     auto *constvalNode = dynamic_cast<const ConstvalNode *>(node);
2686     if (this == constvalNode) {
2687         return true;
2688     }
2689     if (constvalNode == nullptr) {
2690         return false;
2691     }
2692     const MIRConst *mirConst = constvalNode->GetConstVal();
2693     if (constVal == mirConst) {
2694         return true;
2695     }
2696     if (constVal->GetKind() != mirConst->GetKind()) {
2697         return false;
2698     }
2699     if (constVal->GetKind() == kConstInt) {
2700         // integer may differ in primtype, and they may be different MIRIntConst Node
2701         return static_cast<MIRIntConst *>(constVal)->GetValue() ==
2702                static_cast<const MIRIntConst *>(mirConst)->GetValue();
2703     } else {
2704         return false;
2705     }
2706 }
2707 
IsSameContent(const BaseNode * node) const2708 bool ConststrNode::IsSameContent(const BaseNode *node) const
2709 {
2710     if (node->GetOpCode() != OP_conststr) {
2711         return false;
2712     }
2713     auto *cstrNode = static_cast<const ConststrNode *>(node);
2714     return strIdx == cstrNode->strIdx;
2715 }
2716 
IsSameContent(const BaseNode * node) const2717 bool Conststr16Node::IsSameContent(const BaseNode *node) const
2718 {
2719     if (node->GetOpCode() != OP_conststr16) {
2720         return false;
2721     }
2722     auto *cstr16Node = static_cast<const Conststr16Node *>(node);
2723     return strIdx == cstr16Node->strIdx;
2724 }
2725 
IsSameContent(const BaseNode * node) const2726 bool AddrofNode::IsSameContent(const BaseNode *node) const
2727 {
2728     auto *addrofNode = dynamic_cast<const AddrofNode *>(node);
2729     if ((this == addrofNode) ||
2730         (addrofNode != nullptr && (GetOpCode() == addrofNode->GetOpCode()) &&
2731          (GetPrimType() == addrofNode->GetPrimType()) && (GetNumOpnds() == addrofNode->GetNumOpnds()) &&
2732          (stIdx.FullIdx() == addrofNode->GetStIdx().FullIdx()) && (fieldID == addrofNode->GetFieldID()))) {
2733         return true;
2734     } else {
2735         return false;
2736     }
2737 }
2738 
IsSameContent(const BaseNode * node) const2739 bool DreadoffNode::IsSameContent(const BaseNode *node) const
2740 {
2741     auto *dreaddoffNode = dynamic_cast<const DreadoffNode *>(node);
2742     if ((this == dreaddoffNode) || (dreaddoffNode != nullptr && (GetOpCode() == dreaddoffNode->GetOpCode()) &&
2743                                     (GetPrimType() == dreaddoffNode->GetPrimType()) &&
2744                                     (stIdx == dreaddoffNode->stIdx) && (offset == dreaddoffNode->offset))) {
2745         return true;
2746     } else {
2747         return false;
2748     }
2749 }
2750 
IsSameContent(const BaseNode * node) const2751 bool RegreadNode::IsSameContent(const BaseNode *node) const
2752 {
2753     auto *regreadNode = dynamic_cast<const RegreadNode *>(node);
2754     if ((this == regreadNode) ||
2755         (regreadNode != nullptr && (GetOpCode() == regreadNode->GetOpCode()) &&
2756          (GetPrimType() == regreadNode->GetPrimType()) && (regIdx == regreadNode->GetRegIdx()))) {
2757         return true;
2758     } else {
2759         return false;
2760     }
2761 }
2762 
IsSameContent(const BaseNode * node) const2763 bool AddroffuncNode::IsSameContent(const BaseNode *node) const
2764 {
2765     auto *addroffuncNode = dynamic_cast<const AddroffuncNode *>(node);
2766     if ((this == addroffuncNode) ||
2767         (addroffuncNode != nullptr && (GetOpCode() == addroffuncNode->GetOpCode()) &&
2768          (GetPrimType() == addroffuncNode->GetPrimType()) && (puIdx == addroffuncNode->GetPUIdx()))) {
2769         return true;
2770     } else {
2771         return false;
2772     }
2773 }
2774 
IsSameContent(const BaseNode * node) const2775 bool AddroflabelNode::IsSameContent(const BaseNode *node) const
2776 {
2777     auto *addroflabelNode = dynamic_cast<const AddroflabelNode *>(node);
2778     if ((this == addroflabelNode) ||
2779         (addroflabelNode != nullptr && (GetOpCode() == addroflabelNode->GetOpCode()) &&
2780          (GetPrimType() == addroflabelNode->GetPrimType()) && (offset == addroflabelNode->GetOffset()))) {
2781         return true;
2782     } else {
2783         return false;
2784     }
2785 }
2786 }  // namespace maple
2787