fix bug where pseudo-code assignments modify more than just the variable being assign...
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 25 Apr 2023 06:15:11 +0000 (23:15 -0700)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:17 +0000 (19:51 +0100)
src/openpower/decoder/helpers.py
src/openpower/decoder/pseudo/parser.py
src/openpower/decoder/pseudo/pyfnwriter.py
src/openpower/decoder/pseudo/pywriter.py

index 3f8845bf04c9cee1a83e78d14fa9d1ee376d56f7..17ddbe0b3a3f4403e6cc18a78b5ed73a0560f035 100644 (file)
@@ -68,6 +68,31 @@ def EXTS128(value):
     return SelectableInt(exts(value.value, value.bits) & ((1 << 128)-1), 128)
 
 
+def copy_assign_rhs(inp):
+    """ implicitly added function call to all assignment RHSes.
+        This copies the passed-in value so later assignments to parts of the
+        LHS don't modify the RHS if it's a SelectableInt.
+
+        Example:
+        ```
+        # this needs to copy the SelectableInt instance in RA
+        # not just assign a reference to it to A
+        A <- RA
+        A[0] <- 1  # if the copy wasn't performed, we just modified RA too!
+        ```
+    """
+    if isinstance(inp, (str, int)):
+        return inp
+    if isinstance(inp, SelectableInt):
+        return SelectableInt(inp)
+    if isinstance(inp, tuple):
+        return tuple(map(copy_assign_rhs, inp))
+    if isinstance(inp, dict):
+        return {copy_assign_rhs(k): copy_assign_rhs(v) for k, v in inp.items()}
+    raise TypeError("tried to assign an unsupported type in pseudo-code",
+                    repr(type(inp)))
+
+
 # signed version of MUL
 def MULS(a, b):
     if isinstance(b, int):
index 42df81be96e83c43ac8bcac7fb0f7fee3c37e0eb..94864896a8c493e0a2cbfc3ce5059854ee43d4a3 100644 (file)
@@ -496,7 +496,12 @@ class PowerParser:
                     self.read_regs.add(toname)
             if name and name in self.gprs:
                 self.write_regs.add(name)  # add to list of regs to write
-            p[0] = Assign(autoassign, name, p[1], p[3], iea_mode)
+
+            # copy rhs -- see openpower.decoder.helpers.copy_assign_rhs()'s
+            # documentation for why we need this
+            copy_fn = ast.Name("copy_assign_rhs", ast.Load())
+            rhs = ast.Call(copy_fn, (p[3],), [])
+            p[0] = Assign(autoassign, name, p[1], rhs, iea_mode)
             if name:
                 self.declared_vars.add(name)
 
index 001c0f0a600dbb634eeee5799dd6962fe0ce1a5c..cb170876d70435c1a3165a816bd74624f04fa1b8 100644 (file)
@@ -19,7 +19,7 @@ header = """\
 
 from openpower.decoder.helpers import (ISACallerHelper,
                                  ne, eq, gt, ge, lt, le, ltu, gtu, length,
-                                 trunc_divs, trunc_rems,
+                                 trunc_divs, trunc_rems, copy_assign_rhs,
                                 )
 from openpower.decoder.selectable_int import SelectableInt
 from openpower.decoder.selectable_int import selectconcat as concat
index b01fc4cc0a0008f492b35bd1e397f2a1862271b7..353c2aa156b740b067ebfcd6cd40838dac1ddb87 100644 (file)
@@ -22,7 +22,7 @@ header = """\
 from openpower.decoder.isa.caller import inject, instruction_info
 from openpower.decoder.helpers import (
                                  ne, eq, gt, ge, lt, le, ltu, gtu, length,
-                                 RANGE,
+                                 RANGE, copy_assign_rhs,
                                  ISACallerHelper,
                                 )
 from openpower.decoder.selectable_int import SelectableInt