1
1
use crate :: builder:: Builder ;
2
+ use crate :: common:: Funclet ;
2
3
use crate :: context:: CodegenCx ;
3
4
use crate :: llvm;
5
+ use crate :: llvm_util;
4
6
use crate :: type_:: Type ;
5
7
use crate :: type_of:: LayoutLlvmExt ;
6
8
use crate :: value:: Value ;
@@ -98,6 +100,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
98
100
ia. alignstack ,
99
101
ia. dialect ,
100
102
& [ span] ,
103
+ false ,
104
+ None ,
101
105
) ;
102
106
if r. is_none ( ) {
103
107
return false ;
@@ -121,6 +125,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
121
125
options : InlineAsmOptions ,
122
126
line_spans : & [ Span ] ,
123
127
instance : Instance < ' _ > ,
128
+ dest_catch_funclet : Option < ( Self :: BasicBlock , Self :: BasicBlock , Option < & Self :: Funclet > ) > ,
124
129
) {
125
130
let asm_arch = self . tcx . sess . asm_arch . unwrap ( ) ;
126
131
@@ -355,6 +360,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
355
360
alignstack,
356
361
dialect,
357
362
line_spans,
363
+ options. contains ( InlineAsmOptions :: MAY_UNWIND ) ,
364
+ dest_catch_funclet,
358
365
)
359
366
. unwrap_or_else ( || span_bug ! ( line_spans[ 0 ] , "LLVM asm constraint validation failed" ) ) ;
360
367
@@ -447,9 +454,16 @@ pub(crate) fn inline_asm_call(
447
454
alignstack : bool ,
448
455
dia : LlvmAsmDialect ,
449
456
line_spans : & [ Span ] ,
457
+ unwind : bool ,
458
+ dest_catch_funclet : Option < (
459
+ & ' ll llvm:: BasicBlock ,
460
+ & ' ll llvm:: BasicBlock ,
461
+ Option < & Funclet < ' ll > > ,
462
+ ) > ,
450
463
) -> Option < & ' ll Value > {
451
464
let volatile = if volatile { llvm:: True } else { llvm:: False } ;
452
465
let alignstack = if alignstack { llvm:: True } else { llvm:: False } ;
466
+ let can_throw = if unwind { llvm:: True } else { llvm:: False } ;
453
467
454
468
let argtys = inputs
455
469
. iter ( )
@@ -466,6 +480,13 @@ pub(crate) fn inline_asm_call(
466
480
let constraints_ok = llvm:: LLVMRustInlineAsmVerify ( fty, cons. as_ptr ( ) . cast ( ) , cons. len ( ) ) ;
467
481
debug ! ( "constraint verification result: {:?}" , constraints_ok) ;
468
482
if constraints_ok {
483
+ if unwind && llvm_util:: get_version ( ) < ( 13 , 0 , 0 ) {
484
+ bx. cx . sess ( ) . span_fatal (
485
+ line_spans[ 0 ] ,
486
+ "unwinding from inline assembly is only supported on llvm >= 13." ,
487
+ ) ;
488
+ }
489
+
469
490
let v = llvm:: LLVMRustInlineAsm (
470
491
fty,
471
492
asm. as_ptr ( ) . cast ( ) ,
@@ -475,8 +496,14 @@ pub(crate) fn inline_asm_call(
475
496
volatile,
476
497
alignstack,
477
498
llvm:: AsmDialect :: from_generic ( dia) ,
499
+ can_throw,
478
500
) ;
479
- let call = bx. call ( fty, v, inputs, None ) ;
501
+
502
+ let call = if let Some ( ( dest, catch, funclet) ) = dest_catch_funclet {
503
+ bx. invoke ( fty, v, inputs, dest, catch, funclet)
504
+ } else {
505
+ bx. call ( fty, v, inputs, None )
506
+ } ;
480
507
481
508
// Store mark in a metadata node so we can map LLVM errors
482
509
// back to source locations. See #17552.
0 commit comments