@@ -6,12 +6,37 @@ use std::fmt::Write;
66
77use rustc_ast:: ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
88use rustc_middle:: mir:: InlineAsmOperand ;
9+ use rustc_middle:: ty:: SymbolName ;
910use rustc_span:: sym;
1011use rustc_target:: asm:: * ;
1112
13+ enum CInlineAsmOperand < ' tcx > {
14+ In {
15+ reg : InlineAsmRegOrRegClass ,
16+ value : CValue < ' tcx > ,
17+ } ,
18+ Out {
19+ reg : InlineAsmRegOrRegClass ,
20+ late : bool ,
21+ place : Option < CPlace < ' tcx > > ,
22+ } ,
23+ InOut {
24+ reg : InlineAsmRegOrRegClass ,
25+ _late : bool ,
26+ in_value : CValue < ' tcx > ,
27+ out_place : Option < CPlace < ' tcx > > ,
28+ } ,
29+ Const {
30+ value : String ,
31+ } ,
32+ Symbol {
33+ symbol : SymbolName < ' tcx > ,
34+ } ,
35+ }
36+
1237pub ( crate ) fn codegen_inline_asm < ' tcx > (
1338 fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
14- _span : Span ,
39+ span : Span ,
1540 template : & [ InlineAsmTemplatePiece ] ,
1641 operands : & [ InlineAsmOperand < ' tcx > ] ,
1742 options : InlineAsmOptions ,
@@ -198,6 +223,59 @@ pub(crate) fn codegen_inline_asm<'tcx>(
198223 }
199224 }
200225
226+ let operands = operands
227+ . into_iter ( )
228+ . map ( |operand| match * operand {
229+ InlineAsmOperand :: In { reg, ref value } => {
230+ CInlineAsmOperand :: In { reg, value : crate :: base:: codegen_operand ( fx, value) }
231+ }
232+ InlineAsmOperand :: Out { reg, late, ref place } => CInlineAsmOperand :: Out {
233+ reg,
234+ late,
235+ place : place. map ( |place| crate :: base:: codegen_place ( fx, place) ) ,
236+ } ,
237+ InlineAsmOperand :: InOut { reg, late, ref in_value, ref out_place } => {
238+ CInlineAsmOperand :: InOut {
239+ reg,
240+ _late : late,
241+ in_value : crate :: base:: codegen_operand ( fx, in_value) ,
242+ out_place : out_place. map ( |place| crate :: base:: codegen_place ( fx, place) ) ,
243+ }
244+ }
245+ InlineAsmOperand :: Const { ref value } => {
246+ let ( const_value, ty) = crate :: constant:: eval_mir_constant ( fx, & * value)
247+ . unwrap_or_else ( || span_bug ! ( span, "asm const cannot be resolved" ) ) ;
248+ let value = rustc_codegen_ssa:: common:: asm_const_to_str (
249+ fx. tcx ,
250+ span,
251+ const_value,
252+ fx. layout_of ( ty) ,
253+ ) ;
254+ CInlineAsmOperand :: Const { value }
255+ }
256+ InlineAsmOperand :: SymFn { ref value } => {
257+ let literal = fx. monomorphize ( value. literal ) ;
258+ if let ty:: FnDef ( def_id, substs) = * literal. ty ( ) . kind ( ) {
259+ let instance = ty:: Instance :: resolve_for_fn_ptr (
260+ fx. tcx ,
261+ ty:: ParamEnv :: reveal_all ( ) ,
262+ def_id,
263+ substs,
264+ )
265+ . unwrap ( ) ;
266+ CInlineAsmOperand :: Symbol { symbol : fx. tcx . symbol_name ( instance) }
267+ } else {
268+ span_bug ! ( span, "invalid type for asm sym (fn)" ) ;
269+ }
270+ }
271+ InlineAsmOperand :: SymStatic { def_id } => {
272+ assert ! ( fx. tcx. is_static( def_id) ) ;
273+ let instance = Instance :: mono ( fx. tcx , def_id) . polymorphize ( fx. tcx ) ;
274+ CInlineAsmOperand :: Symbol { symbol : fx. tcx . symbol_name ( instance) }
275+ }
276+ } )
277+ . collect :: < Vec < _ > > ( ) ;
278+
201279 let mut inputs = Vec :: new ( ) ;
202280 let mut outputs = Vec :: new ( ) ;
203281
@@ -206,7 +284,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
206284 arch : fx. tcx . sess . asm_arch . unwrap ( ) ,
207285 enclosing_def_id : fx. instance . def_id ( ) ,
208286 template,
209- operands,
287+ operands : & operands ,
210288 options,
211289 registers : Vec :: new ( ) ,
212290 stack_slots_clobber : Vec :: new ( ) ,
@@ -229,36 +307,22 @@ pub(crate) fn codegen_inline_asm<'tcx>(
229307 fx. cx . global_asm . push_str ( & generated_asm) ;
230308
231309 for ( i, operand) in operands. iter ( ) . enumerate ( ) {
232- match * operand {
233- InlineAsmOperand :: In { reg : _, ref value } => {
234- inputs. push ( (
235- asm_gen. stack_slots_input [ i] . unwrap ( ) ,
236- crate :: base:: codegen_operand ( fx, value) . load_scalar ( fx) ,
237- ) ) ;
238- }
239- InlineAsmOperand :: Out { reg : _, late : _, place } => {
310+ match operand {
311+ CInlineAsmOperand :: In { reg : _, value } => {
312+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , value. load_scalar ( fx) ) ) ;
313+ }
314+ CInlineAsmOperand :: Out { reg : _, late : _, place } => {
240315 if let Some ( place) = place {
241- outputs. push ( (
242- asm_gen. stack_slots_output [ i] . unwrap ( ) ,
243- crate :: base:: codegen_place ( fx, place) ,
244- ) ) ;
316+ outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , place. clone ( ) ) ) ;
245317 }
246318 }
247- InlineAsmOperand :: InOut { reg : _, late : _, ref in_value, out_place } => {
248- inputs. push ( (
249- asm_gen. stack_slots_input [ i] . unwrap ( ) ,
250- crate :: base:: codegen_operand ( fx, in_value) . load_scalar ( fx) ,
251- ) ) ;
319+ CInlineAsmOperand :: InOut { reg : _, _late : _, in_value, out_place } => {
320+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , in_value. load_scalar ( fx) ) ) ;
252321 if let Some ( out_place) = out_place {
253- outputs. push ( (
254- asm_gen. stack_slots_output [ i] . unwrap ( ) ,
255- crate :: base:: codegen_place ( fx, out_place) ,
256- ) ) ;
322+ outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , out_place. clone ( ) ) ) ;
257323 }
258324 }
259- InlineAsmOperand :: Const { value : _ } => todo ! ( ) ,
260- InlineAsmOperand :: SymFn { value : _ } => todo ! ( ) ,
261- InlineAsmOperand :: SymStatic { def_id : _ } => todo ! ( ) ,
325+ CInlineAsmOperand :: Const { value : _ } | CInlineAsmOperand :: Symbol { symbol : _ } => { }
262326 }
263327 }
264328
@@ -280,7 +344,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
280344 arch : InlineAsmArch ,
281345 enclosing_def_id : DefId ,
282346 template : & ' a [ InlineAsmTemplatePiece ] ,
283- operands : & ' a [ InlineAsmOperand < ' tcx > ] ,
347+ operands : & ' a [ CInlineAsmOperand < ' tcx > ] ,
284348 options : InlineAsmOptions ,
285349 registers : Vec < Option < InlineAsmReg > > ,
286350 stack_slots_clobber : Vec < Option < Size > > ,
@@ -304,18 +368,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
304368 // Add explicit registers to the allocated set.
305369 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
306370 match * operand {
307- InlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
371+ CInlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
308372 regs[ i] = Some ( reg) ;
309373 allocated. entry ( reg) . or_default ( ) . 0 = true ;
310374 }
311- InlineAsmOperand :: Out {
312- reg : InlineAsmRegOrRegClass :: Reg ( reg) , late : true , ..
375+ CInlineAsmOperand :: Out {
376+ reg : InlineAsmRegOrRegClass :: Reg ( reg) ,
377+ late : true ,
378+ ..
313379 } => {
314380 regs[ i] = Some ( reg) ;
315381 allocated. entry ( reg) . or_default ( ) . 1 = true ;
316382 }
317- InlineAsmOperand :: Out { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. }
318- | InlineAsmOperand :: InOut { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
383+ CInlineAsmOperand :: Out { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. }
384+ | CInlineAsmOperand :: InOut { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
319385 regs[ i] = Some ( reg) ;
320386 allocated. insert ( reg, ( true , true ) ) ;
321387 }
@@ -326,12 +392,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
326392 // Allocate out/inout/inlateout registers first because they are more constrained.
327393 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
328394 match * operand {
329- InlineAsmOperand :: Out {
395+ CInlineAsmOperand :: Out {
330396 reg : InlineAsmRegOrRegClass :: RegClass ( class) ,
331397 late : false ,
332398 ..
333399 }
334- | InlineAsmOperand :: InOut {
400+ | CInlineAsmOperand :: InOut {
335401 reg : InlineAsmRegOrRegClass :: RegClass ( class) , ..
336402 } => {
337403 let mut alloc_reg = None ;
@@ -360,7 +426,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
360426 // Allocate in/lateout.
361427 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
362428 match * operand {
363- InlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: RegClass ( class) , .. } => {
429+ CInlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: RegClass ( class) , .. } => {
364430 let mut alloc_reg = None ;
365431 for & reg in & map[ & class] {
366432 let mut used = false ;
@@ -380,7 +446,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
380446 regs[ i] = Some ( reg) ;
381447 allocated. entry ( reg) . or_default ( ) . 0 = true ;
382448 }
383- InlineAsmOperand :: Out {
449+ CInlineAsmOperand :: Out {
384450 reg : InlineAsmRegOrRegClass :: RegClass ( class) ,
385451 late : true ,
386452 ..
@@ -455,7 +521,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
455521 // Allocate stack slots for inout
456522 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
457523 match * operand {
458- InlineAsmOperand :: InOut { reg, out_place : Some ( _) , .. } => {
524+ CInlineAsmOperand :: InOut { reg, out_place : Some ( _) , .. } => {
459525 let slot = new_slot ( reg. reg_class ( ) ) ;
460526 slots_input[ i] = Some ( slot) ;
461527 slots_output[ i] = Some ( slot) ;
@@ -470,8 +536,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
470536 // Allocate stack slots for input
471537 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
472538 match * operand {
473- InlineAsmOperand :: In { reg, .. }
474- | InlineAsmOperand :: InOut { reg, out_place : None , .. } => {
539+ CInlineAsmOperand :: In { reg, .. }
540+ | CInlineAsmOperand :: InOut { reg, out_place : None , .. } => {
475541 slots_input[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
476542 }
477543 _ => ( ) ,
@@ -487,7 +553,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
487553 // Allocate stack slots for output
488554 for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
489555 match * operand {
490- InlineAsmOperand :: Out { reg, place : Some ( _) , .. } => {
556+ CInlineAsmOperand :: Out { reg, place : Some ( _) , .. } => {
491557 slots_output[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
492558 }
493559 _ => ( ) ,
@@ -549,13 +615,23 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
549615 generated_asm. push_str ( s) ;
550616 }
551617 InlineAsmTemplatePiece :: Placeholder { operand_idx, modifier, span : _ } => {
552- if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
553- generated_asm. push ( '%' ) ;
618+ match self . operands [ * operand_idx] {
619+ CInlineAsmOperand :: In { .. }
620+ | CInlineAsmOperand :: Out { .. }
621+ | CInlineAsmOperand :: InOut { .. } => {
622+ if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
623+ generated_asm. push ( '%' ) ;
624+ }
625+ self . registers [ * operand_idx]
626+ . unwrap ( )
627+ . emit ( & mut generated_asm, self . arch , * modifier)
628+ . unwrap ( ) ;
629+ }
630+ CInlineAsmOperand :: Const { ref value } => {
631+ generated_asm. push_str ( value) ;
632+ }
633+ CInlineAsmOperand :: Symbol { symbol } => generated_asm. push_str ( symbol. name ) ,
554634 }
555- self . registers [ * operand_idx]
556- . unwrap ( )
557- . emit ( & mut generated_asm, self . arch , * modifier)
558- . unwrap ( ) ;
559635 }
560636 }
561637 }
0 commit comments