【问题标题】:Traversal of LLVM OperandsLLVM 操作数的遍历
【发布时间】:2017-07-06 10:39:53
【问题描述】:

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

  1. 操作数是元数据/常量(简单:只需尝试转换为常量类型)还是变量?
  2. 如果它是一个变量,请获取定义它的 Statement(因为 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 语句开始。现在我想知道我返回的是什么:

  1. 我将为自己获取 return 语句的操作数
  2. 我检测到操作数是一个名为 %tmp2 的变量
  3. 我将为自己获取定义 %tmp2 的语句的操作数
  4. 我会先遍历第一个操作数,%tmp
  5. (...)
  6. %x 是一个函数参数,因此可能是我遍历的结束(或者是它?)
  7. (...继续此 DFS 中的其他分支...)

我将如何使用 C++ API 来实现这些步骤?

【问题讨论】:

  • "适当使用"

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


【解决方案1】:

解决方案很简单,我将尽可能笼统地描述它。

LLVM 中llvm::Instruction 中的每个Operand 都是超类型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 Passes:true 值描述了对 IR 的修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多