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::*;
        use llvm_sys::target_machine::*;
        let triple = LLVMGetDefaultTargetTriple();
        LLVM_InitializeNativeTarget();
        let target = LLVMGetFirstTarget();
        let cpu = "x86-64\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_ptr() as *mut *mut i8);
    }
}

我正在编写一个玩具编译器,我想生成对象文件,但文件LLVM输出是空的。
我发现LLVMTargetMachineEmitToFile返回1,这意味着我做错了什么,但我做错了什么?
如果我能知道我怎么知道是怎么回事就更好了。有什么方法可以让我得到一些错误信息吗?我没有C/C++的经验。

最佳答案

正如评论家已经说过的,要做你想做的事(用LLVM编写编译器),你就需要能够在至少C和C++中读(并且可能写)。
即使您使用Rust编译器编译代码,实际上您还没有编写任何Rust。您的整个程序被封装在unsafe块中,因为您正在调用由LVVM(用C++编写)所公开的C函数。这可能就是为什么有些评论者会问你是否已经让你的代码先在C中工作了。
your other question中,您仍然错误地调用LLVM方法。在这种情况下,请查看the documentation for LLVMTargetMachineEmitToFile

LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T,
                                     LLVMModuleRef M,
                                     char *Filename,
                                     LLVMCodeGenFileType codegen,
                                     char **ErrorMessage)

返回ErrorMessage中的任何错误。使用LLVMDisposeMessage来处理消息。
方法本身会告诉您什么是错误的,但是您必须给它一个存储错误消息的位置。不应为其提供错误字符串。我敢肯定,当当前代码试图写入字符串文字时,可能会产生一些令人兴奋的内存错误。
如果我重写您的代码以使用错误消息:
extern crate llvm_sys;

use llvm_sys::*;
use llvm_sys::prelude::*;
use llvm_sys::core::*;

use std::ptr;
use std::ffi::{CStr, CString};

pub fn emit(module: LLVMModuleRef) {
    let cpu = CString::new("x86-64").expect("invalid cpu");
    let feature = CString::new("").expect("invalid feature");
    let output_file = CString::new("/tmp/output.o").expect("invalid file");

    unsafe {
        use llvm_sys::target::*;
        use llvm_sys::target_machine::*;
        let triple = LLVMGetDefaultTargetTriple();
        LLVM_InitializeNativeTarget();
        let target = LLVMGetFirstTarget();
        let opt_level = LLVMCodeGenOptLevel::LLVMCodeGenLevelNone;
        let reloc_mode = LLVMRelocMode::LLVMRelocDefault;
        let code_model = LLVMCodeModel::LLVMCodeModelDefault;
        let target_machine = LLVMCreateTargetMachine(target, triple, cpu.as_ptr(), feature.as_ptr(), opt_level, reloc_mode, code_model);
        let file_type = LLVMCodeGenFileType::LLVMObjectFile;

        let mut error_str = ptr::null_mut();
        let res = LLVMTargetMachineEmitToFile(target_machine, module, output_file.as_ptr() as *mut i8, file_type, &mut error_str);
        if res == 1 {
            let x = CStr::from_ptr(error_str);
            panic!("It failed! {:?}", x);
            // TODO: Use LLVMDisposeMessage here
        }
    }
}

fn main() {
    unsafe {
        let module = LLVMModuleCreateWithName("Main\0".as_ptr() as *const i8);
        emit(module);
    }
}

TargetMachine无法发出此类型的文件
所以这就是你的问题。
在防锈方面,您可能需要完成处理愚蠢的LLVMBool所需的工作,以便可以重用它。一种方法是:
fn llvm_bool<F>(f: F) -> Result<(), String>
    where F: FnOnce(&mut *mut i8) -> i32
{
    let mut error_str = ptr::null_mut();
    let res = f(&mut error_str);
    if res == 1 {
        let err = unsafe { CStr::from_ptr(error_str) };
        Err(err.to_string_lossy().into_owned())
        //LLVMDisposeMessage(error_str);
    } else {
        Ok(())
    }
}

// later

llvm_bool(|error_str| LLVMTargetMachineEmitToFile(target_machine, module, output_file.as_ptr() as *mut i8, file_type, error_str)).expect("Couldn't output");

关于rust - 如何确定为什么使用llvm-sys调用LLVMTargetMachineEmitToFile时失败?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37267769/

10-10 18:34