Как избежать отключения итератора с помощью `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 вставляет инструкции перед инструкцией, указанной итератором, переданным в конструктор, поэтому вам не нужно вносить какие-либо другие изменения.

Другие вопросы по тегам