@@ -114,7 +114,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
114
114
options : InlineAsmOptions ,
115
115
span : & [ Span ] ,
116
116
instance : Instance < ' _ > ,
117
- _dest_catch_funclet : Option < ( Self :: BasicBlock , Self :: BasicBlock , Option < & Self :: Funclet > ) > ,
117
+ _catch_funclet : Option < ( Self :: BasicBlock , Self :: BasicBlock , Option < & Self :: Funclet > ) > ,
118
118
) {
119
119
if options. contains ( InlineAsmOptions :: MAY_UNWIND ) {
120
120
self . sess ( ) . dcx ( ) . create_err ( UnwindingInlineAsm { span : span[ 0 ] } ) . emit ( ) ;
@@ -132,6 +132,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
132
132
// added to `outputs.len()`
133
133
let mut inputs = vec ! [ ] ;
134
134
135
+ // GCC index of a label equals its position in the array added to
136
+ // `outputs.len() + inputs.len()`.
137
+ let mut labels = vec ! [ ] ;
138
+
135
139
// Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _`
136
140
let mut clobbers = vec ! [ ] ;
137
141
@@ -283,6 +287,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
283
287
constants_len +=
284
288
self . tcx . symbol_name ( Instance :: mono ( self . tcx , def_id) ) . name . len ( ) ;
285
289
}
290
+
291
+ InlineAsmOperandRef :: Label { label } => {
292
+ labels. push ( label) ;
293
+ }
286
294
}
287
295
}
288
296
@@ -381,6 +389,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
381
389
InlineAsmOperandRef :: Const { .. } => {
382
390
// processed in the previous pass
383
391
}
392
+
393
+ InlineAsmOperandRef :: Label { .. } => {
394
+ // processed in the previous pass
395
+ }
384
396
}
385
397
}
386
398
@@ -470,6 +482,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
470
482
InlineAsmOperandRef :: Const { ref string } => {
471
483
template_str. push_str ( string) ;
472
484
}
485
+
486
+ InlineAsmOperandRef :: Label { label } => {
487
+ let label_gcc_index = labels. iter ( )
488
+ . position ( |& l| l == label)
489
+ . expect ( "wrong rust index" ) ;
490
+ let gcc_index = label_gcc_index + outputs. len ( ) + inputs. len ( ) ;
491
+ push_to_template ( Some ( 'l' ) , gcc_index) ;
492
+ }
473
493
}
474
494
}
475
495
}
@@ -482,7 +502,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
482
502
// 4. Generate Extended Asm block
483
503
484
504
let block = self . llbb ( ) ;
485
- let extended_asm = block. add_extended_asm ( None , & template_str) ;
505
+ let extended_asm = if let Some ( dest) = dest {
506
+ assert ! ( !labels. is_empty( ) ) ;
507
+ block. end_with_extended_asm_goto ( None , & template_str, & labels, Some ( dest) )
508
+ } else {
509
+ block. add_extended_asm ( None , & template_str)
510
+ } ;
486
511
487
512
for op in & outputs {
488
513
extended_asm. add_output_operand ( None , & op. to_constraint ( ) , op. tmp_var ) ;
@@ -510,7 +535,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
510
535
if !options. contains ( InlineAsmOptions :: NOSTACK ) {
511
536
// TODO(@Commeownist): figure out how to align stack
512
537
}
513
- if options. contains ( InlineAsmOptions :: NORETURN ) {
538
+ if dest . is_none ( ) && options. contains ( InlineAsmOptions :: NORETURN ) {
514
539
let builtin_unreachable = self . context . get_builtin_function ( "__builtin_unreachable" ) ;
515
540
let builtin_unreachable: RValue < ' gcc > =
516
541
unsafe { std:: mem:: transmute ( builtin_unreachable) } ;
0 commit comments