@@ -308,20 +308,32 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
308
308
}
309
309
310
310
pub ( crate ) enum FunctionSignature < ' ll > {
311
- /// The signature is obtained directly from LLVM, and **may not match the Rust signature**
312
- Intrinsic ( & ' ll Type ) ,
311
+ /// This is an LLVM intrinsic, the signature is obtained directly from LLVM, and **may not match the Rust signature**
312
+ LLVMSignature ( llvm:: Intrinsic , & ' ll Type ) ,
313
+ /// This is an LLVM intrinsic, but the signature is just the Rust signature.
314
+ /// FIXME: this should ideally not exist, we should be using the LLVM signature for all LLVM intrinsics
315
+ RustSignature ( llvm:: Intrinsic , & ' ll Type ) ,
313
316
/// The name starts with `llvm.`, but can't obtain the intrinsic ID. May be invalid or upgradable
314
- MaybeInvalidIntrinsic ( & ' ll Type ) ,
317
+ MaybeInvalid ( & ' ll Type ) ,
315
318
/// Just the Rust signature
316
- Rust ( & ' ll Type ) ,
319
+ NotIntrinsic ( & ' ll Type ) ,
317
320
}
318
321
319
322
impl < ' ll > FunctionSignature < ' ll > {
320
323
pub ( crate ) fn fn_ty ( & self ) -> & ' ll Type {
321
324
match self {
322
- FunctionSignature :: Intrinsic ( fn_ty)
323
- | FunctionSignature :: MaybeInvalidIntrinsic ( fn_ty)
324
- | FunctionSignature :: Rust ( fn_ty) => fn_ty,
325
+ FunctionSignature :: LLVMSignature ( _, fn_ty)
326
+ | FunctionSignature :: RustSignature ( _, fn_ty)
327
+ | FunctionSignature :: MaybeInvalid ( fn_ty)
328
+ | FunctionSignature :: NotIntrinsic ( fn_ty) => fn_ty,
329
+ }
330
+ }
331
+
332
+ pub ( crate ) fn intrinsic ( & self ) -> Option < llvm:: Intrinsic > {
333
+ match self {
334
+ FunctionSignature :: RustSignature ( intrinsic, _)
335
+ | FunctionSignature :: LLVMSignature ( intrinsic, _) => Some ( * intrinsic) ,
336
+ _ => None ,
325
337
}
326
338
}
327
339
}
@@ -332,12 +344,9 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
332
344
/// When `do_verify` is set, this function performs checks for the signature of LLVM intrinsics
333
345
/// and emits a fatal error if it doesn't match. These checks are important,but somewhat expensive
334
346
/// So they are only used at function definitions, not at callsites
335
- fn llvm_type (
336
- & self ,
337
- cx : & CodegenCx < ' ll , ' tcx > ,
338
- name : & [ u8 ] ,
339
- do_verify : bool ,
340
- ) -> FunctionSignature < ' ll > ;
347
+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> FunctionSignature < ' ll > ;
348
+ /// The normal Rust signature for this
349
+ fn rust_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
341
350
/// **If this function is an LLVM intrinsic** checks if the LLVM signature provided matches with this
342
351
fn verify_intrinsic_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > , llvm_ty : & ' ll Type ) -> bool ;
343
352
fn ptr_to_llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
@@ -481,52 +490,36 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
481
490
. all ( |( rust_ty, llvm_ty) | cx. equate_ty ( rust_ty, llvm_ty) )
482
491
}
483
492
484
- fn llvm_type (
485
- & self ,
486
- cx : & CodegenCx < ' ll , ' tcx > ,
487
- name : & [ u8 ] ,
488
- do_verify : bool ,
489
- ) -> FunctionSignature < ' ll > {
490
- let mut maybe_invalid = false ;
493
+ fn rust_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type {
494
+ let return_ty = self . llvm_return_type ( cx) ;
495
+ let argument_tys = self . llvm_argument_types ( cx) ;
496
+
497
+ if self . c_variadic {
498
+ cx. type_variadic_func ( & argument_tys, return_ty)
499
+ } else {
500
+ cx. type_func ( & argument_tys, return_ty)
501
+ }
502
+ }
491
503
504
+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> FunctionSignature < ' ll > {
492
505
if name. starts_with ( b"llvm." ) {
493
506
if let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name) {
494
507
if !intrinsic. is_overloaded ( ) {
495
508
// FIXME: also do this for overloaded intrinsics
496
- let llvm_fn_ty = intrinsic. get_type ( cx. llcx , & [ ] ) ;
497
- if do_verify {
498
- if !self . verify_intrinsic_signature ( cx, llvm_fn_ty) {
499
- cx. tcx . dcx ( ) . fatal ( format ! (
500
- "Intrinsic signature mismatch for `{}`: expected signature `{llvm_fn_ty:?}`" ,
501
- str :: from_utf8( name) . unwrap( )
502
- ) ) ;
503
- }
504
- }
505
- return FunctionSignature :: Intrinsic ( llvm_fn_ty) ;
509
+ FunctionSignature :: LLVMSignature ( intrinsic, intrinsic. get_type ( cx. llcx , & [ ] ) )
510
+ } else {
511
+ FunctionSignature :: RustSignature ( intrinsic, self . rust_signature ( cx) )
506
512
}
507
513
} else {
508
514
// it's one of 2 cases,
509
515
// - either the base name is invalid
510
516
// - it has been superseded by something else, so the intrinsic was removed entirely
511
517
// to check for upgrades, we need the `llfn`, so we defer it for now
512
518
513
- maybe_invalid = true ;
519
+ FunctionSignature :: MaybeInvalid ( self . rust_signature ( cx ) )
514
520
}
515
- }
516
-
517
- let return_ty = self . llvm_return_type ( cx) ;
518
- let argument_tys = self . llvm_argument_types ( cx) ;
519
-
520
- let fn_ty = if self . c_variadic {
521
- cx. type_variadic_func ( & argument_tys, return_ty)
522
521
} else {
523
- cx. type_func ( & argument_tys, return_ty)
524
- } ;
525
-
526
- if maybe_invalid {
527
- FunctionSignature :: MaybeInvalidIntrinsic ( fn_ty)
528
- } else {
529
- FunctionSignature :: Rust ( fn_ty)
522
+ FunctionSignature :: NotIntrinsic ( self . rust_signature ( cx) )
530
523
}
531
524
}
532
525
@@ -684,15 +677,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
684
677
callsite : & ' ll Value ,
685
678
llfn : & ' ll Value ,
686
679
) {
687
- // if we are using the LLVM signature, use the LLVM attributes otherwise it might be problematic
688
- let name = llvm:: get_value_name ( llfn) ;
689
- if name. starts_with ( b"llvm." )
690
- && let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( & name)
691
- {
692
- // FIXME: also do this for overloaded intrinsics
693
- if !intrinsic. is_overloaded ( ) {
694
- return ;
695
- }
680
+ // Don't apply any attributes to LLVM intrinsics, they will be applied by AutoUpgrade
681
+ if llvm:: get_value_name ( llfn) . starts_with ( b"llvm." ) {
682
+ return ;
696
683
}
697
684
698
685
let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
0 commit comments