0

Я пишу модуль модуля оптимизации LLVM, и я хочу, чтобы иметь возможность восстановить исходную функцию, если мне не нравятся результаты. Так что я написал ModulePass следующую базовую структуру:CloneFunction затем заменит оригинальную функцию клонированным в LLVM opt pass

while(cloneAndTryAgain){ 

    ValueToValueMapTy vmap; 
    Function *F_clone = CloneFunction(F, vmap, true); 

    .... trying out things on F 

    if(cloneAndTryAgain){ //not happy with changes to F 
     //replace F with clone 
     replaceCurrentFunction(F, F_clone); 
     F_clone = NULL; 
    } 
} 

Однако после запуска replaceCurrentFunction (..), я пытаюсь напечатать F, но я получаю Segfault. Что-то не так с F после попытки заменить его клоном.

replaceCurrentFunction(..) выглядит следующим образом:

void replaceCurrentFunction(Function *F, Function *F_clone) { 

    Module *M = F->getParent(); 

    // New function will take the name of the current function. 
    F_clone->takeName(F); 

    // Insert new function right next to current function. 
    M->getFunctionList().insert(F, F_clone); 

    // Erase current function. 
    F->eraseFromParent(); 

    // The new function is now the current function. 
    F = F_clone; 

} 

Вот выдаёт ошибку сегментации и трассировки стека:

Program received signal SIGSEGV, Segmentation fault. 
(anonymous namespace)::SlotTracker::SlotTracker (this=0x7fffffff94b0, F=0x1b) at AsmWriter.cpp:438 
438  mNext(0), fNext(0), mdnNext(0) { 

#0 (anonymous namespace)::SlotTracker::SlotTracker (this=0x7fffffff94b0, F=0x1b) at AsmWriter.cpp:438 
#1 0x00007ffff63c66dc in llvm::Value::print (this=0x6d4a30, ROS=..., AAW=0x0) at AsmWriter.cpp:2092 
#2 0x00007ffff6fb536c in operator<< (V=..., OS=...) at /llvm/include/llvm/Value.h:318 
#4 .... 

ответ

0

Wow вы используете кучу небезопасных API, здесь, и некоторые операторы даже не делая смысл. Например, что вы ожидаете от последней строки void replaceCurrentFunction(Function *F, Function *F_clone), которая равна F = F_clone;? Если вы хотите обновить «F» в вызывающем абоненте, вы должны завершить эту функцию с помощью return F_clone и называть его таким образом F = replaceCurrentFunction(F, F_clone);.

Для фактического LLVM API, правильная последовательность:

  1. Заменить все виды использования старой функции с клоном: F->replaceAllUsesWith(F_clone)
  2. Сохранить имя: std::string Name = F->getName()
  3. Удалить F: F->eraseFromParent()
  4. Переименование клона: F_clone->setName(Name)
+0

I nee d указатель F остаться в живых, потому что я использую его для создания другого клона, поэтому у меня есть F = F_clone – mohsaied

+0

относительно 'F = F_clone', я делал это неправильно. Мне нужно передать ссылку указателя на функцию, чтобы правильно установить ее. Итак, мой новый прототип функции теперь: 'replaceCurrentFunction (Function * & F, Function * & F_clone)'. Это означает, что F указывает на правильную вещь в моем внешнем цикле, где я буду клонировать ее и повторить попытку. – mohsaied

+0

С F, являющимся ссылкой указателя, тогда да, это имеет смысл. Однако это не очень хорошая практика. Вы должны вернуть указатель вместо того, чтобы выполнять задание на сайте вызова. Остальная часть описанного мной действия все еще действительна (вы должны отметить ответ, принятый, если он правильно задает ваш вопрос, в противном случае дайте мне знать, как улучшить). – Joky