]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_gcc/src/back/write.rs
Merge commit '0c89065b934397b62838fe3e4ef6f6352fc52daf' into libgccjit-codegen
[rust.git] / compiler / rustc_codegen_gcc / src / back / write.rs
1 use std::fs;
2
3 use gccjit::OutputKind;
4 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
5 use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig};
6 use rustc_errors::Handler;
7 use rustc_session::config::OutputType;
8 use rustc_span::fatal_error::FatalError;
9 use rustc_target::spec::SplitDebuginfo;
10
11 use crate::{GccCodegenBackend, GccContext};
12
13 pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
14     let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]);
15     {
16         let context = &module.module_llvm.context;
17
18         //let llcx = &*module.module_llvm.llcx;
19         //let tm = &*module.module_llvm.tm;
20         let module_name = module.name.clone();
21         let module_name = Some(&module_name[..]);
22         //let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
23
24         /*if cgcx.msvc_imps_needed {
25             create_msvc_imps(cgcx, llcx, llmod);
26         }*/
27
28         // A codegen-specific pass manager is used to generate object
29         // files for an GCC module.
30         //
31         // Apparently each of these pass managers is a one-shot kind of
32         // thing, so we create a new one for each type of output. The
33         // pass manager passed to the closure should be ensured to not
34         // escape the closure itself, and the manager should only be
35         // used once.
36         /*unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine, llmod: &'ll llvm::Module, no_builtins: bool, f: F) -> R
37         where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
38         {
39             let cpm = llvm::LLVMCreatePassManager();
40             llvm::LLVMAddAnalysisPasses(tm, cpm);
41             llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
42             f(cpm)
43         }*/
44
45         // Two things to note:
46         // - If object files are just LLVM bitcode we write bitcode, copy it to
47         //   the .o file, and delete the bitcode if it wasn't otherwise
48         //   requested.
49         // - If we don't have the integrated assembler then we need to emit
50         //   asm from LLVM and use `gcc` to create the object file.
51
52         let _bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
53         let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
54
55         if config.bitcode_needed() {
56             // TODO
57             /*let _timer = cgcx
58                 .prof
59                 .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]);
60             let thin = ThinBuffer::new(llmod);
61             let data = thin.data();
62
63             if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
64                 let _timer = cgcx.prof.generic_activity_with_arg(
65                     "LLVM_module_codegen_emit_bitcode",
66                     &module.name[..],
67                 );
68                 if let Err(e) = fs::write(&bc_out, data) {
69                     let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
70                     diag_handler.err(&msg);
71                 }
72             }
73
74             if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
75                 let _timer = cgcx.prof.generic_activity_with_arg(
76                     "LLVM_module_codegen_embed_bitcode",
77                     &module.name[..],
78                 );
79                 embed_bitcode(cgcx, llcx, llmod, Some(data));
80             }
81
82             if config.emit_bc_compressed {
83                 let _timer = cgcx.prof.generic_activity_with_arg(
84                     "LLVM_module_codegen_emit_compressed_bitcode",
85                     &module.name[..],
86                 );
87                 let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
88                 let data = bytecode::encode(&module.name, data);
89                 if let Err(e) = fs::write(&dst, data) {
90                     let msg = format!("failed to write bytecode to {}: {}", dst.display(), e);
91                     diag_handler.err(&msg);
92                 }
93             }*/
94         } /*else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
95             unimplemented!();
96             //embed_bitcode(cgcx, llcx, llmod, None);
97         }*/
98
99         if config.emit_ir {
100             unimplemented!();
101             /*let _timer = cgcx
102                 .prof
103                 .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]);
104             let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
105             let out_c = path_to_c_string(&out);
106
107             extern "C" fn demangle_callback(
108                 input_ptr: *const c_char,
109                 input_len: size_t,
110                 output_ptr: *mut c_char,
111                 output_len: size_t,
112             ) -> size_t {
113                 let input =
114                     unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
115
116                 let input = match str::from_utf8(input) {
117                     Ok(s) => s,
118                     Err(_) => return 0,
119                 };
120
121                 let output = unsafe {
122                     slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
123                 };
124                 let mut cursor = io::Cursor::new(output);
125
126                 let demangled = match rustc_demangle::try_demangle(input) {
127                     Ok(d) => d,
128                     Err(_) => return 0,
129                 };
130
131                 if write!(cursor, "{:#}", demangled).is_err() {
132                     // Possible only if provided buffer is not big enough
133                     return 0;
134                 }
135
136                 cursor.position() as size_t
137             }
138
139             let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
140             result.into_result().map_err(|()| {
141                 let msg = format!("failed to write LLVM IR to {}", out.display());
142                 llvm_err(diag_handler, &msg)
143             })?;*/
144         }
145
146         if config.emit_asm {
147             let _timer = cgcx
148                 .prof
149                 .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
150             let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
151             context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
152
153             /*with_codegen(tm, llmod, config.no_builtins, |cpm| {
154                 write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
155             })?;*/
156         }
157
158         match config.emit_obj {
159             EmitObj::ObjectCode(_) => {
160                 let _timer = cgcx
161                     .prof
162                     .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
163                 //with_codegen(tm, llmod, config.no_builtins, |cpm| {
164                     //println!("1: {}", module.name);
165                     match &*module.name {
166                         "std_example.7rcbfp3g-cgu.15" => {
167                             println!("Dumping reproducer {}", module.name);
168                             let _ = fs::create_dir("/tmp/reproducers");
169                             // FIXME: segfault in dump_reproducer_to_file() might be caused by
170                             // transmuting an rvalue to an lvalue.
171                             // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue
172                             context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
173                             println!("Dumped reproducer {}", module.name);
174                         },
175                         _ => (),
176                     }
177                     /*let _ = fs::create_dir("/tmp/dumps");
178                     context.dump_to_file(&format!("/tmp/dumps/{}.c", module.name), true);
179                     println!("Dumped {}", module.name);*/
180                     //println!("Compile module {}", module.name);
181                     context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
182                 //})?;
183             }
184
185             EmitObj::Bitcode => {
186                 //unimplemented!();
187                 /*debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
188                 if let Err(e) = link_or_copy(&bc_out, &obj_out) {
189                     diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
190                 }
191
192                 if !config.emit_bc {
193                     debug!("removing_bitcode {:?}", bc_out);
194                     if let Err(e) = fs::remove_file(&bc_out) {
195                         diag_handler.err(&format!("failed to remove bitcode: {}", e));
196                     }
197                 }*/
198             }
199
200             EmitObj::None => {}
201         }
202
203         //drop(handlers);
204     }
205
206     Ok(module.into_compiled_module(
207         config.emit_obj != EmitObj::None,
208         cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked,
209         config.emit_bc,
210         &cgcx.output_filenames,
211     ))
212 }
213
214 pub(crate) fn link(_cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, mut _modules: Vec<ModuleCodegen<GccContext>>) -> Result<ModuleCodegen<GccContext>, FatalError> {
215     unimplemented!();
216     /*use super::lto::{Linker, ModuleBuffer};
217     // Sort the modules by name to ensure to ensure deterministic behavior.
218     modules.sort_by(|a, b| a.name.cmp(&b.name));
219     let (first, elements) =
220         modules.split_first().expect("Bug! modules must contain at least one module.");
221
222     let mut linker = Linker::new(first.module_llvm.llmod());
223     for module in elements {
224         let _timer =
225             cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name));
226         let buffer = ModuleBuffer::new(module.module_llvm.llmod());
227         linker.add(&buffer.data()).map_err(|()| {
228             let msg = format!("failed to serialize module {:?}", module.name);
229             llvm_err(&diag_handler, &msg)
230         })?;
231     }
232     drop(linker);
233     Ok(modules.remove(0))*/
234 }