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