软件工程作业-方舟学习笔记09-SSA(续

今天继续回到ssa构建上分析分析
ssaTab是MeFuncPhase类的phase之一,而且按照目前公布的代码,它是phase列表中第一个运行的MeFuncPhase类的phase。
ssaTab phrase的对应实现类是MeDoSSATab。其定义和实现的位置为src/maple_me/src/me_ssa_tab.cpp 和me_ssa_tab.cpp

namespace maple {
BaseNode *SSATab::CreateSSAExpr(BaseNode *expr) {
  bool arrayLowered = false;
  while (expr->GetOpCode() == OP_array && !mirModule.IsJavaModule() && !func->IsLfo()) {
    MIRLower mirLower(mirModule, mirModule.CurFunction());
    expr = mirLower.LowerCArray(static_cast<ArrayNode*>(expr));
    arrayLowered = true;
  }
  if (expr->GetOpCode() == OP_addrof || expr->GetOpCode() == OP_dread) {
    if (expr->IsSSANode()) {
      return mirModule.CurFunction()->GetCodeMemPool()->New<AddrofSSANode>(*static_cast<AddrofSSANode*>(expr));
    }
    AddrofNode *addrofNode = static_cast<AddrofNode*>(expr);
    AddrofSSANode *ssaNode = mirModule.CurFunction()->GetCodeMemPool()->New<AddrofSSANode>(*addrofNode);
    MIRSymbol *st = mirModule.CurFunction()->GetLocalOrGlobalSymbol(ssaNode->GetStIdx());
    OriginalSt *ost = FindOrCreateSymbolOriginalSt(*st, mirModule.CurFunction()->GetPuidx(), ssaNode->GetFieldID());
    versionStTable.CreateZeroVersionSt(ost);
    ssaNode->SetSSAVar(*versionStTable.GetZeroVersionSt(ost));
    return ssaNode;
  } else if (expr->GetOpCode() == OP_regread) {
    RegreadNode *regReadNode = static_cast<RegreadNode*>(expr);
    RegreadSSANode *ssaNode = mirModule.CurFunction()->GetCodeMemPool()->New<RegreadSSANode>(*regReadNode);
    OriginalSt *ost =
        originalStTable.FindOrCreatePregOriginalSt(ssaNode->GetRegIdx(), mirModule.CurFunction()->GetPuidx());
    versionStTable.CreateZeroVersionSt(ost);
    ssaNode->SetSSAVar(*versionStTable.GetZeroVersionSt(ost));
    return ssaNode;
  } else if (expr->GetOpCode() == OP_iread) {
    if (expr->IsSSANode()) {
      return mirModule.CurFunction()->GetCodeMemPool()->New<IreadSSANode>(*static_cast<IreadSSANode*>(expr));
    }
    IreadNode *ireadNode = static_cast<IreadNode*>(expr);
    IreadSSANode *ssaNode = mirModule.CurFunction()->GetCodeMempool()->New<IreadSSANode>(*ireadNode);
    BaseNode *newOpnd = CreateSSAExpr(ireadNode->Opnd(0));
    if (newOpnd != nullptr) {
      ssaNode->SetOpnd(newOpnd, 0);
    }
    return ssaNode;
  }

MeDoSSATab的Run函数,主要执行了一下几个操作:
为处理的MeFunction添加一个名为ssaTab的SSATab;遍历MeFunction的所有BB,然后在每个BB内部遍历每条语句,为语句构建SSA版本的语句,并将其添加到ssaTab;返回新构建好的ssaTab。
SSATab的定义和实现位于src/maple_me/include/ssa_tab.h和src/maple_me/src/ssa_tab.cpp,它继承于AnalysisResult类,用来存储构建的SSA语句。stmtsSSAPart用来存储语句节点的SSA信息。注释里也说明了这点: Statement nodes’ SSA information is stored in class SSATab’s StmtsSSAPart, which has an array of pointers indexed by the stmtID field of each statement node. 所以,前面调用的CreateSSAStmt,也是将最终信息存储到了stmtsSSAPart里。SSATab的设计与实现也不复杂,除了操作成员变量及其内部数据的设置和获取之外,就是CreateSSAExpr和CreateSSAStmt的成员函数。前者还是为后者服务的。

// allocate the data structure to store SSA information
namespace maple {
bool MESSATab::PhaseRun(maple::MeFunction &f) {
  auto *cfg = f.GetCfg();
  MPLTimer timer;
  timer.Start();
  if (DEBUGFUNC_NEWPM(f)) {
    LogInfo::MapleLogger() << "\n============== SSA and AA preparation =============" << '\n';
  }
  MemPool *memPool = GetPhaseMemPool();
  // allocate ssaTab including its SSAPart to store SSA information for statements
  ssaTab = memPool->New<SSATab>(memPool, f.GetVersMp(), &f.GetMIRModule(), &f);
  f.SetMeSSATab(ssaTab);
#if DEBUG
  globalSSATab = ssaTab;
#endif
  // pass through the program statements
  for (auto bIt = cfg->valid_begin(); bIt != cfg->valid_end(); ++bIt) {
    auto *bb = *bIt;
    for (auto &stmt : bb->GetStmtNodes()) {
      ssaTab->CreateSSAStmt(stmt, bb);  // this adds the SSANodes for exprs
    }
  }
  if (DEBUGFUNC_NEWPM(f)) {
    timer.Stop();
    LogInfo::MapleLogger() << "ssaTab consumes cumulatively " << timer.Elapsed() << "seconds " << '\n';
  }
  return false;
}

void MESSATab::GetAnalysisDependence(AnalysisDep &aDep) const {
  aDep.AddRequired<MEMeCfg>();
}
}  // namespace maple

MeDoSSA的Run函数的实际返回值是MeSSA类型的指针。MeSSA和MeDoSSA定义在同个头文件之中,它继承自SSA和AnalysisResult 。
MeDoSSA的所做的工作是构建MeFunction的SSA形式。在构建函数的SSA形式之前,需要已经获取了函数的支配树以及BB的支配边界。关于支配树和支配边界的相关背景知识,推荐文章:https://blog.csdn.net/dashuniuniu/article/details/52224882。而支配树以及支配边界相关的操作,实际上是在dominance这个phase里实现的相关操作。
dominance这个phase,主要是分析MeFunction的控制流图,采用 Keith Cooper的算法来生成支配树和支配边界,这都是为了插入phi节点做准备。(Keith Cooper就是《Engineering a Compiler》的作者)dominance对应的实现类是MeDoDominance,它的定义和实现是src/maple_me/include/me_dominance.h和src/maple_me/src/me_dominance.cpp。
需要注意的是,dominance这个phase虽然在源码之中定义并实现了,但是它并没有注册在phases.def之中。但是它又是ssa所必须的前提,所以phases.def里列的phase列表,并不足以构成一个完整的执行phase序列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值