@@ -313,6 +313,8 @@ pub(crate) enum FunctionSignature<'ll> {
313313 /// This is an LLVM intrinsic, but the signature is just the Rust signature.
314314 /// FIXME: this should ideally not exist, we should be using the LLVM signature for all LLVM intrinsics
315315 RustSignature ( llvm:: Intrinsic , & ' ll Type ) ,
316+ /// FIXME: This shouldn't exist as well, but needed to get around autocast
317+ NonMatchingSignature { intrinsic : llvm:: Intrinsic , llvm_ty : & ' ll Type , rust_ty : & ' ll Type } ,
316318 /// The name starts with `llvm.`, but can't obtain the intrinsic ID. May be invalid or upgradable
317319 MaybeInvalid ( & ' ll Type ) ,
318320 /// Just the Rust signature
@@ -326,13 +328,15 @@ impl<'ll> FunctionSignature<'ll> {
326328 | FunctionSignature :: RustSignature ( _, fn_ty)
327329 | FunctionSignature :: MaybeInvalid ( fn_ty)
328330 | FunctionSignature :: NotIntrinsic ( fn_ty) => fn_ty,
331+ FunctionSignature :: NonMatchingSignature { rust_ty, .. } => rust_ty,
329332 }
330333 }
331334
332335 pub ( crate ) fn intrinsic ( & self ) -> Option < llvm:: Intrinsic > {
333336 match self {
334337 FunctionSignature :: RustSignature ( intrinsic, _)
335- | FunctionSignature :: LLVMSignature ( intrinsic, _) => Some ( * intrinsic) ,
338+ | FunctionSignature :: LLVMSignature ( intrinsic, _)
339+ | FunctionSignature :: NonMatchingSignature { intrinsic, .. } => Some ( * intrinsic) ,
336340 _ => None ,
337341 }
338342 }
@@ -375,40 +379,26 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
375379 return true ;
376380 }
377381
378- match self . type_kind ( llvm_ty) {
379- TypeKind :: BFloat => rust_ty == self . type_i16 ( ) ,
380-
381- // Some LLVM intrinsics return **non-packed** structs, but they can't be mimicked from Rust
382- // due to auto field-alignment in non-packed structs (packed structs are represented in LLVM
383- // as, well, packed structs, so they won't match with those either)
384- TypeKind :: Struct if self . type_kind ( rust_ty) == TypeKind :: Struct => {
385- let rust_element_tys = self . struct_element_types ( rust_ty) ;
386- let llvm_element_tys = self . struct_element_types ( llvm_ty) ;
387-
388- if rust_element_tys. len ( ) != llvm_element_tys. len ( ) {
389- return false ;
390- }
382+ // Some LLVM intrinsics return **non-packed** structs, but they can't be mimicked from Rust
383+ // due to auto field-alignment in non-packed structs (packed structs are represented in LLVM
384+ // as, well, packed structs, so they won't match with those either)
385+ if self . type_kind ( llvm_ty) == TypeKind :: Struct
386+ && self . type_kind ( rust_ty) == TypeKind :: Struct
387+ {
388+ let rust_element_tys = self . struct_element_types ( rust_ty) ;
389+ let llvm_element_tys = self . struct_element_types ( llvm_ty) ;
391390
392- iter:: zip ( rust_element_tys, llvm_element_tys) . all (
393- |( rust_element_ty, llvm_element_ty) | {
394- self . equate_ty ( rust_element_ty, llvm_element_ty)
395- } ,
396- )
397- }
398- TypeKind :: Vector => {
399- let element_count = self . vector_length ( llvm_ty) as u64 ;
400- let llvm_element_ty = self . element_type ( llvm_ty) ;
401-
402- if llvm_element_ty == self . type_bf16 ( ) {
403- rust_ty == self . type_vector ( self . type_i16 ( ) , element_count)
404- } else if llvm_element_ty == self . type_i1 ( ) {
405- let int_width = element_count. next_power_of_two ( ) . max ( 8 ) ;
406- rust_ty == self . type_ix ( int_width)
407- } else {
408- false
409- }
391+ if rust_element_tys. len ( ) != llvm_element_tys. len ( ) {
392+ return false ;
410393 }
411- _ => false ,
394+
395+ iter:: zip ( rust_element_tys, llvm_element_tys) . all (
396+ |( rust_element_ty, llvm_element_ty) | {
397+ self . equate_ty ( rust_element_ty, llvm_element_ty)
398+ } ,
399+ )
400+ } else {
401+ false
412402 }
413403 }
414404}
@@ -520,7 +510,16 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
520510 if let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name) {
521511 if !intrinsic. is_overloaded ( ) {
522512 // FIXME: also do this for overloaded intrinsics
523- FunctionSignature :: LLVMSignature ( intrinsic, intrinsic. get_type ( cx. llcx , & [ ] ) )
513+ let llvm_ty = intrinsic. get_type ( cx. llcx , & [ ] ) ;
514+ if self . verify_intrinsic_signature ( cx, llvm_ty) {
515+ FunctionSignature :: LLVMSignature ( intrinsic, llvm_ty)
516+ } else {
517+ FunctionSignature :: NonMatchingSignature {
518+ intrinsic,
519+ llvm_ty,
520+ rust_ty : self . rust_signature ( cx) ,
521+ }
522+ }
524523 } else {
525524 FunctionSignature :: RustSignature ( intrinsic, self . rust_signature ( cx) )
526525 }
0 commit comments