1
1
use crate :: common;
2
2
use crate :: mir:: FunctionCx ;
3
- use crate :: traits:: { AsmMethods , BuilderMethods , GlobalAsmOperandRef } ;
3
+ use crate :: traits:: { AsmMethods , BuilderMethods , GlobalAsmOperandRef , MiscMethods } ;
4
+ use rustc_attr:: InstructionSetAttr ;
4
5
use rustc_middle:: bug;
6
+ use rustc_middle:: mir:: mono:: { Linkage , MonoItem , MonoItemData , Visibility } ;
5
7
use rustc_middle:: mir:: InlineAsmOperand ;
6
8
use rustc_middle:: ty;
7
9
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
@@ -29,7 +31,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
29
31
let operands: Vec < _ > =
30
32
operands. iter ( ) . map ( |op| self . inline_to_global_operand ( op) ) . collect ( ) ;
31
33
32
- let ( begin, end) = crate :: mir:: naked_asm:: prefix_and_suffix ( cx. tcx ( ) , instance) ;
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) ;
33
36
34
37
let mut template_vec = Vec :: new ( ) ;
35
38
template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin) ) ;
@@ -90,7 +93,33 @@ impl AsmBinaryFormat {
90
93
}
91
94
}
92
95
93
- fn prefix_and_suffix < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> ( String , String ) {
96
+ fn linkage_directive ( linkage : Linkage ) -> Option < & ' static str > {
97
+ if true {
98
+ // this is required. emitting nothing or .weak will emit
99
+ //
100
+ // > Global is external, but doesn't have external or weak linkage!
101
+ //
102
+ // and then aborts compilation
103
+ return Some ( ".globl" ) ;
104
+ }
105
+
106
+ match linkage {
107
+ Linkage :: External => Some ( ".globl" ) ,
108
+ Linkage :: WeakAny | Linkage :: WeakODR => Some ( ".weak" ) ,
109
+ Linkage :: LinkOnceAny | Linkage :: LinkOnceODR => Some ( ".weak" ) ,
110
+ Linkage :: Internal | Linkage :: Private => None , // just doesn't emit any attribute
111
+ Linkage :: ExternalWeak => None , // terminates with sigill on godbolt
112
+ Linkage :: AvailableExternally => None , // does not even emit the definition
113
+ Linkage :: Appending => None , // only valid on global variables
114
+ Linkage :: Common => None , // function may not have common linkage
115
+ }
116
+ }
117
+
118
+ fn prefix_and_suffix < ' tcx > (
119
+ tcx : TyCtxt < ' tcx > ,
120
+ instance : Instance < ' tcx > ,
121
+ item_data : & MonoItemData ,
122
+ ) -> ( String , String ) {
94
123
use std:: fmt:: Write ;
95
124
96
125
let target = & tcx. sess . target ;
@@ -109,19 +138,16 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
109
138
. and_then ( |attr| attr. value_str ( ) )
110
139
. map ( |attr| attr. as_str ( ) . to_string ( ) ) ;
111
140
112
- let instruction_set =
113
- tcx. get_attr ( instance. def . def_id ( ) , sym:: instruction_set) . and_then ( |attr| attr. value_str ( ) ) ;
114
-
141
+ let attrs = tcx. codegen_fn_attrs ( instance. def_id ( ) ) ;
115
142
let ( arch_prefix, arch_suffix) = if is_arm {
116
143
(
117
- match instruction_set {
144
+ match attrs . instruction_set {
118
145
None => match is_thumb {
119
146
true => ".thumb\n .thumb_func" ,
120
147
false => ".arm" ,
121
148
} ,
122
- Some ( sym:: a32) => ".arm" ,
123
- Some ( sym:: t32) => ".thumb\n .thumb_func" ,
124
- Some ( other) => bug ! ( "invalid instruction set: {other}" ) ,
149
+ Some ( InstructionSetAttr :: ArmA32 ) => ".arm" ,
150
+ Some ( InstructionSetAttr :: ArmT32 ) => ".thumb\n .thumb_func" ,
125
151
} ,
126
152
match is_thumb {
127
153
true => ".thumb" ,
@@ -150,10 +176,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
150
176
151
177
writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
152
178
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
153
- writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
154
- writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
179
+ if let Some ( linkage) = linkage_directive ( item_data. linkage ) {
180
+ writeln ! ( begin, "{linkage} {asm_name}" ) . unwrap ( ) ;
181
+ }
182
+ if let Visibility :: Hidden = item_data. visibility {
183
+ writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
184
+ }
155
185
writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
156
- if let Some ( instruction_set) = instruction_set {
186
+ if let Some ( instruction_set) = attrs . instruction_set {
157
187
writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
158
188
}
159
189
if !arch_prefix. is_empty ( ) {
@@ -172,9 +202,13 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
172
202
let section = opt_section. unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
173
203
writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
174
204
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
175
- writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
176
- writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
177
- if let Some ( instruction_set) = instruction_set {
205
+ if let Some ( linkage) = linkage_directive ( item_data. linkage ) {
206
+ writeln ! ( begin, "{linkage} {asm_name}" ) . unwrap ( ) ;
207
+ }
208
+ if let Visibility :: Hidden = item_data. visibility {
209
+ writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
210
+ }
211
+ if let Some ( instruction_set) = attrs. instruction_set {
178
212
writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
179
213
}
180
214
writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
@@ -189,12 +223,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
189
223
let section = opt_section. unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
190
224
writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
191
225
writeln ! ( begin, ".balign 4" ) . unwrap ( ) ;
192
- writeln ! ( begin, ".globl {asm_name}" ) . unwrap ( ) ;
226
+ if let Some ( linkage) = linkage_directive ( item_data. linkage ) {
227
+ writeln ! ( begin, "{linkage} {asm_name}" ) . unwrap ( ) ;
228
+ }
193
229
writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
194
230
writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
195
231
writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
196
232
writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
197
- if let Some ( instruction_set) = instruction_set {
233
+ if let Some ( instruction_set) = attrs . instruction_set {
198
234
writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
199
235
}
200
236
writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
0 commit comments