@@ -438,6 +438,10 @@ pub trait TypeReflection<'gcc, 'tcx> {
438
438
fn is_u128 ( & self , cx : & CodegenCx < ' gcc , ' tcx > ) -> bool ;
439
439
440
440
fn is_vector ( & self ) -> bool ;
441
+ /// Checks if 2 types are "known to be equal". Returns Some(true) if types are equal(e.g. bool and bool),
442
+ /// Some(false) if they can't possibly be equal(e.g. a struct and a float), and None if there is no way
443
+ /// to check for their equality(struct and struct)
444
+ fn known_eq ( & self , rhs : & Self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Option < bool > ;
441
445
}
442
446
443
447
impl < ' gcc , ' tcx > TypeReflection < ' gcc , ' tcx > for Type < ' gcc > {
@@ -537,4 +541,106 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> {
537
541
538
542
false
539
543
}
544
+ fn known_eq ( & self , other : & Self , cx : & CodegenCx < ' gcc , ' tcx > ) -> Option < bool > {
545
+ // "Happy" path: types represented using the same pointer
546
+ if self == other {
547
+ return Some ( true ) ;
548
+ }
549
+ if self . is_bool ( ) {
550
+ return Some ( other. is_bool ( ) ) ;
551
+ } else if self . is_integral ( ) {
552
+ // Int and.. something? Not equal.
553
+ if !other. is_integral ( ) {
554
+ return Some ( false ) ;
555
+ }
556
+ // Do the intigers have the same size and sign?
557
+ return Some (
558
+ ( self . get_size ( ) == other. get_size ( ) )
559
+ && ( self . is_signed ( cx) == other. is_signed ( cx) ) ,
560
+ ) ;
561
+ } else if self . is_vector ( ) {
562
+ // Vector and.. something? Different types.
563
+ if !other. is_vector ( ) {
564
+ return Some ( false ) ;
565
+ }
566
+ // Both are vectors - try to get them directly
567
+ let ( Some ( lhs) , Some ( rhs) ) = ( self . dyncast_vector ( ) , other. dyncast_vector ( ) ) else {
568
+ return None ;
569
+ } ;
570
+ // Different element count - different types.
571
+ if lhs. get_num_units ( ) != rhs. get_num_units ( ) {
572
+ return Some ( false ) ;
573
+ }
574
+ // Same element - same type.
575
+ return lhs. get_element_type ( ) . known_eq ( & rhs. get_element_type ( ) , cx) ;
576
+ } else if let Some ( lhs) = self . is_struct ( ) {
577
+ // Struct and a not-struct? Different types.
578
+ let Some ( rhs) = other. is_struct ( ) else {
579
+ return Some ( false ) ;
580
+ } ;
581
+ // Different *field count*? Different types.
582
+ if lhs. get_field_count ( ) != rhs. get_field_count ( ) {
583
+ return Some ( false ) ;
584
+ }
585
+ // We can't get the type of a filed quite yet. So, we will say that we don't know if the structs are equal.
586
+ return None ;
587
+ } else if let Some ( s_ptr) = self . get_pointee ( ) {
588
+ let Some ( other_ptr) = other. get_pointee ( ) else {
589
+ return Some ( false ) ;
590
+ } ;
591
+ return s_ptr. known_eq ( & other_ptr, cx) ;
592
+ } else if let Some ( lhs_elem) = self . dyncast_array ( ) {
593
+ // Array and not an array - not equal.
594
+ let Some ( rhs_elem) = other. dyncast_array ( ) else {
595
+ return Some ( false ) ;
596
+ } ;
597
+ // Mismatched elements - not equal
598
+ if !lhs_elem. known_eq ( & rhs_elem, cx) ? {
599
+ return Some ( false ) ;
600
+ }
601
+ return None ;
602
+ } else if let Some ( lhs_ptr) = self . dyncast_function_ptr_type ( ) {
603
+ // Fn ptr and not fn ptr - not equal.
604
+ let Some ( rhs_ptr) = other. dyncast_function_ptr_type ( ) else {
605
+ return Some ( false ) ;
606
+ } ;
607
+ // Wrong argc
608
+ if lhs_ptr. get_param_count ( ) != rhs_ptr. get_param_count ( ) {
609
+ return Some ( false ) ;
610
+ }
611
+ // Wrong ret
612
+ if !lhs_ptr. get_return_type ( ) . known_eq ( & rhs_ptr. get_return_type ( ) , cx) ? {
613
+ return Some ( false ) ;
614
+ }
615
+ // Wrong param count.
616
+ for idx in 0 ..lhs_ptr. get_param_count ( ) {
617
+ if !lhs_ptr. get_param_type ( idx) . known_eq ( & rhs_ptr. get_param_type ( idx) , cx) ? {
618
+ return Some ( false ) ;
619
+ }
620
+ }
621
+ return None ;
622
+ }
623
+ #[ cfg( feature = "master" ) ]
624
+ if self . is_floating_point ( ) {
625
+ if !other. is_floating_point ( ) {
626
+ return Some ( false ) ;
627
+ }
628
+ return Some ( self . get_size ( ) == other. get_size ( ) ) ;
629
+ }
630
+ #[ cfg( not( feature = "master" ) ) ]
631
+ {
632
+ fn is_floating_point < ' gcc > ( ty : & Type < ' gcc > , cx : & CodegenCx < ' gcc , ' _ > ) -> bool {
633
+ ty. is_compatible_with ( cx. context . new_type :: < f32 > ( ) )
634
+ || ty. is_compatible_with ( cx. context . new_type :: < f64 > ( ) )
635
+ }
636
+ if is_floating_point ( self , cx) {
637
+ if !is_floating_point ( self , cx) {
638
+ return Some ( false ) ;
639
+ }
640
+ return Some ( self . get_size ( ) == other. get_size ( ) ) ;
641
+ }
642
+ }
643
+ // Unknown type...
644
+ None
645
+ }
540
646
}
0 commit comments