Skip to content

Commit

Permalink
Show better errors for LLVM IR output
Browse files Browse the repository at this point in the history
I was trying to output LLVM IR directly to the console:

    $ rustc hello.rs --emit=llvm-ir -o /dev/stdout
    LLVM ERROR: IO failure on output stream: Bad file descriptor

Now `LLVMRustPrintModule` returns an error, and we print:

    error: failed to write LLVM IR to /dev/stdout.hello.7rcbfp3g-cgu.0.rcgu.ll: Permission denied

... which is more informative.
  • Loading branch information
cuviper committed Apr 6, 2019
1 parent acd8dd6 commit aafe2c6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
25 changes: 15 additions & 10 deletions src/librustc_codegen_llvm/back/write.rs
Expand Up @@ -73,12 +73,10 @@ pub fn write_output_file(
unsafe {
let output_c = path_to_c_string(output);
let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
if result.into_result().is_err() {
result.into_result().map_err(|()| {
let msg = format!("could not write output to {}", output.display());
Err(llvm_err(handler, &msg))
} else {
Ok(())
}
llvm_err(handler, &msg)
})
}
}

Expand Down Expand Up @@ -505,7 +503,8 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
if write_bc {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_bitcode");
if let Err(e) = fs::write(&bc_out, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
diag_handler.err(&msg);
}
}

Expand All @@ -520,7 +519,8 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
let data = bytecode::encode(&module.name, data);
if let Err(e) = fs::write(&dst, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
let msg = format!("failed to write bytecode to {}: {}", dst.display(), e);
diag_handler.err(&msg);
}
}
} else if config.embed_bitcode_marker {
Expand All @@ -532,7 +532,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
if config.emit_ir {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_ir");
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
let out = path_to_c_string(&out);
let out_c = path_to_c_string(&out);

extern "C" fn demangle_callback(input_ptr: *const c_char,
input_len: size_t,
Expand Down Expand Up @@ -566,9 +566,14 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
}

with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
let result =
llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback);
llvm::LLVMDisposePassManager(cpm);
});
result.into_result().map_err(|()| {
let msg = format!("failed to write LLVM IR to {}", out.display());
llvm_err(diag_handler, &msg)
})
})?;
}

if config.emit_asm || asm_to_obj {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_codegen_llvm/llvm/ffi.rs
Expand Up @@ -1687,7 +1687,8 @@ extern "C" {
Demangle: extern fn(*const c_char,
size_t,
*mut c_char,
size_t) -> size_t);
size_t) -> size_t,
) -> LLVMRustResult;
pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
pub fn LLVMRustPrintPasses();
pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
Expand Down
11 changes: 9 additions & 2 deletions src/rustllvm/PassWrapper.cpp
Expand Up @@ -646,21 +646,28 @@ char RustPrintModulePass::ID = 0;
INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
"Print rust module to stderr", false, false)

extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
const char *Path, DemangleFn Demangle) {
extern "C" LLVMRustResult
LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
const char *Path, DemangleFn Demangle) {
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
std::string ErrorInfo;

std::error_code EC;
raw_fd_ostream OS(Path, EC, sys::fs::F_None);
if (EC)
ErrorInfo = EC.message();
if (ErrorInfo != "") {
LLVMRustSetLastError(ErrorInfo.c_str());
return LLVMRustResult::Failure;
}

formatted_raw_ostream FOS(OS);

PM->add(new RustPrintModulePass(FOS, Demangle));

PM->run(*unwrap(M));

return LLVMRustResult::Success;
}

extern "C" void LLVMRustPrintPasses() {
Expand Down

0 comments on commit aafe2c6

Please sign in to comment.