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;
11 use crate::{GccCodegenBackend, GccContext};
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[..]);
16 let context = &module.module_llvm.context;
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);
24 /*if cgcx.msvc_imps_needed {
25 create_msvc_imps(cgcx, llcx, llmod);
28 // A codegen-specific pass manager is used to generate object
29 // files for an GCC module.
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
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,
39 let cpm = llvm::LLVMCreatePassManager();
40 llvm::LLVMAddAnalysisPasses(tm, cpm);
41 llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
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
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.
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);
55 if config.bitcode_needed() {
59 .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]);
60 let thin = ThinBuffer::new(llmod);
61 let data = thin.data();
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",
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);
74 if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
75 let _timer = cgcx.prof.generic_activity_with_arg(
76 "LLVM_module_codegen_embed_bitcode",
79 embed_bitcode(cgcx, llcx, llmod, Some(data));
82 if config.emit_bc_compressed {
83 let _timer = cgcx.prof.generic_activity_with_arg(
84 "LLVM_module_codegen_emit_compressed_bitcode",
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);
94 } /*else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
96 //embed_bitcode(cgcx, llcx, llmod, None);
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);
107 extern "C" fn demangle_callback(
108 input_ptr: *const c_char,
110 output_ptr: *mut c_char,
114 unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
116 let input = match str::from_utf8(input) {
121 let output = unsafe {
122 slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
124 let mut cursor = io::Cursor::new(output);
126 let demangled = match rustc_demangle::try_demangle(input) {
131 if write!(cursor, "{:#}", demangled).is_err() {
132 // Possible only if provided buffer is not big enough
136 cursor.position() as size_t
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)
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"));
153 /*with_codegen(tm, llmod, config.no_builtins, |cpm| {
154 write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
158 match config.emit_obj {
159 EmitObj::ObjectCode(_) => {
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);
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"));
185 EmitObj::Bitcode => {
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));
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));
206 Ok(module.into_compiled_module(
207 config.emit_obj != EmitObj::None,
208 cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked,
210 &cgcx.output_filenames,
214 pub(crate) fn link(_cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, mut _modules: Vec<ModuleCodegen<GccContext>>) -> Result<ModuleCodegen<GccContext>, FatalError> {
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.");
222 let mut linker = Linker::new(first.module_llvm.llmod());
223 for module in elements {
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)
233 Ok(modules.remove(0))*/