LLVM操作数的遍历
Traversal of LLVM Operands
使用 ModulePass,我的目标是向上遍历 SSA 图:从一个带有 0..2 个操作数的语句开始(大多数操作码都属于那个),我想找出两件事:
- 操作数是元数据/常量(简单:只需尝试转换为常量类型)还是变量?
- 如果它是一个变量,给我它定义的语句(因为 LLVM IR 是 SSA 形式,这是一个格式良好的查询),所以我可以递归地继续这个遍历。
例如,假设以下 LLVM IR:
define i32 @mul_add(i32 %x, i32 %y, i32 %z) {
entry:
%tmp = mul i32 %x, %y
%tmp2 = add i32 %tmp, %z
ret i32 %tmp2
}
我将从 return 语句开始。现在我想知道我在 returning:
- 我将自己获取 return 语句的操作数
- 我检测到操作数是一个名为 %tmp2
的变量
- 我将自己获取定义了 %tmp2 的语句的操作数
- 我先遍历第一个操作数,%tmp
- (...)
- %x 是一个函数参数,因此可能是我的遍历结束(或者是?)
- (...继续此 DFS 中的其他分支...)
我将如何使用 C++ API 来实现这些步骤?
解决方案很简单,我将尽可能通用地描述它。
LLVM 中 llvm::Instruction
的每个 Operand
都是超类型 llvm::Value
。 Value
的子类型是 llvm::Instruction
。这允许通过以下方法递归:
bool runOnInstruction(llvm::Instruction *instruction) {
bool flag = false;
for (auto operand = instruction->operands().begin();
operand != instruction->operands().end(); ++operand) {
printOperandStats(operand->get());
flag = runOnOperand(operand->get()) | flag;
}
return flag;
}
bool runOnOperand(llvm::Value *operand) {
operand->printAsOperand(errs(), true);
// ... do something else ...
auto *instruction = dyn_cast<llvm::Instruction>(operand);
if (nullptr != instruction) {
return runOnInstruction(instruction);
} else {
return false;
}
}
这等于问题所要求的DFS。每个操作数都将被转换为一条指令,并将被递归分析。布尔值 return 照常用于 LLVM Passes:true 值描述了对 IR 的修改。
使用 ModulePass,我的目标是向上遍历 SSA 图:从一个带有 0..2 个操作数的语句开始(大多数操作码都属于那个),我想找出两件事:
- 操作数是元数据/常量(简单:只需尝试转换为常量类型)还是变量?
- 如果它是一个变量,给我它定义的语句(因为 LLVM IR 是 SSA 形式,这是一个格式良好的查询),所以我可以递归地继续这个遍历。
例如,假设以下 LLVM IR:
define i32 @mul_add(i32 %x, i32 %y, i32 %z) {
entry:
%tmp = mul i32 %x, %y
%tmp2 = add i32 %tmp, %z
ret i32 %tmp2
}
我将从 return 语句开始。现在我想知道我在 returning:
- 我将自己获取 return 语句的操作数
- 我检测到操作数是一个名为 %tmp2 的变量
- 我将自己获取定义了 %tmp2 的语句的操作数
- 我先遍历第一个操作数,%tmp
- (...)
- %x 是一个函数参数,因此可能是我的遍历结束(或者是?)
- (...继续此 DFS 中的其他分支...)
我将如何使用 C++ API 来实现这些步骤?
解决方案很简单,我将尽可能通用地描述它。
LLVM 中 llvm::Instruction
的每个 Operand
都是超类型 llvm::Value
。 Value
的子类型是 llvm::Instruction
。这允许通过以下方法递归:
bool runOnInstruction(llvm::Instruction *instruction) {
bool flag = false;
for (auto operand = instruction->operands().begin();
operand != instruction->operands().end(); ++operand) {
printOperandStats(operand->get());
flag = runOnOperand(operand->get()) | flag;
}
return flag;
}
bool runOnOperand(llvm::Value *operand) {
operand->printAsOperand(errs(), true);
// ... do something else ...
auto *instruction = dyn_cast<llvm::Instruction>(operand);
if (nullptr != instruction) {
return runOnInstruction(instruction);
} else {
return false;
}
}
这等于问题所要求的DFS。每个操作数都将被转换为一条指令,并将被递归分析。布尔值 return 照常用于 LLVM Passes:true 值描述了对 IR 的修改。