@@ -313,6 +313,8 @@ pub(crate) enum FunctionSignature<'ll> {
313
313
/// This is an LLVM intrinsic, but the signature is just the Rust signature.
314
314
/// FIXME: this should ideally not exist, we should be using the LLVM signature for all LLVM intrinsics
315
315
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 } ,
316
318
/// The name starts with `llvm.`, but can't obtain the intrinsic ID. May be invalid or upgradable
317
319
MaybeInvalid ( & ' ll Type ) ,
318
320
/// Just the Rust signature
@@ -326,13 +328,15 @@ impl<'ll> FunctionSignature<'ll> {
326
328
| FunctionSignature :: RustSignature ( _, fn_ty)
327
329
| FunctionSignature :: MaybeInvalid ( fn_ty)
328
330
| FunctionSignature :: NotIntrinsic ( fn_ty) => fn_ty,
331
+ FunctionSignature :: NonMatchingSignature { rust_ty, .. } => rust_ty,
329
332
}
330
333
}
331
334
332
335
pub ( crate ) fn intrinsic ( & self ) -> Option < llvm:: Intrinsic > {
333
336
match self {
334
337
FunctionSignature :: RustSignature ( intrinsic, _)
335
- | FunctionSignature :: LLVMSignature ( intrinsic, _) => Some ( * intrinsic) ,
338
+ | FunctionSignature :: LLVMSignature ( intrinsic, _)
339
+ | FunctionSignature :: NonMatchingSignature { intrinsic, .. } => Some ( * intrinsic) ,
336
340
_ => None ,
337
341
}
338
342
}
@@ -375,40 +379,26 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
375
379
return true ;
376
380
}
377
381
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) ;
391
390
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 ;
410
393
}
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
412
402
}
413
403
}
414
404
}
@@ -520,7 +510,16 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
520
510
if let Some ( intrinsic) = llvm:: Intrinsic :: lookup ( name) {
521
511
if !intrinsic. is_overloaded ( ) {
522
512
// 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
+ }
524
523
} else {
525
524
FunctionSignature :: RustSignature ( intrinsic, self . rust_signature ( cx) )
526
525
}
0 commit comments