遍历LLVM操作数

时间:2017-07-06 10:39:53

标签: llvm llvm-ir llvm-c++-api

使用ModulePass,我的目标是向上遍历一个SSA图:从一个带有0..2个操作数的语句(大多数操作码都属于那个),我想找出两件事:

  1. 操作数是元数据/常量(简单:只是尝试转换为常量类型)还是变量?
  2. 如果它是一个变量,请告诉我定义它的语句(因为LLVM IR是SSA形式,这是一个格式正确的查询),所以我可以递归地继续这个遍历。
  3. 例如,假设遵循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语句开始。现在我想知道我要回来的东西:

    1. 我将获得返回声明的操作数
    2. 我检测到操作数是一个名为%tmp2
    3. 的变量
    4. 我将自己定义%tmp2定义的语句的操作数
    5. 我将首先遍历第一个操作数%tmp
    6. (...)
    7. %x是一个函数参数,因此可能是遍历的结束(或者是它?)
    8. (...继续本DFS中的其他分支......)
    9. 我如何使用C ++ API来实现这些步骤?

1 个答案:

答案 0 :(得分:1)

解决方案很简单,我会尽可能地将其描述为通用。

LLVM中Operand的每个llvm::Instruction都是超类型llvm::ValueValue的子类型为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。每个操作数将被转换为一个指令,并将进行递归分析。布尔返回值通常用于LLVM通过:值true表示对IR的修改。