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之中:
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等操作。