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 ¤tClassName = 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 ¤tClassName = 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