【问题标题】:How do I avoid invaliding the iterator using `ReplaceInstWithValue()`?如何避免使用 `ReplaceInstWithValue()` 使迭代器无效?
【发布时间】:2017-06-21 23:38:28
【问题描述】:

在下面的程序中,当我使用ReplaceInstWithValue() 时,它会进入无限循环,因为我将add 指令替换为包含add 指令的指令序列。因此,程序会打印出类似xoraddmul、...的内容。

我猜这个问题与插入到 BasicBlock 指令列表中的指令有关,即执行迭代的列表。

如何解决此问题,以便继续处理列表中的下一个元素,而忽略插入的说明?

是否只有将所有插入点放入数据结构并在迭代完成后执行替换的唯一方法?

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <map>
#include <string>

using namespace llvm;

namespace {
struct CountOp : public FunctionPass {    
    static char ID;

    CountOp() : FunctionPass(ID) {}

    virtual bool runOnFunction(Function &F) {

        for (Function::iterator bs = F.begin(), be = F.end(); bs != be; ++be) {
            for (BasicBlock::iterator is = bs->begin(), ie = be->end(); is != ie; ++is) {
                Instruction& inst  = *is;
                BinaryOperator* binop = dyn_cast<BinaryOperator>(&inst);
                if (!binop) {
                    continue;
                }
                unsigned opcode = binop->getOpcode();
                errs() << binop->getOpcodeName() << "\n";

                if (opcode != Instruction::Add) {

                    continue;
                }

                IRBuilder<> builder(binop);
                Value* v = builder.CreateAdd(builder.CreateXor(binop->getOperand(0), binop->getOperand(1)), 
                                             builder.CreateMul(ConstantInt::get(binop->getType(), 2), 
                                                               builder.CreateAnd(binop->getOperand(0), binop->getOperand(1))));

                ReplaceInstWithValue(bs->getInstList(), is, v);
            } 
        }

        errs() << "\n";
        return true;
    }
};
}

char CountOp::ID = 0;
static RegisterPass<CountOp> X("opCounter", "Counts opcodes per functions", false, false);

【问题讨论】:

  • 为什么要在外循环中增加?
  • 这是基本块。

标签: c++ c++11 clang llvm clang++


【解决方案1】:

正如 w1ck3dg0ph3r 指出的那样,当您应该递增 bs 时,您正在外循环中递增 be。这应该可以解决您的无限循环问题。 llvm::IRBuilder 在传递给构造函数的迭代器指向的指令之前插入指令,因此您不需要进行任何其他更改。

【讨论】:

  • 实际上,更改为++bs 并不能解决问题。我还是陷入了无限循环。
  • 您是否建议我将ReplaceInstWithValue 替换为其他内容?
  • 这很奇怪。你记得重新编译你的通行证吗?您能否提供一个示例 LLVM IR 输入?我自己测试过,效果很好:pastebin.com/dR8dbhCu
  • 我稍后会上传,但它基本上只是一个简单的.ll文件,包含一个主函数,两个变量,变量相加,返回结果。
  • 是的,我已经重新编译了:)
猜你喜欢
  • 1970-01-01
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 2016-07-15
  • 2021-09-01
  • 2011-08-28
  • 1970-01-01
相关资源
最近更新 更多