]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_gcc/src/lib.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_codegen_gcc / src / lib.rs
CommitLineData
c295e0f8 1/*
5e7ed085 2 * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
c295e0f8 3 * TODO(antoyo): support #[inline] attributes.
5e7ed085 4 * TODO(antoyo): support LTO (gcc's equivalent to Thin LTO is enabled by -fwhopr: https://stackoverflow.com/questions/64954525/does-gcc-have-thin-lto).
c295e0f8
XL
5 *
6 * TODO(antoyo): remove the patches.
7 */
8
064997fb
FG
9#![feature(
10 rustc_private,
11 decl_macro,
12 associated_type_bounds,
13 never_type,
14 trusted_len,
15 hash_raw_entry
16)]
c295e0f8
XL
17#![allow(broken_intra_doc_links)]
18#![recursion_limit="256"]
19#![warn(rust_2018_idioms)]
20#![warn(unused_lifetimes)]
21
f2b60f7d 22extern crate rustc_apfloat;
c295e0f8
XL
23extern crate rustc_ast;
24extern crate rustc_codegen_ssa;
25extern crate rustc_data_structures;
26extern crate rustc_errors;
27extern crate rustc_hir;
28extern crate rustc_metadata;
29extern crate rustc_middle;
30extern crate rustc_session;
31extern crate rustc_span;
c295e0f8 32extern crate rustc_target;
5e7ed085 33extern crate tempfile;
c295e0f8
XL
34
35// This prevents duplicating functions and statics that are already part of the host rustc process.
36#[allow(unused_extern_crates)]
37extern crate rustc_driver;
38
39mod abi;
40mod allocator;
41mod archive;
42mod asm;
43mod back;
44mod base;
45mod builder;
46mod callee;
47mod common;
48mod consts;
49mod context;
50mod coverageinfo;
51mod debuginfo;
52mod declare;
5e7ed085 53mod int;
c295e0f8
XL
54mod intrinsic;
55mod mono_item;
56mod type_;
57mod type_of;
58
59use std::any::Any;
5e7ed085 60use std::sync::{Arc, Mutex};
c295e0f8 61
5e7ed085 62use gccjit::{Context, OptimizationLevel, CType};
c295e0f8
XL
63use rustc_ast::expand::allocator::AllocatorKind;
64use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
65use rustc_codegen_ssa::base::codegen_crate;
66use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryFn};
67use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
68use rustc_codegen_ssa::target_features::supported_target_features;
69use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
70use rustc_data_structures::fx::FxHashMap;
5e7ed085 71use rustc_errors::{ErrorGuaranteed, Handler};
c295e0f8
XL
72use rustc_metadata::EncodedMetadata;
73use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
74use rustc_middle::ty::TyCtxt;
5e7ed085 75use rustc_middle::ty::query::Providers;
c295e0f8
XL
76use rustc_session::config::{Lto, OptLevel, OutputFilenames};
77use rustc_session::Session;
78use rustc_span::Symbol;
79use rustc_span::fatal_error::FatalError;
5e7ed085 80use tempfile::TempDir;
c295e0f8
XL
81
82pub struct PrintOnPanic<F: Fn() -> String>(pub F);
83
84impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
85 fn drop(&mut self) {
86 if ::std::thread::panicking() {
87 println!("{}", (self.0)());
88 }
89 }
90}
91
92#[derive(Clone)]
5e7ed085
FG
93pub struct GccCodegenBackend {
94 supports_128bit_integers: Arc<Mutex<bool>>,
95}
c295e0f8
XL
96
97impl CodegenBackend for GccCodegenBackend {
98 fn init(&self, sess: &Session) {
99 if sess.lto() != Lto::No {
100 sess.warn("LTO is not supported. You may get a linker error.");
101 }
5e7ed085
FG
102
103 let temp_dir = TempDir::new().expect("cannot create temporary directory");
104 let temp_file = temp_dir.into_path().join("result.asm");
105 let check_context = Context::default();
106 check_context.set_print_errors_to_stderr(false);
107 let _int128_ty = check_context.new_c_type(CType::UInt128t);
108 // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
109 check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
110 *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None);
111 }
112
113 fn provide(&self, providers: &mut Providers) {
114 // FIXME(antoyo) compute list of enabled features from cli flags
115 providers.global_backend_features = |_tcx, ()| vec![];
c295e0f8
XL
116 }
117
118 fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
119 let target_cpu = target_cpu(tcx.sess);
120 let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module);
121
c295e0f8
XL
122 Box::new(res)
123 }
124
5e7ed085 125 fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
c295e0f8
XL
126 let (codegen_results, work_products) = ongoing_codegen
127 .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
128 .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
129 .join(sess);
130
131 Ok((codegen_results, work_products))
132 }
133
5e7ed085 134 fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
c295e0f8
XL
135 use rustc_codegen_ssa::back::link::link_binary;
136
064997fb 137 link_binary(
c295e0f8 138 sess,
064997fb 139 &crate::archive::ArArchiveBuilderBuilder,
c295e0f8
XL
140 &codegen_results,
141 outputs,
142 )
143 }
144
064997fb
FG
145 fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
146 target_features(sess, allow_unstable)
c295e0f8
XL
147 }
148}
149
150impl ExtraBackendMethods for GccCodegenBackend {
04454e1e
FG
151 fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) -> Self::Module {
152 let mut mods = GccContext {
c295e0f8 153 context: Context::default(),
04454e1e
FG
154 };
155 unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, has_alloc_error_handler); }
156 mods
c295e0f8
XL
157 }
158
159 fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
5e7ed085 160 base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
c295e0f8
XL
161 }
162
5e7ed085 163 fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
c295e0f8
XL
164 // TODO(antoyo): set opt level.
165 Arc::new(|_| {
166 Ok(())
167 })
168 }
169
170 fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str {
171 unimplemented!();
172 }
173
174 fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> {
175 None
176 // TODO(antoyo)
177 }
178}
179
180pub struct ModuleBuffer;
181
182impl ModuleBufferMethods for ModuleBuffer {
183 fn data(&self) -> &[u8] {
184 unimplemented!();
185 }
186}
187
188pub struct ThinBuffer;
189
190impl ThinBufferMethods for ThinBuffer {
191 fn data(&self) -> &[u8] {
192 unimplemented!();
193 }
194}
195
196pub struct GccContext {
197 context: Context<'static>,
198}
199
200unsafe impl Send for GccContext {}
201// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here.
202unsafe impl Sync for GccContext {}
203
204impl WriteBackendMethods for GccCodegenBackend {
205 type Module = GccContext;
206 type TargetMachine = ();
207 type ModuleBuffer = ModuleBuffer;
208 type Context = ();
209 type ThinData = ();
210 type ThinBuffer = ThinBuffer;
211
212 fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLTOInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
213 // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
214 // NOTE: implemented elsewhere.
923072b8 215 // TODO(antoyo): what is implemented elsewhere ^ ?
c295e0f8
XL
216 let module =
217 match modules.remove(0) {
218 FatLTOInput::InMemory(module) => module,
219 FatLTOInput::Serialized { .. } => {
220 unimplemented!();
221 }
222 };
04454e1e 223 Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: vec![] })
c295e0f8
XL
224 }
225
226 fn run_thin_lto(_cgcx: &CodegenContext<Self>, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
227 unimplemented!();
228 }
229
230 fn print_pass_timings(&self) {
231 unimplemented!();
232 }
233
234 unsafe fn optimize(_cgcx: &CodegenContext<Self>, _diag_handler: &Handler, module: &ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<(), FatalError> {
235 module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
236 Ok(())
237 }
238
04454e1e
FG
239 fn optimize_fat(_cgcx: &CodegenContext<Self>, _module: &mut ModuleCodegen<Self::Module>) -> Result<(), FatalError> {
240 // TODO(antoyo)
241 Ok(())
242 }
243
244 unsafe fn optimize_thin(_cgcx: &CodegenContext<Self>, _thin: ThinModule<Self>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
c295e0f8
XL
245 unimplemented!();
246 }
247
248 unsafe fn codegen(cgcx: &CodegenContext<Self>, diag_handler: &Handler, module: ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
249 back::write::codegen(cgcx, diag_handler, module, config)
250 }
251
252 fn prepare_thin(_module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
253 unimplemented!();
254 }
255
256 fn serialize_module(_module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
257 unimplemented!();
258 }
259
c295e0f8
XL
260 fn run_link(cgcx: &CodegenContext<Self>, diag_handler: &Handler, modules: Vec<ModuleCodegen<Self::Module>>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
261 back::write::link(cgcx, diag_handler, modules)
262 }
263}
264
265/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
266#[no_mangle]
267pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
5e7ed085
FG
268 Box::new(GccCodegenBackend {
269 supports_128bit_integers: Arc::new(Mutex::new(false)),
270 })
c295e0f8
XL
271}
272
273fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
274 match optlevel {
275 None => OptimizationLevel::None,
276 Some(level) => {
277 match level {
278 OptLevel::No => OptimizationLevel::None,
279 OptLevel::Less => OptimizationLevel::Limited,
280 OptLevel::Default => OptimizationLevel::Standard,
281 OptLevel::Aggressive => OptimizationLevel::Aggressive,
282 OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
283 }
284 },
285 }
286}
287
288fn handle_native(name: &str) -> &str {
289 if name != "native" {
290 return name;
291 }
292
293 unimplemented!();
294}
295
296pub fn target_cpu(sess: &Session) -> &str {
5e7ed085
FG
297 match sess.opts.cg.target_cpu {
298 Some(ref name) => handle_native(name),
299 None => handle_native(sess.target.cpu.as_ref()),
300 }
c295e0f8
XL
301}
302
064997fb 303pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
c295e0f8
XL
304 supported_target_features(sess)
305 .iter()
306 .filter_map(
307 |&(feature, gate)| {
064997fb 308 if sess.is_nightly_build() || allow_unstable || gate.is_none() { Some(feature) } else { None }
c295e0f8
XL
309 },
310 )
311 .filter(|_feature| {
312 // TODO(antoyo): implement a way to get enabled feature in libgccjit.
923072b8
FG
313 // Probably using the equivalent of __builtin_cpu_supports.
314 #[cfg(feature="master")]
315 {
316 _feature.contains("sse") || _feature.contains("avx")
317 }
318 #[cfg(not(feature="master"))]
319 {
320 false
321 }
322 /*
323 adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512gfni,
324 avx512ifma, avx512pf, avx512vaes, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpclmulqdq,
325 avx512vpopcntdq, bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
326 sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, xsave, xsavec, xsaveopt, xsaves
327 */
328 //false
c295e0f8
XL
329 })
330 .map(|feature| Symbol::intern(feature))
331 .collect()
332}