11use crate :: common;
2- use crate :: mir :: FunctionCx ;
3- use crate :: traits :: { AsmMethods , BuilderMethods , GlobalAsmOperandRef } ;
2+ use crate :: traits :: { AsmMethods , BuilderMethods , GlobalAsmOperandRef , MiscMethods } ;
3+ use rustc_attr :: InstructionSetAttr ;
44use rustc_middle:: bug;
5+ use rustc_middle:: mir:: mono:: { MonoItem , MonoItemData , Visibility } ;
6+ use rustc_middle:: mir:: Body ;
57use rustc_middle:: mir:: InlineAsmOperand ;
68use rustc_middle:: ty;
79use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
810use rustc_middle:: ty:: { Instance , TyCtxt } ;
9-
10- use rustc_span:: sym;
1111use rustc_target:: asm:: InlineAsmArch ;
1212
13- impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
14- pub fn codegen_naked_asm ( & self , instance : Instance < ' tcx > ) {
15- let cx = & self . cx ;
16-
17- let rustc_middle:: mir:: TerminatorKind :: InlineAsm {
18- template,
19- ref operands,
20- options,
21- line_spans,
22- targets : _,
23- unwind : _,
24- } = self . mir . basic_blocks . iter ( ) . next ( ) . unwrap ( ) . terminator ( ) . kind
25- else {
26- bug ! ( "#[naked] functions should always terminate with an asm! block" )
27- } ;
28-
29- let operands: Vec < _ > =
30- operands. iter ( ) . map ( |op| self . inline_to_global_operand ( op) ) . collect ( ) ;
31-
32- let ( begin, end) = crate :: mir:: naked_asm:: prefix_and_suffix ( cx. tcx ( ) , instance) ;
33-
34- let mut template_vec = Vec :: new ( ) ;
35- template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin) ) ;
36- template_vec. extend ( template. iter ( ) . cloned ( ) ) ;
37- template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( end) ) ;
38-
39- cx. codegen_global_asm ( & template_vec, & operands, options, line_spans) ;
40- }
13+ pub fn codegen_naked_asm < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
14+ cx : & ' a Bx :: CodegenCx ,
15+ mir : & Body < ' tcx > ,
16+ instance : Instance < ' tcx > ,
17+ ) {
18+ let rustc_middle:: mir:: TerminatorKind :: InlineAsm {
19+ template,
20+ ref operands,
21+ options,
22+ line_spans,
23+ targets : _,
24+ unwind : _,
25+ } = mir. basic_blocks . iter ( ) . next ( ) . unwrap ( ) . terminator ( ) . kind
26+ else {
27+ bug ! ( "#[naked] functions should always terminate with an asm! block" )
28+ } ;
4129
42- fn inline_to_global_operand ( & self , op : & InlineAsmOperand < ' tcx > ) -> GlobalAsmOperandRef < ' tcx > {
43- match op {
44- InlineAsmOperand :: Const { value } => {
45- let const_value = self . eval_mir_constant ( value) ;
46- let string = common:: asm_const_to_str (
47- self . cx . tcx ( ) ,
48- value. span ,
49- const_value,
50- self . cx . layout_of ( value. ty ( ) ) ,
51- ) ;
52- GlobalAsmOperandRef :: Const { string }
53- }
54- InlineAsmOperand :: SymFn { value } => {
55- let instance = match value. ty ( ) . kind ( ) {
56- & ty:: FnDef ( def_id, args) => Instance :: new ( def_id, args) ,
57- _ => bug ! ( "asm sym is not a function" ) ,
58- } ;
30+ let operands: Vec < _ > =
31+ operands. iter ( ) . map ( |op| inline_to_global_operand :: < Bx > ( cx, instance, op) ) . collect ( ) ;
5932
60- GlobalAsmOperandRef :: SymFn { instance }
61- }
62- InlineAsmOperand :: SymStatic { def_id } => {
63- GlobalAsmOperandRef :: SymStatic { def_id : * def_id }
64- }
65- InlineAsmOperand :: In { .. }
66- | InlineAsmOperand :: Out { .. }
67- | InlineAsmOperand :: InOut { .. }
68- | InlineAsmOperand :: Label { .. } => {
69- bug ! ( "invalid operand type for naked_asm!" )
70- }
33+ let item_data = cx. codegen_unit ( ) . items ( ) . get ( & MonoItem :: Fn ( instance) ) . unwrap ( ) ;
34+ let ( begin, end) = crate :: mir:: naked_asm:: prefix_and_suffix ( cx. tcx ( ) , instance, item_data) ;
35+
36+ let mut template_vec = Vec :: new ( ) ;
37+ template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin. into ( ) ) ) ;
38+ template_vec. extend ( template. iter ( ) . cloned ( ) ) ;
39+ template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( end. into ( ) ) ) ;
40+
41+ cx. codegen_global_asm ( & template_vec, & operands, options, line_spans) ;
42+ }
43+
44+ fn inline_to_global_operand < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
45+ cx : & ' a Bx :: CodegenCx ,
46+ instance : Instance < ' tcx > ,
47+ op : & InlineAsmOperand < ' tcx > ,
48+ ) -> GlobalAsmOperandRef < ' tcx > {
49+ match op {
50+ InlineAsmOperand :: Const { value } => {
51+ let const_value = instance
52+ . instantiate_mir_and_normalize_erasing_regions (
53+ cx. tcx ( ) ,
54+ ty:: ParamEnv :: reveal_all ( ) ,
55+ ty:: EarlyBinder :: bind ( value. const_ ) ,
56+ )
57+ . eval ( cx. tcx ( ) , ty:: ParamEnv :: reveal_all ( ) , value. span )
58+ . expect ( "erroneous constant missed by mono item collection" ) ;
59+
60+ let mono_type = instance. instantiate_mir_and_normalize_erasing_regions (
61+ cx. tcx ( ) ,
62+ ty:: ParamEnv :: reveal_all ( ) ,
63+ ty:: EarlyBinder :: bind ( value. ty ( ) ) ,
64+ ) ;
65+
66+ let string = common:: asm_const_to_str (
67+ cx. tcx ( ) ,
68+ value. span ,
69+ const_value,
70+ cx. layout_of ( mono_type) ,
71+ ) ;
72+
73+ GlobalAsmOperandRef :: Const { string }
74+ }
75+ InlineAsmOperand :: SymFn { value } => {
76+ let mono_type = instance. instantiate_mir_and_normalize_erasing_regions (
77+ cx. tcx ( ) ,
78+ ty:: ParamEnv :: reveal_all ( ) ,
79+ ty:: EarlyBinder :: bind ( value. ty ( ) ) ,
80+ ) ;
81+
82+ let instance = match mono_type. kind ( ) {
83+ & ty:: FnDef ( def_id, args) => Instance :: new ( def_id, args) ,
84+ _ => bug ! ( "asm sym is not a function" ) ,
85+ } ;
86+
87+ GlobalAsmOperandRef :: SymFn { instance }
88+ }
89+ InlineAsmOperand :: SymStatic { def_id } => {
90+ GlobalAsmOperandRef :: SymStatic { def_id : * def_id }
91+ }
92+ InlineAsmOperand :: In { .. }
93+ | InlineAsmOperand :: Out { .. }
94+ | InlineAsmOperand :: InOut { .. }
95+ | InlineAsmOperand :: Label { .. } => {
96+ bug ! ( "invalid operand type for naked_asm!" )
7197 }
7298 }
7399}
@@ -90,7 +116,11 @@ impl AsmBinaryFormat {
90116 }
91117}
92118
93- fn prefix_and_suffix < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> ( String , String ) {
119+ fn prefix_and_suffix < ' tcx > (
120+ tcx : TyCtxt < ' tcx > ,
121+ instance : Instance < ' tcx > ,
122+ item_data : & MonoItemData ,
123+ ) -> ( String , String ) {
94124 use std:: fmt:: Write ;
95125
96126 let target = & tcx. sess . target ;
@@ -104,24 +134,18 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
104134
105135 let asm_name = format ! ( "{}{}" , if mangle { "_" } else { "" } , tcx. symbol_name( instance) . name) ;
106136
107- let opt_section = tcx
108- . get_attr ( instance. def . def_id ( ) , sym:: link_section)
109- . and_then ( |attr| attr. value_str ( ) )
110- . map ( |attr| attr. as_str ( ) . to_string ( ) ) ;
111-
112- let instruction_set =
113- tcx. get_attr ( instance. def . def_id ( ) , sym:: instruction_set) . and_then ( |attr| attr. value_str ( ) ) ;
137+ let attrs = tcx. codegen_fn_attrs ( instance. def_id ( ) ) ;
138+ let link_section = attrs. link_section . map ( |symbol| symbol. as_str ( ) . to_string ( ) ) ;
114139
115140 let ( arch_prefix, arch_suffix) = if is_arm {
116141 (
117- match instruction_set {
142+ match attrs . instruction_set {
118143 None => match is_thumb {
119144 true => ".thumb\n .thumb_func" ,
120145 false => ".arm" ,
121146 } ,
122- Some ( sym:: a32) => ".arm" ,
123- Some ( sym:: t32) => ".thumb\n .thumb_func" ,
124- Some ( other) => bug ! ( "invalid instruction set: {other}" ) ,
147+ Some ( InstructionSetAttr :: ArmA32 ) => ".arm" ,
148+ Some ( InstructionSetAttr :: ArmT32 ) => ".thumb\n .thumb_func" ,
125149 } ,
126150 match is_thumb {
127151 true => ".thumb" ,
@@ -136,7 +160,7 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
136160 let mut end = String :: new ( ) ;
137161 match AsmBinaryFormat :: from_target ( & tcx. sess . target ) {
138162 AsmBinaryFormat :: Elf => {
139- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
163+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
140164
141165 let progbits = match is_arm {
142166 true => "%progbits" ,
@@ -151,11 +175,10 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
151175 writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
152176 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
153177 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
154- writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
155- writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
156- if let Some ( instruction_set) = instruction_set {
157- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
178+ if let Visibility :: Hidden = item_data. visibility {
179+ writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
158180 }
181+ writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
159182 if !arch_prefix. is_empty ( ) {
160183 writeln ! ( begin, "{}" , arch_prefix) . unwrap ( ) ;
161184 }
@@ -169,13 +192,12 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
169192 }
170193 }
171194 AsmBinaryFormat :: Macho => {
172- let section = opt_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
195+ let section = link_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
173196 writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
174197 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
175198 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
176- writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
177- if let Some ( instruction_set) = instruction_set {
178- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
199+ if let Visibility :: Hidden = item_data. visibility {
200+ writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
179201 }
180202 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
181203
@@ -186,17 +208,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
186208 }
187209 }
188210 AsmBinaryFormat :: Coff => {
189- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
211+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
190212 writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
191213 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
192214 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
193215 writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
194216 writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
195217 writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
196218 writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
197- if let Some ( instruction_set) = instruction_set {
198- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
199- }
200219 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
201220
202221 writeln ! ( end) . unwrap ( ) ;
0 commit comments