mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
GH-131498: Cases generator: Allow input and 'peek' variables to be modified (GH-132506)
This commit is contained in:
parent
be763e550e
commit
844596c09f
9 changed files with 90 additions and 116 deletions
2
Include/internal/pycore_uop_metadata.h
generated
2
Include/internal/pycore_uop_metadata.h
generated
|
@ -1081,7 +1081,7 @@ int _PyUop_num_popped(int opcode, int oparg)
|
||||||
case _CALL_KW_NON_PY:
|
case _CALL_KW_NON_PY:
|
||||||
return 3 + oparg;
|
return 3 + oparg;
|
||||||
case _MAKE_CALLARGS_A_TUPLE:
|
case _MAKE_CALLARGS_A_TUPLE:
|
||||||
return 2;
|
return 0;
|
||||||
case _MAKE_FUNCTION:
|
case _MAKE_FUNCTION:
|
||||||
return 1;
|
return 1;
|
||||||
case _SET_FUNCTION_ATTRIBUTE:
|
case _SET_FUNCTION_ATTRIBUTE:
|
||||||
|
|
|
@ -1862,13 +1862,28 @@ class TestGeneratedCases(unittest.TestCase):
|
||||||
|
|
||||||
def test_reassigning_live_inputs(self):
|
def test_reassigning_live_inputs(self):
|
||||||
input = """
|
input = """
|
||||||
inst(OP, (in -- )) {
|
inst(OP, (in -- in)) {
|
||||||
in = 0;
|
in = 0;
|
||||||
DEAD(in);
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
with self.assertRaises(SyntaxError):
|
|
||||||
self.run_cases_test(input, "")
|
output = """
|
||||||
|
TARGET(OP) {
|
||||||
|
#if Py_TAIL_CALL_INTERP
|
||||||
|
int opcode = OP;
|
||||||
|
(void)(opcode);
|
||||||
|
#endif
|
||||||
|
frame->instr_ptr = next_instr;
|
||||||
|
next_instr += 1;
|
||||||
|
INSTRUCTION_STATS(OP);
|
||||||
|
_PyStackRef in;
|
||||||
|
in = stack_pointer[-1];
|
||||||
|
in = 0;
|
||||||
|
stack_pointer[-1] = in;
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.run_cases_test(input, output)
|
||||||
|
|
||||||
def test_reassigning_dead_inputs(self):
|
def test_reassigning_dead_inputs(self):
|
||||||
input = """
|
input = """
|
||||||
|
|
|
@ -4725,15 +4725,9 @@ dummy_func(
|
||||||
_CALL_KW_NON_PY +
|
_CALL_KW_NON_PY +
|
||||||
_CHECK_PERIODIC;
|
_CHECK_PERIODIC;
|
||||||
|
|
||||||
op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) {
|
op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs -- func, unused, callargs, kwargs)) {
|
||||||
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
||||||
if (PyTuple_CheckExact(callargs_o)) {
|
if (!PyTuple_CheckExact(callargs_o)) {
|
||||||
tuple = callargs;
|
|
||||||
kwargs_out = kwargs_in;
|
|
||||||
DEAD(kwargs_in);
|
|
||||||
DEAD(callargs);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
ERROR_NO_POP();
|
ERROR_NO_POP();
|
||||||
|
@ -4742,10 +4736,9 @@ dummy_func(
|
||||||
if (tuple_o == NULL) {
|
if (tuple_o == NULL) {
|
||||||
ERROR_NO_POP();
|
ERROR_NO_POP();
|
||||||
}
|
}
|
||||||
kwargs_out = kwargs_in;
|
_PyStackRef temp = callargs;
|
||||||
DEAD(kwargs_in);
|
callargs = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||||
PyStackRef_CLOSE(callargs);
|
PyStackRef_CLOSE(temp);
|
||||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4965,11 +4958,11 @@ dummy_func(
|
||||||
|
|
||||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP;
|
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP;
|
||||||
|
|
||||||
pure inst(SWAP, (bottom[1], unused[oparg-2], top[1] --
|
pure inst(SWAP, (bottom, unused[oparg-2], top --
|
||||||
bottom[1], unused[oparg-2], top[1])) {
|
bottom, unused[oparg-2], top)) {
|
||||||
_PyStackRef temp = bottom[0];
|
_PyStackRef temp = bottom;
|
||||||
bottom[0] = top[0];
|
bottom = top;
|
||||||
top[0] = temp;
|
top = temp;
|
||||||
assert(oparg >= 2);
|
assert(oparg >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
Python/executor_cases.c.h
generated
39
Python/executor_cases.c.h
generated
|
@ -6350,20 +6350,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _MAKE_CALLARGS_A_TUPLE: {
|
case _MAKE_CALLARGS_A_TUPLE: {
|
||||||
_PyStackRef kwargs_in;
|
|
||||||
_PyStackRef callargs;
|
_PyStackRef callargs;
|
||||||
_PyStackRef func;
|
_PyStackRef func;
|
||||||
_PyStackRef tuple;
|
|
||||||
_PyStackRef kwargs_out;
|
|
||||||
kwargs_in = stack_pointer[-1];
|
|
||||||
callargs = stack_pointer[-2];
|
callargs = stack_pointer[-2];
|
||||||
func = stack_pointer[-4];
|
func = stack_pointer[-4];
|
||||||
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
||||||
if (PyTuple_CheckExact(callargs_o)) {
|
if (!PyTuple_CheckExact(callargs_o)) {
|
||||||
tuple = callargs;
|
|
||||||
kwargs_out = kwargs_in;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -6376,17 +6368,14 @@
|
||||||
if (tuple_o == NULL) {
|
if (tuple_o == NULL) {
|
||||||
JUMP_TO_ERROR();
|
JUMP_TO_ERROR();
|
||||||
}
|
}
|
||||||
kwargs_out = kwargs_in;
|
_PyStackRef temp = callargs;
|
||||||
stack_pointer += -2;
|
callargs = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
stack_pointer[-2] = callargs;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(callargs);
|
PyStackRef_CLOSE(temp);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
|
||||||
stack_pointer += 2;
|
|
||||||
}
|
}
|
||||||
stack_pointer[-2] = tuple;
|
stack_pointer[-2] = callargs;
|
||||||
stack_pointer[-1] = kwargs_out;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6631,15 +6620,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _SWAP: {
|
case _SWAP: {
|
||||||
_PyStackRef *top;
|
_PyStackRef top;
|
||||||
_PyStackRef *bottom;
|
_PyStackRef bottom;
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
top = &stack_pointer[-1];
|
top = stack_pointer[-1];
|
||||||
bottom = &stack_pointer[-2 - (oparg-2)];
|
bottom = stack_pointer[-2 - (oparg-2)];
|
||||||
_PyStackRef temp = bottom[0];
|
_PyStackRef temp = bottom;
|
||||||
bottom[0] = top[0];
|
bottom = top;
|
||||||
top[0] = temp;
|
top = temp;
|
||||||
assert(oparg >= 2);
|
assert(oparg >= 2);
|
||||||
|
stack_pointer[-2 - (oparg-2)] = bottom;
|
||||||
|
stack_pointer[-1] = top;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
68
Python/generated_cases.c.h
generated
68
Python/generated_cases.c.h
generated
|
@ -2330,9 +2330,6 @@
|
||||||
opcode = CALL_FUNCTION_EX;
|
opcode = CALL_FUNCTION_EX;
|
||||||
_PyStackRef func;
|
_PyStackRef func;
|
||||||
_PyStackRef callargs;
|
_PyStackRef callargs;
|
||||||
_PyStackRef kwargs_in;
|
|
||||||
_PyStackRef tuple;
|
|
||||||
_PyStackRef kwargs_out;
|
|
||||||
_PyStackRef func_st;
|
_PyStackRef func_st;
|
||||||
_PyStackRef null;
|
_PyStackRef null;
|
||||||
_PyStackRef callargs_st;
|
_PyStackRef callargs_st;
|
||||||
|
@ -2340,15 +2337,10 @@
|
||||||
_PyStackRef result;
|
_PyStackRef result;
|
||||||
// _MAKE_CALLARGS_A_TUPLE
|
// _MAKE_CALLARGS_A_TUPLE
|
||||||
{
|
{
|
||||||
kwargs_in = stack_pointer[-1];
|
|
||||||
callargs = stack_pointer[-2];
|
callargs = stack_pointer[-2];
|
||||||
func = stack_pointer[-4];
|
func = stack_pointer[-4];
|
||||||
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
||||||
if (PyTuple_CheckExact(callargs_o)) {
|
if (!PyTuple_CheckExact(callargs_o)) {
|
||||||
tuple = callargs;
|
|
||||||
kwargs_out = kwargs_in;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -2361,20 +2353,18 @@
|
||||||
if (tuple_o == NULL) {
|
if (tuple_o == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
kwargs_out = kwargs_in;
|
_PyStackRef temp = callargs;
|
||||||
stack_pointer += -2;
|
callargs = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
stack_pointer[-2] = callargs;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(callargs);
|
PyStackRef_CLOSE(temp);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
|
||||||
stack_pointer += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// _DO_CALL_FUNCTION_EX
|
// _DO_CALL_FUNCTION_EX
|
||||||
{
|
{
|
||||||
kwargs_st = kwargs_out;
|
kwargs_st = stack_pointer[-1];
|
||||||
callargs_st = tuple;
|
callargs_st = callargs;
|
||||||
null = stack_pointer[-3];
|
null = stack_pointer[-3];
|
||||||
func_st = func;
|
func_st = func;
|
||||||
(void)null;
|
(void)null;
|
||||||
|
@ -2390,7 +2380,6 @@
|
||||||
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
|
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
|
||||||
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
|
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
|
||||||
stack_pointer[-2] = callargs_st;
|
stack_pointer[-2] = callargs_st;
|
||||||
stack_pointer[-1] = kwargs_st;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = _Py_call_instrumentation_2args(
|
int err = _Py_call_instrumentation_2args(
|
||||||
tstate, PY_MONITORING_EVENT_CALL,
|
tstate, PY_MONITORING_EVENT_CALL,
|
||||||
|
@ -2456,7 +2445,6 @@
|
||||||
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
|
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
|
||||||
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
|
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
|
||||||
stack_pointer[-2] = callargs_st;
|
stack_pointer[-2] = callargs_st;
|
||||||
stack_pointer[-1] = kwargs_st;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
result_o = PyObject_Call(func, callargs, kwargs);
|
result_o = PyObject_Call(func, callargs, kwargs);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -6289,9 +6277,6 @@
|
||||||
opcode = INSTRUMENTED_CALL_FUNCTION_EX;
|
opcode = INSTRUMENTED_CALL_FUNCTION_EX;
|
||||||
_PyStackRef func;
|
_PyStackRef func;
|
||||||
_PyStackRef callargs;
|
_PyStackRef callargs;
|
||||||
_PyStackRef kwargs_in;
|
|
||||||
_PyStackRef tuple;
|
|
||||||
_PyStackRef kwargs_out;
|
|
||||||
_PyStackRef func_st;
|
_PyStackRef func_st;
|
||||||
_PyStackRef null;
|
_PyStackRef null;
|
||||||
_PyStackRef callargs_st;
|
_PyStackRef callargs_st;
|
||||||
|
@ -6299,15 +6284,10 @@
|
||||||
_PyStackRef result;
|
_PyStackRef result;
|
||||||
// _MAKE_CALLARGS_A_TUPLE
|
// _MAKE_CALLARGS_A_TUPLE
|
||||||
{
|
{
|
||||||
kwargs_in = stack_pointer[-1];
|
|
||||||
callargs = stack_pointer[-2];
|
callargs = stack_pointer[-2];
|
||||||
func = stack_pointer[-4];
|
func = stack_pointer[-4];
|
||||||
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
|
||||||
if (PyTuple_CheckExact(callargs_o)) {
|
if (!PyTuple_CheckExact(callargs_o)) {
|
||||||
tuple = callargs;
|
|
||||||
kwargs_out = kwargs_in;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -6320,20 +6300,18 @@
|
||||||
if (tuple_o == NULL) {
|
if (tuple_o == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
kwargs_out = kwargs_in;
|
_PyStackRef temp = callargs;
|
||||||
stack_pointer += -2;
|
callargs = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
stack_pointer[-2] = callargs;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(callargs);
|
PyStackRef_CLOSE(temp);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
|
||||||
stack_pointer += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// _DO_CALL_FUNCTION_EX
|
// _DO_CALL_FUNCTION_EX
|
||||||
{
|
{
|
||||||
kwargs_st = kwargs_out;
|
kwargs_st = stack_pointer[-1];
|
||||||
callargs_st = tuple;
|
callargs_st = callargs;
|
||||||
null = stack_pointer[-3];
|
null = stack_pointer[-3];
|
||||||
func_st = func;
|
func_st = func;
|
||||||
(void)null;
|
(void)null;
|
||||||
|
@ -6349,7 +6327,6 @@
|
||||||
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
|
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
|
||||||
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
|
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
|
||||||
stack_pointer[-2] = callargs_st;
|
stack_pointer[-2] = callargs_st;
|
||||||
stack_pointer[-1] = kwargs_st;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = _Py_call_instrumentation_2args(
|
int err = _Py_call_instrumentation_2args(
|
||||||
tstate, PY_MONITORING_EVENT_CALL,
|
tstate, PY_MONITORING_EVENT_CALL,
|
||||||
|
@ -6415,7 +6392,6 @@
|
||||||
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
|
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
|
||||||
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
|
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
|
||||||
stack_pointer[-2] = callargs_st;
|
stack_pointer[-2] = callargs_st;
|
||||||
stack_pointer[-1] = kwargs_st;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
result_o = PyObject_Call(func, callargs, kwargs);
|
result_o = PyObject_Call(func, callargs, kwargs);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -11358,14 +11334,16 @@
|
||||||
frame->instr_ptr = next_instr;
|
frame->instr_ptr = next_instr;
|
||||||
next_instr += 1;
|
next_instr += 1;
|
||||||
INSTRUCTION_STATS(SWAP);
|
INSTRUCTION_STATS(SWAP);
|
||||||
_PyStackRef *bottom;
|
_PyStackRef bottom;
|
||||||
_PyStackRef *top;
|
_PyStackRef top;
|
||||||
top = &stack_pointer[-1];
|
top = stack_pointer[-1];
|
||||||
bottom = &stack_pointer[-2 - (oparg-2)];
|
bottom = stack_pointer[-2 - (oparg-2)];
|
||||||
_PyStackRef temp = bottom[0];
|
_PyStackRef temp = bottom;
|
||||||
bottom[0] = top[0];
|
bottom = top;
|
||||||
top[0] = temp;
|
top = temp;
|
||||||
assert(oparg >= 2);
|
assert(oparg >= 2);
|
||||||
|
stack_pointer[-2 - (oparg-2)] = bottom;
|
||||||
|
stack_pointer[-1] = top;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
Python/optimizer_cases.c.h
generated
6
Python/optimizer_cases.c.h
generated
|
@ -2047,12 +2047,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _MAKE_CALLARGS_A_TUPLE: {
|
case _MAKE_CALLARGS_A_TUPLE: {
|
||||||
JitOptSymbol *tuple;
|
|
||||||
JitOptSymbol *kwargs_out;
|
|
||||||
tuple = sym_new_not_null(ctx);
|
|
||||||
kwargs_out = sym_new_not_null(ctx);
|
|
||||||
stack_pointer[-2] = tuple;
|
|
||||||
stack_pointer[-1] = kwargs_out;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -500,9 +500,6 @@ class Emitter:
|
||||||
if tkn in local_stores:
|
if tkn in local_stores:
|
||||||
for var in storage.inputs:
|
for var in storage.inputs:
|
||||||
if var.name == tkn.text:
|
if var.name == tkn.text:
|
||||||
if var.in_local or var.in_memory():
|
|
||||||
msg = f"Cannot assign to already defined input variable '{tkn.text}'"
|
|
||||||
raise analysis_error(msg, tkn)
|
|
||||||
var.in_local = True
|
var.in_local = True
|
||||||
var.memory_offset = None
|
var.memory_offset = None
|
||||||
break
|
break
|
||||||
|
|
|
@ -283,7 +283,7 @@ class Stack:
|
||||||
self.base_offset = self.logical_sp
|
self.base_offset = self.logical_sp
|
||||||
|
|
||||||
def push(self, var: Local) -> None:
|
def push(self, var: Local) -> None:
|
||||||
assert(var not in self.variables)
|
assert(var not in self.variables), var
|
||||||
self.variables.append(var)
|
self.variables.append(var)
|
||||||
self.logical_sp = self.logical_sp.push(var.item)
|
self.logical_sp = self.logical_sp.push(var.item)
|
||||||
|
|
||||||
|
@ -325,6 +325,7 @@ class Stack:
|
||||||
var_offset = var_offset.push(var.item)
|
var_offset = var_offset.push(var.item)
|
||||||
|
|
||||||
def flush(self, out: CWriter) -> None:
|
def flush(self, out: CWriter) -> None:
|
||||||
|
self._print(out)
|
||||||
self.save_variables(out)
|
self.save_variables(out)
|
||||||
self._save_physical_sp(out)
|
self._save_physical_sp(out)
|
||||||
out.start_line()
|
out.start_line()
|
||||||
|
@ -432,12 +433,14 @@ class Storage:
|
||||||
stack: Stack
|
stack: Stack
|
||||||
inputs: list[Local]
|
inputs: list[Local]
|
||||||
outputs: list[Local]
|
outputs: list[Local]
|
||||||
|
peeks: int
|
||||||
check_liveness: bool
|
check_liveness: bool
|
||||||
spilled: int = 0
|
spilled: int = 0
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def needs_defining(var: Local) -> bool:
|
def needs_defining(var: Local) -> bool:
|
||||||
return (
|
return (
|
||||||
|
not var.item.peek and
|
||||||
not var.in_local and
|
not var.in_local and
|
||||||
not var.is_array() and
|
not var.is_array() and
|
||||||
var.name != "unused"
|
var.name != "unused"
|
||||||
|
@ -454,7 +457,7 @@ class Storage:
|
||||||
)
|
)
|
||||||
|
|
||||||
def clear_inputs(self, reason:str) -> None:
|
def clear_inputs(self, reason:str) -> None:
|
||||||
while self.inputs:
|
while len(self.inputs) > self.peeks:
|
||||||
tos = self.inputs.pop()
|
tos = self.inputs.pop()
|
||||||
if self.is_live(tos) and self.check_liveness:
|
if self.is_live(tos) and self.check_liveness:
|
||||||
raise StackError(
|
raise StackError(
|
||||||
|
@ -464,14 +467,14 @@ class Storage:
|
||||||
|
|
||||||
def clear_dead_inputs(self) -> None:
|
def clear_dead_inputs(self) -> None:
|
||||||
live = ""
|
live = ""
|
||||||
while self.inputs:
|
while len(self.inputs) > self.peeks:
|
||||||
tos = self.inputs[-1]
|
tos = self.inputs[-1]
|
||||||
if self.is_live(tos):
|
if self.is_live(tos):
|
||||||
live = tos.name
|
live = tos.name
|
||||||
break
|
break
|
||||||
self.inputs.pop()
|
self.inputs.pop()
|
||||||
self.stack.drop(tos.item, self.check_liveness)
|
self.stack.drop(tos.item, self.check_liveness)
|
||||||
for var in self.inputs:
|
for var in self.inputs[self.peeks:]:
|
||||||
if not self.is_live(var):
|
if not self.is_live(var):
|
||||||
raise StackError(
|
raise StackError(
|
||||||
f"Input '{var.name}' is not live, but '{live}' is"
|
f"Input '{var.name}' is not live, but '{live}' is"
|
||||||
|
@ -493,8 +496,8 @@ class Storage:
|
||||||
f"Expected '{undefined}' to be defined before '{out.name}'"
|
f"Expected '{undefined}' to be defined before '{out.name}'"
|
||||||
else:
|
else:
|
||||||
undefined = out.name
|
undefined = out.name
|
||||||
while self.outputs and not self.needs_defining(self.outputs[0]):
|
while len(self.outputs) > self.peeks and not self.needs_defining(self.outputs[0]):
|
||||||
out = self.outputs.pop(0)
|
out = self.outputs.pop(self.peeks)
|
||||||
self.stack.push(out)
|
self.stack.push(out)
|
||||||
|
|
||||||
def locals_cached(self) -> bool:
|
def locals_cached(self) -> bool:
|
||||||
|
@ -541,12 +544,9 @@ class Storage:
|
||||||
local = stack.pop(input, out)
|
local = stack.pop(input, out)
|
||||||
if input.peek:
|
if input.peek:
|
||||||
peeks.append(local)
|
peeks.append(local)
|
||||||
else:
|
|
||||||
inputs.append(local)
|
inputs.append(local)
|
||||||
inputs.reverse()
|
inputs.reverse()
|
||||||
peeks.reverse()
|
peeks.reverse()
|
||||||
for peek in peeks:
|
|
||||||
stack.push(peek)
|
|
||||||
offset = stack.logical_sp - stack.physical_sp
|
offset = stack.logical_sp - stack.physical_sp
|
||||||
for ouput in uop.stack.outputs:
|
for ouput in uop.stack.outputs:
|
||||||
if ouput.is_array() and ouput.used and not ouput.peek:
|
if ouput.is_array() and ouput.used and not ouput.peek:
|
||||||
|
@ -555,8 +555,8 @@ class Storage:
|
||||||
offset = offset.push(ouput)
|
offset = offset.push(ouput)
|
||||||
for var in inputs:
|
for var in inputs:
|
||||||
stack.push(var)
|
stack.push(var)
|
||||||
outputs = [ Local.undefined(var) for var in uop.stack.outputs if not var.peek ]
|
outputs = peeks + [ Local.undefined(var) for var in uop.stack.outputs if not var.peek ]
|
||||||
return Storage(stack, inputs, outputs, check_liveness)
|
return Storage(stack, inputs, outputs, len(peeks), check_liveness)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def copy_list(arg: list[Local]) -> list[Local]:
|
def copy_list(arg: list[Local]) -> list[Local]:
|
||||||
|
@ -568,7 +568,7 @@ class Storage:
|
||||||
inputs = [ variables[var.name] for var in self.inputs]
|
inputs = [ variables[var.name] for var in self.inputs]
|
||||||
assert [v.name for v in inputs] == [v.name for v in self.inputs], (inputs, self.inputs)
|
assert [v.name for v in inputs] == [v.name for v in self.inputs], (inputs, self.inputs)
|
||||||
return Storage(
|
return Storage(
|
||||||
new_stack, inputs, self.copy_list(self.outputs),
|
new_stack, inputs, self.copy_list(self.outputs), self.peeks,
|
||||||
self.check_liveness, self.spilled
|
self.check_liveness, self.spilled
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -602,6 +602,8 @@ class Storage:
|
||||||
other.clear_dead_inputs()
|
other.clear_dead_inputs()
|
||||||
if len(self.inputs) != len(other.inputs) and self.check_liveness:
|
if len(self.inputs) != len(other.inputs) and self.check_liveness:
|
||||||
diff = self.inputs[-1] if len(self.inputs) > len(other.inputs) else other.inputs[-1]
|
diff = self.inputs[-1] if len(self.inputs) > len(other.inputs) else other.inputs[-1]
|
||||||
|
self._print(out)
|
||||||
|
other._print(out)
|
||||||
raise StackError(f"Unmergeable inputs. Differing state of '{diff.name}'")
|
raise StackError(f"Unmergeable inputs. Differing state of '{diff.name}'")
|
||||||
for var, other_var in zip(self.inputs, other.inputs):
|
for var, other_var in zip(self.inputs, other.inputs):
|
||||||
if var.in_local != other_var.in_local:
|
if var.in_local != other_var.in_local:
|
||||||
|
@ -624,11 +626,11 @@ class Storage:
|
||||||
if self.spilled:
|
if self.spilled:
|
||||||
raise StackError(f"Unbalanced stack spills")
|
raise StackError(f"Unbalanced stack spills")
|
||||||
self.clear_inputs("at the end of the micro-op")
|
self.clear_inputs("at the end of the micro-op")
|
||||||
if self.inputs and self.check_liveness:
|
if len(self.inputs) > self.peeks and self.check_liveness:
|
||||||
raise StackError(f"Input variable '{self.inputs[-1].name}' is still live")
|
raise StackError(f"Input variable '{self.inputs[-1].name}' is still live")
|
||||||
self._push_defined_outputs()
|
self._push_defined_outputs()
|
||||||
if self.outputs:
|
if self.outputs:
|
||||||
for out in self.outputs:
|
for out in self.outputs[self.peeks:]:
|
||||||
if self.needs_defining(out):
|
if self.needs_defining(out):
|
||||||
raise StackError(f"Output variable '{self.outputs[0].name}' is not defined")
|
raise StackError(f"Output variable '{self.outputs[0].name}' is not defined")
|
||||||
self.stack.push(out)
|
self.stack.push(out)
|
||||||
|
@ -641,6 +643,10 @@ class Storage:
|
||||||
outputs = ", ".join([var.compact_str() for var in self.outputs])
|
outputs = ", ".join([var.compact_str() for var in self.outputs])
|
||||||
return f"{stack_comment[:-2]}{next_line}inputs: {inputs} outputs: {outputs}*/"
|
return f"{stack_comment[:-2]}{next_line}inputs: {inputs} outputs: {outputs}*/"
|
||||||
|
|
||||||
|
def _print(self, out: CWriter) -> None:
|
||||||
|
if PRINT_STACKS:
|
||||||
|
out.emit(self.as_comment() + "\n")
|
||||||
|
|
||||||
def close_inputs(self, out: CWriter) -> None:
|
def close_inputs(self, out: CWriter) -> None:
|
||||||
|
|
||||||
tmp_defined = False
|
tmp_defined = False
|
||||||
|
|
|
@ -204,7 +204,7 @@ def generate_tier1_labels(
|
||||||
# Emit tail-callable labels as function defintions
|
# Emit tail-callable labels as function defintions
|
||||||
for name, label in analysis.labels.items():
|
for name, label in analysis.labels.items():
|
||||||
emitter.emit(f"LABEL({name})\n")
|
emitter.emit(f"LABEL({name})\n")
|
||||||
storage = Storage(Stack(), [], [], False)
|
storage = Storage(Stack(), [], [], 0, False)
|
||||||
if label.spilled:
|
if label.spilled:
|
||||||
storage.spilled = 1
|
storage.spilled = 1
|
||||||
emitter.emit_tokens(label, storage, None)
|
emitter.emit_tokens(label, storage, None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue