1
1
use std:: fs;
2
- use std:: io:: Write ;
2
+ use std:: io:: { self , Write } ;
3
+ use std:: path:: PathBuf ;
3
4
use std:: process:: { Command , Stdio } ;
4
5
5
6
use rustc_codegen_ssa:: back:: write:: { CodegenContext , ModuleConfig } ;
@@ -8,11 +9,33 @@ use rustc_errors::{DiagCtxtHandle, FatalError};
8
9
use rustc_session:: config:: OutputType ;
9
10
use tracing:: error;
10
11
12
+ fn write_module ( c_out : & PathBuf , module : & ModuleCodegen < String > ) -> io:: Result < ( ) > {
13
+ let mut c_out_file = fs:: File :: create ( c_out) ?;
14
+ writeln ! ( c_out_file, "// file: {}.c" , module. name) ?;
15
+ write ! ( c_out_file, "{}" , module. module_llvm) ?;
16
+ Ok ( ( ) )
17
+ }
18
+ fn compiled_module (
19
+ success : bool ,
20
+ module : ModuleCodegen < String > ,
21
+ cgcx : & CodegenContext < crate :: CCodegen > ,
22
+ ) -> CompiledModule {
23
+ module. into_compiled_module (
24
+ success,
25
+ false ,
26
+ false ,
27
+ false ,
28
+ false ,
29
+ & cgcx. output_filenames ,
30
+ cgcx. invocation_temp . as_deref ( ) ,
31
+ )
32
+ }
33
+
11
34
pub ( crate ) fn codegen (
12
35
cgcx : & CodegenContext < crate :: CCodegen > ,
13
36
module : ModuleCodegen < String > ,
14
37
_config : & ModuleConfig ,
15
- ) -> Result < CompiledModule , FatalError > {
38
+ ) -> CompiledModule {
16
39
let dcx = cgcx. create_dcx ( ) ;
17
40
let dcx = dcx. handle ( ) ;
18
41
let obj_out = cgcx. output_filenames . temp_path_for_cgu (
@@ -23,44 +46,41 @@ pub(crate) fn codegen(
23
46
let c_out = obj_out. with_extension ( "c" ) ;
24
47
25
48
// output c source code
26
- let c_out_file = fs:: File :: create ( & c_out) . map_err ( |_| FatalError ) ?;
27
- writeln ! ( & c_out_file, "// file: {}.c" , module. name) . map_err ( |_| FatalError ) ?;
28
- write ! ( & c_out_file, "{}" , module. module_llvm) . map_err ( |_| FatalError ) ?;
49
+ if let Err ( c_out_err) = write_module ( & c_out, & module) {
50
+ dcx. emit_err ( crate :: errors:: CFileWriteError { err : c_out_err } ) ;
51
+ return compiled_module ( false , module, cgcx) ;
52
+ }
29
53
30
54
// invoke cc to compile
31
55
// FIXME: configure cc
32
56
// FIXME: handle long command line (windows)
33
57
// FIXME: flush_linked_file (windows)
34
58
let mut cmd = Command :: new ( "clang" ) ;
35
59
cmd. arg ( & c_out) . arg ( "-o" ) . arg ( & obj_out) . arg ( "-c" ) ;
36
- let output = match cmd
60
+ let success = match cmd
37
61
. stdout ( Stdio :: piped ( ) )
38
62
. stderr ( Stdio :: piped ( ) )
39
63
. spawn ( )
40
64
. and_then ( |child| child. wait_with_output ( ) )
41
65
{
42
- Ok ( output) => output,
66
+ Ok ( output) if !output. status . success ( ) => {
67
+ error ! ( "compiler stderr:\n {}" , String :: from_utf8_lossy( & output. stderr) ) ;
68
+ error ! ( "compiler stdout:\n {}" , String :: from_utf8_lossy( & output. stdout) ) ;
69
+ dcx. emit_err ( crate :: errors:: CCompilerError {
70
+ cc_stderr : String :: from_utf8_lossy ( & output. stderr ) . to_string ( ) ,
71
+ cc_stdout : String :: from_utf8_lossy ( & output. stdout ) . to_string ( ) ,
72
+ } ) ;
73
+ false
74
+ }
75
+ Ok ( _) => true ,
43
76
Err ( e) => {
44
77
error ! ( "failed to spawn C compiler: {}" , e) ;
45
- return Err ( FatalError ) ;
78
+ dcx. emit_err ( crate :: errors:: CCompilerSpawnError { err : e } ) ;
79
+ false
46
80
}
47
81
} ;
48
82
49
- if !output. status . success ( ) {
50
- error ! ( "compiler stderr:\n {}" , String :: from_utf8_lossy( & output. stderr) ) ;
51
- error ! ( "compiler stdout:\n {}" , String :: from_utf8_lossy( & output. stdout) ) ;
52
- return Err ( FatalError ) ;
53
- }
54
-
55
- Ok ( module. into_compiled_module (
56
- true ,
57
- false ,
58
- false ,
59
- false ,
60
- false ,
61
- & cgcx. output_filenames ,
62
- cgcx. invocation_temp . as_deref ( ) ,
63
- ) )
83
+ compiled_module ( success, module, cgcx)
64
84
}
65
85
66
86
pub ( crate ) fn link (
0 commit comments