1- use crate :: common;
2- use crate :: mir:: FunctionCx ;
3- use crate :: traits:: { AsmMethods , BuilderMethods , GlobalAsmOperandRef } ;
4- use rustc_middle:: bug;
5- use rustc_middle:: mir:: InlineAsmOperand ;
6- use rustc_middle:: ty;
7- use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
1+ use rustc_attr:: InstructionSetAttr ;
2+ use rustc_middle:: mir:: mono:: { MonoItem , MonoItemData , Visibility } ;
3+ use rustc_middle:: mir:: { Body , InlineAsmOperand } ;
4+ use rustc_middle:: ty:: layout:: { HasTyCtxt , HasTypingEnv , LayoutOf } ;
85use rustc_middle:: ty:: { Instance , TyCtxt } ;
9-
10- use rustc_span:: sym;
6+ use rustc_middle:: { bug, ty} ;
117use rustc_target:: asm:: InlineAsmArch ;
128
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- asm_macro : _,
19- template,
20- ref operands,
21- options,
22- line_spans,
23- targets : _,
24- unwind : _,
25- } = self . mir . basic_blocks . iter ( ) . next ( ) . unwrap ( ) . terminator ( ) . kind
26- else {
27- bug ! ( "#[naked] functions should always terminate with an asm! block" )
28- } ;
29-
30- let operands: Vec < _ > =
31- operands. iter ( ) . map ( |op| self . inline_to_global_operand ( op) ) . collect ( ) ;
32-
33- let ( begin, end) = crate :: mir:: naked_asm:: prefix_and_suffix ( cx. tcx ( ) , instance) ;
34-
35- let mut template_vec = Vec :: new ( ) ;
36- template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin) ) ;
37- template_vec. extend ( template. iter ( ) . cloned ( ) ) ;
38- template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( end) ) ;
39-
40- cx. codegen_global_asm ( & template_vec, & operands, options, line_spans) ;
41- }
9+ use crate :: common;
10+ use crate :: traits:: { AsmCodegenMethods , BuilderMethods , GlobalAsmOperandRef , MiscCodegenMethods } ;
11+
12+ pub ( crate ) fn codegen_naked_asm < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
13+ cx : & ' a Bx :: CodegenCx ,
14+ mir : & Body < ' tcx > ,
15+ instance : Instance < ' tcx > ,
16+ ) {
17+ let rustc_middle:: mir:: TerminatorKind :: InlineAsm {
18+ asm_macro : _,
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+ } ;
4229
43- fn inline_to_global_operand ( & self , op : & InlineAsmOperand < ' tcx > ) -> GlobalAsmOperandRef < ' tcx > {
44- match op {
45- InlineAsmOperand :: Const { value } => {
46- let const_value = self . eval_mir_constant ( value) ;
47- let string = common:: asm_const_to_str (
48- self . cx . tcx ( ) ,
49- value. span ,
50- const_value,
51- self . cx . layout_of ( value. ty ( ) ) ,
52- ) ;
53- GlobalAsmOperandRef :: Const { string }
54- }
55- InlineAsmOperand :: SymFn { value } => {
56- let instance = match value. ty ( ) . kind ( ) {
57- & ty:: FnDef ( def_id, args) => Instance :: new ( def_id, args) ,
58- _ => bug ! ( "asm sym is not a function" ) ,
59- } ;
30+ let operands: Vec < _ > =
31+ operands. iter ( ) . map ( |op| inline_to_global_operand :: < Bx > ( cx, instance, op) ) . collect ( ) ;
6032
61- GlobalAsmOperandRef :: SymFn { instance }
62- }
63- InlineAsmOperand :: SymStatic { def_id } => {
64- GlobalAsmOperandRef :: SymStatic { def_id : * def_id }
65- }
66- InlineAsmOperand :: In { .. }
67- | InlineAsmOperand :: Out { .. }
68- | InlineAsmOperand :: InOut { .. }
69- | InlineAsmOperand :: Label { .. } => {
70- bug ! ( "invalid operand type for naked_asm!" )
71- }
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+ cx. typing_env ( ) ,
55+ ty:: EarlyBinder :: bind ( value. const_ ) ,
56+ )
57+ . eval ( cx. tcx ( ) , cx. typing_env ( ) , 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+ cx. typing_env ( ) ,
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+ cx. typing_env ( ) ,
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!" )
7297 }
7398 }
7499}
@@ -91,7 +116,11 @@ impl AsmBinaryFormat {
91116 }
92117}
93118
94- 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 ) {
95124 use std:: fmt:: Write ;
96125
97126 let target = & tcx. sess . target ;
@@ -105,24 +134,18 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
105134
106135 let asm_name = format ! ( "{}{}" , if mangle { "_" } else { "" } , tcx. symbol_name( instance) . name) ;
107136
108- let opt_section = tcx
109- . get_attr ( instance. def . def_id ( ) , sym:: link_section)
110- . and_then ( |attr| attr. value_str ( ) )
111- . map ( |attr| attr. as_str ( ) . to_string ( ) ) ;
112-
113- let instruction_set =
114- 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 ( ) ) ;
115139
116140 let ( arch_prefix, arch_suffix) = if is_arm {
117141 (
118- match instruction_set {
142+ match attrs . instruction_set {
119143 None => match is_thumb {
120144 true => ".thumb\n .thumb_func" ,
121145 false => ".arm" ,
122146 } ,
123- Some ( sym:: a32) => ".arm" ,
124- Some ( sym:: t32) => ".thumb\n .thumb_func" ,
125- Some ( other) => bug ! ( "invalid instruction set: {other}" ) ,
147+ Some ( InstructionSetAttr :: ArmA32 ) => ".arm" ,
148+ Some ( InstructionSetAttr :: ArmT32 ) => ".thumb\n .thumb_func" ,
126149 } ,
127150 match is_thumb {
128151 true => ".thumb" ,
@@ -137,7 +160,7 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
137160 let mut end = String :: new ( ) ;
138161 match AsmBinaryFormat :: from_target ( & tcx. sess . target ) {
139162 AsmBinaryFormat :: Elf => {
140- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
163+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
141164
142165 let progbits = match is_arm {
143166 true => "%progbits" ,
@@ -152,11 +175,10 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
152175 writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
153176 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
154177 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
155- writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
156- writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
157- if let Some ( instruction_set) = instruction_set {
158- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
178+ if let Visibility :: Hidden = item_data. visibility {
179+ writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
159180 }
181+ writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
160182 if !arch_prefix. is_empty ( ) {
161183 writeln ! ( begin, "{}" , arch_prefix) . unwrap ( ) ;
162184 }
@@ -170,13 +192,12 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
170192 }
171193 }
172194 AsmBinaryFormat :: Macho => {
173- let section = opt_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
195+ let section = link_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
174196 writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
175197 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
176198 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
177- writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
178- if let Some ( instruction_set) = instruction_set {
179- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
199+ if let Visibility :: Hidden = item_data. visibility {
200+ writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
180201 }
181202 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
182203
@@ -187,17 +208,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
187208 }
188209 }
189210 AsmBinaryFormat :: Coff => {
190- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
211+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
191212 writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
192213 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
193214 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
194215 writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
195216 writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
196217 writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
197218 writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
198- if let Some ( instruction_set) = instruction_set {
199- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
200- }
201219 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
202220
203221 writeln ! ( end) . unwrap ( ) ;
0 commit comments