copy-merging works afaict! -- some tests still broken: out-of-date
[bigint-presentation-code.git] / src / bigint_presentation_code / compiler_ir.py
index 699102b655fe86d19dd67283e21620861c012985..4f8fb79bbbf15788663ca0875fd6150db7679e51 100644 (file)
@@ -787,6 +787,20 @@ class Loc(metaclass=InternedMeta):
         return Loc(kind=self.kind,
                    start=self.start + offset, reg_len=subloc_ty.reg_len)
 
+    def get_superloc_with_self_at_offset(self, superloc_ty, offset):
+        # type: (Ty, int) -> Loc
+        """get the Loc containing `self` such that:
+        `retval.get_subloc_at_offset(self.ty, offset) == self`
+        and `retval.ty == superloc_ty`
+        """
+        if superloc_ty.base_ty != self.kind.base_ty:
+            raise ValueError("BaseTy mismatch")
+        if offset < 0 or offset + self.reg_len > superloc_ty.reg_len:
+            raise ValueError("invalid sub-Loc: offset and/or "
+                             "superloc_ty.reg_len out of range")
+        return Loc(kind=self.kind,
+                   start=self.start - offset, reg_len=superloc_ty.reg_len)
+
 
 SPECIAL_GPRS = (
     Loc(kind=LocKind.GPR, start=0, reg_len=1),
@@ -900,6 +914,18 @@ class LocSet(OFSet[Loc], metaclass=InternedMeta):
     def __repr__(self):
         return f"LocSet(starts={self.starts!r}, ty={self.ty!r})"
 
+    @cached_property
+    def only_loc(self):
+        # type: () -> Loc | None
+        """if len(self) == 1 then return the Loc in self, otherwise None"""
+        only_loc = None
+        for i in self:
+            if only_loc is None:
+                only_loc = i
+            else:
+                return None  # len(self) > 1
+        return only_loc
+
 
 @plain_data(frozen=True, unsafe_hash=True)
 @final