@@ -302,20 +302,32 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
302
302
}
303
303
304
304
pub ( crate ) enum FunctionSignature < ' ll > {
305
- /// The signature is obtained directly from LLVM, and **may not match the Rust signature**
306
- Intrinsic ( & ' ll Type ) ,
305
+ /// This is an LLVM intrinsic, the signature is obtained directly from LLVM, and **may not match the Rust signature**
306
+ LLVMSignature ( llvm:: Intrinsic , & ' ll Type ) ,
307
+ /// This is an LLVM intrinsic, but the signature is just the Rust signature.
308
+ /// FIXME: this should ideally not exist, we should be using the LLVM signature for all LLVM intrinsics
309
+ RustSignature ( llvm:: Intrinsic , & ' ll Type ) ,
307
310
/// The name starts with `llvm.`, but can't obtain the intrinsic ID. May be invalid or upgradable
308
- MaybeInvalidIntrinsic ( & ' ll Type ) ,
311
+ MaybeInvalid ( & ' ll Type ) ,
309
312
/// Just the Rust signature
310
- Rust ( & ' ll Type ) ,
313
+ NotIntrinsic ( & ' ll Type ) ,
311
314
}
312
315
313
316
impl < ' ll > FunctionSignature < ' ll > {
314
317
pub ( crate ) fn fn_ty ( & self ) -> & ' ll Type {
315
318
match self {
316
- FunctionSignature :: Intrinsic ( fn_ty)
317
- | FunctionSignature :: MaybeInvalidIntrinsic ( fn_ty)
318
- | FunctionSignature :: Rust ( fn_ty) => fn_ty,
319
+ FunctionSignature :: LLVMSignature ( _, fn_ty)
320
+ | FunctionSignature :: RustSignature ( _, fn_ty)
321
+ | FunctionSignature :: MaybeInvalid ( fn_ty)
322
+ | FunctionSignature :: NotIntrinsic ( fn_ty) => fn_ty,
323
+ }
324
+ }
325
+
326
+ pub ( crate ) fn intrinsic ( & self ) -> Option < llvm:: Intrinsic > {
327
+ match self {
328
+ FunctionSignature :: RustSignature ( intrinsic, _)
329
+ | FunctionSignature :: LLVMSignature ( intrinsic, _) => Some ( * intrinsic) ,
330
+ _ => None ,
319
331
}
320
332
}
321
333
}
@@ -326,12 +338,9 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
326
338
/// When `do_verify` is set, this function performs checks for the signature of LLVM intrinsics
327
339
/// and emits a fatal error if it doesn't match. These checks are important,but somewhat expensive
328
340
/// So they are only used at function definitions, not at callsites
329
- fn llvm_type (
330
- & self ,
331
- cx : & CodegenCx < ' ll , ' tcx > ,
332
- name : & [ u8 ] ,
333
- do_verify : bool ,
334
- ) -> FunctionSignature < ' ll > ;
341
+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> FunctionSignature < ' ll > ;
342
+ /// The normal Rust signature for this
343
+ fn rust_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
335
344
/// **If this function is an LLVM intrinsic** checks if the LLVM signature provided matches with this
336
345
fn verify_intrinsic_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > , llvm_ty : & ' ll Type ) -> bool ;
337
346
fn ptr_to_llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type ;
@@ -499,58 +508,41 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
499
508
return false ;
500
509
}
501
510
502
- // todo: add bypasses for types not accessible from Rust here
503
511
iter:: once ( ( rust_return_ty, llvm_return_ty) )
504
512
. chain ( iter:: zip ( rust_argument_tys, llvm_argument_tys) )
505
513
. all ( |( rust_ty, llvm_ty) | cx. equate_ty ( rust_ty, llvm_ty) )
506
514
}
507
515
508
- fn llvm_type (
509
- & self ,
510
- cx : & CodegenCx < ' ll , ' tcx > ,
511
- name : & [ u8 ] ,
512
- do_verify : bool ,
513
- ) -> FunctionSignature < ' ll > {
514
- let mut maybe_invalid = false ;
516
+ fn rust_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > ) -> & ' ll Type {
517
+ let return_ty = self . llvm_return_type ( cx) ;
518
+ let argument_tys = self . llvm_argument_types ( cx) ;
519
+
520
+ if self . c_variadic {
521
+ cx. type_variadic_func ( & argument_tys, return_ty)
522
+ } else {
523
+ cx. type_func ( & argument_tys, return_ty)
524
+ }
525
+ }
515
526
527
+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> FunctionSignature < ' ll > {
516
528
if name. starts_with ( b"llvm." ) {
517
529
if let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name) {
518
530
if !intrinsic. is_overloaded ( ) {
519
531
// FIXME: also do this for overloaded intrinsics
520
- let llvm_fn_ty = cx. intrinsic_type ( intrinsic, & [ ] ) ;
521
- if do_verify {
522
- if !self . verify_intrinsic_signature ( cx, llvm_fn_ty) {
523
- cx. tcx . dcx ( ) . fatal ( format ! (
524
- "Intrinsic signature mismatch for `{}`: expected signature `{llvm_fn_ty:?}`" ,
525
- str :: from_utf8( name) . unwrap( )
526
- ) ) ;
527
- }
528
- }
529
- return FunctionSignature :: Intrinsic ( llvm_fn_ty) ;
532
+ FunctionSignature :: LLVMSignature ( intrinsic, cx. intrinsic_type ( intrinsic, & [ ] ) )
533
+ } else {
534
+ FunctionSignature :: RustSignature ( intrinsic, self . rust_signature ( cx) )
530
535
}
531
536
} else {
532
537
// it's one of 2 cases,
533
538
// - either the base name is invalid
534
539
// - it has been superceded by something else, so the intrinsic was removed entirely
535
540
// to check for upgrades, we need the `llfn`, so we defer it for now
536
541
537
- maybe_invalid = true ;
542
+ FunctionSignature :: MaybeInvalid ( self . rust_signature ( cx ) )
538
543
}
539
- }
540
-
541
- let return_ty = self . llvm_return_type ( cx) ;
542
- let argument_tys = self . llvm_argument_types ( cx) ;
543
-
544
- let fn_ty = if self . c_variadic {
545
- cx. type_variadic_func ( & argument_tys, return_ty)
546
544
} else {
547
- cx. type_func ( & argument_tys, return_ty)
548
- } ;
549
-
550
- if maybe_invalid {
551
- FunctionSignature :: MaybeInvalidIntrinsic ( fn_ty)
552
- } else {
553
- FunctionSignature :: Rust ( fn_ty)
545
+ FunctionSignature :: NotIntrinsic ( self . rust_signature ( cx) )
554
546
}
555
547
}
556
548
@@ -699,15 +691,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
699
691
callsite : & ' ll Value ,
700
692
llfn : & ' ll Value ,
701
693
) {
702
- // if we are using the LLVM signature, use the LLVM attributes otherwise it might be problematic
703
- let name = llvm:: get_value_name ( llfn) ;
704
- if name. starts_with ( b"llvm." )
705
- && let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name)
706
- {
707
- // FIXME: also do this for overloaded intrinsics
708
- if !intrinsic. is_overloaded ( ) {
709
- return ;
710
- }
694
+ // Don't apply any attributes to LLVM intrinsics, they will be applied by AutoUpgrade
695
+ if llvm:: get_value_name ( llfn) . starts_with ( b"llvm." ) {
696
+ return ;
711
697
}
712
698
713
699
let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
0 commit comments