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