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