From 4e701a851536bba6648779c183293ba75e7ea7b8 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 24 Apr 2023 23:15:11 -0700 Subject: [PATCH] fix bug where pseudo-code assignments modify more than just the variable being assigned to --- src/openpower/decoder/helpers.py | 25 ++++++++++++++++++++++ src/openpower/decoder/pseudo/parser.py | 7 +++++- src/openpower/decoder/pseudo/pyfnwriter.py | 2 +- src/openpower/decoder/pseudo/pywriter.py | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index 3f8845bf..17ddbe0b 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -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): diff --git a/src/openpower/decoder/pseudo/parser.py b/src/openpower/decoder/pseudo/parser.py index 42df81be..94864896 100644 --- a/src/openpower/decoder/pseudo/parser.py +++ b/src/openpower/decoder/pseudo/parser.py @@ -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) diff --git a/src/openpower/decoder/pseudo/pyfnwriter.py b/src/openpower/decoder/pseudo/pyfnwriter.py index 001c0f0a..cb170876 100644 --- a/src/openpower/decoder/pseudo/pyfnwriter.py +++ b/src/openpower/decoder/pseudo/pyfnwriter.py @@ -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 diff --git a/src/openpower/decoder/pseudo/pywriter.py b/src/openpower/decoder/pseudo/pywriter.py index b01fc4cc..353c2aa1 100644 --- a/src/openpower/decoder/pseudo/pywriter.py +++ b/src/openpower/decoder/pseudo/pywriter.py @@ -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 -- 2.30.2