@@ -107,7 +107,7 @@ enum ConstraintOrRegister {
107107
108108
109109impl < ' a , ' gcc , ' tcx > AsmBuilderMethods < ' tcx > for Builder < ' a , ' gcc , ' tcx > {
110- fn codegen_inline_asm ( & mut self , template : & [ InlineAsmTemplatePiece ] , rust_operands : & [ InlineAsmOperandRef < ' tcx , Self > ] , options : InlineAsmOptions , span : & [ Span ] , instance : Instance < ' _ > , _dest_catch_funclet : Option < ( Self :: BasicBlock , Self :: BasicBlock , Option < & Self :: Funclet > ) > ) {
110+ fn codegen_inline_asm ( & mut self , template : & [ InlineAsmTemplatePiece ] , rust_operands : & [ InlineAsmOperandRef < ' tcx , Self > ] , options : InlineAsmOptions , span : & [ Span ] , instance : Instance < ' _ > , dest : Option < Self :: BasicBlock > , _catch_funclet : Option < ( Self :: BasicBlock , Option < & Self :: Funclet > ) > ) {
111111 if options. contains ( InlineAsmOptions :: MAY_UNWIND ) {
112112 self . sess ( ) . dcx ( )
113113 . create_err ( UnwindingInlineAsm { span : span[ 0 ] } )
@@ -126,6 +126,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
126126 // added to `outputs.len()`
127127 let mut inputs = vec ! [ ] ;
128128
129+ // GCC index of a label equals its position in the array added to
130+ // `outputs.len() + inputs.len()`.
131+ let mut labels = vec ! [ ] ;
132+
129133 // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _`
130134 let mut clobbers = vec ! [ ] ;
131135
@@ -269,6 +273,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
269273 // some targets to add a leading underscore (Mach-O).
270274 constants_len += self . tcx . symbol_name ( Instance :: mono ( self . tcx , def_id) ) . name . len ( ) ;
271275 }
276+
277+ InlineAsmOperandRef :: Label { label } => {
278+ labels. push ( label) ;
279+ }
272280 }
273281 }
274282
@@ -368,6 +376,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
368376 InlineAsmOperandRef :: Const { .. } => {
369377 // processed in the previous pass
370378 }
379+
380+ InlineAsmOperandRef :: Label { .. } => {
381+ // processed in the previous pass
382+ }
371383 }
372384 }
373385
@@ -454,6 +466,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
454466 InlineAsmOperandRef :: Const { ref string } => {
455467 template_str. push_str ( string) ;
456468 }
469+
470+ InlineAsmOperandRef :: Label { label } => {
471+ let label_gcc_index = labels. iter ( )
472+ . position ( |& l| l == label)
473+ . expect ( "wrong rust index" ) ;
474+ let gcc_index = label_gcc_index + outputs. len ( ) + inputs. len ( ) ;
475+ push_to_template ( Some ( 'l' ) , gcc_index) ;
476+ }
457477 }
458478 }
459479 }
@@ -466,7 +486,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
466486 // 4. Generate Extended Asm block
467487
468488 let block = self . llbb ( ) ;
469- let extended_asm = block. add_extended_asm ( None , & template_str) ;
489+ let extended_asm = if let Some ( dest) = dest {
490+ assert ! ( !labels. is_empty( ) ) ;
491+ block. end_with_extended_asm_goto ( None , & template_str, & labels, Some ( dest) )
492+ } else {
493+ block. add_extended_asm ( None , & template_str)
494+ } ;
470495
471496 for op in & outputs {
472497 extended_asm. add_output_operand ( None , & op. to_constraint ( ) , op. tmp_var ) ;
@@ -494,7 +519,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
494519 if !options. contains ( InlineAsmOptions :: NOSTACK ) {
495520 // TODO(@Commeownist): figure out how to align stack
496521 }
497- if options. contains ( InlineAsmOptions :: NORETURN ) {
522+ if dest . is_none ( ) && options. contains ( InlineAsmOptions :: NORETURN ) {
498523 let builtin_unreachable = self . context . get_builtin_function ( "__builtin_unreachable" ) ;
499524 let builtin_unreachable: RValue < ' gcc > = unsafe { std:: mem:: transmute ( builtin_unreachable) } ;
500525 self . call ( self . type_void ( ) , None , None , builtin_unreachable, & [ ] , None ) ;
0 commit comments