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- 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- }
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+ asm_macro : _,
20+ template,
21+ ref operands,
22+ options,
23+ line_spans,
24+ targets : _,
25+ unwind : _,
26+ } = mir. basic_blocks . iter ( ) . next ( ) . unwrap ( ) . terminator ( ) . kind
27+ else {
28+ bug ! ( "#[naked] functions should always terminate with an asm! block" )
29+ } ;
4230
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- } ;
31+ let operands: Vec < _ > =
32+ operands. iter ( ) . map ( |op| inline_to_global_operand :: < Bx > ( cx, instance, op) ) . collect ( ) ;
6033
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- }
34+ let item_data = cx. codegen_unit ( ) . items ( ) . get ( & MonoItem :: Fn ( instance) ) . unwrap ( ) ;
35+ let ( begin, end) = crate :: mir:: naked_asm:: prefix_and_suffix ( cx. tcx ( ) , instance, item_data) ;
36+
37+ let mut template_vec = Vec :: new ( ) ;
38+ template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin. into ( ) ) ) ;
39+ template_vec. extend ( template. iter ( ) . cloned ( ) ) ;
40+ template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( end. into ( ) ) ) ;
41+
42+ cx. codegen_global_asm ( & template_vec, & operands, options, line_spans) ;
43+ }
44+
45+ fn inline_to_global_operand < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
46+ cx : & ' a Bx :: CodegenCx ,
47+ instance : Instance < ' tcx > ,
48+ op : & InlineAsmOperand < ' tcx > ,
49+ ) -> GlobalAsmOperandRef < ' tcx > {
50+ match op {
51+ InlineAsmOperand :: Const { value } => {
52+ let const_value = instance
53+ . instantiate_mir_and_normalize_erasing_regions (
54+ cx. tcx ( ) ,
55+ ty:: ParamEnv :: reveal_all ( ) ,
56+ ty:: EarlyBinder :: bind ( value. const_ ) ,
57+ )
58+ . eval ( cx. tcx ( ) , ty:: ParamEnv :: reveal_all ( ) , value. span )
59+ . expect ( "erroneous constant missed by mono item collection" ) ;
60+
61+ let mono_type = instance. instantiate_mir_and_normalize_erasing_regions (
62+ cx. tcx ( ) ,
63+ ty:: ParamEnv :: reveal_all ( ) ,
64+ ty:: EarlyBinder :: bind ( value. ty ( ) ) ,
65+ ) ;
66+
67+ let string = common:: asm_const_to_str (
68+ cx. tcx ( ) ,
69+ value. span ,
70+ const_value,
71+ cx. layout_of ( mono_type) ,
72+ ) ;
73+
74+ GlobalAsmOperandRef :: Const { string }
75+ }
76+ InlineAsmOperand :: SymFn { value } => {
77+ let mono_type = instance. instantiate_mir_and_normalize_erasing_regions (
78+ cx. tcx ( ) ,
79+ ty:: ParamEnv :: reveal_all ( ) ,
80+ ty:: EarlyBinder :: bind ( value. ty ( ) ) ,
81+ ) ;
82+
83+ let instance = match mono_type. kind ( ) {
84+ & ty:: FnDef ( def_id, args) => Instance :: new ( def_id, args) ,
85+ _ => bug ! ( "asm sym is not a function" ) ,
86+ } ;
87+
88+ GlobalAsmOperandRef :: SymFn { instance }
89+ }
90+ InlineAsmOperand :: SymStatic { def_id } => {
91+ GlobalAsmOperandRef :: SymStatic { def_id : * def_id }
92+ }
93+ InlineAsmOperand :: In { .. }
94+ | InlineAsmOperand :: Out { .. }
95+ | InlineAsmOperand :: InOut { .. }
96+ | InlineAsmOperand :: Label { .. } => {
97+ bug ! ( "invalid operand type for naked_asm!" )
7298 }
7399 }
74100}
@@ -91,7 +117,11 @@ impl AsmBinaryFormat {
91117 }
92118}
93119
94- fn prefix_and_suffix < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> ( String , String ) {
120+ fn prefix_and_suffix < ' tcx > (
121+ tcx : TyCtxt < ' tcx > ,
122+ instance : Instance < ' tcx > ,
123+ item_data : & MonoItemData ,
124+ ) -> ( String , String ) {
95125 use std:: fmt:: Write ;
96126
97127 let target = & tcx. sess . target ;
@@ -105,24 +135,18 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
105135
106136 let asm_name = format ! ( "{}{}" , if mangle { "_" } else { "" } , tcx. symbol_name( instance) . name) ;
107137
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 ( ) ) ;
138+ let attrs = tcx. codegen_fn_attrs ( instance. def_id ( ) ) ;
139+ let link_section = attrs. link_section . map ( |symbol| symbol. as_str ( ) . to_string ( ) ) ;
115140
116141 let ( arch_prefix, arch_suffix) = if is_arm {
117142 (
118- match instruction_set {
143+ match attrs . instruction_set {
119144 None => match is_thumb {
120145 true => ".thumb\n .thumb_func" ,
121146 false => ".arm" ,
122147 } ,
123- Some ( sym:: a32) => ".arm" ,
124- Some ( sym:: t32) => ".thumb\n .thumb_func" ,
125- Some ( other) => bug ! ( "invalid instruction set: {other}" ) ,
148+ Some ( InstructionSetAttr :: ArmA32 ) => ".arm" ,
149+ Some ( InstructionSetAttr :: ArmT32 ) => ".thumb\n .thumb_func" ,
126150 } ,
127151 match is_thumb {
128152 true => ".thumb" ,
@@ -137,7 +161,7 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
137161 let mut end = String :: new ( ) ;
138162 match AsmBinaryFormat :: from_target ( & tcx. sess . target ) {
139163 AsmBinaryFormat :: Elf => {
140- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
164+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
141165
142166 let progbits = match is_arm {
143167 true => "%progbits" ,
@@ -152,11 +176,10 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
152176 writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
153177 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
154178 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 ( ) ;
179+ if let Visibility :: Hidden = item_data. visibility {
180+ writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
159181 }
182+ writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
160183 if !arch_prefix. is_empty ( ) {
161184 writeln ! ( begin, "{}" , arch_prefix) . unwrap ( ) ;
162185 }
@@ -170,13 +193,12 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
170193 }
171194 }
172195 AsmBinaryFormat :: Macho => {
173- let section = opt_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
196+ let section = link_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
174197 writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
175198 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
176199 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 ( ) ;
200+ if let Visibility :: Hidden = item_data. visibility {
201+ writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
180202 }
181203 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
182204
@@ -187,17 +209,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
187209 }
188210 }
189211 AsmBinaryFormat :: Coff => {
190- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
212+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
191213 writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
192214 writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
193215 writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
194216 writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
195217 writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
196218 writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
197219 writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
198- if let Some ( instruction_set) = instruction_set {
199- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
200- }
201220 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
202221
203222 writeln ! ( end) . unwrap ( ) ;
0 commit comments