2017-02-04 6 views
0

В приведенной ниже программе, когда я использую ReplaceInstWithValue(), он переходит в бесконечный цикл, так как я заменяю инструкцию add последовательностью инструкций, содержащей инструкцию add. Таким образом, программа печатает что-то вдоль линий xor, add, mul, ...Как избежать исключения итератора с помощью `ReplaceInstWithValue()`?

Я предполагаю, что проблема связана с инструкциями, вставленных в список 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); 
+2

Зачем вам увеличиваться во внешнем цикле? – w1ck3dg0ph3r

+0

Это основные блоки. – Shuzheng

ответ

1

Как w1ck3dg0ph3r указывает, вы приращением be во внешнем контуре, когда вы должны быть увеличивающиеся bs. Это должно исправить вашу проблему с бесконечным циклом. llvm::IRBuilder вставляет инструкции перед инструкцией, указанной итератором, переданной конструктору, поэтому вам не нужно делать никаких других изменений.

+0

Фактически, переход на '++ bs' не устраняет проблему. Я все еще вхожу в бесконечный цикл. – Shuzheng

+0

Вы предполагаете, что я должен заменить 'ReplaceInstWithValue' чем-то еще? – Shuzheng

+0

Это странно. Помните ли вы перекомпилировать свой пропуск? Не могли бы вы представить пример ввода LLVM IR? Я тестировал его сам, и он отлично работает: http://pastebin.com/dR8dbhCu – SPAT