diff --git a/src/bin/maple b/src/bin/maple index 4f3c69dd6df17cf7698c6cf16453374ebfe43e1d..87a51ec8d19571ebbe02704798b5ff91fa008677 100755 Binary files a/src/bin/maple and b/src/bin/maple differ diff --git a/src/maple_be/mdgen/gendef.py b/src/maple_be/mdgen/gendef.py index 5f8981e3521295410314cf9d5a2e370365ac7ca9..6296937df33119b4e78db7469fa7379d1735c0ae 100755 --- a/src/maple_be/mdgen/gendef.py +++ b/src/maple_be/mdgen/gendef.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# coding=utf-8 # # Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. # diff --git a/src/maple_be/src/cg/script/genmop.py b/src/maple_be/src/cg/script/genmop.py index f7df82ef64ae86a13c53bba3ce4ead673f5a49f0..a5654b54756ac360395f3bd7d646cda151dd68a6 100644 --- a/src/maple_be/src/cg/script/genmop.py +++ b/src/maple_be/src/cg/script/genmop.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# coding=utf-8 # # Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. # diff --git a/src/maple_driver/defs/phases.def b/src/maple_driver/defs/phases.def index 289690c15471d0616cd976a906e1e324620f4af2..91dd4619e29287d439219a889f757858dc8fb3e8 100644 --- a/src/maple_driver/defs/phases.def +++ b/src/maple_driver/defs/phases.def @@ -19,6 +19,7 @@ ADD_PHASE("classhierarchy", true) ADD_PHASE("callgraph", true) ADD_PHASE("vtableanalysis", true) ADD_PHASE("reflectionanalysis", JAVALANG) +ADD_PHASE("GenNativeStubFunc", true) ADD_PHASE("gencheckcast", JAVALANG) ADD_PHASE("javaintrnlowering", JAVALANG) // mephase begin @@ -43,9 +44,9 @@ ADD_PHASE("rclowering", JAVALANG) ADD_PHASE("rename2preg", MeOption::optLevel == 2) //ADD_PHASE("lpre", MeOption::optLevel == 2) ADD_PHASE("pregrename", MeOption::optLevel == 2) +ADD_PHASE("bblayout", MeOption::optLevel == 2 || JAVALANG) ADD_PHASE("emit", MeOption::optLevel == 2 || JAVALANG) // mephase end -ADD_PHASE("GenNativeStubFunc", true) ADD_PHASE("clinit", true) ADD_PHASE("VtableImpl", true) ADD_PHASE("CodeReLayout", MeOption::optLevel == 2) diff --git a/src/maple_me/include/hdse.h b/src/maple_me/include/hdse.h index 836068196bef338ed7818ed315f12ac478b0f4c0..0729c41374db72a0580bc53ed269c56db0b653d2 100644 --- a/src/maple_me/include/hdse.h +++ b/src/maple_me/include/hdse.h @@ -64,7 +64,7 @@ class HDSE { void MarkLastBranchStmtInBBRequired(BB &bb); void MarkLastStmtInPDomBBRequired(const BB &bb); void MarkLastUnconditionalGotoInPredBBRequired(const BB &bb); - void MarkDefStmt(ScalarMeExpr &scalarExpr); + void MarkVarDefByStmt(VarMeExpr &varMeExpr); void MarkRegDefByStmt(RegMeExpr ®MeExpr); void CollectNotNullExpr(MeStmt &stmt); // NotNullExpr means it is impossible value of the expr is nullptr after go through this stmt. @@ -79,14 +79,6 @@ class HDSE { exprLive.at(static_cast(static_cast(meExpr.GetExprID()))) = true; } - void AddNewUse(MeExpr &meExpr) { - if (IsExprNeeded(meExpr)) { - return; - } - SetExprNeeded(meExpr); - workList.push_front(&meExpr); - } - void PropagateLive() { while (!workList.empty()) { MeExpr *meExpr = workList.front(); @@ -95,8 +87,6 @@ class HDSE { } } - void RemoveNotRequiredCallAssignPart(MeStmt &stmt); - void RemoveNotRequiredStmts() { for (auto *bb : bbVec) { if (bb == nullptr) { diff --git a/src/maple_me/include/me_bb_layout.h b/src/maple_me/include/me_bb_layout.h index 2f0655a46cfea27fb9d1a9f77a15c9ac3569d7b0..1bc50a156fe6e97d764416b04c9a942e6fae75d8 100644 --- a/src/maple_me/include/me_bb_layout.h +++ b/src/maple_me/include/me_bb_layout.h @@ -19,11 +19,10 @@ #include "me_pgo_instrument.h" namespace maple { -class BBLayout : public AnalysisResult { +class BBLayout{ public: BBLayout(MemPool &memPool, MeFunction &f, bool enabledDebug) - : AnalysisResult(&memPool), - func(f), + : func(f), layoutAlloc(&memPool), layoutBBs(layoutAlloc.Adapter()), startTryBBVec(func.GetAllBBs().size(), false, layoutAlloc.Adapter()), @@ -35,7 +34,7 @@ class BBLayout : public AnalysisResult { laidOut[func.GetCommonExitBB()->GetBBId()] = true; } - virtual ~BBLayout() = default; + ~BBLayout() = default; BB *NextBB() { // return the next BB following strictly program input order ++curBBId; diff --git a/src/maple_me/include/me_function.h b/src/maple_me/include/me_function.h index eb06124d16d65dd1413dcaa5406c84e8e372337a..3b67ff4671fa2c5fd777aaafe8c07b2095dedec0 100644 --- a/src/maple_me/include/me_function.h +++ b/src/maple_me/include/me_function.h @@ -170,6 +170,7 @@ class MeFunction : public FuncEmit { mirFunc(func), labelBBIdMap(alloc.Adapter()), bbVec(alloc.Adapter()), + laidOutBBVec(alloc.Adapter()), bbTryNodeMap(alloc.Adapter()), endTryBB2TryBB(alloc.Adapter()), sccTopologicalVec(alloc.Adapter()), @@ -341,6 +342,25 @@ class MeFunction : public FuncEmit { return bbVec; } + const MapleVector &GetLaidOutBBs() const { + return laidOutBBVec; + } + + void SetLaidOutBBs(const MapleVector &laidout) { + laidOutBBVec = laidout; + } + + bool HasLaidOut() const { + return !laidOutBBVec.empty(); + } + + void ClearLayout() { + if (laidOutBBVec.empty()) { + return; + } + laidOutBBVec.clear(); + } + BB *GetBBFromID(BBId bbID) { ASSERT(bbID < bbVec.size(), "array index out of range"); return bbVec.at(bbID); @@ -514,6 +534,7 @@ class MeFunction : public FuncEmit { /* mempool */ MapleUnorderedMap labelBBIdMap; BBPtrHolder bbVec; + MapleVector laidOutBBVec; MeCFG *theCFG = nullptr; SSATab *meSSATab = nullptr; MeIRMap *irmap = nullptr; diff --git a/src/maple_me/src/alias_class.cpp b/src/maple_me/src/alias_class.cpp index 75b671ce909f462462f7326a09fb01baf8128ff2..b0e9ce5339dc5a7c1b5679275ffdb6a1f024f182 100644 --- a/src/maple_me/src/alias_class.cpp +++ b/src/maple_me/src/alias_class.cpp @@ -36,6 +36,9 @@ namespace maple { bool AliasClass::CallHasNoSideEffectOrPrivateDefEffect(const CallNode &stmt, FuncAttrKind attrKind) const { ASSERT(attrKind == FUNCATTR_nosideeffect || attrKind == FUNCATTR_noprivate_defeffect, "Not supportted attrKind"); MIRFunction *callee = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(stmt.GetPUIdx()); + if (callee == nullptr) { + return false; + } bool hasAttr = false; if (callee->GetFuncAttrs().GetAttr(attrKind)) { hasAttr = true; diff --git a/src/maple_me/src/hdse.cpp b/src/maple_me/src/hdse.cpp index b74042f98b75927a094d325e1446f915c311986f..c5acba75e7782b09ffc6712e6aadea0fc8caeb64 100755 --- a/src/maple_me/src/hdse.cpp +++ b/src/maple_me/src/hdse.cpp @@ -36,22 +36,6 @@ namespace maple { using namespace utils; -void HDSE::RemoveNotRequiredCallAssignPart(MeStmt &stmt) { - if (!kOpcodeInfo.IsCallAssigned(stmt.GetOp())) { - return; - } - auto *assignPart = stmt.GetMustDefList(); - bool assignPartRequired = false; - for (auto it = assignPart->begin(); it != assignPart->end(); ++it) { - if (IsExprNeeded(*it->GetLHS())) { - assignPartRequired = true; - } - } - if (!assignPartRequired) { - assignPart->clear(); - } -} - void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { for (auto &meStmt : bb.GetMeStmts()) { if (!meStmt.GetIsLive()) { @@ -59,7 +43,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { mirModule.GetOut() << "========== HSSA DSE is deleting this stmt: "; meStmt.Dump(&irMap); } - if (meStmt.IsCondBr() || meStmt.GetOp() == OP_switch) { + if (meStmt.GetOp() != OP_dassign && (meStmt.IsCondBr() || meStmt.GetOp() == OP_switch)) { // update CFG while (bb.GetSucc().size() != 1) { BB *succ = bb.GetSucc().back(); @@ -83,7 +67,6 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } bb.RemoveMeStmt(&meStmt); } - RemoveNotRequiredCallAssignPart(meStmt); } } @@ -104,7 +87,7 @@ bool HDSE::NeedNotNullCheck(MeExpr &meExpr, const BB &bb) { void HDSE::MarkMuListRequired(MapleMap &muList) { for (auto &pair : muList) { - AddNewUse(*pair.second); + workList.push_front(pair.second); } } @@ -113,7 +96,7 @@ void HDSE::MarkChiNodeRequired(ChiMeNode &chiNode) { return; } chiNode.SetIsLive(true); - AddNewUse(*chiNode.GetRHS()); + workList.push_front(chiNode.GetRHS()); MeStmt *meStmt = chiNode.GetBase(); MarkStmtRequired(*meStmt); } @@ -132,25 +115,30 @@ void HDSE::MarkPhiRequired(VarOrRegPhiNode &mePhiNode) { MarkControlDependenceLive(*mePhiNode.GetDefBB()); } -void HDSE::MarkDefStmt(ScalarMeExpr &scalarExpr) { - switch (scalarExpr.GetDefBy()) { +void HDSE::MarkVarDefByStmt(VarMeExpr &varExpr) { + switch (varExpr.GetDefBy()) { case kDefByNo: break; case kDefByStmt: { - auto *defStmt = scalarExpr.GetDefStmt(); - MarkStmtRequired(*defStmt); + auto *defStmt = varExpr.GetDefStmt(); + if (defStmt != nullptr) { + MarkStmtRequired(*defStmt); + } break; } case kDefByPhi: { - MarkPhiRequired(scalarExpr.GetDefPhi()); + MarkPhiRequired(varExpr.GetDefPhi()); break; } case kDefByChi: { - MarkChiNodeRequired(scalarExpr.GetDefChi()); + auto *defChi = &varExpr.GetDefChi(); + if (defChi != nullptr) { + MarkChiNodeRequired(*defChi); + } break; } case kDefByMustDef: { - auto *mustDef = &scalarExpr.GetDefMustDef(); + auto *mustDef = &varExpr.GetDefMustDef(); if (!mustDef->GetIsLive()) { mustDef->SetIsLive(true); MarkStmtRequired(*mustDef->GetBase()); @@ -163,28 +151,62 @@ void HDSE::MarkDefStmt(ScalarMeExpr &scalarExpr) { } } +void HDSE::MarkRegDefByStmt(RegMeExpr ®MeExpr) { + PregIdx regIdx = regMeExpr.GetRegIdx(); + if (regIdx == -kSregRetval0) { + if (regMeExpr.GetDefStmt()) { + MarkStmtRequired(*regMeExpr.GetDefStmt()); + } + return; + } + switch (regMeExpr.GetDefBy()) { + case kDefByNo: + break; + case kDefByStmt: { + auto *defStmt = regMeExpr.GetDefStmt(); + if (defStmt != nullptr) { + MarkStmtRequired(*defStmt); + } + break; + } + case kDefByPhi: + MarkPhiRequired(regMeExpr.GetDefPhi()); + break; + case kDefByMustDef: { + MustDefMeNode *mustDef = ®MeExpr.GetDefMustDef(); + if (!mustDef->GetIsLive()) { + mustDef->SetIsLive(true); + MarkStmtRequired(*mustDef->GetBase()); + } + break; + } + default: + ASSERT(false, "MarkRegDefByStmt unexpected defBy value"); + break; + } +} + // Find all stmt contains ivar and save to stmt2NotNullExpr // Find all not null expr used as ivar's base、OP_array's or OP_assertnonnull's opnd // And save to notNullExpr2Stmt void HDSE::CollectNotNullExpr(MeStmt &stmt) { size_t opndNum = stmt.NumMeStmtOpnds(); - size_t i = 0; - if (opndNum > 0 && instance_of(stmt)) { - CallMeStmt &callStmt = static_cast(stmt); - if (callStmt.GetTargetFunction().IsStatic()) { - CollectNotNullExpr(stmt, ToRef(stmt.GetOpnd(0)), kExprTypeNormal); - } - CollectNotNullExpr(stmt, ToRef(stmt.GetOpnd(0)), kExprTypeNotNull); - ++i; - } - for (; i < opndNum; ++i) { + uint8 exprType = kExprTypeNormal; + for (size_t i = 0; i < opndNum; ++i) { MeExpr *opnd = stmt.GetOpnd(i); - // A normal opnd not sure - MeExprOp meOp = opnd->GetMeOp(); - if (meOp == kMeOpVar || meOp == kMeOpReg) { - continue; + if (i == 0 && instance_of(stmt)) { + // A non-static call's first opnd is this, should be not null + CallMeStmt &callStmt = static_cast(stmt); + exprType = callStmt.GetTargetFunction().IsStatic() ? kExprTypeNormal : kExprTypeNotNull; + } else { + // A normal opnd not sure + MeExprOp meOp = opnd->GetMeOp(); + if (meOp == kMeOpVar || meOp == kMeOpReg) { + continue; + } + exprType = kExprTypeNormal; } - CollectNotNullExpr(stmt, ToRef(opnd), kExprTypeNormal); + CollectNotNullExpr(stmt, ToRef(opnd), exprType); } } @@ -213,7 +235,7 @@ void HDSE::CollectNotNullExpr(MeStmt &stmt, MeExpr &meExpr, uint8 exprType) { } default: { if (exprType != kExprTypeNormal) { - // Ref expr used in ivar array or assertnotnull + // Ref expr used in ivar、array or assertnotnull PrimType type = meExpr.GetPrimType(); if (type == PTY_ref || type == PTY_ptr) { notNullExpr2Stmt[&meExpr].push_back(&stmt); @@ -234,9 +256,14 @@ void HDSE::CollectNotNullExpr(MeStmt &stmt, MeExpr &meExpr, uint8 exprType) { void HDSE::PropagateUseLive(MeExpr &meExpr) { switch (meExpr.GetMeOp()) { - case kMeOpVar: + case kMeOpVar: { + auto &varMeExpr = static_cast(meExpr); + MarkVarDefByStmt(varMeExpr); + return; + } case kMeOpReg: { - MarkDefStmt(static_cast(meExpr)); + auto ®MeExpr = static_cast(meExpr); + MarkRegDefByStmt(regMeExpr); return; } default: { @@ -392,16 +419,14 @@ void HDSE::MarkSingleUseLive(MeExpr &meExpr) { case kMeOpVar: case kMeOpReg: { workList.push_front(&meExpr); - return; + break; } case kMeOpIvar: { auto *base = static_cast(meExpr).GetBase(); if (base != nullptr) { MarkSingleUseLive(*base); } - - MarkSingleUseLive(*static_cast(meExpr).GetMu()); - return; + break; } default: break; @@ -440,10 +465,6 @@ void HDSE::MarkStmtRequired(MeStmt &meStmt) { if (meStmt.GetOp() == OP_comment) { return; } - auto *prev = meStmt.GetPrev(); - if (prev != nullptr && prev->GetOp() == OP_comment) { - prev->SetIsLive(true); - } // mark use MarkStmtUseLive(meStmt); @@ -455,7 +476,7 @@ void HDSE::MarkStmtRequired(MeStmt &meStmt) { bool HDSE::StmtMustRequired(const MeStmt &meStmt, const BB &bb) const { Opcode op = meStmt.GetOp(); // special opcode cannot be eliminated - if (IsStmtMustRequire(op)) { + if (IsStmtMustRequire(op) || op == OP_comment) { return true; } // control flow in an infinite loop cannot be eliminated @@ -477,10 +498,10 @@ void HDSE::MarkSpecialStmtRequired() { auto &meStmtNodes = bb->GetMeStmts(); for (auto itStmt = meStmtNodes.rbegin(); itStmt != meStmtNodes.rend(); ++itStmt) { MeStmt *pStmt = to_ptr(itStmt); + CollectNotNullExpr(*pStmt); if (pStmt->GetIsLive()) { continue; } - CollectNotNullExpr(*pStmt); if (StmtMustRequired(*pStmt, *bb)) { MarkStmtRequired(*pStmt); } diff --git a/src/maple_me/src/me_bb_layout.cpp b/src/maple_me/src/me_bb_layout.cpp index aecbae47e606c1e5aaf5c65d39c8ac69029e127d..dba2fee849a3c2f9d0bf58b5f59b0f73f0e054ad 100644 --- a/src/maple_me/src/me_bb_layout.cpp +++ b/src/maple_me/src/me_bb_layout.cpp @@ -835,13 +835,12 @@ AnalysisResult *MeDoBBLayout::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, func->GetTheCfg()->DumpToFile("beforeBBLayout", false); } bbLayout->RunLayout(); - if (bbLayout->IsNewBBInLayout()) { - funcResMgr->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, func); - } + func->SetLaidOutBBs(bbLayout->GetBBs()); + funcResMgr->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, func); if (DEBUGFUNC(func)) { bbLayout->DumpBBPhyOrder(); func->GetTheCfg()->DumpToFile("afterBBLayout", false); } - return bbLayout; + return nullptr; } } // namespace maple diff --git a/src/maple_me/src/me_emit.cpp b/src/maple_me/src/me_emit.cpp index e04eea5a07a069c87e5905fc601c23380730d494..891230a0c9250482748f939911e9ec153476a4e4 100644 --- a/src/maple_me/src/me_emit.cpp +++ b/src/maple_me/src/me_emit.cpp @@ -19,46 +19,30 @@ namespace maple { // emit IR to specified file -AnalysisResult *MeDoEmit::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, ModuleResultMgr*) { - bool emitHssaOrAfter = (func->GetIRMap() != nullptr); +AnalysisResult *MeDoEmit::Run(MeFunction *func, MeFuncResultMgr*, ModuleResultMgr*) { if (func->NumBBs() > 0) { + CHECK_FATAL(func->GetIRMap() != nullptr, "Why not hssa?"); // generate bblist after layout (bb physical position) - if (!MeOption::quiet) { - CHECK_FATAL(funcResMgr->GetAnalysisPhase(MeFuncPhase_BBLAYOUT) != nullptr, "null ptr check"); - LogInfo::MapleLogger() << "===== Check/run Depended Phase [ " - << funcResMgr->GetAnalysisPhase(MeFuncPhase_BBLAYOUT)->PhaseName() << " ]=====\n"; + CHECK_FATAL(func->HasLaidOut(), "Check/Run bb layout phase."); + auto layoutBBs = func->GetLaidOutBBs(); + MIRFunction *mirFunction = func->GetMirFunc(); + if (mirFunction->GetCodeMempool() != nullptr) { + mirFunction->GetCodeMempool()->Release(); } - auto *layoutBBs = static_cast(funcResMgr->GetAnalysisResult(MeFuncPhase_BBLAYOUT, func)); - if (!MeOption::quiet) { - LogInfo::MapleLogger() << "===== Depended Phase ended =====\n"; - } - ASSERT(layoutBBs != nullptr, "layout phase has problem"); - if (emitHssaOrAfter) { - ASSERT(func->GetIRMap() != nullptr, "null ptr check"); - MIRFunction *mirFunction = func->GetMirFunc(); - if (mirFunction->GetCodeMempool() != nullptr) { - mirFunction->GetCodeMempool()->Release(); - } - mirFunction->SetCodeMemPool(memPoolCtrler.NewMemPool("IR from IRMap::Emit()")); - mirFunction->GetCodeMPAllocator().SetMemPool(mirFunction->GetCodeMempool()); - mirFunction->SetBody(mirFunction->GetCodeMempool()->New()); - // initialize is_deleted field to true; will reset when emitting Maple IR - for (size_t k = 1; k < mirFunction->GetSymTab()->GetSymbolTableSize(); ++k) { - MIRSymbol *sym = mirFunction->GetSymTab()->GetSymbolFromStIdx(k); - if (sym->GetSKind() == kStVar) { - sym->SetIsDeleted(); - } - } - for (BB *bb : layoutBBs->GetBBs()) { - ASSERT(bb != nullptr, "null ptr check"); - func->GetIRMap()->EmitBB(*bb, *mirFunction->GetBody()); - } - } else { - auto *mirFunc = func->GetMirFunc(); - if (mirFunc != nullptr) { - func->EmitBeforeHSSA(*mirFunc, layoutBBs->GetBBs()); + mirFunction->SetCodeMemPool(memPoolCtrler.NewMemPool("IR from IRMap::Emit()")); + mirFunction->GetCodeMPAllocator().SetMemPool(mirFunction->GetCodeMempool()); + mirFunction->SetBody(mirFunction->GetCodeMempool()->New()); + // initialize is_deleted field to true; will reset when emitting Maple IR + for (size_t k = 1; k < mirFunction->GetSymTab()->GetSymbolTableSize(); ++k) { + MIRSymbol *sym = mirFunction->GetSymTab()->GetSymbolFromStIdx(k); + if (sym->GetSKind() == kStVar) { + sym->SetIsDeleted(); } } + for (BB *bb : layoutBBs) { + ASSERT(bb != nullptr, "Check bblayout phase"); + func->GetIRMap()->EmitBB(*bb, *mirFunction->GetBody()); + } if (DEBUGFUNC(func)) { LogInfo::MapleLogger() << "\n==============after meemit =============" << '\n'; func->GetMirFunc()->Dump(); diff --git a/src/maple_me/src/me_phase_manager.cpp b/src/maple_me/src/me_phase_manager.cpp index 0c22260611440c3b422c1d8ccc3f53ffda95a4b4..4c0fa69a1d7e25066682f9ee3d82178501408715 100644 --- a/src/maple_me/src/me_phase_manager.cpp +++ b/src/maple_me/src/me_phase_manager.cpp @@ -116,6 +116,7 @@ void MeFuncPhaseManager::AddPhases(const std::unordered_set &skipPh addPhase("aliasclass"); addPhase("ssa"); addPhase("rclowering"); + addPhase("bblayout"); addPhase("emit"); } } diff --git a/src/maple_me/src/prop.cpp b/src/maple_me/src/prop.cpp index d6fa9ff98b4006fbf6e608c11ad1da82f8b0a0b0..45560935e3e8382e26c6eee723672549b8433331 100755 --- a/src/maple_me/src/prop.cpp +++ b/src/maple_me/src/prop.cpp @@ -243,7 +243,7 @@ void Prop::PropUpdateDef(MeExpr &meExpr) { void Prop::PropUpdateChiListDef(const MapleMap &chiList) { for (auto it = chiList.begin(); it != chiList.end(); ++it) { - PropUpdateDef(*it->second->GetLHS()); + PropUpdateDef(*static_cast(it->second->GetLHS())); } } @@ -274,17 +274,23 @@ void Prop::CollectSubVarMeExpr(const MeExpr &meExpr, std::vector // warning: I suppose the vector vervec is on the stack, otherwise would cause memory leak bool Prop::IsVersionConsistent(const std::vector &vstVec, const std::vector> &vstLiveStack) const { - for (auto *subExpr : vstVec) { + for (auto it = vstVec.begin(); it != vstVec.end(); ++it) { // iterate each cur defintion of related symbols of rhs, check the version + const MeExpr *subExpr = *it; CHECK_FATAL(subExpr->GetMeOp() == kMeOpVar || subExpr->GetMeOp() == kMeOpReg, "error: sub expr error"); - uint32 stackIdx = static_cast(subExpr)->GetOStIdx(); + uint32 stackIdx = 0; + if (subExpr->GetMeOp() == kMeOpVar) { + stackIdx = static_cast(subExpr)->GetOStIdx(); + } else { + stackIdx = static_cast(subExpr)->GetOstIdx(); + } auto &pStack = vstLiveStack.at(stackIdx); if (pStack.empty()) { // no definition so far go ahead continue; } SafeMeExprPtr curDef = pStack.top(); - ASSERT(curDef->GetMeOp() == subExpr->GetMeOp(), "error: cur def error"); + CHECK_FATAL(curDef->GetMeOp() == kMeOpVar || curDef->GetMeOp() == kMeOpReg, "error: cur def error"); if (subExpr != curDef.get()) { return false; } @@ -351,7 +357,7 @@ bool Prop::Propagatable(const MeExpr &expr, const BB &fromBB, bool atParm) const if (!IsVersionConsistent(varMeExprVec, vstLiveStackVec)) { return false; } - return true; + break; } case kMeOpIvar: { auto &ivarMeExpr = static_cast(expr); @@ -410,10 +416,6 @@ MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) const { if (rhs->GetDepth() <= kPropTreeLevel && Propagatable(utils::ToRef(rhs), utils::ToRef(defStmt->GetBB()), atParm)) { // mark propagated for iread ref - if (rhs->GetMeOp() == kMeOpVar) { - auto &preRHS = PropVar(static_cast(*rhs), atParm, checkPhi); - return preRHS; - } if (rhs->GetMeOp() == kMeOpIvar && rhs->GetPrimType() == PTY_ref) { defStmt->SetPropagated(true); } diff --git a/src/mpl2mpl/include/native_stub_func.h b/src/mpl2mpl/include/native_stub_func.h index b0b60602f99d66d0d76d343aad41c5f7d3c79793..959243890752bbde01a869d44bed5035be741e5b 100644 --- a/src/mpl2mpl/include/native_stub_func.h +++ b/src/mpl2mpl/include/native_stub_func.h @@ -110,7 +110,10 @@ class DoGenerateNativeStubFunc : public ModulePhase { } AnalysisResult *Run(MIRModule *mod, ModuleResultMgr *mrm) override { + bool origUsePreg = Options::usePreg; + Options::usePreg = false; // As a pre mpl2mpl phase, NativeStubFunc always use symbols OPT_TEMPLATE(NativeStubFuncGeneration); + Options::usePreg = origUsePreg; return nullptr; } }; diff --git a/src/mpl2mpl/src/native_stub_func.cpp b/src/mpl2mpl/src/native_stub_func.cpp index 8a9651fddfdc5303ef866ae8414b7428b5759610..580635453269cf9c29b0bcf2c8c0fd60d0af97d2 100644 --- a/src/mpl2mpl/src/native_stub_func.cpp +++ b/src/mpl2mpl/src/native_stub_func.cpp @@ -329,26 +329,27 @@ void NativeStubFuncGeneration::GenerateRegisteredNativeFuncCall(MIRFunction &fun nrets.push_back(CallReturnPair(ret->GetStIdx(), RegFieldPair(0, 0))); } size_t loc = regFuncTabConst->GetConstVec().size(); - auto ®ArrayType = static_cast(regFuncTabConst->GetType()); + auto &arrayType = static_cast(regFuncTabConst->GetType()); AddrofNode *regFuncExpr = builder->CreateExprAddrof(0, *regFuncSymbol); - ArrayNode *arrayExpr = builder->CreateExprArray(regArrayType, regFuncExpr, builder->CreateIntConst(loc - 1, PTY_i32)); + ArrayNode *arrayExpr = builder->CreateExprArray(arrayType, regFuncExpr, builder->CreateIntConst(loc - 1, PTY_i32)); arrayExpr->SetBoundsCheck(false); - auto *elemType = static_cast(regArrayType).GetElemType(); + auto *elemType = static_cast(arrayType).GetElemType(); BaseNode *ireadExpr = builder->CreateExprIread(*elemType, *GlobalTables::GetTypeTable().GetOrCreatePointerType(*elemType), 0, arrayExpr); - // assign registered func ptr to a preg. - auto funcptrPreg = func.GetPregTab()->CreatePreg(PTY_ptr); - RegassignNode *funcptrAssign = builder->CreateStmtRegassign(PTY_ptr, funcptrPreg, ireadExpr); - // read func ptr from preg - auto readFuncPtr = builder->CreateExprRegread(PTY_ptr, funcptrPreg); + // assign registered func ptr to a symbol. + auto funcPtrSym = builder->CreateSymbol(GlobalTables::GetTypeTable().GetVoidPtr()->GetTypeIndex(), "func_ptr", + kStVar, kScAuto, &func, kScopeLocal); + DassignNode *funcPtrAssign = builder->CreateStmtDassign(*funcPtrSym, 0, ireadExpr); + // read func ptr from symbol + auto readFuncPtr = builder->CreateExprDread(*funcPtrSym); NativeFuncProperty funcProperty; bool needCheckThrowPendingExceptionFunc = (!func.GetAttr(FUNCATTR_critical_native)) && (funcProperty.jniType == kJniTypeNormal); bool needIndirectCall = func.GetAttr(FUNCATTR_critical_native) || func.GetAttr(FUNCATTR_fast_native); // Get current native method function ptr from reg_jni_func_tab slot - BaseNode *regReadExpr = builder->CreateExprRegread(PTY_ptr, funcptrPreg); + BaseNode *regReadExpr = builder->CreateExprDread(*funcPtrSym); #ifdef TARGARM32 BaseNode *checkRegExpr = builder->CreateExprCompare(OP_lt, *GlobalTables::GetTypeTable().GetUInt1(), @@ -359,13 +360,14 @@ void NativeStubFuncGeneration::GenerateRegisteredNativeFuncCall(MIRFunction &fun constexpr int intConstLength = 1; BaseNode *andExpr = builder->CreateExprBinary(OP_band, *GlobalTables::GetTypeTable().GetPtr(), regReadExpr, builder->CreateIntConst(intConstLength, PTY_u32)); - auto funcPtrAndOpPreg = func.GetPregTab()->CreatePreg(PTY_ptr); - RegassignNode *funcPtrAndOpAssign = builder->CreateStmtRegassign(PTY_ptr, funcPtrAndOpPreg, andExpr); - auto readFuncPtrAndReg = builder->CreateExprRegread(PTY_ptr, funcPtrAndOpPreg); + auto flagSym = builder->CreateSymbol(GlobalTables::GetTypeTable().GetVoidPtr()->GetTypeIndex(), "flag", + kStVar, kScAuto, &func, kScopeLocal); + auto flagSymAssign = builder->CreateStmtDassign(*flagSym, 0, andExpr); + auto readFlag = builder->CreateExprDread(*flagSym); BaseNode *checkRegExpr = builder->CreateExprCompare(OP_eq, *GlobalTables::GetTypeTable().GetUInt1(), *GlobalTables::GetTypeTable().GetPtr(), - readFuncPtrAndReg, builder->CreateIntConst(kInvalidCode, PTY_ptr)); + readFlag, builder->CreateIntConst(kInvalidCode, PTY_ptr)); #endif auto *ifStmt = static_cast(builder->CreateStmtIf(checkRegExpr)); @@ -383,42 +385,43 @@ void NativeStubFuncGeneration::GenerateRegisteredNativeFuncCall(MIRFunction &fun if (IsStaticBindingMethod(func.GetName())) { // Get current func_ptr (strong/weak symbol address) auto *nativeFuncAddr = builder->CreateExprAddroffunc(nativeFunc.GetPuidx()); - funcptrAssign = builder->CreateStmtRegassign(PTY_ptr, funcptrPreg, nativeFuncAddr); - func.GetBody()->AddStatement(funcptrAssign); + funcPtrAssign = builder->CreateStmtDassign(*funcPtrSym, 0, nativeFuncAddr); + func.GetBody()->AddStatement(funcPtrAssign); // Define wrapper function call StmtNode *wrapperCall = CreateNativeWrapperCallNode(func, readFuncPtr, args, ret, needIndirectCall); func.GetBody()->AddStatement(wrapperCall); } else if (!Options::regNativeDynamicOnly) { // Qemu - func.GetBody()->AddStatement(funcptrAssign); + func.GetBody()->AddStatement(funcPtrAssign); #ifdef TARGAARCH64 - func.GetBody()->AddStatement(funcPtrAndOpAssign); + func.GetBody()->AddStatement(flagSymAssign); #endif // Get find_native_func function MIRFunction *findNativeFunc = builder->GetOrCreateFunction(namemangler::kFindNativeFuncNoeh, voidPointerType->GetTypeIndex()); findNativeFunc->SetAttr(FUNCATTR_nosideeffect); // CallAssigned statement for unregistered situation - CallNode *callGetFindNativeFunc = builder->CreateStmtCallRegassigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, - funcptrPreg, OP_callassigned); + CallNode *callGetFindNativeFunc = builder->CreateStmtCallAssigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, + funcPtrSym, OP_callassigned); // Check return value of dynamic linking stub MIRFunction *dummyNativeFunc = builder->GetOrCreateFunction(namemangler::kDummyNativeFunc, voidPointerType->GetTypeIndex()); dummyNativeFunc->SetAttr(FUNCATTR_nosideeffect); - auto dummyFuncPreg = func.GetPregTab()->CreatePreg(PTY_ptr); - auto readDummyFuncPtr = builder->CreateExprRegread(PTY_ptr, dummyFuncPreg); + auto dummyFuncSym = builder->CreateSymbol(voidPointerType->GetTypeIndex(), "dummy_ret", + kStVar, kScAuto, &func, kScopeLocal); + auto readDummyFuncPtr = builder->CreateExprDread(*dummyFuncSym); MapleVector dummyFuncOpnds(func.GetCodeMempoolAllocator().Adapter()); - CallNode *callDummyNativeFunc = builder->CreateStmtCallRegassigned(dummyNativeFunc->GetPuidx(), dummyFuncOpnds, - dummyFuncPreg, OP_callassigned); + CallNode *callDummyNativeFunc = builder->CreateStmtCallAssigned(dummyNativeFunc->GetPuidx(), dummyFuncOpnds, + dummyFuncSym, OP_callassigned); BaseNode *checkStubReturnExpr = builder->CreateExprCompare(OP_eq, *GlobalTables::GetTypeTable().GetUInt1(), *GlobalTables::GetTypeTable().GetPtr(), readFuncPtr, readDummyFuncPtr); auto *subIfStmt = static_cast(builder->CreateStmtIf(checkStubReturnExpr)); // Assign with address of strong/weak symbol auto *nativeFuncAddr = builder->CreateExprAddroffunc(nativeFunc.GetPuidx()); - funcptrAssign = builder->CreateStmtRegassign(PTY_ptr, funcptrPreg, nativeFuncAddr); - subIfStmt->GetThenPart()->AddStatement(funcptrAssign); + funcPtrAssign = builder->CreateStmtDassign(*funcPtrSym, 0, nativeFuncAddr); + subIfStmt->GetThenPart()->AddStatement(funcPtrAssign); // Rewrite reg_jni_func_tab with current funcIdx_ptr(weak/strong symbol address) - auto nativeMethodPtr = builder->CreateExprRegread(PTY_ptr, funcptrPreg); + auto nativeMethodPtr = builder->CreateExprDread(*funcPtrSym); IassignNode *nativeFuncTableEntry = builder->CreateStmtIassign( *GlobalTables::GetTypeTable().GetOrCreatePointerType(*elemType), 0, arrayExpr, nativeMethodPtr); subIfStmt->GetThenPart()->AddStatement(nativeFuncTableEntry); @@ -445,16 +448,16 @@ void NativeStubFuncGeneration::GenerateRegisteredNativeFuncCall(MIRFunction &fun func.GetBody()->AddStatement(ifStmt); } } else { // EMUI - func.GetBody()->AddStatement(funcptrAssign); + func.GetBody()->AddStatement(funcPtrAssign); #ifdef TARGAARCH64 - func.GetBody()->AddStatement(funcPtrAndOpAssign); + func.GetBody()->AddStatement(flagSymAssign); #endif MIRFunction *findNativeFunc = builder->GetOrCreateFunction(namemangler::kFindNativeFunc, voidPointerType->GetTypeIndex()); findNativeFunc->SetAttr(FUNCATTR_nosideeffect); // CallAssigned statement for unregistered situation - CallNode *callGetFindNativeFunc = builder->CreateStmtCallRegassigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, - funcptrPreg, OP_callassigned); + CallNode *callGetFindNativeFunc = builder->CreateStmtCallAssigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, + funcPtrSym, OP_callassigned); // Add if-statement to function body ifStmt->GetThenPart()->AddStatement(callGetFindNativeFunc); if (!needCheckThrowPendingExceptionFunc) { @@ -485,7 +488,7 @@ void NativeStubFuncGeneration::GenerateRegisteredNativeFuncCall(MIRFunction &fun findNativeFunc->SetAttr(FUNCATTR_nosideeffect); // CallAssigned statement for unregistered situation CallNode *callGetFindNativeFunc = - builder->CreateStmtCallRegassigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, funcptrPreg, OP_callassigned); + builder->CreateStmtCallAssigned(findNativeFunc->GetPuidx(), dynamicStubOpnds, funcPtrSym, OP_callassigned); ifStmt->GetThenPart()->AddStatement(callGetFindNativeFunc); if (!needCheckThrowPendingExceptionFunc) { MapleVector opnds(builder->GetCurrentFuncCodeMpAllocator()->Adapter()); diff --git a/src/mplfe/common/include/fe_function.h b/src/mplfe/common/include/fe_function.h index 799340dc2181975c8500d8ca4c6a4414d360dde0..4def4db0975f8eca5671441b830b31db10ff94ec 100644 --- a/src/mplfe/common/include/fe_function.h +++ b/src/mplfe/common/include/fe_function.h @@ -140,6 +140,7 @@ class FEFunction { void TypeInfer(); bool SetupFEIRStmtGoto(FEIRStmtGoto &stmt); bool SetupFEIRStmtSwitch(FEIRStmtSwitch &stmt); + FEIRStmtPesudoLOC *GetLOCForStmt(const FEIRStmt &feStmt); std::list> genStmtList; std::list> genBBList; diff --git a/src/mplfe/common/include/feir_stmt.h b/src/mplfe/common/include/feir_stmt.h index 440d6c91b5051a63a10e8aa693c8637e72ea3356..c9202dbef945b8ef283307c4319d6e58bd85d038 100644 --- a/src/mplfe/common/include/feir_stmt.h +++ b/src/mplfe/common/include/feir_stmt.h @@ -157,9 +157,11 @@ class FEIRStmt : public GeneralStmt { void SetKind(FEIRNodeKind argKind) { kind = argKind; } - + bool IsStmtInstComment() const; + bool ShouldHaveLOC() const; protected: virtual std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const; + virtual bool IsStmtInstImpl() const; FEIRNodeKind kind; }; diff --git a/src/mplfe/common/src/fe_function.cpp b/src/mplfe/common/src/fe_function.cpp index 58b7485c3e5932885a34568a76bdf76ba6592635..edc4ddd1ca1c36054fca16f7db0a3ca1031982d7 100644 --- a/src/mplfe/common/src/fe_function.cpp +++ b/src/mplfe/common/src/fe_function.cpp @@ -454,6 +454,25 @@ bool FEFunction::ReleaseGenStmts(const std::string &phaseName) { return phaseResult.Finish(); } +FEIRStmtPesudoLOC *FEFunction::GetLOCForStmt(const FEIRStmt &feIRStmt) { + if (!feIRStmt.ShouldHaveLOC()) { + return nullptr; + } + FELinkListNode *prevNode = static_cast(feIRStmt.GetPrev()); + while (prevNode != nullptr) { + if ((*static_cast(prevNode)).ShouldHaveLOC()) { + return nullptr; + } + FEIRStmt *stmt = static_cast(prevNode); + if (stmt->GetKind() == kStmtPesudoLOC) { + FEIRStmtPesudoLOC *loc = static_cast(stmt); + return loc; + } + prevNode = prevNode->GetPrev(); + } + return nullptr; +} + void FEFunction::BuildMapLabelIdx() { FELinkListNode *nodeStmt = feirStmtHead->GetNext(); while (nodeStmt != nullptr && nodeStmt != feirStmtTail) { @@ -572,7 +591,12 @@ void FEFunction::EmitToMIRStmt() { FELinkListNode *nodeStmt = feirStmtHead->GetNext(); while (nodeStmt != nullptr && nodeStmt != feirStmtTail) { FEIRStmt *stmt = static_cast(nodeStmt); + FEIRStmtPesudoLOC *pesudoLoc = GetLOCForStmt(*stmt); std::list mirStmts = stmt->GenMIRStmts(FEManager::GetMIRBuilder()); + if (pesudoLoc != nullptr) { + mirStmts.front()->GetSrcPos().SetFileNum(static_cast(pesudoLoc->GetSrcFileIdx())); + mirStmts.front()->GetSrcPos().SetLineNum(pesudoLoc->GetLineNumber()); + } for (StmtNode *mirStmt : mirStmts) { FEManager::GetMIRBuilder().AddStmtInCurrentFunctionBody(*mirStmt); } diff --git a/src/mplfe/common/src/feir_stmt.cpp b/src/mplfe/common/src/feir_stmt.cpp index 65831c6bf37cf1ec404e95f40b7f66f71b876e8a..b8cf694d906cc251d03018906174782ce1d44a4e 100644 --- a/src/mplfe/common/src/feir_stmt.cpp +++ b/src/mplfe/common/src/feir_stmt.cpp @@ -28,6 +28,41 @@ std::list FEIRStmt::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { return std::list(); } +bool FEIRStmt::IsStmtInstImpl() const { + switch (kind) { + case kStmtAssign: + case kStmtNonAssign: + case kStmtDAssign: + case kStmtJavaTypeCheck: + case kStmtJavaConstClass: + case kStmtJavaConstString: + case kStmtJavaMultiANewArray: + case kStmtCallAssign: + case kStmtJavaDynamicCallAssign: + case kStmtIAssign: + case kStmtUseOnly: + case kStmtReturn: + case kStmtBranch: + case kStmtGoto: + case kStmtCondGoto: + case kStmtSwitch: + case kStmtArrayStore: + case kStmtFieldStore: + case kStmtFieldLoad: + return true; + default: + return false; + } +} + +bool FEIRStmt::IsStmtInstComment() const { + return (kind == kStmtPesudoComment); +} + +bool FEIRStmt::ShouldHaveLOC() const { + return (IsStmtInstImpl() || IsStmtInstComment()); +} + // ---------- FEIRStmtCheckPoint ---------- void FEIRStmtCheckPoint::Reset() { predCPs.clear(); diff --git a/src/mplfe/jbc_input/src/jbc_stmt.cpp b/src/mplfe/jbc_input/src/jbc_stmt.cpp index 7a31cd7c7e53a55fa1a31a71934ea56ac926ad2a..a1a1389624dd82773b8735db823a76d8737e6a43 100644 --- a/src/mplfe/jbc_input/src/jbc_stmt.cpp +++ b/src/mplfe/jbc_input/src/jbc_stmt.cpp @@ -1529,6 +1529,8 @@ std::string JBCStmtPesudoLOC::DumpDotStringImpl() const { std::list JBCStmtPesudoLOC::EmitToFEIRImpl(JBCFunctionContext &context, bool &success) const { std::list ans; + UniqueFEIRStmt stmt = std::make_unique(srcFileIdx, lineNumber); + ans.push_back(std::move(stmt)); return ans; } } // namespace maple diff --git a/src/mplfe/test/feir_stmt_loc_test.cpp b/src/mplfe/test/feir_stmt_loc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9128c557d980f08c84c202c0031f467972f0c4f --- /dev/null +++ b/src/mplfe/test/feir_stmt_loc_test.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#include +#include +#include "jbc_function.h" +#include "fe_manager.h" +#include "redirect_buffer.h" +#include "feir_type_helper.h" +#include "mplfe_ut_regx.h" +#include "mplfe_ut_environment.h" +#include "feir_stmt.h" +#include "feir_var.h" +#include "feir_var_reg.h" +#include "feir_var_name.h" +#include "feir_test_base.h" +#define protected public +#define private public +namespace maple { +class FEIRStmtLOCTest : public FEIRTestBase { + public: + static MemPool *mp; + MapleAllocator allocator; + jbc::JBCClass jbcClass; + jbc::JBCClassMethod jbcMethod; + JBCClassMethod2FEHelper jbcMethodHelper; + MIRFunction mirFunction; + JBCFunction jbcFunction; + FEIRStmtLOCTest() + : allocator(mp), + jbcClass(allocator), + jbcMethod(allocator, jbcClass), + jbcMethodHelper(allocator, jbcMethod), + mirFunction(&MPLFEUTEnvironment::GetMIRModule(), StIdx(0, 0)), + jbcFunction(jbcMethodHelper, mirFunction, std::make_unique(true)) {} + ~FEIRStmtLOCTest() = default; + + static void SetUpTestCase() { + mp = memPoolCtrler.NewMemPool("MemPool for FEIRStmtLOCTest"); + } + + static void TearDownTestCase() { + memPoolCtrler.DeleteMemPool(mp); + mp = nullptr; + } +}; +MemPool *FEIRStmtLOCTest::mp = nullptr; + +// ---------- FEIRStmtDAssign ---------- +TEST_F(FEIRStmtLOCTest, GetLOCForStmt) { + std::unique_ptr type = FEIRTypeHelper::CreateTypeByJavaName("Ljava/lang/String;", false, true); + std::unique_ptr dstVar = std::make_unique(0, type->Clone()); + std::unique_ptr srcVar = std::make_unique(1, type->Clone()); + std::unique_ptr exprDRead = std::make_unique(std::move(srcVar)); + std::unique_ptr stmtDAssign = + std::make_unique(std::move(dstVar), std::move(exprDRead)); + + uint32 srcFileIdx = 2; + uint32 lineNumber = 10; + std::unique_ptr stmtPesudoLOC = std::make_unique(srcFileIdx, lineNumber); + jbcFunction.InitImpl(); + jbcFunction.feirStmtTail->InsertBefore(static_cast(stmtPesudoLOC.get())); + jbcFunction.feirStmtTail->InsertBefore(static_cast(stmtDAssign.get())); + FEIRStmtPesudoLOC *expectedLOC = jbcFunction.GetLOCForStmt(*static_cast(stmtDAssign.get())); + std::list mirStmts = stmtDAssign->GenMIRStmts(mirBuilder); + mirStmts.front()->GetSrcPos().SetFileNum(static_cast(expectedLOC->GetSrcFileIdx())); + mirStmts.front()->GetSrcPos().SetLineNum(expectedLOC->GetLineNumber()); + RedirectCout(); + mirStmts.front()->Dump(); + std::string dumpStr = GetBufferString(); + std::string pattern = std::string("LOC 2 10\n") + std::string("dassign %Reg0_") + + MPLFEUTRegx::RefIndex(MPLFEUTRegx::kAnyNumber) + + " 0 \\(dread ref %Reg1_" + MPLFEUTRegx::RefIndex(MPLFEUTRegx::kAnyNumber) + "\\)" + + MPLFEUTRegx::Any(); + EXPECT_EQ(MPLFEUTRegx::Match(dumpStr, pattern), true); + RestoreCout(); +} +} // namespace maple