@@ -51,10 +51,11 @@ pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> Fatal
5151 }
5252}
5353
54- fn write_output_file < ' ll > (
54+ // SAFETY: the pass manager must come from the closure argument of `with_codegen`.
55+ unsafe fn write_output_file < ' ll > (
5556 dcx : DiagCtxtHandle < ' _ > ,
5657 target : & ' ll llvm:: TargetMachine ,
57- pm : & llvm:: PassManager < ' ll > ,
58+ pm : * mut llvm:: PassManager < ' ll > ,
5859 m : & ' ll llvm:: Module ,
5960 output : & Path ,
6061 dwo_output : Option < & Path > ,
@@ -63,39 +64,39 @@ fn write_output_file<'ll>(
6364 verify_llvm_ir : bool ,
6465) -> Result < ( ) , FatalError > {
6566 debug ! ( "write_output_file output={:?} dwo_output={:?}" , output, dwo_output) ;
66- unsafe {
67- let output_c = path_to_c_string ( output ) ;
68- let dwo_output_c ;
69- let dwo_output_ptr = if let Some ( dwo_output) = dwo_output {
70- dwo_output_c = path_to_c_string ( dwo_output ) ;
71- dwo_output_c . as_ptr ( )
72- } else {
73- std :: ptr :: null ( )
74- } ;
75- let result = llvm:: LLVMRustWriteOutputFile (
67+ let output_c = path_to_c_string ( output ) ;
68+ let dwo_output_c ;
69+ let dwo_output_ptr = if let Some ( dwo_output ) = dwo_output {
70+ dwo_output_c = path_to_c_string ( dwo_output) ;
71+ dwo_output_c. as_ptr ( )
72+ } else {
73+ std :: ptr :: null ( )
74+ } ;
75+ let result = unsafe {
76+ llvm:: LLVMRustWriteOutputFile (
7677 target,
7778 pm,
7879 m,
7980 output_c. as_ptr ( ) ,
8081 dwo_output_ptr,
8182 file_type,
8283 verify_llvm_ir,
83- ) ;
84+ )
85+ } ;
8486
85- // Record artifact sizes for self-profiling
86- if result == llvm:: LLVMRustResult :: Success {
87- let artifact_kind = match file_type {
88- llvm:: FileType :: ObjectFile => "object_file" ,
89- llvm:: FileType :: AssemblyFile => "assembly_file" ,
90- } ;
91- record_artifact_size ( self_profiler_ref, artifact_kind, output) ;
92- if let Some ( dwo_file) = dwo_output {
93- record_artifact_size ( self_profiler_ref, "dwo_file" , dwo_file) ;
94- }
87+ // Record artifact sizes for self-profiling
88+ if result == llvm:: LLVMRustResult :: Success {
89+ let artifact_kind = match file_type {
90+ llvm:: FileType :: ObjectFile => "object_file" ,
91+ llvm:: FileType :: AssemblyFile => "assembly_file" ,
92+ } ;
93+ record_artifact_size ( self_profiler_ref, artifact_kind, output) ;
94+ if let Some ( dwo_file) = dwo_output {
95+ record_artifact_size ( self_profiler_ref, "dwo_file" , dwo_file) ;
9596 }
96-
97- result. into_result ( ) . map_err ( |( ) | llvm_err ( dcx, LlvmError :: WriteOutput { path : output } ) )
9897 }
98+
99+ result. into_result ( ) . map_err ( |( ) | llvm_err ( dcx, LlvmError :: WriteOutput { path : output } ) )
99100}
100101
101102pub ( crate ) fn create_informational_target_machine (
@@ -325,13 +326,17 @@ pub(crate) fn save_temp_bitcode(
325326 if !cgcx. save_temps {
326327 return ;
327328 }
329+ let ext = format ! ( "{name}.bc" ) ;
330+ let cgu = Some ( & module. name [ ..] ) ;
331+ let path = cgcx. output_filenames . temp_path_ext ( & ext, cgu) ;
332+ write_bitcode_to_file ( module, & path)
333+ }
334+
335+ fn write_bitcode_to_file ( module : & ModuleCodegen < ModuleLlvm > , path : & Path ) {
328336 unsafe {
329- let ext = format ! ( "{name}.bc" ) ;
330- let cgu = Some ( & module. name [ ..] ) ;
331- let path = cgcx. output_filenames . temp_path_ext ( & ext, cgu) ;
332- let cstr = path_to_c_string ( & path) ;
337+ let path = path_to_c_string ( & path) ;
333338 let llmod = module. module_llvm . llmod ( ) ;
334- llvm:: LLVMWriteBitcodeToFile ( llmod, cstr . as_ptr ( ) ) ;
339+ llvm:: LLVMWriteBitcodeToFile ( llmod, path . as_ptr ( ) ) ;
335340 }
336341}
337342
@@ -661,7 +666,6 @@ pub(crate) unsafe fn optimize(
661666) -> Result < ( ) , FatalError > {
662667 let _timer = cgcx. prof . generic_activity_with_arg ( "LLVM_module_optimize" , & * module. name ) ;
663668
664- let llmod = module. module_llvm . llmod ( ) ;
665669 let llcx = & * module. module_llvm . llcx ;
666670 let _handlers = DiagnosticHandlers :: new ( cgcx, dcx, llcx, module, CodegenDiagnosticsStage :: Opt ) ;
667671
@@ -670,8 +674,7 @@ pub(crate) unsafe fn optimize(
670674
671675 if config. emit_no_opt_bc {
672676 let out = cgcx. output_filenames . temp_path_ext ( "no-opt.bc" , module_name) ;
673- let out = path_to_c_string ( & out) ;
674- unsafe { llvm:: LLVMWriteBitcodeToFile ( llmod, out. as_ptr ( ) ) } ;
677+ write_bitcode_to_file ( module, & out)
675678 }
676679
677680 // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts
@@ -748,18 +751,18 @@ pub(crate) unsafe fn codegen(
748751 // files for an LLVM module.
749752 //
750753 // Apparently each of these pass managers is a one-shot kind of
751- // thing, so we create a new one for each type of output. The
752- // pass manager passed to the closure should be ensured to not
753- // escape the closure itself, and the manager should only be
754- // used once.
755- unsafe fn with_codegen < ' ll , F , R > (
754+ // thing, so we create a new one for each type of output.
755+ // The pass manager must be consumed by `LLVMRustWriteOutputFile`,
756+ // which also takes care of freeing its memory. For details of why it's
757+ // this way, see the C++ code of `LLVMRustWriteOutputFile`
758+ fn with_codegen < ' ll , F , R > (
756759 tm : & ' ll llvm:: TargetMachine ,
757760 llmod : & ' ll llvm:: Module ,
758761 no_builtins : bool ,
759762 f : F ,
760763 ) -> R
761764 where
762- F : FnOnce ( & ' ll mut PassManager < ' ll > ) -> R ,
765+ F : FnOnce ( * mut PassManager < ' ll > ) -> R ,
763766 {
764767 unsafe {
765768 let cpm = llvm:: LLVMCreatePassManager ( ) ;
@@ -890,21 +893,19 @@ pub(crate) unsafe fn codegen(
890893 } else {
891894 llmod
892895 } ;
893- unsafe {
894- with_codegen ( tm, llmod, config. no_builtins , |cpm| {
895- write_output_file (
896- dcx,
897- tm,
898- cpm,
899- llmod,
900- & path,
901- None ,
902- llvm:: FileType :: AssemblyFile ,
903- & cgcx. prof ,
904- config. verify_llvm_ir ,
905- )
906- } ) ?;
907- }
896+ with_codegen ( tm, llmod, config. no_builtins , |cpm| unsafe {
897+ write_output_file (
898+ dcx,
899+ tm,
900+ cpm,
901+ llmod,
902+ & path,
903+ None ,
904+ llvm:: FileType :: AssemblyFile ,
905+ & cgcx. prof ,
906+ config. verify_llvm_ir ,
907+ )
908+ } ) ?;
908909 }
909910
910911 match config. emit_obj {
@@ -928,21 +929,19 @@ pub(crate) unsafe fn codegen(
928929 ( _, SplitDwarfKind :: Split ) => Some ( dwo_out. as_path ( ) ) ,
929930 } ;
930931
931- unsafe {
932- with_codegen ( tm, llmod, config. no_builtins , |cpm| {
933- write_output_file (
934- dcx,
935- tm,
936- cpm,
937- llmod,
938- & obj_out,
939- dwo_out,
940- llvm:: FileType :: ObjectFile ,
941- & cgcx. prof ,
942- config. verify_llvm_ir ,
943- )
944- } ) ?;
945- }
932+ with_codegen ( tm, llmod, config. no_builtins , |cpm| unsafe {
933+ write_output_file (
934+ dcx,
935+ tm,
936+ cpm,
937+ llmod,
938+ & obj_out,
939+ dwo_out,
940+ llvm:: FileType :: ObjectFile ,
941+ & cgcx. prof ,
942+ config. verify_llvm_ir ,
943+ )
944+ } ) ?;
946945 }
947946
948947 EmitObj :: Bitcode => {
@@ -1069,24 +1068,18 @@ unsafe fn embed_bitcode(
10691068 {
10701069 // We don't need custom section flags, create LLVM globals.
10711070 let llconst = common:: bytes_in_context ( llcx, bitcode) ;
1072- let llglobal = llvm:: LLVMAddGlobal (
1073- llmod,
1074- common:: val_ty ( llconst) ,
1075- c"rustc.embedded.module" . as_ptr ( ) ,
1076- ) ;
1077- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1071+ let llglobal =
1072+ llvm:: add_global ( llmod, common:: val_ty ( llconst) , c"rustc.embedded.module" ) ;
1073+ llvm:: set_initializer ( llglobal, llconst) ;
10781074
10791075 llvm:: set_section ( llglobal, bitcode_section_name ( cgcx) ) ;
10801076 llvm:: set_linkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
10811077 llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
10821078
10831079 let llconst = common:: bytes_in_context ( llcx, cmdline. as_bytes ( ) ) ;
1084- let llglobal = llvm:: LLVMAddGlobal (
1085- llmod,
1086- common:: val_ty ( llconst) ,
1087- c"rustc.embedded.cmdline" . as_ptr ( ) ,
1088- ) ;
1089- llvm:: LLVMSetInitializer ( llglobal, llconst) ;
1080+ let llglobal =
1081+ llvm:: add_global ( llmod, common:: val_ty ( llconst) , c"rustc.embedded.cmdline" ) ;
1082+ llvm:: set_initializer ( llglobal, llconst) ;
10901083 let section = if cgcx. target_is_like_osx {
10911084 c"__LLVM,__cmdline"
10921085 } else if cgcx. target_is_like_aix {
@@ -1126,31 +1119,29 @@ fn create_msvc_imps(
11261119 // underscores added in front).
11271120 let prefix = if cgcx. target_arch == "x86" { "\x01 __imp__" } else { "\x01 __imp_" } ;
11281121
1129- unsafe {
1130- let ptr_ty = Type :: ptr_llcx ( llcx) ;
1131- let globals = base:: iter_globals ( llmod)
1132- . filter ( |& val| {
1133- llvm:: get_linkage ( val) == llvm:: Linkage :: ExternalLinkage
1134- && llvm:: LLVMIsDeclaration ( val) == 0
1135- } )
1136- . filter_map ( |val| {
1137- // Exclude some symbols that we know are not Rust symbols.
1138- let name = llvm:: get_value_name ( val) ;
1139- if ignored ( name) { None } else { Some ( ( val, name) ) }
1140- } )
1141- . map ( move |( val, name) | {
1142- let mut imp_name = prefix. as_bytes ( ) . to_vec ( ) ;
1143- imp_name. extend ( name) ;
1144- let imp_name = CString :: new ( imp_name) . unwrap ( ) ;
1145- ( imp_name, val)
1146- } )
1147- . collect :: < Vec < _ > > ( ) ;
1122+ let ptr_ty = Type :: ptr_llcx ( llcx) ;
1123+ let globals = base:: iter_globals ( llmod)
1124+ . filter ( |& val| {
1125+ llvm:: get_linkage ( val) == llvm:: Linkage :: ExternalLinkage && llvm:: is_declaration ( val)
1126+ } )
1127+ . filter_map ( |val| {
1128+ // Exclude some symbols that we know are not Rust symbols.
1129+ let name = llvm:: get_value_name ( val) ;
1130+ if ignored ( name) { None } else { Some ( ( val, name) ) }
1131+ } )
1132+ . map ( move |( val, name) | {
1133+ let mut imp_name = prefix. as_bytes ( ) . to_vec ( ) ;
1134+ imp_name. extend ( name) ;
1135+ let imp_name = CString :: new ( imp_name) . unwrap ( ) ;
1136+ ( imp_name, val)
1137+ } )
1138+ . collect :: < Vec < _ > > ( ) ;
11481139
1149- for ( imp_name, val) in globals {
1150- let imp = llvm:: LLVMAddGlobal ( llmod, ptr_ty, imp_name. as_ptr ( ) ) ;
1151- llvm :: LLVMSetInitializer ( imp , val ) ;
1152- llvm:: set_linkage ( imp, llvm :: Linkage :: ExternalLinkage ) ;
1153- }
1140+ for ( imp_name, val) in globals {
1141+ let imp = llvm:: add_global ( llmod, ptr_ty, & imp_name) ;
1142+
1143+ llvm:: set_initializer ( imp, val ) ;
1144+ llvm :: set_linkage ( imp , llvm :: Linkage :: ExternalLinkage ) ;
11541145 }
11551146
11561147 // Use this function to exclude certain symbols from `__imp` generation.
0 commit comments