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 } ;
8
5
use rustc_middle:: ty:: { Instance , TyCtxt } ;
9
-
10
- use rustc_span:: sym;
6
+ use rustc_middle:: { bug, ty} ;
11
7
use rustc_target:: asm:: InlineAsmArch ;
12
8
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
+ } ;
42
29
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 ( ) ;
60
32
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!" )
72
97
}
73
98
}
74
99
}
@@ -91,7 +116,11 @@ impl AsmBinaryFormat {
91
116
}
92
117
}
93
118
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 ) {
95
124
use std:: fmt:: Write ;
96
125
97
126
let target = & tcx. sess . target ;
@@ -105,24 +134,18 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
105
134
106
135
let asm_name = format ! ( "{}{}" , if mangle { "_" } else { "" } , tcx. symbol_name( instance) . name) ;
107
136
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 ( ) ) ;
115
139
116
140
let ( arch_prefix, arch_suffix) = if is_arm {
117
141
(
118
- match instruction_set {
142
+ match attrs . instruction_set {
119
143
None => match is_thumb {
120
144
true => ".thumb\n .thumb_func" ,
121
145
false => ".arm" ,
122
146
} ,
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" ,
126
149
} ,
127
150
match is_thumb {
128
151
true => ".thumb" ,
@@ -137,7 +160,7 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
137
160
let mut end = String :: new ( ) ;
138
161
match AsmBinaryFormat :: from_target ( & tcx. sess . target ) {
139
162
AsmBinaryFormat :: Elf => {
140
- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
163
+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
141
164
142
165
let progbits = match is_arm {
143
166
true => "%progbits" ,
@@ -152,11 +175,10 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
152
175
writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
153
176
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
154
177
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 ( ) ;
159
180
}
181
+ writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
160
182
if !arch_prefix. is_empty ( ) {
161
183
writeln ! ( begin, "{}" , arch_prefix) . unwrap ( ) ;
162
184
}
@@ -170,13 +192,12 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
170
192
}
171
193
}
172
194
AsmBinaryFormat :: Macho => {
173
- let section = opt_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
195
+ let section = link_section . unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
174
196
writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
175
197
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
176
198
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 ( ) ;
180
201
}
181
202
writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
182
203
@@ -187,17 +208,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
187
208
}
188
209
}
189
210
AsmBinaryFormat :: Coff => {
190
- let section = opt_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
211
+ let section = link_section . unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
191
212
writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
192
213
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
193
214
writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
194
215
writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
195
216
writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
196
217
writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
197
218
writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
198
- if let Some ( instruction_set) = instruction_set {
199
- writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
200
- }
201
219
writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
202
220
203
221
writeln ! ( end) . unwrap ( ) ;
0 commit comments