2021SC@SDUSC
仍然是老规矩,官方源码献上:
今天和以后的几篇博客将研究分析编译器代码中me体系的me_ir部分,这一部分是me体系中最重要的一部分,因为这部分直接决定了me和ir两个体系的结合,这部分代码将对整个方舟编译器的运行产生至关重要的作用。鉴于此,这部分的代码量极为庞大,分析起来难度也很大,故我可能需要6-9周(按每周一篇的速度)才能将之分析完。目前计划用3篇博客分析其头文件。
我看代码的平台网址如下:
头文件:
src/mapleall/maple_me/include/me_ir.h · 方舟编译器/OpenArkCompiler - Gitee.com
cpp文件:
开头定义了几个类,注释中明确提到,存在循环依赖,别无选择,也就是说这些类之间的关系非常复杂而且缺一不可。按理来说这样的代码并不太好,耦合度太高,出bug的概率很大。但是程序嘛,总是会有各种各样的问题,有的问题甚至要拖很久才能解决,如直到今年9月份新发布的JDK17,才刚刚解决了浮点数运算的问题。所以说这个不太好的地方肯定也是不得已而为之。
namespace maple {
class PhiNode; // circular dependency exists, no other choice
class MeStmt; // circular dependency exists, no other choice
class IRMap; // circular dependency exists, no other choice
class SSATab; // circular dependency exists, no other choice
class VarMeExpr; // circular dependency exists, no other choice
class Dominance; // circular dependency exists, no other choice
using MeStmtPtr = MeStmt*;
enum MeExprOp : uint8 {
kMeOpUnknown,
kMeOpVar,
kMeOpIvar,
kMeOpAddrof,
kMeOpAddroffunc,
kMeOpAddroflabel,
kMeOpGcmalloc,
kMeOpReg,
kMeOpConst,
kMeOpConststr,
kMeOpConststr16,
kMeOpSizeoftype,
kMeOpFieldsDist,
kMeOpOp,
kMeOpNary
}; // cache the op to avoid dynamic cast
这是VarMeExpr and RegMeExpr的基类,定义了这两个类中共同的基础功能,继承自MeExpr 类:
// base class for VarMeExpr and RegMeExpr
class ScalarMeExpr : public MeExpr {
public:
ScalarMeExpr(int32 exprid, OriginalSt *origSt, uint32 vidx, MeExprOp meop, Opcode o, PrimType ptyp)
: MeExpr(exprid, meop, o, ptyp, 0),
ost(origSt),
vstIdx(vidx),
defBy(kDefByNo) {
def.defStmt = nullptr;
}
~ScalarMeExpr() = default;
bool IsIdentical(MeExpr&) const {
CHECK_FATAL(false, "ScalarMeExpr::IsIdentical() should not be called");
return true;
}
bool IsUseSameSymbol(const MeExpr&) const override;
.......(中间是getter和setter,无需多管)
MeStmt *GetDefByMeStmt() const;
BB *GetDefByBBMeStmt(const Dominance&, MeStmtPtr&) const;
void Dump(const IRMap*, int32 indent = 0) const override;
BaseNode &EmitExpr(SSATab&) override;
bool IsSameVariableValue(const VarMeExpr&) const override;
ScalarMeExpr *FindDefByStmt(std::set<ScalarMeExpr*> &visited);
protected:
OriginalSt *ost;
uint32 vstIdx; // the index in MEOptimizer's VersionStTable, 0 if not in VersionStTable
MeDefBy defBy : 3;
union {
MeStmt *defStmt; // definition stmt of this var
MePhiNode *defPhi;
ChiMeNode *defChi; // definition node by Chi
MustDefMeNode *defMustDef; // definition by callassigned
} def;
};
继承自ScalarMeExpr的类:
下面的两个私有的bool变量会在其不能通过委托人优化的时候值为true
using RegMeExpr = ScalarMeExpr;
// represant dread
class VarMeExpr final : public ScalarMeExpr {
public:
VarMeExpr(int32 exprid, OriginalSt *ost, size_t vidx, PrimType ptyp)
: ScalarMeExpr(exprid, ost, vidx, kMeOpVar, OP_dread, ptyp) {}
~VarMeExpr() = default;
void Dump(const IRMap*, int32 indent = 0) const override;
BaseNode &EmitExpr(SSATab&) override;
bool IsValidVerIdx(const SSATab &ssaTab) const;
bool IsVolatile() const override;
// indicate if the variable is local variable but not a function formal variable
bool IsPureLocal(const MIRFunction&) const;
bool IsZeroVersion() const;
bool IsSameVariableValue(const VarMeExpr&) const override;
VarMeExpr &ResolveVarMeValue();
bool PointsToStringLiteral();
FieldID GetFieldID() const {
return GetOst()->GetFieldID();
}
TyIdx GetInferredTyIdx() const {
return inferredTyIdx;
}
void SetInferredTyIdx(TyIdx inferredTyIdxVal) {
inferredTyIdx = inferredTyIdxVal;
}
bool GetMaybeNull() const {
return maybeNull;
}
void SetMaybeNull(bool maybeNullVal) {
maybeNull = maybeNullVal;
}
bool GetNoDelegateRC() const {
return noDelegateRC;
}
void SetNoDelegateRC(bool noDelegateRCVal) {
noDelegateRC = noDelegateRCVal;
}
bool GetNoSubsumeRC() const {
return noSubsumeRC;
}
void SetNoSubsumeRC(bool noSubsumeRCVal) {
noSubsumeRC = noSubsumeRCVal;
}
MIRType *GetType() const override {
return GlobalTables::GetTypeTable().GetTypeFromTyIdx(ost->GetTyIdx());
}
bool HasAddressValue() override { return GetType()->GetKind() == kTypePointer; }
private:
bool noDelegateRC = false; // true if this cannot be optimized by delegaterc
bool noSubsumeRC = false; // true if this cannot be optimized by subsumrc
TyIdx inferredTyIdx{ 0 }; /* Non zero if it has a known type (allocation type is seen). */
bool maybeNull = true; // false if definitely not null
};
继承自 MeExpr的另一个类:
class ConstMeExpr : public MeExpr {
public:
ConstMeExpr(int32 exprID, MIRConst *constValParam, PrimType t)
: MeExpr(exprID, kMeOpConst, OP_constval, t, 0), constVal(constValParam) {}
~ConstMeExpr() = default;
void Dump(const IRMap*, int32 indent = 0) const override;
BaseNode &EmitExpr(SSATab &) override;
bool GeZero() const;
bool GtZero() const;
bool IsZero() const override;
bool IsOne() const;
int64 GetIntValue() const;
MIRConst *GetConstVal() {
return constVal;
}
MeExpr *GetIdenticalExpr(MeExpr &expr, bool) const override;
uint32 GetHashIndex() const override {
CHECK_FATAL(constVal != nullptr, "constVal is null");
if (constVal->GetKind() == kConstInt) {
auto *intConst = safe_cast<MIRIntConst>(constVal);
CHECK_NULL_FATAL(intConst);
return intConst->GetValue();
}
if (constVal->GetKind() == kConstFloatConst) {
auto *floatConst = safe_cast<MIRFloatConst>(constVal);
CHECK_NULL_FATAL(floatConst);
return floatConst->GetIntValue();
}
if (constVal->GetKind() == kConstDoubleConst) {
auto *doubleConst = safe_cast<MIRDoubleConst>(constVal);
CHECK_NULL_FATAL(doubleConst);
return doubleConst->GetIntValue();
}
if (constVal->GetKind() == kConstLblConst) {
auto *lblConst = safe_cast<MIRLblConst>(constVal);
CHECK_NULL_FATAL(lblConst);
return lblConst->GetValue();
}
ASSERT(false, "ComputeHash: const type not yet implemented");
return 0;
}
private:
MIRConst *constVal;
};
今天的分析就到这里吧,最近事情有点多,先看这么多,剩下的下次再说