Удалить инструкцию llvm, которая не может быть удалена - PullRequest
0 голосов
/ 11 марта 2020

Я пытаюсь использовать llvm pass для преобразования вызова функции pthread_create в обычный вызов функции в родительском потоке вместо дочернего потока. Простая иллюстрация ввода и вывода показана ниже. Однако когда я пытаюсь использовать eraseFromParent для удаления оригинала pthread_create CallInst, это всегда вызывает ошибку сегментации. После более глубокого погружения я обнаружил, что инструкция всегда возвращает false из mayHaveSideEffect . Я действительно не знаю, почему удаление инструкции вызовет какой-либо побочный эффект.

void *foo(void *args) {
  sleep(2);
}

int main() {
  pthread_t tid;
  pthread_create(&tid, NULL, foo, NULL);
  // => foo();
  pthread_join();
}

Спасибо за комментарий @ arnt. Вот именно то, что я хочу сделать. Я создаю CallInst, вызываемый функцией foo, и заменю его исходным вызовом функции pthread_create.

for (auto &inst: main_func) { // Iterate every instructions in the main function
  if (isa<CallInst>(inst)) {
    CallInst *ci = dyn_cast<CallInst>(&inst);
    if (ci->getCalledFunction()->getName().compare("pthread_create") == 0) {
      Function *start_routine = dyn_cast<Function>(ci->getArgOperand(2));
      Value *routine_args[1] = { ci->getArgOperand(3) };
      ArrayRef<Value *> arr_ref(routine_args);

      // Create a new CallInst and insert it before the "pthread_create" call instruction
      CallInst *foo = CallInst::create(start_routine, arr_ref, "startRoutineOutput", ci);

      ci->eraseFromParent(); // Segmentation fault happens here.
    }
  }
}
...