2014-11-24 9 views
5

Sto tentando di implementare un semplice compilatore JIT utilizzando l'API LLVM C. Finora, non ho problemi a generare codice IR e ad eseguirlo, cioè: fino a quando non ho iniziato a smaltire gli oggetti e a ricrearli.LLVM: modo corretto per creare/eliminare

Quello che fondamentalmente mi piacerebbe fare è ripulire le risorse JIT nel momento in cui non vengono più utilizzate dal motore. Quello che sto fondamentalmente tentando di fare è qualcosa di simile:

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

Tuttavia, questo non sembra funzionare correttamente: la seconda iterazione del ciclo ottengo un errore piuttosto male ...

Quindi, per riassumere: qual è il modo corretto per distruggere e ricreare l'API LLVM?

+0

Suppongo che sia necessario eliminare prima il modulo. – arrowd

+0

@arrowdodger Mi sembra impossibile. Il motore di esecuzione fa riferimento al modulo e fa un 'delete'. Anche se ogni fibra nel mio corpo spinge a cancellarla, il tuo programma segnerà sicuramente se lo fai. – atlaste

+0

Prova a spostare 'InitializeNativeTarget()' out of loop, quindi. – arrowd

risposta

3

Inserendo questo come risposta perché il codice è troppo lungo. Se possibile e nessun altro vincolo, prova ad usare LLVM in questo modo. Sono abbastanza sicuro che lo Shutdown() all'interno del loop sia il colpevole qui. E non penso che sarebbe dannoso tenere fuori anche lo Builder. Questo riflette bene il modo in cui utilizzo LLVM nel mio 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

Grazie, ho intenzione di fare un tentativo, vediamo cosa succede, mi accorgo che non si distrugge il modulo, è stato apposta? – atlaste

+0

Ho profilato un bel po 'e sembra che le perdite siano finite, alcuni importanti indicatori: Disponi sempre il motore di esecuzione, altrimenti tu ottenere una perdita di memoria importante.Anche, assicurati di disporre di tutti i valori generici passati alle funzioni LLVM (incluso il valore restituito dalla funzione) .In combinazione con la tua soluzione, questo ha fatto il trucco per me. rk la tua risposta come la soluzione corretta. – atlaste

+0

Sì, come ho scoperto il modo doloroso (segfault), il modulo è di proprietà di Execution Engine e viene eliminato con esso. – antipattern