2014-11-24 18 views
5

Próbuję zaimplementować prosty kompilator JIT za pomocą interfejsu API LLVM C. Do tej pory nie mam problemów z generowaniem kodu IR i jego wykonaniem, to znaczy dopóki nie zacznę rozrzucać obiektów i odtwarzać je.Interfejs API LLVM: poprawny sposób tworzenia/usuwania

W zasadzie chciałbym wyczyścić zasoby JIT w momencie, gdy nie są już używane przez silnik. Co mam w zasadzie próbuje zrobić coś takiego:

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(); 
} 

to jednak nie wydaje się działać poprawnie: druga iteracja pętli Dostaję dość poważny błąd ...

Podsumowując: jaki jest właściwy sposób na zniszczenie i ponowne utworzenie interfejsu API LLVM?

+0

Przypuszczam, że należy najpierw usunąć moduł. – arrowd

+0

@arrowdodger Wydaje mi się, że to niemożliwe. Mechanizm wykonawczy odwołuje się do modułu i wykonuje "usuń". Nawet jeśli każde włókno w moim ciele nakłania to do usunięcia go, twój program na pewno naruszy to, jeśli to zrobisz. – atlaste

+0

Spróbuj przenieść 'InitializeNativeTarget()' z pętli, następnie. – arrowd

Odpowiedz

3

Publikowanie tego jako odpowiedź, ponieważ kod jest za długi. Jeśli to możliwe i żadnych innych ograniczeń, spróbuj użyć LLVM w ten sposób. Jestem całkiem pewny, że przyczyną jest tutaj Shutdown() w pętli. I nie sądzę, że zraniłoby to także utrzymanie na zewnątrz Builder. Odzwierciedla to dobrze sposób, w jaki używam LLVM w moim 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

Dzięki, zamierzam dać temu szansę; zobaczmy co się stanie, nie zauważyłem, że nie niszczysz modułu, czy to było celowe? – atlaste

+0

Sprofilowałem całkiem sporo i wygląda na to, że wszystkie wycieki zniknęły Kilka ważnych wskazówek: Zawsze wyrzucaj silnik wykonawczy, w przeciwnym razie A także, pamiętaj, aby pozbyć się wszystkich ogólnych wartości przekazywanych do funkcji LLVM (w tym wartości zwracanej przez funkcję) .W połączeniu z rozwiązaniem, to mi się udało. rk twoja odpowiedź jako poprawne rozwiązanie. – atlaste

+0

Tak, ponieważ odkryłem bolesny (segfault) sposób, moduł jest własnością aparatu wykonawczego i zostaje usunięty wraz z nim. – antipattern

Powiązane problemy