@@ -51,10 +51,10 @@ pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> Fatal
51
51
}
52
52
}
53
53
54
- fn write_output_file < ' ll > (
54
+ unsafe fn write_output_file < ' ll > (
55
55
dcx : DiagCtxtHandle < ' _ > ,
56
56
target : & ' ll llvm:: TargetMachine ,
57
- pm : & llvm:: PassManager < ' ll > ,
57
+ pm : * mut llvm:: PassManager < ' ll > ,
58
58
m : & ' ll llvm:: Module ,
59
59
output : & Path ,
60
60
dwo_output : Option < & Path > ,
@@ -63,39 +63,39 @@ fn write_output_file<'ll>(
63
63
verify_llvm_ir : bool ,
64
64
) -> Result < ( ) , FatalError > {
65
65
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 (
66
+ let output_c = path_to_c_string ( output ) ;
67
+ let dwo_output_c ;
68
+ let dwo_output_ptr = if let Some ( dwo_output ) = dwo_output {
69
+ dwo_output_c = path_to_c_string ( dwo_output) ;
70
+ dwo_output_c. as_ptr ( )
71
+ } else {
72
+ std :: ptr :: null ( )
73
+ } ;
74
+ let result = unsafe {
75
+ llvm:: LLVMRustWriteOutputFile (
76
76
target,
77
77
pm,
78
78
m,
79
79
output_c. as_ptr ( ) ,
80
80
dwo_output_ptr,
81
81
file_type,
82
82
verify_llvm_ir,
83
- ) ;
83
+ )
84
+ } ;
84
85
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
- }
86
+ // Record artifact sizes for self-profiling
87
+ if result == llvm:: LLVMRustResult :: Success {
88
+ let artifact_kind = match file_type {
89
+ llvm:: FileType :: ObjectFile => "object_file" ,
90
+ llvm:: FileType :: AssemblyFile => "assembly_file" ,
91
+ } ;
92
+ record_artifact_size ( self_profiler_ref, artifact_kind, output) ;
93
+ if let Some ( dwo_file) = dwo_output {
94
+ record_artifact_size ( self_profiler_ref, "dwo_file" , dwo_file) ;
95
95
}
96
-
97
- result. into_result ( ) . map_err ( |( ) | llvm_err ( dcx, LlvmError :: WriteOutput { path : output } ) )
98
96
}
97
+
98
+ result. into_result ( ) . map_err ( |( ) | llvm_err ( dcx, LlvmError :: WriteOutput { path : output } ) )
99
99
}
100
100
101
101
pub ( crate ) fn create_informational_target_machine (
@@ -325,13 +325,17 @@ pub(crate) fn save_temp_bitcode(
325
325
if !cgcx. save_temps {
326
326
return ;
327
327
}
328
+ let ext = format ! ( "{name}.bc" ) ;
329
+ let cgu = Some ( & module. name [ ..] ) ;
330
+ let path = cgcx. output_filenames . temp_path_ext ( & ext, cgu) ;
331
+ write_bitcode_to_file ( module, & path)
332
+ }
333
+
334
+ fn write_bitcode_to_file ( module : & ModuleCodegen < ModuleLlvm > , path : & Path ) {
328
335
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) ;
336
+ let path = path_to_c_string ( & path) ;
333
337
let llmod = module. module_llvm . llmod ( ) ;
334
- llvm:: LLVMWriteBitcodeToFile ( llmod, cstr . as_ptr ( ) ) ;
338
+ llvm:: LLVMWriteBitcodeToFile ( llmod, path . as_ptr ( ) ) ;
335
339
}
336
340
}
337
341
@@ -661,7 +665,6 @@ pub(crate) unsafe fn optimize(
661
665
) -> Result < ( ) , FatalError > {
662
666
let _timer = cgcx. prof . generic_activity_with_arg ( "LLVM_module_optimize" , & * module. name ) ;
663
667
664
- let llmod = module. module_llvm . llmod ( ) ;
665
668
let llcx = & * module. module_llvm . llcx ;
666
669
let _handlers = DiagnosticHandlers :: new ( cgcx, dcx, llcx, module, CodegenDiagnosticsStage :: Opt ) ;
667
670
@@ -670,8 +673,7 @@ pub(crate) unsafe fn optimize(
670
673
671
674
if config. emit_no_opt_bc {
672
675
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 ( ) ) } ;
676
+ write_bitcode_to_file ( module, & out)
675
677
}
676
678
677
679
// FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts
@@ -748,18 +750,18 @@ pub(crate) unsafe fn codegen(
748
750
// files for an LLVM module.
749
751
//
750
752
// 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 > (
753
+ // thing, so we create a new one for each type of output.
754
+ // The pass manager must be consumed by `LLVMRustWriteOutputFile`,
755
+ // which also takes care of freeing its memory. For details of why it's
756
+ // this way, see the C++ code of `LLVMRustWriteOutputFile`
757
+ fn with_codegen < ' ll , F , R > (
756
758
tm : & ' ll llvm:: TargetMachine ,
757
759
llmod : & ' ll llvm:: Module ,
758
760
no_builtins : bool ,
759
761
f : F ,
760
762
) -> R
761
763
where
762
- F : FnOnce ( & ' ll mut PassManager < ' ll > ) -> R ,
764
+ F : FnOnce ( * mut PassManager < ' ll > ) -> R ,
763
765
{
764
766
unsafe {
765
767
let cpm = llvm:: LLVMCreatePassManager ( ) ;
@@ -890,21 +892,19 @@ pub(crate) unsafe fn codegen(
890
892
} else {
891
893
llmod
892
894
} ;
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
- }
895
+ with_codegen ( tm, llmod, config. no_builtins , |cpm| unsafe {
896
+ write_output_file (
897
+ dcx,
898
+ tm,
899
+ cpm,
900
+ llmod,
901
+ & path,
902
+ None ,
903
+ llvm:: FileType :: AssemblyFile ,
904
+ & cgcx. prof ,
905
+ config. verify_llvm_ir ,
906
+ )
907
+ } ) ?;
908
908
}
909
909
910
910
match config. emit_obj {
@@ -928,21 +928,19 @@ pub(crate) unsafe fn codegen(
928
928
( _, SplitDwarfKind :: Split ) => Some ( dwo_out. as_path ( ) ) ,
929
929
} ;
930
930
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
- }
931
+ with_codegen ( tm, llmod, config. no_builtins , |cpm| unsafe {
932
+ write_output_file (
933
+ dcx,
934
+ tm,
935
+ cpm,
936
+ llmod,
937
+ & obj_out,
938
+ dwo_out,
939
+ llvm:: FileType :: ObjectFile ,
940
+ & cgcx. prof ,
941
+ config. verify_llvm_ir ,
942
+ )
943
+ } ) ?;
946
944
}
947
945
948
946
EmitObj :: Bitcode => {
@@ -1069,24 +1067,18 @@ unsafe fn embed_bitcode(
1069
1067
{
1070
1068
// We don't need custom section flags, create LLVM globals.
1071
1069
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) ;
1070
+ let llglobal =
1071
+ llvm:: add_global ( llmod, common:: val_ty ( llconst) , c"rustc.embedded.module" ) ;
1072
+ llvm:: set_initializer ( llglobal, llconst) ;
1078
1073
1079
1074
llvm:: set_section ( llglobal, bitcode_section_name ( cgcx) ) ;
1080
1075
llvm:: set_linkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
1081
1076
llvm:: LLVMSetGlobalConstant ( llglobal, llvm:: True ) ;
1082
1077
1083
1078
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) ;
1079
+ let llglobal =
1080
+ llvm:: add_global ( llmod, common:: val_ty ( llconst) , c"rustc.embedded.cmdline" ) ;
1081
+ llvm:: set_initializer ( llglobal, llconst) ;
1090
1082
let section = if cgcx. target_is_like_osx {
1091
1083
c"__LLVM,__cmdline"
1092
1084
} else if cgcx. target_is_like_aix {
@@ -1126,31 +1118,29 @@ fn create_msvc_imps(
1126
1118
// underscores added in front).
1127
1119
let prefix = if cgcx. target_arch == "x86" { "\x01 __imp__" } else { "\x01 __imp_" } ;
1128
1120
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 < _ > > ( ) ;
1121
+ let ptr_ty = Type :: ptr_llcx ( llcx) ;
1122
+ let globals = base:: iter_globals ( llmod)
1123
+ . filter ( |& val| {
1124
+ llvm:: get_linkage ( val) == llvm:: Linkage :: ExternalLinkage && llvm:: is_declaration ( val)
1125
+ } )
1126
+ . filter_map ( |val| {
1127
+ // Exclude some symbols that we know are not Rust symbols.
1128
+ let name = llvm:: get_value_name ( val) ;
1129
+ if ignored ( name) { None } else { Some ( ( val, name) ) }
1130
+ } )
1131
+ . map ( move |( val, name) | {
1132
+ let mut imp_name = prefix. as_bytes ( ) . to_vec ( ) ;
1133
+ imp_name. extend ( name) ;
1134
+ let imp_name = CString :: new ( imp_name) . unwrap ( ) ;
1135
+ ( imp_name, val)
1136
+ } )
1137
+ . collect :: < Vec < _ > > ( ) ;
1148
1138
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
- }
1139
+ for ( imp_name, val) in globals {
1140
+ let imp = llvm:: add_global ( llmod, ptr_ty, & imp_name) ;
1141
+
1142
+ llvm:: set_initializer ( imp, val ) ;
1143
+ llvm :: set_linkage ( imp , llvm :: Linkage :: ExternalLinkage ) ;
1154
1144
}
1155
1145
1156
1146
// Use this function to exclude certain symbols from `__imp` generation.
0 commit comments