• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::env;
2 use std::time::Instant;
3 
4 use gccjit::{
5     Context,
6     FunctionType,
7     GlobalKind,
8 };
9 use rustc_middle::dep_graph;
10 use rustc_middle::ty::TyCtxt;
11 #[cfg(feature="master")]
12 use rustc_middle::mir::mono::Visibility;
13 use rustc_middle::mir::mono::Linkage;
14 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
15 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
16 use rustc_codegen_ssa::mono_item::MonoItemExt;
17 use rustc_codegen_ssa::traits::DebugInfoMethods;
18 use rustc_session::config::DebugInfo;
19 use rustc_span::Symbol;
20 
21 use crate::GccContext;
22 use crate::builder::Builder;
23 use crate::context::CodegenCx;
24 
25 #[cfg(feature="master")]
visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility26 pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
27     match linkage {
28         Visibility::Default => gccjit::Visibility::Default,
29         Visibility::Hidden => gccjit::Visibility::Hidden,
30         Visibility::Protected => gccjit::Visibility::Protected,
31     }
32 }
33 
global_linkage_to_gcc(linkage: Linkage) -> GlobalKind34 pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
35     match linkage {
36         Linkage::External => GlobalKind::Imported,
37         Linkage::AvailableExternally => GlobalKind::Imported,
38         Linkage::LinkOnceAny => unimplemented!(),
39         Linkage::LinkOnceODR => unimplemented!(),
40         Linkage::WeakAny => unimplemented!(),
41         Linkage::WeakODR => unimplemented!(),
42         Linkage::Appending => unimplemented!(),
43         Linkage::Internal => GlobalKind::Internal,
44         Linkage::Private => GlobalKind::Internal,
45         Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage.
46         Linkage::Common => unimplemented!(),
47     }
48 }
49 
linkage_to_gcc(linkage: Linkage) -> FunctionType50 pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
51     match linkage {
52         Linkage::External => FunctionType::Exported,
53         Linkage::AvailableExternally => FunctionType::Extern,
54         Linkage::LinkOnceAny => unimplemented!(),
55         Linkage::LinkOnceODR => unimplemented!(),
56         Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce.
57         Linkage::WeakODR => unimplemented!(),
58         Linkage::Appending => unimplemented!(),
59         Linkage::Internal => FunctionType::Internal,
60         Linkage::Private => FunctionType::Internal,
61         Linkage::ExternalWeak => unimplemented!(),
62         Linkage::Common => unimplemented!(),
63     }
64 }
65 
compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64)66 pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
67     let prof_timer = tcx.prof.generic_activity("codegen_module");
68     let start_time = Instant::now();
69 
70     let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
71     let (module, _) = tcx.dep_graph.with_task(
72         dep_node,
73         tcx,
74         (cgu_name, supports_128bit_integers),
75         module_codegen,
76         Some(dep_graph::hash_result),
77     );
78     let time_to_codegen = start_time.elapsed();
79     drop(prof_timer);
80 
81     // We assume that the cost to run GCC on a CGU is proportional to
82     // the time we needed for codegenning it.
83     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
84 
85     fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol, bool)) -> ModuleCodegen<GccContext> {
86         let cgu = tcx.codegen_unit(cgu_name);
87         // Instantiate monomorphizations without filling out definitions yet...
88         //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
89         let context = Context::default();
90 
91         context.add_command_line_option("-fexceptions");
92         context.add_driver_option("-fexceptions");
93 
94         // TODO(antoyo): only set on x86 platforms.
95         context.add_command_line_option("-masm=intel");
96         // TODO(antoyo): only add the following cli argument if the feature is supported.
97         context.add_command_line_option("-msse2");
98         context.add_command_line_option("-mavx2");
99         // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU.
100         // Only add if the CPU supports it.
101         context.add_command_line_option("-msha");
102         context.add_command_line_option("-mpclmul");
103         context.add_command_line_option("-mfma");
104         context.add_command_line_option("-mfma4");
105         context.add_command_line_option("-m64");
106         context.add_command_line_option("-mbmi");
107         context.add_command_line_option("-mgfni");
108         //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option.
109         context.add_command_line_option("-mf16c");
110         context.add_command_line_option("-maes");
111         context.add_command_line_option("-mxsavec");
112         context.add_command_line_option("-mbmi2");
113         context.add_command_line_option("-mrtm");
114         context.add_command_line_option("-mvaes");
115         context.add_command_line_option("-mvpclmulqdq");
116         context.add_command_line_option("-mavx");
117 
118         for arg in &tcx.sess.opts.cg.llvm_args {
119             context.add_command_line_option(arg);
120         }
121         // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc.
122         context.add_command_line_option("-fno-var-tracking-assignments");
123         // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
124         context.add_command_line_option("-fno-semantic-interposition");
125         // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292).
126         context.add_command_line_option("-fno-strict-aliasing");
127         // NOTE: Rust relies on LLVM doing wrapping on overflow.
128         context.add_command_line_option("-fwrapv");
129 
130         if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) {
131             context.add_command_line_option("-ffunction-sections");
132             context.add_command_line_option("-fdata-sections");
133         }
134 
135         if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
136             context.add_command_line_option("-fdump-rtl-vregs");
137         }
138         if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
139             context.add_command_line_option("-fdump-tree-all");
140         }
141         if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
142             context.set_dump_code_on_compile(true);
143         }
144         if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
145             context.set_dump_initial_gimple(true);
146         }
147         context.set_debug_info(true);
148         if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") {
149             context.set_dump_everything(true);
150         }
151         if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") {
152             context.set_keep_intermediates(true);
153         }
154 
155         // NOTE: The codegen generates unrechable blocks.
156         context.set_allow_unreachable_blocks(true);
157 
158         {
159             let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers);
160 
161             let mono_items = cgu.items_in_deterministic_order(tcx);
162             for &(mono_item, (linkage, visibility)) in &mono_items {
163                 mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
164             }
165 
166             // ... and now that we have everything pre-defined, fill out those definitions.
167             for &(mono_item, _) in &mono_items {
168                 mono_item.define::<Builder<'_, '_, '_>>(&cx);
169             }
170 
171             // If this codegen unit contains the main function, also create the
172             // wrapper here
173             maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
174 
175             // Finalize debuginfo
176             if cx.sess().opts.debuginfo != DebugInfo::None {
177                 cx.debuginfo_finalize();
178             }
179         }
180 
181         ModuleCodegen {
182             name: cgu_name.to_string(),
183             module_llvm: GccContext {
184                 context
185             },
186             kind: ModuleKind::Regular,
187         }
188     }
189 
190     (module, cost)
191 }
192