Using a ModulePass, my goal is to traverse a SSA graph upwards: going from one Statement with 0..2 operands (most opcodes fall under that), I want to find out two things:
As an example, assume following 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
}
I will be starting with the return statement. Now I want to find out what I'm returning:
How would I use the C++ API to implement those steps?
The solution is simple and I will describe it as generic as possible.
Each Operand
of an llvm::Instruction
in LLVM is of supertype llvm::Value
. A subtype of Value
is llvm::Instruction
. This allows recursion via following methods:
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;
}
}
This equals a DFS as required by the question. Each Operand will be cast to an Instruction and will be recursively analyzed. The boolean return value is used as usual for LLVM Passes: a value of true describes a modification to the IR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With