6363from . import output
6464import dml .globals
6565import abc
66+ import zlib
6667
6768class DMLTypeError (Exception ): pass
6869
@@ -510,6 +511,27 @@ def __init__(self, bits, signed, members = None, const = False):
510511 def is_bitfields (self ):
511512 return self .members is not None
512513
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+
513535 @property
514536 def bytes (self ):
515537 return (self .bits - 1 ) // 8 + 1
@@ -543,8 +565,29 @@ def cmp(self, other):
543565 return NotImplemented
544566 elif other .is_endian :
545567 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
548591
549592 def cmp_fuzzy (self , other ):
550593 if not other .is_int :
@@ -570,7 +613,11 @@ def cmp_fuzzy(self, other):
570613 def hashed (self ):
571614 cls = type (self ) if self .is_arch_dependent else IntegerType
572615 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 ))
574621
575622 # This is the most restrictive canstore definition for
576623 # IntegerTypes, if this is overridden then it should be
@@ -600,12 +647,8 @@ class TInt(IntegerType):
600647 def __init__ (self , bits , signed , members = None , const = False ):
601648 IntegerType .__init__ (self , bits , signed , members , const )
602649
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 } '
609652 def __repr__ (self ):
610653 return 'TInt(%r,%r,%r,%r)' % (self .bits , self .signed ,
611654 self .members , self .const )
@@ -671,7 +714,7 @@ def __init__(self, signed, const=False):
671714 def c_name (self ):
672715 return self .const_str + ('long' if self .signed else 'unsigned long' )
673716
674- def describe (self ):
717+ def describe_backing_type (self ):
675718 return self .c_name ()
676719
677720 def __repr__ (self ):
@@ -692,7 +735,7 @@ def __init__(self, signed, const=False):
692735 def c_name (self ):
693736 return self .const_str + ('ssize_t' if self .signed else 'size_t' )
694737
695- def describe (self ):
738+ def describe_backing_type (self ):
696739 return self .c_name ()
697740
698741 def __repr__ (self ):
@@ -719,7 +762,7 @@ def c_name(self):
719762 name = 'int64_t' if self .signed else 'uint64_t'
720763 return f'const { name } ' if self .const else name
721764
722- def describe (self ):
765+ def describe_backing_type (self ):
723766 return self .c_name ()
724767
725768 def __repr__ (self ):
@@ -755,7 +798,7 @@ def c_name(self):
755798 self .const_str , "" if self .signed else "u" , self .bits ,
756799 "be" if self .big_endian else "le" )
757800
758- def describe (self ):
801+ def describe_backing_type (self ):
759802 return self .c_name ()
760803
761804 def __repr__ (self ):
0 commit comments