Are instr_iterators invalidated when function inlining is performed?

Hi,

I'm trying to write a small piece of code that inlines all calls to a
particular function. The codes is as follows

  Function* klee_check_divF = module->getFunction("klee_div_zero_check");
  assert(klee_check_divF != 0 && "Failed to find klee_div_zero_check function");
  // Hack inline checks
  for (Module::iterator f = module->begin(), fe = module->end(); f != fe; ++f) {
    for (inst_iterator i=inst_begin(f), ie = inst_end(f); i != ie; ++i) {
      if ( CallInst* ci = dyn_cast<CallInst>(&*i) )
      {
        if ( ci->getCalledFunction() == klee_check_divF)
        {
            std::cout << "Trying to inline klee_div_zero_check" << std::endl;
            InlineFunctionInfo IFI(0,0);
            if (InlineFunction(ci,IFI))
            {
              std::cout << "Did inline" << std::endl; std::cout.flush();
            }
            else
              std::cout << "Failed to inline" << std::endl;
        }
      }

    }
  }

The problem I'm finding is after doing the first inline of a call
(using InlineFunction(ci,IFI) ) the program then SEGFAULTS which I
believe is happening because the instruction iterator is made invalid
when I do inlining (looking in gdb one of its fields I see is
NodePtr=0x0 ).

Is this normal behaviour? If so what is the correct way to implement
what I'm trying to do?

For now I'm going to implement the code so that it instead collects a
set of pointers to all the CallInstr of interest whilst iterating
through the module. Then after iterating through the module, iterate
through the set of collected CallInstr* and inline each one.

Thanks,
Dan Liew

Hi,

I'm trying to write a small piece of code that inlines all calls to a
particular function. The codes is as follows

  Function* klee_check_divF = module->getFunction("klee_div_zero_check");
  assert(klee_check_divF != 0 && "Failed to find klee_div_zero_check function");
  // Hack inline checks
  for (Module::iterator f = module->begin(), fe = module->end(); f != fe; ++f) {
    for (inst_iterator i=inst_begin(f), ie = inst_end(f); i != ie; ++i) {
      if ( CallInst* ci = dyn_cast<CallInst>(&*i) )
      {
        if ( ci->getCalledFunction() == klee_check_divF)
        {
            std::cout << "Trying to inline klee_div_zero_check" << std::endl;
            InlineFunctionInfo IFI(0,0);
            if (InlineFunction(ci,IFI))
            {
              std::cout << "Did inline" << std::endl; std::cout.flush();
            }
            else
              std::cout << "Failed to inline" << std::endl;
        }
      }

    }
  }

The problem I'm finding is after doing the first inline of a call
(using InlineFunction(ci,IFI) ) the program then SEGFAULTS which I
believe is happening because the instruction iterator is made invalid
when I do inlining (looking in gdb one of its fields I see is
NodePtr=0x0 ).

Is this normal behaviour?

In many situations in C++ this is normal behavior (inlining
presumably, removes the instruction you pass it - because there's no
longer a call) - if you remove an element from a sequence (eg: using
std::list<T>::erase(iterator)) the current iterator becomes invalid.

The common idiom to deal with this is to copy the iterator and
increment the copy before the operation that invalidates the iterator:

instead of:

for (iter i = begin(); i != end(); ++i) {
  if (cond)
    erase(i); // next increment will be invalid
}

one would write:

for (iter i = begin(); i != end(); ) {
  if (cond) {
    iter t = i;
    ++i;
    erase(t);
  } else {
    ++i;
  }
}

I just realised I forgot to reply to this. Thanks for advise, it's good to know.

Thanks,
Dan Liew.