2014-10-08 8 views
6

Pracuję teraz nad tutorialem LLVM w Rust. Zaimplementowałem już niektóre części Kaleidoscope REPL. Udało mi się to dobrze, ale nagle przestał działać i każda próba obliczenia wartości kończy się teraz w LLVM ERROR: Target does not support MC emission!. Wygląda na to, że stało się tak po aktualizacji kompilatora Rusta do najnowszego wieczoru (ale nie jestem tego pewien).Co może być przyczyną `LLMM ERROR: Target nie obsługuje emisji MC!`?

Stosuje się odpowiednie fragmenty kodu. Funkcja

Inicjalizacja:

#[allow(non_snake_case)] 
pub unsafe fn LLVMInitializeNativeTarget() { 
    llvm::LLVMInitializeX86TargetInfo(); 
    llvm::LLVMInitializeX86Target(); 
    llvm::LLVMInitializeX86TargetMC(); 
} 

stworzenie modułu:

 let module = llvm::LLVMModuleCreateWithNameInContext(module_name.to_c_str().as_ptr(), context); 

Wykonanie stworzenie silnika:

 let mut exec_engine = 0 as llvm::ExecutionEngineRef; 
     let mut error = 0 as *const c_char; 
     LLVMCreateExecutionEngineForModule(&mut exec_engine, module, &mut error); 
     assert!(exec_engine != 0 as llvm::ExecutionEngineRef); 

Kompilacja i uruchamianie funkcji:

pub fn run(value: llvm::ValueRef, context: &Context) -> f64 { 
    unsafe { 
     let result = LLVMRunFunction(context.exec_engine, 
            value, 
            0, 
            0 as *const GenericValueRef); 
     let ty = llvm::LLVMDoubleTypeInContext(context.context); 
     LLVMGenericValueToFloat(ty, result) 
    } 
} 

Funkcje LLVM z prefexem przez llvm :: są importowane przez rustc, te, które nie są wstępnie zaznaczone przez llvm :: są importowane przez mój kod, patrz https://github.com/jauhien/iron-kaleidoscope/blob/master/src/missing_llvm_bindings/mod.rs.

Aby zobaczyć pełną Listing, spojrzeć na https://github.com/jauhien/iron-kaleidoscope/blob/master/src/builder.rs

używam najnowszego nightly rdzy i LLVM 3.5.0.

UPD: Po skomentowaniu połączenia z LLVMInitializeNativeTarget, JIT rozpoczął pracę ponownie. Nadal zastanawiam się, jaki jest powód problemu i jak należy właściwie wykorzystywać JIT.

UPD2: po skomentowaniu linii z inicjalizacją nie wszystko znów zaczęło działać: wywołania funkcji zdefiniowanej w kodzie Rust zawodzą teraz z LLVM ERROR: Tried to execute an unknown external function.

Funkcja Próbuję zadzwonić (ten pracował wcześniej):

#[no_mangle] 
pub extern fn print(x: f64) -> f64 { 
    println!("> {} <", x); 
    x 
} 

Przykład sesji:

[email protected] iron-repl % ./target/iron_kaleidoscope 
>extern print(x) 

declare double @print(double) 

>print(1) 
LLVM ERROR: Tried to execute an unknown external function: print 
+0

Nie wiem, czy to jest przyczyną twojego problemu, ale 'module_name.to_c_str(). As_ptr()' jest pamięcią niebezpieczną. Nie gwarantujesz, że ciąg C przestanie być wskaźnikiem. Zobacz [docs] (http://doc.rust-lang.org/std/str/trait.StrSlice.html#tymethod.as_ptr). Polecam zamiast tego używać ['with_c_str'] (http://doc.rust-lang.org/std/c_str/trait.ToCStr.html#tymethod.with_c_str). – Dylan

+0

Polecam również unikanie istniejącego API LLVM w Rust. Jest oparty na API LLVM C, który nie jest tak dobrze obsługiwany jak API C++ i jest całkowicie "niebezpieczny". Przekonasz się również, że brakuje niektórych części API. Dla projektu, nad którym pracuję, buduję własne bezpieczne wiązania dla klas/funkcji C++. To nie jest takie trudne, a efekt końcowy jest o wiele łatwiejszy w użyciu. – Dylan

+0

Wiem, ale to jest tutorial. Używam więc tego, co jest już dostępne. Gdyby istniał jakiś bezpieczny interfejs API, użyłbym go. Co z 'with_c_str'? Nie widzę powodu, aby używać go tutaj.Czy ciąg może być deallocated przed funkcją, w której jest przekazywany jako parametr nazywa się? W każdym razie nie ma to nic wspólnego z moim problemem. –

Odpowiedz

4

miałem same problem i mogłoby rozwiązać go również uruchomiony

LLVMInitializeNativeAsmPrinter(); 
LLVMInitializeNativeAsmParser(); 

po zainicjowaniu X86Target. Znalazłem to w kodzie źródłowym lli.

Powiązane problemy