@@ -22,6 +22,7 @@ use rustc_hir::attrs::Linkage;
2222use rustc_middle:: dep_graph;
2323use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrs , SanitizerFnAttrs } ;
2424use rustc_middle:: mono:: Visibility ;
25+ use rustc_middle:: query:: { QueryHashHelper , QueryHelper } ;
2526use rustc_middle:: ty:: TyCtxt ;
2627use rustc_session:: config:: { DebugInfo , Offload } ;
2728use rustc_span:: Symbol ;
@@ -62,122 +63,150 @@ pub(crate) fn compile_codegen_unit(
6263 let start_time = Instant :: now ( ) ;
6364
6465 let dep_node = tcx. codegen_unit ( cgu_name) . codegen_dep_node ( tcx) ;
65- let ( module, _) = tcx. dep_graph . with_task (
66- dep_node,
67- tcx,
68- cgu_name,
69- module_codegen,
70- Some ( dep_graph:: hash_result) ,
71- ) ;
72- let time_to_codegen = start_time. elapsed ( ) ;
7366
74- // We assume that the cost to run LLVM on a CGU is proportional to
75- // the time we needed for codegenning it.
76- let cost = time_to_codegen. as_nanos ( ) as u64 ;
67+ #[ derive( Default ) ]
68+ struct CompileCguHashHelper ;
7769
78- fn module_codegen ( tcx : TyCtxt < ' _ > , cgu_name : Symbol ) -> ModuleCodegen < ModuleLlvm > {
79- let cgu = tcx. codegen_unit ( cgu_name) ;
80- let _prof_timer =
81- tcx. prof . generic_activity_with_arg_recorder ( "codegen_module" , |recorder| {
82- recorder. record_arg ( cgu_name. to_string ( ) ) ;
83- recorder. record_arg ( cgu. size_estimate ( ) . to_string ( ) ) ;
84- } ) ;
85- // Instantiate monomorphizations without filling out definitions yet...
86- let llvm_module = ModuleLlvm :: new ( tcx, cgu_name. as_str ( ) ) ;
87- {
88- let mut cx = CodegenCx :: new ( tcx, cgu, & llvm_module) ;
89-
90- // Declare and store globals shared by all offload kernels
91- //
92- // These globals are left in the LLVM-IR host module so all kernels can access them.
93- // They are necessary for correct offload execution. We do this here to simplify the
94- // `offload` intrinsic, avoiding the need for tracking whether it's the first
95- // intrinsic call or not.
96- let has_host_offload = cx
97- . sess ( )
98- . opts
99- . unstable_opts
100- . offload
101- . iter ( )
102- . any ( |o| matches ! ( o, Offload :: Host ( _) | Offload :: Test ) ) ;
103- if has_host_offload && !cx. sess ( ) . target . is_like_gpu {
104- cx. offload_globals . replace ( Some ( OffloadGlobals :: declare ( & cx) ) ) ;
105- }
70+ impl QueryHashHelper < ModuleCodegen < ModuleLlvm > > for CompileCguHashHelper {
71+ const NO_HASH : bool = false ;
10672
107- let mono_items = cx. codegen_unit . items_in_deterministic_order ( cx. tcx ) ;
108- for & ( mono_item, data) in & mono_items {
109- mono_item. predefine :: < Builder < ' _ , ' _ , ' _ > > (
110- & mut cx,
111- cgu_name. as_str ( ) ,
112- data. linkage ,
113- data. visibility ,
114- ) ;
115- }
73+ fn hash_value_fn (
74+ hcx : & mut rustc_middle:: ich:: StableHashingContext < ' _ > ,
75+ result : & ModuleCodegen < ModuleLlvm > ,
76+ ) -> rustc_data_structures:: fingerprint:: Fingerprint {
77+ dep_graph:: hash_result ( hcx, result)
78+ }
11679
117- // ... and now that we have everything pre-defined, fill out those definitions.
118- for & ( mono_item , item_data ) in & mono_items {
119- mono_item . define :: < Builder < ' _ , ' _ , ' _ > > ( & mut cx , cgu_name . as_str ( ) , item_data ) ;
120- }
80+ fn format_value ( _ : & ModuleCodegen < ModuleLlvm > ) -> String {
81+ unimplemented ! ( )
82+ }
83+ }
12184
122- // If this codegen unit contains the main function, also create the
123- // wrapper here
124- if let Some ( entry) =
125- maybe_create_entry_wrapper :: < Builder < ' _ , ' _ , ' _ > > ( & cx, cx. codegen_unit )
85+ impl < ' tcx > QueryHelper < ' tcx , Symbol , ModuleCodegen < ModuleLlvm > > for CompileCguHashHelper {
86+ fn try_load_from_disk_fn (
87+ _: TyCtxt < ' tcx > ,
88+ _: dep_graph:: SerializedDepNodeIndex ,
89+ ) -> Option < ModuleCodegen < ModuleLlvm > > {
90+ unimplemented ! ( )
91+ }
92+
93+ fn will_cache_on_disk_for_key ( _: Symbol ) -> bool {
94+ unimplemented ! ( )
95+ }
96+
97+ fn invoke_provider_fn ( tcx : TyCtxt < ' tcx > , cgu_name : Symbol ) -> ModuleCodegen < ModuleLlvm > {
98+ // Module codegen
99+ let cgu = tcx. codegen_unit ( cgu_name) ;
100+ let _prof_timer =
101+ tcx. prof . generic_activity_with_arg_recorder ( "codegen_module" , |recorder| {
102+ recorder. record_arg ( cgu_name. to_string ( ) ) ;
103+ recorder. record_arg ( cgu. size_estimate ( ) . to_string ( ) ) ;
104+ } ) ;
105+ // Instantiate monomorphizations without filling out definitions yet...
106+ let llvm_module = ModuleLlvm :: new ( tcx, cgu_name. as_str ( ) ) ;
126107 {
127- let attrs = attributes:: sanitize_attrs ( & cx, tcx, SanitizerFnAttrs :: default ( ) ) ;
128- attributes:: apply_to_llfn ( entry, llvm:: AttributePlace :: Function , & attrs) ;
129- }
108+ let mut cx = CodegenCx :: new ( tcx, cgu, & llvm_module) ;
109+
110+ // Declare and store globals shared by all offload kernels
111+ //
112+ // These globals are left in the LLVM-IR host module so all kernels can access them.
113+ // They are necessary for correct offload execution. We do this here to simplify the
114+ // `offload` intrinsic, avoiding the need for tracking whether it's the first
115+ // intrinsic call or not.
116+ let has_host_offload = cx
117+ . sess ( )
118+ . opts
119+ . unstable_opts
120+ . offload
121+ . iter ( )
122+ . any ( |o| matches ! ( o, Offload :: Host ( _) | Offload :: Test ) ) ;
123+ if has_host_offload && !cx. sess ( ) . target . is_like_gpu {
124+ cx. offload_globals . replace ( Some ( OffloadGlobals :: declare ( & cx) ) ) ;
125+ }
130126
131- // Define Objective-C module info and module flags. Note, the module info will
132- // also be added to the `llvm.compiler.used` variable, created later.
133- //
134- // These are only necessary when we need the linker to do its Objective-C-specific
135- // magic. We could theoretically do it unconditionally, but at a slight cost to linker
136- // performance in the common case where it's unnecessary.
137- if !cx. objc_classrefs . borrow ( ) . is_empty ( ) || !cx. objc_selrefs . borrow ( ) . is_empty ( ) {
138- if cx. objc_abi_version ( ) == 1 {
139- cx. define_objc_module_info ( ) ;
127+ let mono_items = cx. codegen_unit . items_in_deterministic_order ( cx. tcx ) ;
128+ for & ( mono_item, data) in & mono_items {
129+ mono_item. predefine :: < Builder < ' _ , ' _ , ' _ > > (
130+ & mut cx,
131+ cgu_name. as_str ( ) ,
132+ data. linkage ,
133+ data. visibility ,
134+ ) ;
140135 }
141- cx. add_objc_module_flags ( ) ;
142- }
143136
144- // Finalize code coverage by injecting the coverage map. Note, the coverage map will
145- // also be added to the `llvm.compiler.used` variable, created next.
146- if cx. sess ( ) . instrument_coverage ( ) {
147- cx. coverageinfo_finalize ( ) ;
148- }
137+ // ... and now that we have everything pre-defined, fill out those definitions.
138+ for & ( mono_item, item_data) in & mono_items {
139+ mono_item. define :: < Builder < ' _ , ' _ , ' _ > > ( & mut cx, cgu_name. as_str ( ) , item_data) ;
140+ }
149141
150- // Create the llvm.used variable.
151- if !cx. used_statics . is_empty ( ) {
152- cx. create_used_variable_impl ( c"llvm.used" , & cx. used_statics ) ;
153- }
142+ // If this codegen unit contains the main function, also create the
143+ // wrapper here
144+ if let Some ( entry) =
145+ maybe_create_entry_wrapper :: < Builder < ' _ , ' _ , ' _ > > ( & cx, cx. codegen_unit )
146+ {
147+ let attrs = attributes:: sanitize_attrs ( & cx, tcx, SanitizerFnAttrs :: default ( ) ) ;
148+ attributes:: apply_to_llfn ( entry, llvm:: AttributePlace :: Function , & attrs) ;
149+ }
154150
155- // Create the llvm.compiler.used variable.
156- {
157- let compiler_used_statics = cx. compiler_used_statics . borrow ( ) ;
158- if !compiler_used_statics. is_empty ( ) {
159- cx. create_used_variable_impl ( c"llvm.compiler.used" , & compiler_used_statics) ;
151+ // Define Objective-C module info and module flags. Note, the module info will
152+ // also be added to the `llvm.compiler.used` variable, created later.
153+ //
154+ // These are only necessary when we need the linker to do its Objective-C-specific
155+ // magic. We could theoretically do it unconditionally, but at a slight cost to linker
156+ // performance in the common case where it's unnecessary.
157+ if !cx. objc_classrefs . borrow ( ) . is_empty ( ) || !cx. objc_selrefs . borrow ( ) . is_empty ( ) {
158+ if cx. objc_abi_version ( ) == 1 {
159+ cx. define_objc_module_info ( ) ;
160+ }
161+ cx. add_objc_module_flags ( ) ;
160162 }
161- }
162163
163- // Run replace-all-uses-with for statics that need it. This must
164- // happen after the llvm.used variables are created.
165- for & ( old_g, new_g) in cx. statics_to_rauw ( ) . borrow ( ) . iter ( ) {
166- unsafe {
167- llvm:: LLVMReplaceAllUsesWith ( old_g, new_g) ;
168- llvm:: LLVMDeleteGlobal ( old_g) ;
164+ // Finalize code coverage by injecting the coverage map. Note, the coverage map will
165+ // also be added to the `llvm.compiler.used` variable, created next.
166+ if cx. sess ( ) . instrument_coverage ( ) {
167+ cx. coverageinfo_finalize ( ) ;
168+ }
169+
170+ // Create the llvm.used variable.
171+ if !cx. used_statics . is_empty ( ) {
172+ cx. create_used_variable_impl ( c"llvm.used" , & cx. used_statics ) ;
173+ }
174+
175+ // Create the llvm.compiler.used variable.
176+ {
177+ let compiler_used_statics = cx. compiler_used_statics . borrow ( ) ;
178+ if !compiler_used_statics. is_empty ( ) {
179+ cx. create_used_variable_impl ( c"llvm.compiler.used" , & compiler_used_statics) ;
180+ }
181+ }
182+
183+ // Run replace-all-uses-with for statics that need it. This must
184+ // happen after the llvm.used variables are created.
185+ for & ( old_g, new_g) in cx. statics_to_rauw ( ) . borrow ( ) . iter ( ) {
186+ unsafe {
187+ llvm:: LLVMReplaceAllUsesWith ( old_g, new_g) ;
188+ llvm:: LLVMDeleteGlobal ( old_g) ;
189+ }
169190 }
170- }
171191
172- // Finalize debuginfo
173- if cx. sess ( ) . opts . debuginfo != DebugInfo :: None {
174- cx. debuginfo_finalize ( ) ;
192+ // Finalize debuginfo
193+ if cx. sess ( ) . opts . debuginfo != DebugInfo :: None {
194+ cx. debuginfo_finalize ( ) ;
195+ }
175196 }
176- }
177197
178- ModuleCodegen :: new_regular ( cgu_name. to_string ( ) , llvm_module)
198+ ModuleCodegen :: new_regular ( cgu_name. to_string ( ) , llvm_module)
199+ }
179200 }
180201
202+ let ( module, _) =
203+ tcx. dep_graph . with_task :: < _ , _ , CompileCguHashHelper > ( dep_node, tcx, cgu_name) ;
204+ let time_to_codegen = start_time. elapsed ( ) ;
205+
206+ // We assume that the cost to run LLVM on a CGU is proportional to
207+ // the time we needed for codegenning it.
208+ let cost = time_to_codegen. as_nanos ( ) as u64 ;
209+
181210 ( module, cost)
182211}
183212
0 commit comments