Segfault при вызове llvm_sys LLVMCreateTargetMachine для создания объектного файла в Rust
extern crate llvm_sys;
use llvm_sys::*;
use llvm_sys::prelude::*;
use llvm_sys::core::*;
pub fn emit(module: LLVMModuleRef) {
unsafe {
use llvm_sys::target_machine::*;
let triple = LLVMGetDefaultTargetTriple();
let mut target: LLVMTargetRef = std::mem::uninitialized();
LLVMGetTargetFromTriple(triple, &mut target, ["Cannot get target.\0".as_ptr() as *mut i8].as_mut_ptr());
let cpu = "x86\0".as_ptr() as *const i8;
let feature = "\0".as_ptr() as *const i8;
let opt_level = LLVMCodeGenOptLevel::LLVMCodeGenLevelNone;
let reloc_mode = LLVMRelocMode::LLVMRelocDefault;
let code_model = LLVMCodeModel::LLVMCodeModelDefault;
let target_machine = LLVMCreateTargetMachine(target, triple, cpu, feature, opt_level, reloc_mode, code_model);
let file_type = LLVMCodeGenFileType::LLVMObjectFile;
// LLVMTargetMachineEmitToFile(target_machine, module, "/Users/andyshiue/Desktop/main.o\0".as_ptr() as *mut i8, file_type, "Cannot generate file.\0".as_ptr() as *mut *mut i8);
}
}
pub fn main() {
use Term::*;
unsafe {
let module = LLVMModuleCreateWithName("Main\0".as_ptr() as *const i8);
emit(module);
}
}
ошибка:
Process didn't exit successfully: `target/debug/ende` (signal: 11, SIGSEGV: invalid memory reference)
Я пишу свой игрушечный компилятор, и теперь я хочу генерировать объектные файлы. Почему код выше производит segfault? Откуда я знаю, что я делаю не так? Можно ли получить трассировку стека? У меня нет опыта работы с C/C++, поэтому я не знаю, как отлаживать. Проблема как-то связана с target
?
1 ответ
Вы неправильно понимаете, как позвонить LLVMGetTargetFromTriple
:
pub unsafe extern "C" fn LLVMGetTargetFromTriple(Triple: *const c_char,
T: *mut LLVMTargetRef,
ErrorMessage: *mut *mut c_char)
-> LLVMBool
Эта функция принимает указатель на строку в стиле C, которая будет заполнена в случае ошибки. Фактический успех метода сообщается в результате.
Согласно документам LLVM:
Находит цель, соответствующую данной тройке, и сохраняет ее в T.
Возвращает 0 в случае успеха. Опционально возвращает любую ошибку в ErrorMessage. Используйте LLVMDisposeMessage для удаления сообщения.
(акцент мой)
Прямо сейчас этот вызов не выполняется, поэтому целевой ref никогда не инициализируется, поэтому вы пытаетесь вызвать методы для неопределенного кода.