学习LLVM常用的API操作
- 常用的结构:
---关于函数和指令以及block和指令的操作;
- 引用的各自类型:
---Dynamic casts
---Instanceof-of casts
- 修改CFG的几种方式
---修改基本块或者指令
一、Runtime type inference(RTTI):
LLVM有五种运行时的value的类型操作,其中有三种是比较常用的:
1.isa<T>(V):知道V这个值的动态类型,如果V是T的一个引用则返回True,否则返回True.
比如:以下主要是判断对应的指令是不是PHINode类型:
Count_Phis() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
errs() << "Function " << F.getName() << '\n';
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
if (isa<PHINode>(*I)) {
errs() << *I << "\n";
}
}
return false;
}
};
2.cast<T>(V):类型的检查。
3.V'=dyn_cast<T>(V):把V转换为V',否则失败。
把为PHINode的指令转换为PN类型:
virtual bool runOnFunction(Function &F) {
errs() << "Function " << F.getName() << '\n';
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
if (PHINode *PN = dyn_cast<PHINode>(&*I)) {
errs() << *PN << "\n";
int numArgs = PN->getNumIncomingValues();
errs() << " - has " << numArgs << " parameters\n";
for (int arg = 0; arg < numArgs; arg++) {
errs() << " Argument " << arg << ":\n";
errs() << " " << PN->getIncomingBlock(arg)->getName() << ": " <<
*(PN->getIncomingValue(arg)) << "\n";
}
}
}
return false;
}
二、对代码结构进行转换:
1.增加/删除指令;指令是BasicBlock中以List的形式存在,无法单独存在,必须是某个BasicBlock中,通常我们通过写Pass进行优化和反优化大部分就是操作的指令。
2.增加/删除基本块;基本块(BasicBlock)是Function中以List的形式存放的,无法单独存在,里面有很多的指令存在,分为普通指令和TerminatorInst指令。
3.增加删除函数;函数是无数个基本块组成,使用列表组成,有且仅有一个EntryBlcok,是列表中得第一个BasicBlock。
举例:SmallVector<PHINode*, 16> Worklist,收集到PHINode结点的指令,再调用 PN->replaceAllUsesWith(PN->getIncomingValue(0)); PN->eraseFromParent()在迭代器外进行删除,不能够在迭代器内部进行删除操作。
virtual bool runOnFunction(Function &F) {
bool cutInstruction = false;
errs() << "Function " << F.getName() << '\n';
SmallVector<PHINode*, 16> Worklist;
for (Function::iterator B = F.begin(), EB = F.end(); B != EB; ++B) {
for (BasicBlock::iterator I = B->begin(), EI = B->end(); I != EI; ++I) {
if (PHINode *PN = dyn_cast<PHINode>(I)) {
if (PN->hasConstantValue()) {
// store for later elimination:
Worklist.push_back(PN);
cutInstruction = true;
}
} else {
continue;
}
}
}
// Eliminate the uses:
while (!Worklist.empty()) {
PHINode* PN = Worklist.pop_back_val();
PN->replaceAllUsesWith(PN->getIncomingValue(0));
PN->eraseFromParent();
}
return cutInstruction;
}
三、总结:
通过本节可以学习到Runtime type inference(RTTI)三种常见的基本类型操作,以及理解LLVM中指令(instructions)、基本块(BasicBlock)、以及函数(Function)之间的关系和对于它们的基本操作。
参考:http://llvm.org/docs/ProgrammersManual.html