11use crate :: common;
22use crate :: mir:: FunctionCx ;
3- use crate :: traits:: { AsmMethods , BuilderMethods , GlobalAsmOperandRef } ;
3+ use crate :: traits:: { AsmMethods , BuilderMethods , GlobalAsmOperandRef , MiscMethods } ;
4+ use rustc_attr:: InstructionSetAttr ;
45use rustc_middle:: bug;
6+ use rustc_middle:: mir:: mono:: { Linkage , MonoItem , MonoItemData , Visibility } ;
57use rustc_middle:: mir:: InlineAsmOperand ;
68use rustc_middle:: ty;
79use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
@@ -29,7 +31,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2931 let operands: Vec < _ > =
3032 operands. iter ( ) . map ( |op| self . inline_to_global_operand ( op) ) . collect ( ) ;
3133
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) ;
3336
3437 let mut template_vec = Vec :: new ( ) ;
3538 template_vec. push ( rustc_ast:: ast:: InlineAsmTemplatePiece :: String ( begin) ) ;
@@ -90,7 +93,33 @@ impl AsmBinaryFormat {
9093 }
9194}
9295
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 ) {
94123 use std:: fmt:: Write ;
95124
96125 let target = & tcx. sess . target ;
@@ -109,19 +138,16 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
109138 . and_then ( |attr| attr. value_str ( ) )
110139 . map ( |attr| attr. as_str ( ) . to_string ( ) ) ;
111140
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 ( ) ) ;
115142 let ( arch_prefix, arch_suffix) = if is_arm {
116143 (
117- match instruction_set {
144+ match attrs . instruction_set {
118145 None => match is_thumb {
119146 true => ".thumb\n .thumb_func" ,
120147 false => ".arm" ,
121148 } ,
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" ,
125151 } ,
126152 match is_thumb {
127153 true => ".thumb" ,
@@ -150,10 +176,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
150176
151177 writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
152178 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+ }
155185 writeln ! ( begin, ".type {asm_name}, {function}" ) . unwrap ( ) ;
156- if let Some ( instruction_set) = instruction_set {
186+ if let Some ( instruction_set) = attrs . instruction_set {
157187 writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
158188 }
159189 if !arch_prefix. is_empty ( ) {
@@ -172,9 +202,13 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
172202 let section = opt_section. unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
173203 writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
174204 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 {
178212 writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
179213 }
180214 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
@@ -189,12 +223,14 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
189223 let section = opt_section. unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
190224 writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
191225 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+ }
193229 writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
194230 writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
195231 writeln ! ( begin, ".type 32" ) . unwrap ( ) ;
196232 writeln ! ( begin, ".endef {asm_name}" ) . unwrap ( ) ;
197- if let Some ( instruction_set) = instruction_set {
233+ if let Some ( instruction_set) = attrs . instruction_set {
198234 writeln ! ( begin, "{}" , instruction_set. as_str( ) ) . unwrap ( ) ;
199235 }
200236 writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
0 commit comments