63
63
from . import output
64
64
import dml .globals
65
65
import abc
66
+ import zlib
66
67
67
68
class DMLTypeError (Exception ): pass
68
69
@@ -510,6 +511,27 @@ def __init__(self, bits, signed, members = None, const = False):
510
511
def is_bitfields (self ):
511
512
return self .members is not None
512
513
514
+ def describe_backing_type (self ):
515
+ raise Exception ("%s.describe_backing_type not implemented"
516
+ % (self .__class__ .__name__ ,))
517
+
518
+ def describe (self ):
519
+ return (f'bitfields (backing type: { self .describe_backing_type ()} )'
520
+ if self .is_bitfields else self .describe_backing_type ())
521
+
522
+ def key (self ):
523
+ if not self .is_bitfields :
524
+ return DMLType .key (self )
525
+
526
+ backing = self .describe_backing_type ()
527
+
528
+ # using adler32 as a quick, dirty, short, implementation-consistent
529
+ # hash that doesn't pull in any dependencies
530
+ hsh = zlib .adler32 (';' .join (
531
+ f'{ name } :{ t .key ()} @{ msb } -{ lsb } '
532
+ for (name , (t , msb , lsb )) in self .members .items ()).encode ('utf-8' ))
533
+ return f'{ self .const_str } bitfields({ backing } , { hsh } )'
534
+
513
535
@property
514
536
def bytes (self ):
515
537
return (self .bits - 1 ) // 8 + 1
@@ -543,8 +565,29 @@ def cmp(self, other):
543
565
return NotImplemented
544
566
elif other .is_endian :
545
567
return NotImplemented
546
- return (0 if (self .bits , self .signed ) == (other .bits , other .signed )
547
- else NotImplemented )
568
+ if (self .bits , self .signed ) != (other .bits , other .signed ):
569
+ return NotImplemented
570
+ if self .members is not other .members :
571
+ if self .members is None or other .members is None :
572
+ return NotImplemented
573
+
574
+ # Slow path, when the two bitfields types have different origins
575
+
576
+ # The specifications have to be completely equivalent.
577
+ # We don't normalize reps via any sorting, as the order matters for
578
+ # compound initializers; we are not lenient on names, as that
579
+ # affects mkSubRef and designated initializers; we are not lenient
580
+ # on types because they SHOULD affect mkSubRef even though they
581
+ # don't today (see SIMICS-8857 and SIMICS-18394)
582
+ if (len (self .members ) != len (other .members )
583
+ or any ((name0 , msb0 , lsb0 ) != (name1 , msb1 , lsb1 )
584
+ or t0 .cmp (t1 ) != 0
585
+ for ((name0 , (t0 , msb0 , lsb0 )),
586
+ (name1 , (t1 , msb1 , lsb1 )))
587
+ in zip (self .members .items (), other .members .items ()))):
588
+ return NotImplemented
589
+
590
+ return 0
548
591
549
592
def cmp_fuzzy (self , other ):
550
593
if not other .is_int :
@@ -570,7 +613,11 @@ def cmp_fuzzy(self, other):
570
613
def hashed (self ):
571
614
cls = type (self ) if self .is_arch_dependent else IntegerType
572
615
byte_order = self .byte_order if self .is_endian else None
573
- return hash ((cls , self .const , self .bits , self .signed , byte_order ))
616
+ members = (tuple ((name , typ .hashed (), lsb , msb )
617
+ for (name , (typ , lsb , msb )) in self .members .items ())
618
+ if self .is_bitfields else None )
619
+ return hash ((cls , self .const , self .bits , self .signed , members ,
620
+ byte_order ))
574
621
575
622
# This is the most restrictive canstore definition for
576
623
# IntegerTypes, if this is overridden then it should be
@@ -600,12 +647,8 @@ class TInt(IntegerType):
600
647
def __init__ (self , bits , signed , members = None , const = False ):
601
648
IntegerType .__init__ (self , bits , signed , members , const )
602
649
603
- def describe (self ):
604
- s = 'int%d' % self .bits
605
- if self .signed :
606
- return s
607
- else :
608
- return 'u' + s
650
+ def describe_backing_type (self ):
651
+ return f'{ "u" * (not self .signed )} int{ self .bits } '
609
652
def __repr__ (self ):
610
653
return 'TInt(%r,%r,%r,%r)' % (self .bits , self .signed ,
611
654
self .members , self .const )
@@ -671,7 +714,7 @@ def __init__(self, signed, const=False):
671
714
def c_name (self ):
672
715
return self .const_str + ('long' if self .signed else 'unsigned long' )
673
716
674
- def describe (self ):
717
+ def describe_backing_type (self ):
675
718
return self .c_name ()
676
719
677
720
def __repr__ (self ):
@@ -692,7 +735,7 @@ def __init__(self, signed, const=False):
692
735
def c_name (self ):
693
736
return self .const_str + ('ssize_t' if self .signed else 'size_t' )
694
737
695
- def describe (self ):
738
+ def describe_backing_type (self ):
696
739
return self .c_name ()
697
740
698
741
def __repr__ (self ):
@@ -719,7 +762,7 @@ def c_name(self):
719
762
name = 'int64_t' if self .signed else 'uint64_t'
720
763
return f'const { name } ' if self .const else name
721
764
722
- def describe (self ):
765
+ def describe_backing_type (self ):
723
766
return self .c_name ()
724
767
725
768
def __repr__ (self ):
@@ -755,7 +798,7 @@ def c_name(self):
755
798
self .const_str , "" if self .signed else "u" , self .bits ,
756
799
"be" if self .big_endian else "le" )
757
800
758
- def describe (self ):
801
+ def describe_backing_type (self ):
759
802
return self .c_name ()
760
803
761
804
def __repr__ (self ):
0 commit comments