From 3b166ca2d7bd7083ca8b9f50100fe02970e50042 Mon Sep 17 00:00:00 2001 From: Marcel Keller Date: Wed, 6 Nov 2024 10:45:26 +1100 Subject: [PATCH] Fix bug when indices are computed using subtraction in loops. --- Compiler/allocator.py | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/Compiler/allocator.py b/Compiler/allocator.py index 557b5a945..2b2c0ea1d 100644 --- a/Compiler/allocator.py +++ b/Compiler/allocator.py @@ -781,10 +781,10 @@ def __init__(self): self.rev_offset_cache = {} self.range_cache = util.dict_by_id() - def add_offset(self, res, new_base, new_offset): - self.offset_cache[res] = new_base, new_offset - if (new_base.i, new_offset) not in self.rev_offset_cache: - self.rev_offset_cache[new_base.i, new_offset] = res + def add_offset(self, res, new_base, new_offset, multiplier): + self.offset_cache[res] = new_base, new_offset, multiplier + if (new_base.i, new_offset, multiplier) not in self.rev_offset_cache: + self.rev_offset_cache[new_base.i, new_offset, multiplier] = res def run(self, instructions, program): for i, inst in enumerate(instructions): @@ -808,31 +808,40 @@ def run(self, instructions, program): def f(base, delta_reg): delta = self.cache[delta_reg] if base in self.offset_cache: - reg, offset = self.offset_cache[base] + reg, offset, mult = self.offset_cache[base] new_base, new_offset = reg, offset + delta else: new_base, new_offset = base, delta - self.add_offset(inst.args[0], new_base, new_offset) + mult = 1 + self.add_offset(inst.args[0], new_base, new_offset, + mult) if inst.args[1] in self.cache: f(inst.args[2], inst.args[1]) elif inst.args[2] in self.cache: f(inst.args[1], inst.args[2]) - elif isinstance(inst, subint_class) and \ - inst.args[2] in self.cache: - delta = self.cache[inst.args[2]] - if inst.args[1] in self.offset_cache: - reg, offset = self.offset_cache[inst.args[1]] - new_base, new_offset = reg, offset - delta - else: - new_base, new_offset = inst.args[1], -delta - self.add_offset(inst.args[0], new_base, new_offset) + elif isinstance(inst, subint_class): + def f(reg, cached, reverse): + delta = self.cache[cached] + if reg in self.offset_cache: + reg, offset, mult = self.offset_cache[reg] + new_base, new_offset = reg, offset - delta + else: + new_base = reg + new_offset = -delta if reverse else delta + mult = 1 + self.add_offset(inst.args[0], new_base, new_offset, + mult if reverse else -mult) + if inst.args[1] in self.cache: + f(inst.args[2], inst.args[1], False) + elif inst.args[2] in self.cache: + f(inst.args[1], inst.args[2], True) elif isinstance(inst, IndirectMemoryInstruction): if inst.args[1] in self.cache: instructions[i] = inst.get_direct(self.cache[inst.args[1]]) instructions[i]._protect = inst._protect elif inst.args[1] in self.offset_cache: - base, offset = self.offset_cache[inst.args[1]] - addr = self.rev_offset_cache[base.i, offset] + base, offset, mult = self.offset_cache[inst.args[1]] + addr = self.rev_offset_cache[base.i, offset, mult] inst.args[1] = addr elif inst.args[1] in self.range_cache: size, base = self.range_cache[inst.args[1]]