Как избежать отключения итератора с помощью `ReplaceInstWithValue()`?
В программе ниже, когда я использую ReplaceInstWithValue()
, это идет в бесконечный цикл, так как я заменяю add
инструкция с последовательностью инструкций, содержащих add
инструкция. Таким образом, программа печатает что-то вроде xor
, add
, mul
...
Я думаю, что проблема связана с инструкциями, вставленными в список 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);
1 ответ
Как указывает w1ck3dg0ph3r, вы увеличиваете be
во внешнем цикле, когда вы должны увеличивать bs
, Это должно исправить вашу проблему с бесконечным циклом. llvm::IRBuilder
вставляет инструкции перед инструкцией, указанной итератором, переданным в конструктор, поэтому вам не нужно вносить какие-либо другие изменения.