2020-05-10 14:54:30 +00:00
/*
2022-03-26 17:29:37 +00:00
* TODO ( antoyo ) : implement equality in libgccjit based on https ://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
2021-08-15 12:28:46 +00:00
* TODO ( antoyo ) : support #[ inline ] attributes .
2023-03-05 17:03:19 +00:00
* TODO ( antoyo ) : support LTO ( gcc ' s equivalent to Full LTO is - flto - flto - partition = one — https ://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html).
2023-10-09 19:53:34 +00:00
* For Thin LTO , this might be helpful :
* In gcc 4.6 - fwhopr was removed and became default with - flto . The non - whopr path can still be executed via - flto - partition = none .
*
* Maybe some missing optizations enabled by rustc ' s LTO is in there : https ://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
* Like - fipa - icf ( should be already enabled ) and maybe - fdevirtualize - at - ltrans .
* TODO : disable debug info always being emitted . Perhaps this slows down things ?
2020-05-10 14:54:30 +00:00
*
2021-08-15 12:28:46 +00:00
* TODO ( antoyo ) : remove the patches .
2020-05-10 14:54:30 +00:00
* /
2023-11-13 12:39:17 +00:00
#![ allow(internal_features) ]
#![ doc(rust_logo) ]
#![ feature(rustdoc_internals) ]
2022-06-28 17:34:24 +00:00
#![ feature(
rustc_private ,
decl_macro ,
associated_type_bounds ,
never_type ,
trusted_len ,
hash_raw_entry
) ]
2020-05-10 14:54:30 +00:00
#![ allow(broken_intra_doc_links) ]
#![ recursion_limit= " 256 " ]
#![ warn(rust_2018_idioms) ]
#![ warn(unused_lifetimes) ]
2022-08-27 22:21:46 +00:00
#![ deny(rustc::untranslatable_diagnostic) ]
#![ deny(rustc::diagnostic_outside_of_impl) ]
2020-05-10 14:54:30 +00:00
2022-08-16 22:46:17 +00:00
extern crate rustc_apfloat ;
2020-05-10 14:54:30 +00:00
extern crate rustc_ast ;
2023-03-05 17:03:19 +00:00
extern crate rustc_attr ;
2020-05-10 14:54:30 +00:00
extern crate rustc_codegen_ssa ;
extern crate rustc_data_structures ;
extern crate rustc_errors ;
2023-04-16 12:33:00 +00:00
extern crate rustc_fluent_macro ;
2023-10-09 19:53:34 +00:00
extern crate rustc_fs_util ;
2020-05-10 14:54:30 +00:00
extern crate rustc_hir ;
2023-10-27 23:31:02 +00:00
#[ cfg(feature= " master " ) ]
extern crate rustc_interface ;
2022-08-27 02:32:04 +00:00
extern crate rustc_macros ;
2020-05-10 14:54:30 +00:00
extern crate rustc_metadata ;
extern crate rustc_middle ;
extern crate rustc_session ;
extern crate rustc_span ;
extern crate rustc_target ;
2023-10-09 19:53:34 +00:00
#[ macro_use ]
extern crate tracing ;
2020-05-10 14:54:30 +00:00
// This prevents duplicating functions and statics that are already part of the host rustc process.
#[ allow(unused_extern_crates) ]
extern crate rustc_driver ;
mod abi ;
mod allocator ;
mod archive ;
mod asm ;
2023-03-05 17:03:19 +00:00
mod attributes ;
2020-05-10 14:54:30 +00:00
mod back ;
mod base ;
mod builder ;
mod callee ;
mod common ;
mod consts ;
mod context ;
mod coverageinfo ;
mod debuginfo ;
mod declare ;
2022-08-27 02:32:04 +00:00
mod errors ;
2023-10-09 19:53:34 +00:00
mod gcc_util ;
2022-03-26 17:29:37 +00:00
mod int ;
2020-05-10 14:54:30 +00:00
mod intrinsic ;
mod mono_item ;
mod type_ ;
mod type_of ;
use std ::any ::Any ;
2023-10-09 20:45:46 +00:00
use std ::fmt ::Debug ;
2023-10-09 19:53:34 +00:00
use std ::sync ::Arc ;
use std ::sync ::Mutex ;
#[ cfg(not(feature= " master " )) ]
use std ::sync ::atomic ::AtomicBool ;
#[ cfg(not(feature= " master " )) ]
use std ::sync ::atomic ::Ordering ;
use gccjit ::{ Context , OptimizationLevel } ;
#[ cfg(feature= " master " ) ]
2023-10-27 23:31:02 +00:00
use gccjit ::{ TargetInfo , Version } ;
2023-10-09 19:53:34 +00:00
#[ cfg(not(feature= " master " )) ]
use gccjit ::CType ;
use errors ::LTONotSupported ;
2020-05-10 14:54:30 +00:00
use rustc_ast ::expand ::allocator ::AllocatorKind ;
use rustc_codegen_ssa ::{ CodegenResults , CompiledModule , ModuleCodegen } ;
use rustc_codegen_ssa ::base ::codegen_crate ;
2023-07-21 01:18:25 +00:00
use rustc_codegen_ssa ::back ::write ::{ CodegenContext , FatLtoInput , ModuleConfig , TargetMachineFactoryFn } ;
2020-05-10 14:54:30 +00:00
use rustc_codegen_ssa ::back ::lto ::{ LtoModuleCodegen , SerializedModule , ThinModule } ;
use rustc_codegen_ssa ::target_features ::supported_target_features ;
2023-04-07 19:56:33 +00:00
use rustc_data_structures ::fx ::FxIndexMap ;
2023-10-09 20:45:46 +00:00
use rustc_data_structures ::sync ::IntoDynSyncSend ;
2023-10-09 19:53:34 +00:00
use rustc_codegen_ssa ::traits ::{ CodegenBackend , ExtraBackendMethods , ThinBufferMethods , WriteBackendMethods } ;
2023-11-21 22:22:39 +00:00
use rustc_errors ::{ ErrorGuaranteed , Handler } ;
2021-09-30 18:22:42 +00:00
use rustc_metadata ::EncodedMetadata ;
2020-05-10 14:54:30 +00:00
use rustc_middle ::dep_graph ::{ WorkProduct , WorkProductId } ;
2023-09-22 16:26:20 +00:00
use rustc_middle ::util ::Providers ;
2020-05-10 14:54:30 +00:00
use rustc_middle ::ty ::TyCtxt ;
2021-09-27 13:34:06 +00:00
use rustc_session ::config ::{ Lto , OptLevel , OutputFilenames } ;
2020-05-10 14:54:30 +00:00
use rustc_session ::Session ;
use rustc_span ::Symbol ;
use rustc_span ::fatal_error ::FatalError ;
2022-03-26 17:29:37 +00:00
use tempfile ::TempDir ;
2020-05-10 14:54:30 +00:00
2023-10-09 19:53:34 +00:00
use crate ::back ::lto ::ModuleBuffer ;
use crate ::gcc_util ::target_cpu ;
2023-11-21 22:53:07 +00:00
rustc_fluent_macro ::fluent_messages! { " ../messages.ftl " }
2022-10-13 09:13:02 +00:00
2020-05-10 14:54:30 +00:00
pub struct PrintOnPanic < F : Fn ( ) -> String > ( pub F ) ;
impl < F : Fn ( ) -> String > Drop for PrintOnPanic < F > {
fn drop ( & mut self ) {
if ::std ::thread ::panicking ( ) {
println! ( " {} " , ( self . 0 ) ( ) ) ;
}
}
}
2023-10-09 19:53:34 +00:00
#[ cfg(not(feature= " master " )) ]
#[ derive(Debug) ]
pub struct TargetInfo {
supports_128bit_integers : AtomicBool ,
}
#[ cfg(not(feature= " master " )) ]
impl TargetInfo {
fn cpu_supports ( & self , _feature : & str ) -> bool {
false
}
fn supports_128bit_int ( & self ) -> bool {
self . supports_128bit_integers . load ( Ordering ::SeqCst )
}
}
2023-10-09 20:45:46 +00:00
#[ derive(Clone) ]
2023-10-09 19:53:34 +00:00
pub struct LockedTargetInfo {
2023-10-09 20:45:46 +00:00
info : Arc < Mutex < IntoDynSyncSend < TargetInfo > > > ,
}
impl Debug for LockedTargetInfo {
fn fmt ( & self , formatter : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
self . info . lock ( ) . expect ( " lock " ) . fmt ( formatter )
}
2023-10-09 19:53:34 +00:00
}
impl LockedTargetInfo {
fn cpu_supports ( & self , feature : & str ) -> bool {
self . info . lock ( ) . expect ( " lock " ) . cpu_supports ( feature )
}
fn supports_128bit_int ( & self ) -> bool {
self . info . lock ( ) . expect ( " lock " ) . supports_128bit_int ( )
}
}
2020-05-10 14:54:30 +00:00
#[ derive(Clone) ]
2022-03-26 17:29:37 +00:00
pub struct GccCodegenBackend {
2023-10-09 19:53:34 +00:00
target_info : LockedTargetInfo ,
2022-03-26 17:29:37 +00:00
}
2020-05-10 14:54:30 +00:00
impl CodegenBackend for GccCodegenBackend {
2022-10-17 13:11:26 +00:00
fn locale_resource ( & self ) -> & 'static str {
crate ::DEFAULT_LOCALE_RESOURCE
}
2020-05-10 14:54:30 +00:00
fn init ( & self , sess : & Session ) {
2023-10-09 19:53:34 +00:00
#[ cfg(feature= " master " ) ]
{
let target_cpu = target_cpu ( sess ) ;
// Get the second TargetInfo with the correct CPU features by setting the arch.
let context = Context ::default ( ) ;
if target_cpu ! = " generic " {
context . add_command_line_option ( & format! ( " -march= {} " , target_cpu ) ) ;
}
2023-10-09 20:45:46 +00:00
* * self . target_info . info . lock ( ) . expect ( " lock " ) = context . get_target_info ( ) ;
2023-10-09 19:53:34 +00:00
}
2023-06-19 22:51:02 +00:00
#[ cfg(feature= " master " ) ]
gccjit ::set_global_personality_function_name ( b " rust_eh_personality \0 " ) ;
2023-10-09 19:53:34 +00:00
if sess . lto ( ) = = Lto ::Thin {
2022-08-27 03:50:37 +00:00
sess . emit_warning ( LTONotSupported { } ) ;
2020-05-10 14:54:30 +00:00
}
2022-03-26 17:29:37 +00:00
2023-10-09 19:53:34 +00:00
#[ cfg(not(feature= " master " )) ]
{
let temp_dir = TempDir ::new ( ) . expect ( " cannot create temporary directory " ) ;
let temp_file = temp_dir . into_path ( ) . join ( " result.asm " ) ;
let check_context = Context ::default ( ) ;
check_context . set_print_errors_to_stderr ( false ) ;
let _int128_ty = check_context . new_c_type ( CType ::UInt128t ) ;
// NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
check_context . compile_to_file ( gccjit ::OutputKind ::Assembler , temp_file . to_str ( ) . expect ( " path to str " ) ) ;
self . target_info . info . lock ( ) . expect ( " lock " ) . supports_128bit_integers . store ( check_context . get_last_error ( ) = = Ok ( None ) , Ordering ::SeqCst ) ;
}
2022-03-26 17:29:37 +00:00
}
2023-09-22 16:26:20 +00:00
fn provide ( & self , providers : & mut Providers ) {
2023-10-09 19:53:34 +00:00
providers . global_backend_features =
| tcx , ( ) | gcc_util ::global_gcc_features ( tcx . sess , true )
2020-05-10 14:54:30 +00:00
}
fn codegen_crate < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , metadata : EncodedMetadata , need_metadata_module : bool ) -> Box < dyn Any > {
let target_cpu = target_cpu ( tcx . sess ) ;
let res = codegen_crate ( self . clone ( ) , tcx , target_cpu . to_string ( ) , metadata , need_metadata_module ) ;
Box ::new ( res )
}
2023-04-07 19:56:33 +00:00
fn join_codegen ( & self , ongoing_codegen : Box < dyn Any > , sess : & Session , _outputs : & OutputFilenames ) -> Result < ( CodegenResults , FxIndexMap < WorkProductId , WorkProduct > ) , ErrorGuaranteed > {
2020-05-10 14:54:30 +00:00
let ( codegen_results , work_products ) = ongoing_codegen
. downcast ::< rustc_codegen_ssa ::back ::write ::OngoingCodegen < GccCodegenBackend > > ( )
. expect ( " Expected GccCodegenBackend's OngoingCodegen, found Box<Any> " )
. join ( sess ) ;
Ok ( ( codegen_results , work_products ) )
}
2022-01-23 18:34:26 +00:00
fn link ( & self , sess : & Session , codegen_results : CodegenResults , outputs : & OutputFilenames ) -> Result < ( ) , ErrorGuaranteed > {
2020-05-10 14:54:30 +00:00
use rustc_codegen_ssa ::back ::link ::link_binary ;
2022-07-28 09:07:49 +00:00
link_binary (
2020-05-10 14:54:30 +00:00
sess ,
2022-07-28 09:07:49 +00:00
& crate ::archive ::ArArchiveBuilderBuilder ,
2020-05-10 14:54:30 +00:00
& codegen_results ,
outputs ,
)
}
2022-07-11 13:26:58 +00:00
fn target_features ( & self , sess : & Session , allow_unstable : bool ) -> Vec < Symbol > {
2023-10-09 19:53:34 +00:00
target_features ( sess , allow_unstable , & self . target_info )
2020-05-10 14:54:30 +00:00
}
}
2023-11-19 18:51:56 +00:00
fn new_context < ' gcc , ' tcx > ( tcx : TyCtxt < ' tcx > ) -> Context < ' gcc > {
2023-10-25 22:26:34 +00:00
let context = Context ::default ( ) ;
if tcx . sess . target . arch = = " x86 " | | tcx . sess . target . arch = = " x86_64 " {
context . add_command_line_option ( " -masm=intel " ) ;
}
2023-10-27 23:31:02 +00:00
#[ cfg(feature= " master " ) ]
{
let version = Version ::get ( ) ;
let version = format! ( " {} . {} . {} " , version . major , version . minor , version . patch ) ;
context . set_output_ident ( & format! ( " rustc version {} with libgccjit {} " ,
rustc_interface ::util ::rustc_version_str ( ) . unwrap_or ( " unknown version " ) ,
version ,
) ) ;
}
// TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
2023-10-25 22:26:34 +00:00
context . add_command_line_option ( " -fno-asynchronous-unwind-tables " ) ;
context
}
2020-05-10 14:54:30 +00:00
impl ExtraBackendMethods for GccCodegenBackend {
2023-04-24 22:08:35 +00:00
fn codegen_allocator < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , module_name : & str , kind : AllocatorKind , alloc_error_handler_kind : AllocatorKind ) -> Self ::Module {
2022-04-30 19:20:08 +00:00
let mut mods = GccContext {
2023-11-19 18:51:56 +00:00
context : new_context ( tcx ) ,
2023-10-09 19:53:34 +00:00
should_combine_object_files : false ,
temp_dir : None ,
2022-04-30 19:20:08 +00:00
} ;
2023-10-09 19:53:34 +00:00
2023-04-24 22:08:35 +00:00
unsafe { allocator ::codegen ( tcx , & mut mods , module_name , kind , alloc_error_handler_kind ) ; }
2022-04-30 19:20:08 +00:00
mods
2020-05-10 14:54:30 +00:00
}
2022-12-20 21:10:40 +00:00
fn compile_codegen_unit ( & self , tcx : TyCtxt < '_ > , cgu_name : Symbol ) -> ( ModuleCodegen < Self ::Module > , u64 ) {
2023-10-09 19:53:34 +00:00
base ::compile_codegen_unit ( tcx , cgu_name , self . target_info . clone ( ) )
2020-05-10 14:54:30 +00:00
}
2021-09-24 15:02:02 +00:00
fn target_machine_factory ( & self , _sess : & Session , _opt_level : OptLevel , _features : & [ String ] ) -> TargetMachineFactoryFn < Self > {
2021-08-15 12:28:46 +00:00
// TODO(antoyo): set opt level.
2020-05-10 14:54:30 +00:00
Arc ::new ( | _ | {
Ok ( ( ) )
} )
}
}
pub struct ThinBuffer ;
impl ThinBufferMethods for ThinBuffer {
fn data ( & self ) -> & [ u8 ] {
unimplemented! ( ) ;
}
}
pub struct GccContext {
context : Context < 'static > ,
2023-10-09 19:53:34 +00:00
should_combine_object_files : bool ,
// Temporary directory used by LTO. We keep it here so that it's not removed before linking.
temp_dir : Option < TempDir > ,
2020-05-10 14:54:30 +00:00
}
unsafe impl Send for GccContext { }
2021-08-15 12:28:46 +00:00
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here.
2020-05-10 14:54:30 +00:00
unsafe impl Sync for GccContext { }
impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext ;
type TargetMachine = ( ) ;
2022-08-19 13:48:15 +00:00
type TargetMachineError = ( ) ;
2020-05-10 14:54:30 +00:00
type ModuleBuffer = ModuleBuffer ;
type ThinData = ( ) ;
type ThinBuffer = ThinBuffer ;
2023-10-09 19:53:34 +00:00
fn run_fat_lto ( cgcx : & CodegenContext < Self > , modules : Vec < FatLtoInput < Self > > , cached_modules : Vec < ( SerializedModule < Self ::ModuleBuffer > , WorkProduct ) > ) -> Result < LtoModuleCodegen < Self > , FatalError > {
back ::lto ::run_fat ( cgcx , modules , cached_modules )
2020-05-10 14:54:30 +00:00
}
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 > {
unimplemented! ( ) ;
}
fn print_pass_timings ( & self ) {
unimplemented! ( ) ;
}
2022-11-05 08:08:57 +00:00
fn print_statistics ( & self ) {
unimplemented! ( )
}
2020-05-10 14:54:30 +00:00
unsafe fn optimize ( _cgcx : & CodegenContext < Self > , _diag_handler : & Handler , module : & ModuleCodegen < Self ::Module > , config : & ModuleConfig ) -> Result < ( ) , FatalError > {
module . module_llvm . context . set_optimization_level ( to_gcc_opt_level ( config . opt_level ) ) ;
Ok ( ( ) )
}
2022-04-30 18:58:42 +00:00
fn optimize_fat ( _cgcx : & CodegenContext < Self > , _module : & mut ModuleCodegen < Self ::Module > ) -> Result < ( ) , FatalError > {
2022-04-30 18:50:17 +00:00
// TODO(antoyo)
Ok ( ( ) )
}
2022-04-30 18:51:17 +00:00
unsafe fn optimize_thin ( _cgcx : & CodegenContext < Self > , _thin : ThinModule < Self > ) -> Result < ModuleCodegen < Self ::Module > , FatalError > {
2020-05-10 14:54:30 +00:00
unimplemented! ( ) ;
}
unsafe fn codegen ( cgcx : & CodegenContext < Self > , diag_handler : & Handler , module : ModuleCodegen < Self ::Module > , config : & ModuleConfig ) -> Result < CompiledModule , FatalError > {
back ::write ::codegen ( cgcx , diag_handler , module , config )
}
fn prepare_thin ( _module : ModuleCodegen < Self ::Module > ) -> ( String , Self ::ThinBuffer ) {
unimplemented! ( ) ;
}
fn serialize_module ( _module : ModuleCodegen < Self ::Module > ) -> ( String , Self ::ModuleBuffer ) {
unimplemented! ( ) ;
}
fn run_link ( cgcx : & CodegenContext < Self > , diag_handler : & Handler , modules : Vec < ModuleCodegen < Self ::Module > > ) -> Result < ModuleCodegen < Self ::Module > , FatalError > {
back ::write ::link ( cgcx , diag_handler , modules )
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
#[ no_mangle ]
pub fn __rustc_codegen_backend ( ) -> Box < dyn CodegenBackend > {
2023-10-09 19:53:34 +00:00
#[ cfg(feature= " master " ) ]
let info = {
// Check whether the target supports 128-bit integers.
let context = Context ::default ( ) ;
2023-10-09 20:45:46 +00:00
Arc ::new ( Mutex ::new ( IntoDynSyncSend ( context . get_target_info ( ) ) ) )
2023-10-09 19:53:34 +00:00
} ;
#[ cfg(not(feature= " master " )) ]
2023-10-09 20:45:46 +00:00
let info = Arc ::new ( Mutex ::new ( IntoDynSyncSend ( TargetInfo {
2023-10-09 19:53:34 +00:00
supports_128bit_integers : AtomicBool ::new ( false ) ,
2023-10-09 20:45:46 +00:00
} ) ) ) ;
2023-10-09 19:53:34 +00:00
2022-03-26 17:29:37 +00:00
Box ::new ( GccCodegenBackend {
2023-10-09 19:53:34 +00:00
target_info : LockedTargetInfo { info } ,
2022-03-26 17:29:37 +00:00
} )
2020-05-10 14:54:30 +00:00
}
fn to_gcc_opt_level ( optlevel : Option < OptLevel > ) -> OptimizationLevel {
match optlevel {
None = > OptimizationLevel ::None ,
Some ( level ) = > {
match level {
OptLevel ::No = > OptimizationLevel ::None ,
OptLevel ::Less = > OptimizationLevel ::Limited ,
OptLevel ::Default = > OptimizationLevel ::Standard ,
OptLevel ::Aggressive = > OptimizationLevel ::Aggressive ,
OptLevel ::Size | OptLevel ::SizeMin = > OptimizationLevel ::Limited ,
}
} ,
}
}
2023-10-09 19:53:34 +00:00
pub fn target_features ( sess : & Session , allow_unstable : bool , target_info : & LockedTargetInfo ) -> Vec < Symbol > {
2020-05-10 14:54:30 +00:00
supported_target_features ( sess )
. iter ( )
. filter_map (
| & ( feature , gate ) | {
2023-11-12 11:41:22 +00:00
if sess . is_nightly_build ( ) | | allow_unstable | | gate . is_stable ( ) { Some ( feature ) } else { None }
2020-05-10 14:54:30 +00:00
} ,
)
. filter ( | _feature | {
2023-10-09 19:53:34 +00:00
target_info . cpu_supports ( _feature )
2022-06-07 02:04:37 +00:00
/*
2022-10-30 03:36:47 +00:00
adx , aes , avx , avx2 , avx512bf16 , avx512bitalg , avx512bw , avx512cd , avx512dq , avx512er , avx512f , avx512ifma ,
avx512pf , avx512vbmi , avx512vbmi2 , avx512vl , avx512vnni , avx512vp2intersect , avx512vpopcntdq ,
bmi1 , bmi2 , cmpxchg16b , ermsb , f16c , fma , fxsr , gfni , lzcnt , movbe , pclmulqdq , popcnt , rdrand , rdseed , rtm ,
sha , sse , sse2 , sse3 , sse4 . 1 , sse4 . 2 , sse4a , ssse3 , tbm , vaes , vpclmulqdq , xsave , xsavec , xsaveopt , xsaves
2022-06-07 02:04:37 +00:00
* /
2020-05-10 14:54:30 +00:00
} )
. map ( | feature | Symbol ::intern ( feature ) )
. collect ( )
}