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