Maple IR中寄存器相关的实现主要是MIRPreg和MIRPregTable类。这两个类名字中的P,猜测是Pseudo的缩写,表达虚拟寄存器,和特殊寄存器(SpecialReg)一起共同构成寄存器系统。本文就MAPLE IR中的寄存器相关的实现做简要的分析。
MIRPreg和MIRPregTable类都定义在src/maple_ir/include/mir_preg.h之中。
MIRPreg是表示基本寄存器,其主要成员变量为:
private:
PrimType primType;
bool isRef;
bool needRC;
int32 pregNo; // the number in maple IR after the %
MIRType *mirType;
primType表示寄存器基本类型;isRef表示是否是引用;needRC表示是否需要RC;pregNo是寄存器编号;mirType表示寄存器所对应的MIRType实例。MIRPreg的成员函数主要都是设置和获取成员变量的操作。
MIRPregTable主要是表示寄存器表,其主要成员变量为:
private:
uint32 pregIndex; // user(maple_ir)'s preg must less than this value
MapleMap<uint32, PregIdx> pregNoToPregIdxMap; // for quick lookup based on pregno
MapleVector<MIRPreg*> pregTable;
MIRPreg specPregTable[kSregLast]; // for the MIRPreg nodes corresponding to special registers
MIRModule *module;
MapleAllocator *mAllocator;
pregIndex用来表示寄存器的最大下标;pregNoToPregIdxMap表示一个寄存器号和寄存器下标构成的map;pregTable表示一个由MIRPreg*构成的Vector;specPregTable[kSregLast]表示一个特殊寄存器数组,存储对应特殊寄存器的MIRPreg ;module是本MIRPregTable对应的MIRModule ;mAllocator是本MIRPregTable对应的MapleAllocator 。
MIRPregTable的成员函数,也主要是针对成员变量的设置和获取操作,除此之外还有几个创建Preg的成员函数。另外,还有一个MIRPregTable::DumpRef在src/maple_ir/src/mir_symbol.cpp之中实现,这点有点特殊,因为寄存器相关实现并没有自己的cpp文件
MIRPregTable的使用,主要可以分为几类:
mir_builder.cpp,mir_function.cpp,parser.cpp,这一类文件之中,都是获取MIRFunction的pregTab,然后进行MIRPregTable的操作;
还有一些Dump操作会用到MIRPregTable。
特殊寄存器有一个SpecialReg ,它作为一个枚举类型实现。
enum SpecialReg : signed int {
kSregSp = 1,
kSregFp = 2,
kSregGp = 3,
kSregThrownval = 4,
kSregMethodhdl = 5,
kSregRetval0 = 6,
kSregLast = 7,
};
MIRPregTable之中有一个成员变量specPregTable[kSregLast],就是特殊寄存器的列表,以数组的形式存在,其中有7个元素。
MIRPreg *PregFromPregIdx(PregIdx pregIdx) {
// pregIdx < 0 denotes special register
return (pregIdx < 0) ? &specPregTable[-pregIdx] : pregTable.at(pregIdx);
}
从上面可以看出特殊寄存器和基本寄存器之间的差别。
如果pregIdx 小于0的话,则去特殊寄存器中取specPregTable[-pregIdx]
bool MIRParser::ParseSpecialReg(PregIdx &pRegIdx) {
const std::string &lexName = lexer.GetName();
int32 lexSize = lexName.size();
int32 retValSize = strlen(kLexerStringRetval);
if (strncmp(lexName.c_str(), kLexerStringRetval, retValSize) == 0 && (lexSize > retValSize) &&
isdigit(lexName[retValSize])) {
int32 retvalNo = lexName[retValSize] - '0';
for (int32 i = retValSize + 1; (i < lexSize) && isdigit(lexName[i]); i++) {
retvalNo = retvalNo * 10 + lexName[i] - '0';
}
pRegIdx = -kSregRetval0 - retvalNo;
lexer.NextToken();
return true;
}
src/maple_ir/src/parser.cpp中有一个专门处理特殊寄存器的ParseSpecialReg,可以看出大致情况。