@@ -302,20 +302,32 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
302302}
303303
304304pub ( 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 ) ,
307310 /// 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 ) ,
309312 /// Just the Rust signature
310- Rust ( & ' ll Type ) ,
313+ NotIntrinsic ( & ' ll Type ) ,
311314}
312315
313316impl < ' ll > FunctionSignature < ' ll > {
314317 pub ( crate ) fn fn_ty ( & self ) -> & ' ll Type {
315318 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 ,
319331 }
320332 }
321333}
@@ -326,12 +338,9 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
326338 /// When `do_verify` is set, this function performs checks for the signature of LLVM intrinsics
327339 /// and emits a fatal error if it doesn't match. These checks are important,but somewhat expensive
328340 /// 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 ;
335344 /// **If this function is an LLVM intrinsic** checks if the LLVM signature provided matches with this
336345 fn verify_intrinsic_signature ( & self , cx : & CodegenCx < ' ll , ' tcx > , llvm_ty : & ' ll Type ) -> bool ;
337346 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>> {
499508 return false ;
500509 }
501510
502- // todo: add bypasses for types not accessible from Rust here
503511 iter:: once ( ( rust_return_ty, llvm_return_ty) )
504512 . chain ( iter:: zip ( rust_argument_tys, llvm_argument_tys) )
505513 . all ( |( rust_ty, llvm_ty) | cx. equate_ty ( rust_ty, llvm_ty) )
506514 }
507515
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+ }
515526
527+ fn llvm_type ( & self , cx : & CodegenCx < ' ll , ' tcx > , name : & [ u8 ] ) -> FunctionSignature < ' ll > {
516528 if name. starts_with ( b"llvm." ) {
517529 if let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name) {
518530 if !intrinsic. is_overloaded ( ) {
519531 // 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) )
530535 }
531536 } else {
532537 // it's one of 2 cases,
533538 // - either the base name is invalid
534539 // - it has been superceded by something else, so the intrinsic was removed entirely
535540 // to check for upgrades, we need the `llfn`, so we defer it for now
536541
537- maybe_invalid = true ;
542+ FunctionSignature :: MaybeInvalid ( self . rust_signature ( cx ) )
538543 }
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)
546544 } 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) )
554546 }
555547 }
556548
@@ -699,15 +691,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
699691 callsite : & ' ll Value ,
700692 llfn : & ' ll Value ,
701693 ) {
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 ;
711697 }
712698
713699 let mut func_attrs = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
0 commit comments