方舟编译器分析三——代码分析(第一篇)

        2021SC@SDUSC

        老规矩,先贴上官方源码:

https://code.opensource.huaweicloud.com/HarmonyOS/OpenArkCompiler/file?ref=master&path=doc%252FDevelopment_Preparation.md

        今天研究分析该编译器代码的me_function部分

        MeFunction的定义在src/maple_me/include/me_function.h之中:

        具体链接在src/mapleall/maple_me/include/me_function.h · 方舟编译器/OpenArkCompiler - Gitee.comhttps://gitee.com/openarkcompiler/OpenArkCompiler/blob/master/src/mapleall/maple_me/include/me_function.h

class MeFunction : public FuncEmit {
  using BBPtrHolder = MapleVector<BB*>;

 public:
  MeFunction(MIRModule *mod, MIRFunction *func, MemPool *memPool, MemPool *versMemPool,
             const std::string &fileName)
      : memPool(memPool),
        alloc(memPool),
        versMemPool(versMemPool),
        versAlloc(versMemPool),
        mirModule(*mod),
        mirFunc(func),
        nextBBId(0),
        labelBBIdMap(alloc.Adapter()),
        bbVec(alloc.Adapter()),
        theCFG(nullptr),
        meSSATab(nullptr),
        irmap(nullptr),
        bbTryNodeMap(alloc.Adapter()),
        endTryBB2TryBB(alloc.Adapter()),
        fileName(fileName),
        regNum(0),
        hints(0),
        hasEH(false),
        secondPass(false) {}

  virtual ~MeFunction() {}
...

        MeFunction继承自FuncEmit类,FuncEmit类定义在src/maple_me/include/func_emit.h,实现在src/maple_me/src/func_emit.cpp之中。其定义较为简单,主要是为MeFunction和WpoFunction提供代码生成服务。按照这个描述,MeFunction和WpoFunction应该都是其子类。但是这次发布的内容之中,没有找到WpoFunction相关的内容,或许等其他部分源码开源之后,再看这个类到底是做什么的了。FuncEmit只有一个public的成员函数EmitBeforeHSSA,其所做的操作是将MapleVector<BB*>的bb,插入到func里。

        MeFunction继承自FuncEmit的EmitBeforeHSSA成员函数,在目前开源的代码范围内只使用了一次,在src/maple_me/src/me_emit.cpp之中。

        MeDoEmission是一个继承自MeFuncPhase的phase,也就是说它本身就是一个MeFuncPhase类别的phase,其核心函数就是这个Run函数。

        MeFunction除了上文提到的Prepare()和EmitBeforeHSSA()之外,还有一系列的BasicBlock相关操作的成员函数。新建BasicBlock的成员函数,共有三个:

BB *MeFunction::NewBasicBlock() {

// new a basic block and insert before position
BB *MeFunction::InsertNewBasicBlock(BB *position) {

/* Split BB at split_point */
BB *MeFunction::SplitBB(BB *bb, StmtNode *splitPoint) {

        1)NewBasicBlock函数主要是被void MeFunction::CreateBasicBlocks()调用。CreateBasicBlocks()函数,在Prepare函数之中也被调用了:

void MeFunction::Prepare(unsigned long rangeNum) {
  if (!MeOptions::quiet) {
    LogInfo::MapleLogger() << "---Preparing Function  < " << mirModule.CurFunction()->GetName() << " > [" << rangeNum
                           << "] ---\n";
  }
  /* lower first */
  MIRLower mirLowerer(mirModule, mirModule.CurFunction());
  mirLowerer.Init();
  mirLowerer.SetLowerME();
  mirLowerer.SetLowerExpandArray();
  mirLowerer.LowerFunc(mirModule.CurFunction());
  CreateBasicBlocks();
  if (NumBBs() == 0) {
    /* there's no basicblock generated */
    return;
  }
  RemoveEhEdgesInSyncRegion();
  theCFG = memPool->New<MirCFG>(this);
  theCFG->BuildMirCFG();
  theCFG->FixMirCFG();
  theCFG->VerifyLabels();
  theCFG->UnreachCodeAnalysis();
  theCFG->WontExitAnalysis();
  theCFG->Verify();
}

我们可以看到,调用它是在执行完lower操作之后,执行CFG(控制流图)相关动作之前。

        2)InsertNewBasicBlock()函数,是要在一个BasicBlock的位置之前插入一个新的BasicBlock。这个成员函数在此次开放的源码之中,并没有被调用。

        3)SplitBB()函数,是在一个split point将BasicBlock进行分割。这个函数主要在void MirCFG::FixMirCFG() 函数中进行调用(src/maple_me/src/me_cfg.cpp)。

        上面的新建BasicBlock的三个函数,只有NewBasicBlock()被MeFunction::CreateBasicBlocks()调用。和BasicBlock有关的成员函数还有:

 

void MeFunction::DeleteBasicBlock(const BB *bb) {
  ASSERT(bbVec[bb->GetBBId().idx] == bb, "runtime check error");
  /* update first_bb_ and last_bb if needed */
  bbVec.at(bb->GetBBId().idx) = nullptr;
}

/* clone stmtnode in orig bb to newBB */
void MeFunction::CloneBasicBlock(BB *newBB, BB *orig) {
  if (orig == nullptr || orig->IsEmpty()) {
    return;
  }
  for (auto &stmt : orig->GetStmtNodes()) {
    StmtNode *newStmt = static_cast<StmtNode*>(stmt.CloneTree(mirModule.CurFuncCodeMemPoolAllocator()));
    ASSERT(newStmt != nullptr, "null ptr check");
    newStmt->SetNext(nullptr);
    newStmt->SetPrev(nullptr);
    newBB->AddStmtNode(newStmt);
    if (meSSATab != nullptr) {
      meSSATab->CreateSSAStmt(newStmt, newBB);
    }
  }
}

        另外,还有一些关于BB的获取的函数: 

/* get next bb in bbVec */
BB *MeFunction::NextBB(const BB *bb) {
  auto bbIt = std::find(begin(), end(), bb);
  CHECK_FATAL(bbIt != end(), "bb must be inside bb_vec");
  for (auto it = ++bbIt; it != end(); ++it) {
    if (*it != nullptr) {
      return *it;
    }
  }
  return nullptr;
}

/* get prev bb in bbVec */
BB *MeFunction::PrevBB(const BB *bb) {
  auto bbIt = std::find(rbegin(), rend(), bb);
  CHECK_FATAL(bbIt != rend(), "bb must be inside bb_vec");
  for (auto it = ++bbIt; it != rend(); ++it) {
    if (*it != nullptr) {
      return *it;
    }
  }
  return nullptr;
}

        MeFunction::RemoveEhEdgesInSyncRegion函数主要是为了处理异常处理相关的情况,在这里不做具体分析,以后在异常处理部分进行分析。

        总结:MeFunction是一个很重要的类,在生命周期上,它通常是发生在MIRFunction之后。MeFunction类是进行MeFuncPhase类别phase进行转化的载体,它必须在phase执行之前构建好,并且进行lower、CFG等操作。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值