2014-11-24 2 views
5

Я пытаюсь реализовать простой JIT-компилятор с использованием API LLVM C. Пока у меня нет проблем с генерированием IR-кода и его выполнением, то есть до тех пор, пока я не начну удалять объекты и не воссоздавать их.LLVM API: правильный способ создания/удаления

Что я хотел бы сделать, так это очистить ресурсы JIT в тот момент, когда они больше не используются двигателем. То, что я в основном пытаюсь сделать что-то вроде этого:

while (true) 
{ 
    // Initialize module & builder 
    InitializeCore(GetGlobalPassRegistry()); 
    module = ModuleCreateWithName(some_unique_name); 
    builder = CreateBuilder(); 

    // Initialize target & execution engine 
    InitializeNativeTarget(); 
    engine = CreateExecutionEngineForModule(...); 
    passmgr = CreateFunctionPassManagerForModule(module); 
    AddTargetData(GetExecutionEngineTargetData(engine), passmgr); 
    InitializeFunctionPassManager(passmgr); 

    // [... my fancy JIT code ...] --** Will give a serious error the second iteration 

    // Destroy 
    DisposePassManager(passmgr); 
    DisposeExecutionEngine(engine); 
    DisposeBuilder(builder); 
    // DisposeModule(module); //--> Commented out: Deleted by execution engine 

    Shutdown(); 
} 

Однако, это, кажется, не работает правильно: вторая итерация цикла я получаю довольно плохую ошибку ...

Итак, чтобы подвести итог: как правильно уничтожить и воссоздать LLVM API?

+0

Я полагаю, вы должны сначала удалить модуль. – arrowd

+0

@arrowdodger Мне кажется, что это невозможно. Механизм выполнения ссылается на модуль и выполняет «удаление». Несмотря на то, что каждое волокно в моем теле также хочет удалить его, ваша программа, безусловно, будет segfault, если вы это сделаете. – atlaste

+0

Попробуйте переместить 'InitializeNativeTarget()' из цикла, затем. – arrowd

ответ

3

Публикуется как ответ, потому что код слишком длинный. Если возможно, и никаких других ограничений, попробуйте использовать LLVM следующим образом. Я вполне уверен, что здесь находится преступник Shutdown(). И я не думаю, что было бы больно держать Builder снаружи. Это хорошо отражает то, как я использую LLVM в своем JIT.

InitializeCore(GetGlobalPassRegistry()); 
InitializeNativeTarget(); 
builder = CreateBuilder(); 

while (true) 
{ 
    // Initialize module & builder 

    module = ModuleCreateWithName(some_unique_name); 


    // Initialize target & execution engine 
    engine = CreateExecutionEngineForModule(...); 
    passmgr = CreateFunctionPassManagerForModule(module); 
    AddTargetData(GetExecutionEngineTargetData(engine), passmgr); 
    InitializeFunctionPassManager(passmgr); 

    // [... my fancy JIT code ...] --** Will give a serious error the second iteration 

    // Destroy 
    DisposePassManager(passmgr); 
    DisposeExecutionEngine(engine);    
} 
DisposeBuilder(builder); 
Shutdown(); 
+0

Спасибо, я собираюсь отдать это, давайте посмотрим что происходит.Я замечаю, что вы не уничтожаете модуль, это было специально? – atlaste

+0

Я проделал довольно много, и кажется, что все утечки исчезли. Несколько важных указателей: всегда располагайте механизм выполнения, иначе вы получите утечку основной памяти. Кроме того, не забудьте удалить все общие значения, которые вы передаете в функции LLVM (включая возвращаемое значение функции). В сочетании с вашим решением это сделало трюк для меня. Еще раз спасибо. rk ваш ответ как правильное решение. – atlaste

+0

Да, поскольку я обнаружил мучительный способ (segfault), модуль принадлежит Механизму выполнения и удаляется вместе с ним. – antipattern