aports/testing/py3-migen/0001-fix-get_var_name.patch
Marian Buschsieweke 8c554f697b testing/py3-migen: fix get_var_name() in tracer.py
This fixes unit test failures in py3-litedram, which builds upon
py3-migen.

See https://github.com/m-labs/migen/pull/283 for an effort to upstream
the patch and the log of the error this fixes.
2024-01-18 23:34:53 +00:00

113 lines
4.2 KiB
Diff

Take get_var_name() from amaranth with minor impedance matching. This
fixes:
test/test_phy_utils.py:54: in serializer_test
dut = Serializer(clk=clk, clkdiv=clkdiv, i_dw=data_width, o_dw=1)
litedram/phy/utils.py:240: in __init__
if i is None: i = Signal(i_dw)
/usr/lib/python3.11/site-packages/migen/fhdl/structure.py:395: in __init__
self.backtrace = _tracer.trace_back(name)
/usr/lib/python3.11/site-packages/migen/fhdl/tracer.py:111: in trace_back
varname = get_var_name(frame)
See https://github.com/amaranth-lang/amaranth/blob/main/amaranth/tracer.py for
original source.
See https://github.com/m-labs/migen/pull/283 for an effort to upstream the fix.
--- a/migen/fhdl/tracer.py 2024-01-11 10:35:38.211748883 +0100
+++ b/migen/fhdl/tracer.py 2024-01-11 10:36:04.864735268 +0100
@@ -1,56 +1,55 @@
import inspect
+import sys
from sys import version_info
from opcode import opname
from collections import defaultdict
-# All opcodes are 2 bytes in length in Python 3.6
-def _bytecode_length_version_guard(old_len):
- return old_len if version_info[1] < 6 else 2
-
-_call_opcodes = {
- "CALL_FUNCTION" : _bytecode_length_version_guard(3),
- "CALL_FUNCTION_KW" : _bytecode_length_version_guard(3),
-}
-
-if version_info[1] < 6:
- _call_opcodes["CALL_FUNCTION_VAR"] = 3
- _call_opcodes["CALL_FUNCTION_VAR_KW"] = 3
-elif version_info[1] < 7:
- _call_opcodes["CALL_FUNCTION_EX"] = 2
-else:
- _call_opcodes["CALL_FUNCTION_EX"] = 2
- _call_opcodes["CALL_METHOD"] = 2
-
-_load_build_opcodes = {
- "LOAD_GLOBAL" : _bytecode_length_version_guard(3),
- "LOAD_ATTR" : _bytecode_length_version_guard(3),
- "LOAD_FAST" : _bytecode_length_version_guard(3),
- "LOAD_DEREF" : _bytecode_length_version_guard(3),
- "DUP_TOP" : _bytecode_length_version_guard(1),
- "BUILD_LIST" : _bytecode_length_version_guard(3),
-}
-
def get_var_name(frame):
code = frame.f_code
call_index = frame.f_lasti
- call_opc = opname[code.co_code[call_index]]
- if call_opc not in _call_opcodes:
+ while call_index > 0 and opname[code.co_code[call_index]] == "CACHE":
+ call_index -= 2
+ while True:
+ call_opc = opname[code.co_code[call_index]]
+ if call_opc in ("EXTENDED_ARG",):
+ call_index += 2
+ else:
+ break
+ if call_opc not in ("CALL_FUNCTION", "CALL_FUNCTION_KW", "CALL_FUNCTION_EX",
+ "CALL_METHOD", "CALL", "CALL_KW"):
return None
- index = call_index+_call_opcodes[call_opc]
+
+ index = call_index + 2
+ imm = 0
while True:
opc = opname[code.co_code[index]]
- if opc == "STORE_NAME" or opc == "STORE_ATTR":
- name_index = int(code.co_code[index+1])
- return code.co_names[name_index]
+ if opc == 'EXTENDED_ARG':
+ imm |= int(code.co_code[index + 1])
+ imm <<= 8
+ index += 2
+ elif opc in ("STORE_NAME", "STORE_ATTR"):
+ imm |= int(code.co_code[index + 1])
+ return code.co_names[imm]
elif opc == "STORE_FAST":
- name_index = int(code.co_code[index+1])
- return code.co_varnames[name_index]
+ imm |= int(code.co_code[index + 1])
+ if sys.version_info >= (3, 11):
+ return code._varname_from_oparg(imm)
+ else:
+ return code.co_varnames[imm]
elif opc == "STORE_DEREF":
- name_index = int(code.co_code[index+1])
- return code.co_cellvars[name_index]
- elif opc in _load_build_opcodes:
- index += _load_build_opcodes[opc]
+ imm |= int(code.co_code[index + 1])
+ if sys.version_info >= (3, 11):
+ return code._varname_from_oparg(imm)
+ else:
+ if imm < len(code.co_cellvars):
+ return code.co_cellvars[imm]
+ else:
+ return code.co_freevars[imm - len(code.co_cellvars)]
+ elif opc in ("LOAD_GLOBAL", "LOAD_NAME", "LOAD_ATTR", "LOAD_FAST", "LOAD_DEREF",
+ "DUP_TOP", "BUILD_LIST", "CACHE", "COPY"):
+ imm = 0
+ index += 2
else:
return None