LLVM Pass : УДАЛИТЬ всю ветку в IR возникают ошибки

Я хочу удалить инструкции перехода в ИК-коде через проход LLVM.

Приведенный ниже код — мой проход функции (Github):

virtual bool runOnFunction(Function &F) {
    for (auto &B : F) {
        for (auto &I : B) {
            auto op_name = I.getOpcodeName();
            if(strcmp(op_name, "br")==0) {
                I.eraseFromParent();
            }
        }
    }
    return true;
}

Передача функции успешно скомпилирована, но когда я использую ее в test.c, возникает ошибка типа Pastebin.


person Y. Tseng    schedule 06.09.2017    source источник
comment
Я не совсем уверен, какой контейнер используется для хранения инструкций, но может ли это быть связано с тем фактом, что вы существенно изменяете контейнер инструкций в базовом блоке, стирая при повторении одного и того же контейнера?   -  person PaulR    schedule 06.09.2017


Ответы (1)


Изменение контейнера во время итерации по нему с помощью диапазона, основанного на цикле for, не будет работать, поскольку конечное выражение не будет переоценено. Более того, в зависимости от контейнера вы можете аннулировать итератор для удаляемого элемента.

cppreference объясняет диапазон на основе циклов for до C++17 следующим образом:

{
    auto && __range = range_expression ;
    for (auto __begin = begin_expr, __end = end_expr;
         // __end not reevaluated!
         __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement

    }
}

eraseFromParent удалит инструкцию из базового блока, поэтому в этом случае вы не можете использовать диапазон, основанный на цикле for. Однако разработчики LLVM заставили его возвращать итератор к следующему элементу, который вы можете использовать для продолжения цикла.

virtual bool runOnFunction(Function &F) {
    for (auto &B : F) {
        auto It = B.begin()
        // we modify B, so we must reevaluate end()
        while(It != B.end()) {
            auto &I = *It;
            auto op_name = I.getOpcodeName();
            if(strcmp(op_name, "br")==0) {
                // we continue with the next element
                It = I.eraseFromParent();
            } else {
                ++It;
            }
        }
    }
    return true;
}
person PaulR    schedule 07.09.2017