mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
GH-131498: Cases generator: manage stacks automatically (GH-132074)
This commit is contained in:
parent
305be5fb1a
commit
7099c75550
15 changed files with 216 additions and 251 deletions
12
Include/internal/pycore_opcode_metadata.h
generated
12
Include/internal/pycore_opcode_metadata.h
generated
|
@ -234,7 +234,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||
case INSTRUMENTED_END_SEND:
|
||||
return 2;
|
||||
case INSTRUMENTED_FOR_ITER:
|
||||
return 0;
|
||||
return 1;
|
||||
case INSTRUMENTED_INSTRUCTION:
|
||||
return 0;
|
||||
case INSTRUMENTED_JUMP_BACKWARD:
|
||||
|
@ -250,13 +250,13 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||
case INSTRUMENTED_POP_ITER:
|
||||
return 1;
|
||||
case INSTRUMENTED_POP_JUMP_IF_FALSE:
|
||||
return 0;
|
||||
return 1;
|
||||
case INSTRUMENTED_POP_JUMP_IF_NONE:
|
||||
return 0;
|
||||
return 1;
|
||||
case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:
|
||||
return 0;
|
||||
return 1;
|
||||
case INSTRUMENTED_POP_JUMP_IF_TRUE:
|
||||
return 0;
|
||||
return 1;
|
||||
case INSTRUMENTED_RESUME:
|
||||
return 0;
|
||||
case INSTRUMENTED_RETURN_VALUE:
|
||||
|
@ -713,7 +713,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
|
|||
case INSTRUMENTED_END_SEND:
|
||||
return 1;
|
||||
case INSTRUMENTED_FOR_ITER:
|
||||
return 0;
|
||||
return 2;
|
||||
case INSTRUMENTED_INSTRUCTION:
|
||||
return 0;
|
||||
case INSTRUMENTED_JUMP_BACKWARD:
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Define this to get precise tracking of closed stackrefs.
|
||||
// This will use unbounded memory, as it can only grow.
|
||||
// Use this to track double closes in short-lived programs
|
||||
// #define Py_STACKREF_CLOSE_DEBUG 1
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,12 @@ typedef struct {
|
|||
// Define this to get precise tracking of stackrefs.
|
||||
// #define Py_STACKREF_DEBUG 1
|
||||
|
||||
// Define this to get precise tracking of closed stackrefs.
|
||||
// This will use unbounded memory, as it can only grow.
|
||||
// Use this to track double closes in short-lived programs
|
||||
// #define Py_STACKREF_CLOSE_DEBUG 1
|
||||
|
||||
|
||||
typedef union _PyStackRef {
|
||||
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||
uint64_t index;
|
||||
|
|
|
@ -204,7 +204,7 @@ dummy_func(
|
|||
ptrdiff_t off = this_instr - _PyFrame_GetBytecode(frame);
|
||||
frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index;
|
||||
frame->instr_ptr = bytecode + off;
|
||||
// Make sure this_instr gets reset correctley for any uops that
|
||||
// Make sure this_instr gets reset correctly for any uops that
|
||||
// follow
|
||||
next_instr = frame->instr_ptr;
|
||||
DISPATCH();
|
||||
|
@ -1111,7 +1111,7 @@ dummy_func(
|
|||
tstate->current_frame = frame->previous;
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
PyObject *result = PyStackRef_AsPyObjectSteal(retval);
|
||||
SYNC_SP(); /* Not strictly necessary, but prevents warnings */
|
||||
LLTRACE_RESUME_FRAME();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1123,7 @@ dummy_func(
|
|||
_PyStackRef temp = PyStackRef_MakeHeapSafe(retval);
|
||||
DEAD(retval);
|
||||
SAVE_STACK();
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
|
@ -1223,8 +1223,9 @@ dummy_func(
|
|||
{
|
||||
PyGenObject *gen = (PyGenObject *)receiver_o;
|
||||
_PyInterpreterFrame *gen_frame = &gen->gi_iframe;
|
||||
STACK_SHRINK(1);
|
||||
_PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v));
|
||||
DEAD(v);
|
||||
SYNC_SP();
|
||||
gen->gi_frame_state = FRAME_EXECUTING;
|
||||
gen->gi_exc_state.previous_item = tstate->exc_info;
|
||||
tstate->exc_info = &gen->gi_exc_state;
|
||||
|
@ -2436,10 +2437,10 @@ dummy_func(
|
|||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
|
||||
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
|
||||
// Manipulate stack directly because we exit with DISPATCH_INLINED().
|
||||
STACK_SHRINK(1);
|
||||
new_frame->localsplus[0] = owner;
|
||||
DEAD(owner);
|
||||
// Manipulate stack directly because we exit with DISPATCH_INLINED().
|
||||
SYNC_SP();
|
||||
new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name);
|
||||
frame->return_offset = INSTRUCTION_SIZE;
|
||||
DISPATCH_INLINED(new_frame);
|
||||
|
@ -3083,12 +3084,11 @@ dummy_func(
|
|||
macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER;
|
||||
|
||||
|
||||
inst(INSTRUMENTED_FOR_ITER, (unused/1 -- )) {
|
||||
_PyStackRef iter_stackref = TOP();
|
||||
PyObject *iter = PyStackRef_AsPyObjectBorrow(iter_stackref);
|
||||
PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter);
|
||||
if (next != NULL) {
|
||||
PUSH(PyStackRef_FromPyObjectSteal(next));
|
||||
inst(INSTRUMENTED_FOR_ITER, (unused/1, iter -- iter, next)) {
|
||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||
if (next_o != NULL) {
|
||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||
}
|
||||
else {
|
||||
|
@ -3105,6 +3105,7 @@ dummy_func(
|
|||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||
/* Skip END_FOR */
|
||||
JUMPBY(oparg + 1);
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4022,7 +4023,6 @@ dummy_func(
|
|||
_PUSH_FRAME;
|
||||
|
||||
inst(EXIT_INIT_CHECK, (should_be_none -- )) {
|
||||
assert(STACK_LEVEL() == 2);
|
||||
if (!PyStackRef_IsNone(should_be_none)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__init__() should return None, not '%.200s'",
|
||||
|
@ -4813,7 +4813,7 @@ dummy_func(
|
|||
PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
|
||||
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
|
||||
ERROR_IF(gen == NULL, error);
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
SAVE_STACK();
|
||||
_PyInterpreterFrame *gen_frame = &gen->gi_iframe;
|
||||
frame->instr_ptr++;
|
||||
|
@ -4932,6 +4932,7 @@ dummy_func(
|
|||
}
|
||||
next_instr = frame->instr_ptr;
|
||||
if (next_instr != this_instr) {
|
||||
SYNC_SP();
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
|
@ -4976,46 +4977,48 @@ dummy_func(
|
|||
_CHECK_PERIODIC +
|
||||
_MONITOR_JUMP_BACKWARD;
|
||||
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) {
|
||||
_PyStackRef cond = POP();
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1, cond -- )) {
|
||||
assert(PyStackRef_BoolCheck(cond));
|
||||
int jump = PyStackRef_IsTrue(cond);
|
||||
DEAD(cond);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_FALSE, (unused/1 -- )) {
|
||||
_PyStackRef cond = POP();
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_FALSE, (unused/1, cond -- )) {
|
||||
assert(PyStackRef_BoolCheck(cond));
|
||||
int jump = PyStackRef_IsFalse(cond);
|
||||
DEAD(cond);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1 -- )) {
|
||||
_PyStackRef value_stackref = POP();
|
||||
int jump = PyStackRef_IsNone(value_stackref);
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1, value -- )) {
|
||||
int jump = PyStackRef_IsNone(value);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
DEAD(value);
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
else {
|
||||
PyStackRef_CLOSE(value_stackref);
|
||||
PyStackRef_CLOSE(value);
|
||||
}
|
||||
}
|
||||
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1 -- )) {
|
||||
_PyStackRef value_stackref = POP();
|
||||
int jump = !PyStackRef_IsNone(value_stackref);
|
||||
inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1, value -- )) {
|
||||
int jump = !PyStackRef_IsNone(value);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
PyStackRef_CLOSE(value_stackref);
|
||||
PyStackRef_CLOSE(value);
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
else {
|
||||
DEAD(value);
|
||||
}
|
||||
}
|
||||
|
||||
tier1 inst(EXTENDED_ARG, ( -- )) {
|
||||
|
@ -5219,22 +5222,26 @@ dummy_func(
|
|||
}
|
||||
|
||||
label(pop_4_error) {
|
||||
STACK_SHRINK(4);
|
||||
stack_pointer -= 4;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto error;
|
||||
}
|
||||
|
||||
label(pop_3_error) {
|
||||
STACK_SHRINK(3);
|
||||
stack_pointer -= 3;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto error;
|
||||
}
|
||||
|
||||
label(pop_2_error) {
|
||||
STACK_SHRINK(2);
|
||||
stack_pointer -= 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto error;
|
||||
}
|
||||
|
||||
label(pop_1_error) {
|
||||
STACK_SHRINK(1);
|
||||
stack_pointer -= 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,18 +151,6 @@ dump_item(_PyStackRef item)
|
|||
printf("<nil>");
|
||||
return;
|
||||
}
|
||||
if (
|
||||
obj == Py_None
|
||||
|| PyBool_Check(obj)
|
||||
|| PyLong_CheckExact(obj)
|
||||
|| PyFloat_CheckExact(obj)
|
||||
|| PyUnicode_CheckExact(obj)
|
||||
) {
|
||||
if (PyObject_Print(obj, stdout, 0) == 0) {
|
||||
return;
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
// Don't call __repr__(), it might recurse into the interpreter.
|
||||
printf("<%s at %p>", Py_TYPE(obj)->tp_name, (void *)obj);
|
||||
}
|
||||
|
@ -182,14 +170,19 @@ dump_stack(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
|
|||
dump_item(*ptr);
|
||||
}
|
||||
printf("]\n");
|
||||
printf(" stack=[");
|
||||
for (_PyStackRef *ptr = stack_base; ptr < stack_pointer; ptr++) {
|
||||
if (ptr != stack_base) {
|
||||
printf(", ");
|
||||
}
|
||||
dump_item(*ptr);
|
||||
if (stack_pointer < stack_base) {
|
||||
printf(" stack=%d\n", (int)(stack_pointer-stack_base));
|
||||
}
|
||||
else {
|
||||
printf(" stack=[");
|
||||
for (_PyStackRef *ptr = stack_base; ptr < stack_pointer; ptr++) {
|
||||
if (ptr != stack_base) {
|
||||
printf(", ");
|
||||
}
|
||||
dump_item(*ptr);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
printf("]\n");
|
||||
fflush(stdout);
|
||||
PyErr_SetRaisedException(exc);
|
||||
_PyFrame_GetStackPointer(frame);
|
||||
|
@ -202,13 +195,13 @@ lltrace_instruction(_PyInterpreterFrame *frame,
|
|||
int opcode,
|
||||
int oparg)
|
||||
{
|
||||
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||
return;
|
||||
int offset = 0;
|
||||
if (frame->owner < FRAME_OWNED_BY_INTERPRETER) {
|
||||
dump_stack(frame, stack_pointer);
|
||||
offset = (int)(next_instr - _PyFrame_GetBytecode(frame));
|
||||
}
|
||||
dump_stack(frame, stack_pointer);
|
||||
const char *opname = _PyOpcode_OpName[opcode];
|
||||
assert(opname != NULL);
|
||||
int offset = (int)(next_instr - _PyFrame_GetBytecode(frame));
|
||||
if (OPCODE_HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
|
||||
printf("%d: %s %d\n", offset * 2, opname, oparg);
|
||||
}
|
||||
|
@ -986,8 +979,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
|||
* These are cached values from the frame and code object. */
|
||||
_Py_CODEUNIT *next_instr;
|
||||
_PyStackRef *stack_pointer;
|
||||
|
||||
#if defined(Py_DEBUG) && !defined(Py_STACKREF_DEBUG)
|
||||
entry_frame.localsplus[0] = PyStackRef_NULL;
|
||||
#ifdef Py_STACKREF_DEBUG
|
||||
entry_frame.f_funcobj = PyStackRef_None;
|
||||
#elif defined(Py_DEBUG)
|
||||
/* Set these to invalid but identifiable values for debugging. */
|
||||
entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
|
||||
entry_frame.f_locals = (PyObject*)0xaaa1;
|
||||
|
@ -1044,7 +1039,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
|||
_PyExecutorObject *current_executor = NULL;
|
||||
const _PyUOpInstruction *next_uop = NULL;
|
||||
#endif
|
||||
|
||||
#if Py_TAIL_CALL_INTERP
|
||||
return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0);
|
||||
#else
|
||||
|
|
|
@ -194,48 +194,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
|||
#define JUMPBY(x) (next_instr += (x))
|
||||
#define SKIP_OVER(x) (next_instr += (x))
|
||||
|
||||
|
||||
/* Stack manipulation macros */
|
||||
|
||||
/* The stack can grow at most MAXINT deep, as co_nlocals and
|
||||
co_stacksize are ints. */
|
||||
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
|
||||
#define STACK_SIZE() (_PyFrame_GetCode(frame)->co_stacksize)
|
||||
#define EMPTY() (STACK_LEVEL() == 0)
|
||||
#define TOP() (stack_pointer[-1])
|
||||
#define SECOND() (stack_pointer[-2])
|
||||
#define THIRD() (stack_pointer[-3])
|
||||
#define FOURTH() (stack_pointer[-4])
|
||||
#define PEEK(n) (stack_pointer[-(n)])
|
||||
#define POKE(n, v) (stack_pointer[-(n)] = (v))
|
||||
#define SET_TOP(v) (stack_pointer[-1] = (v))
|
||||
#define SET_SECOND(v) (stack_pointer[-2] = (v))
|
||||
#define BASIC_STACKADJ(n) (stack_pointer += n)
|
||||
#define BASIC_PUSH(v) (*stack_pointer++ = (v))
|
||||
#define BASIC_POP() (*--stack_pointer)
|
||||
|
||||
#ifdef Py_DEBUG
|
||||
#define PUSH(v) do { \
|
||||
BASIC_PUSH(v); \
|
||||
assert(STACK_LEVEL() <= STACK_SIZE()); \
|
||||
} while (0)
|
||||
#define POP() (assert(STACK_LEVEL() > 0), BASIC_POP())
|
||||
#define STACK_GROW(n) do { \
|
||||
assert(n >= 0); \
|
||||
BASIC_STACKADJ(n); \
|
||||
assert(STACK_LEVEL() <= STACK_SIZE()); \
|
||||
} while (0)
|
||||
#define STACK_SHRINK(n) do { \
|
||||
assert(n >= 0); \
|
||||
assert(STACK_LEVEL() >= n); \
|
||||
BASIC_STACKADJ(-(n)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define PUSH(v) BASIC_PUSH(v)
|
||||
#define POP() BASIC_POP()
|
||||
#define STACK_GROW(n) BASIC_STACKADJ(n)
|
||||
#define STACK_SHRINK(n) BASIC_STACKADJ(-(n))
|
||||
#endif
|
||||
|
||||
#define WITHIN_STACK_BOUNDS() \
|
||||
(frame->owner == FRAME_OWNED_BY_INTERPRETER || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))
|
||||
|
|
23
Python/executor_cases.c.h
generated
23
Python/executor_cases.c.h
generated
|
@ -714,7 +714,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_True;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -798,7 +797,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_True;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -1206,7 +1204,6 @@
|
|||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -3;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -1248,21 +1245,18 @@
|
|||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = container;
|
||||
container = PyStackRef_NULL;
|
||||
stack_pointer[-1] = container;
|
||||
stack_pointer[-3] = container;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = v;
|
||||
v = PyStackRef_NULL;
|
||||
stack_pointer[-2] = v;
|
||||
stack_pointer[-4] = v;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -2;
|
||||
stack_pointer += -4;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
if (err) {
|
||||
JUMP_TO_ERROR();
|
||||
|
@ -1732,7 +1726,7 @@
|
|||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
|
@ -2073,7 +2067,6 @@
|
|||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(seq);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer[-1] = val0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3004,7 +2997,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
self_or_null = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -3057,7 +3049,6 @@
|
|||
}
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -3073,7 +3064,6 @@
|
|||
JUMP_TO_ERROR();
|
||||
}
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
stack_pointer[-1] = attr;
|
||||
|
@ -5289,7 +5279,6 @@
|
|||
case _EXIT_INIT_CHECK: {
|
||||
_PyStackRef should_be_none;
|
||||
should_be_none = stack_pointer[-1];
|
||||
assert(STACK_LEVEL() == 2);
|
||||
if (!PyStackRef_IsNone(should_be_none)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
|
@ -6347,7 +6336,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-2] = tuple;
|
||||
stack_pointer[-1] = kwargs_out;
|
||||
|
@ -6414,7 +6402,7 @@
|
|||
if (gen == NULL) {
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyInterpreterFrame *gen_frame = &gen->gi_iframe;
|
||||
frame->instr_ptr++;
|
||||
|
@ -6513,7 +6501,6 @@
|
|||
else {
|
||||
res = value;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
|
|
120
Python/generated_cases.c.h
generated
120
Python/generated_cases.c.h
generated
|
@ -1062,7 +1062,6 @@
|
|||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -3;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -1498,7 +1497,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -1983,7 +1981,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -2097,7 +2094,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -2212,7 +2208,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -2305,7 +2300,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -2366,7 +2360,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
// _DO_CALL_FUNCTION_EX
|
||||
|
@ -2494,7 +2487,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = result;
|
||||
|
@ -2736,7 +2728,6 @@
|
|||
}
|
||||
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
|
||||
if (CONVERSION_FAILED(args_o)) {
|
||||
stack_pointer[-1] = kwnames;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = kwnames;
|
||||
kwnames = PyStackRef_NULL;
|
||||
|
@ -3070,7 +3061,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -3422,7 +3412,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -3544,7 +3533,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -3646,7 +3634,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -3759,7 +3746,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -3879,7 +3865,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -4154,7 +4139,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -4227,7 +4211,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -5310,7 +5293,6 @@
|
|||
INSTRUCTION_STATS(EXIT_INIT_CHECK);
|
||||
_PyStackRef should_be_none;
|
||||
should_be_none = stack_pointer[-1];
|
||||
assert(STACK_LEVEL() == 2);
|
||||
if (!PyStackRef_IsNone(should_be_none)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
|
@ -5369,7 +5351,6 @@
|
|||
else {
|
||||
res = value;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
|
@ -6130,8 +6111,9 @@
|
|||
}
|
||||
// _DO_CALL
|
||||
{
|
||||
self_or_null = maybe_self;
|
||||
callable = func;
|
||||
args = &stack_pointer[-oparg];
|
||||
self_or_null = &stack_pointer[-1 - oparg];
|
||||
callable = &stack_pointer[-2 - oparg];
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
|
||||
int total_args = oparg;
|
||||
_PyStackRef *arguments = args;
|
||||
|
@ -6246,7 +6228,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = res;
|
||||
|
@ -6307,7 +6288,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
// _DO_CALL_FUNCTION_EX
|
||||
|
@ -6435,7 +6415,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = result;
|
||||
|
@ -6753,14 +6732,16 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER);
|
||||
_PyStackRef iter;
|
||||
_PyStackRef next;
|
||||
/* Skip 1 cache entry */
|
||||
_PyStackRef iter_stackref = TOP();
|
||||
PyObject *iter = PyStackRef_AsPyObjectBorrow(iter_stackref);
|
||||
iter = stack_pointer[-1];
|
||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter);
|
||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (next != NULL) {
|
||||
PUSH(PyStackRef_FromPyObjectSteal(next));
|
||||
if (next_o != NULL) {
|
||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||
}
|
||||
else {
|
||||
|
@ -6779,7 +6760,11 @@
|
|||
assert(next_instr[oparg].op.code == END_FOR ||
|
||||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||
JUMPBY(oparg + 1);
|
||||
DISPATCH();
|
||||
}
|
||||
stack_pointer[0] = next;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -7063,14 +7048,17 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_FALSE);
|
||||
_PyStackRef cond;
|
||||
/* Skip 1 cache entry */
|
||||
_PyStackRef cond = POP();
|
||||
cond = stack_pointer[-1];
|
||||
assert(PyStackRef_BoolCheck(cond));
|
||||
int jump = PyStackRef_IsFalse(cond);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -7084,18 +7072,24 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NONE);
|
||||
_PyStackRef value;
|
||||
/* Skip 1 cache entry */
|
||||
_PyStackRef value_stackref = POP();
|
||||
int jump = PyStackRef_IsNone(value_stackref);
|
||||
value = stack_pointer[-1];
|
||||
int jump = PyStackRef_IsNone(value);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(value_stackref);
|
||||
PyStackRef_CLOSE(value);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 1;
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -7109,16 +7103,22 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NOT_NONE);
|
||||
_PyStackRef value;
|
||||
/* Skip 1 cache entry */
|
||||
_PyStackRef value_stackref = POP();
|
||||
int jump = !PyStackRef_IsNone(value_stackref);
|
||||
value = stack_pointer[-1];
|
||||
int jump = !PyStackRef_IsNone(value);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(value_stackref);
|
||||
PyStackRef_CLOSE(value);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -7132,14 +7132,17 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_TRUE);
|
||||
_PyStackRef cond;
|
||||
/* Skip 1 cache entry */
|
||||
_PyStackRef cond = POP();
|
||||
cond = stack_pointer[-1];
|
||||
assert(PyStackRef_BoolCheck(cond));
|
||||
int jump = PyStackRef_IsTrue(cond);
|
||||
RECORD_BRANCH_TAKEN(this_instr[1].cache, jump);
|
||||
if (jump) {
|
||||
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -7254,7 +7257,7 @@
|
|||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
|
@ -7353,9 +7356,11 @@
|
|||
tstate->current_frame = frame->previous;
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
PyObject *result = PyStackRef_AsPyObjectSteal(retval);
|
||||
LLTRACE_RESUME_FRAME();
|
||||
return result;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
return result;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(IS_OP) {
|
||||
|
@ -7684,7 +7689,6 @@
|
|||
}
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -7700,7 +7704,6 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
}
|
||||
|
@ -7886,8 +7889,9 @@
|
|||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
|
||||
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
|
||||
STACK_SHRINK(1);
|
||||
new_frame->localsplus[0] = owner;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name);
|
||||
frame->return_offset = 10 ;
|
||||
DISPATCH_INLINED(new_frame);
|
||||
|
@ -9551,7 +9555,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
self_or_null = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -10243,7 +10246,7 @@
|
|||
if (gen == NULL) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyInterpreterFrame *gen_frame = &gen->gi_iframe;
|
||||
frame->instr_ptr++;
|
||||
|
@ -10281,7 +10284,7 @@
|
|||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(EMPTY());
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_Py_LeaveRecursiveCallPy(tstate);
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
|
@ -10339,8 +10342,9 @@
|
|||
{
|
||||
PyGenObject *gen = (PyGenObject *)receiver_o;
|
||||
_PyInterpreterFrame *gen_frame = &gen->gi_iframe;
|
||||
STACK_SHRINK(1);
|
||||
_PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v));
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
gen->gi_frame_state = FRAME_EXECUTING;
|
||||
gen->gi_exc_state.previous_item = tstate->exc_info;
|
||||
tstate->exc_info = &gen->gi_exc_state;
|
||||
|
@ -11095,21 +11099,18 @@
|
|||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = container;
|
||||
container = PyStackRef_NULL;
|
||||
stack_pointer[-1] = container;
|
||||
stack_pointer[-3] = container;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = v;
|
||||
v = PyStackRef_NULL;
|
||||
stack_pointer[-2] = v;
|
||||
stack_pointer[-4] = v;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -2;
|
||||
stack_pointer += -4;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
if (err) {
|
||||
JUMP_TO_LABEL(error);
|
||||
|
@ -11465,7 +11466,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_True;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
DISPATCH();
|
||||
|
@ -11573,7 +11573,6 @@
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_True;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
|
@ -11861,7 +11860,6 @@
|
|||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(seq);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer[-1] = val0;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -11984,25 +11982,29 @@ JUMP_TO_LABEL(error);
|
|||
|
||||
LABEL(pop_4_error)
|
||||
{
|
||||
STACK_SHRINK(4);
|
||||
stack_pointer -= 4;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
||||
LABEL(pop_3_error)
|
||||
{
|
||||
STACK_SHRINK(3);
|
||||
stack_pointer -= 3;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
||||
LABEL(pop_2_error)
|
||||
{
|
||||
STACK_SHRINK(2);
|
||||
stack_pointer -= 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
||||
LABEL(pop_1_error)
|
||||
{
|
||||
STACK_SHRINK(1);
|
||||
stack_pointer -= 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
||||
|
|
9
Python/optimizer_cases.c.h
generated
9
Python/optimizer_cases.c.h
generated
|
@ -310,7 +310,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyLong_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -339,7 +338,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyLong_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -368,7 +366,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyLong_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -418,7 +415,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -448,7 +444,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -478,7 +473,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -506,7 +500,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyUnicode_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -1257,7 +1250,6 @@
|
|||
else {
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -2031,7 +2023,6 @@
|
|||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ _Py_stackref_close(_PyStackRef ref, const char *filename, int linenumber)
|
|||
}
|
||||
PyObject *obj;
|
||||
if (ref.index <= LAST_PREDEFINED_STACKREF_INDEX) {
|
||||
if (ref.index == 0) {
|
||||
_Py_FatalErrorFormat(__func__, "Passing NULL to PyStackRef_CLOSE at %s:%d\n", filename, linenumber);
|
||||
}
|
||||
// Pre-allocated reference to None, False or True -- Do not clear
|
||||
TableEntry *entry = _Py_hashtable_get(interp->open_stackrefs_table, (void *)ref.index);
|
||||
obj = entry->obj;
|
||||
|
|
|
@ -13,9 +13,8 @@ from typing import Callable, TextIO, Iterator, Iterable
|
|||
from lexer import Token
|
||||
from stack import Storage, StackError
|
||||
from parser import Stmt, SimpleStmt, BlockStmt, IfStmt, ForStmt, WhileStmt, MacroIfStmt
|
||||
|
||||
# Set this to true for voluminous output showing state of stack and locals
|
||||
PRINT_STACKS = False
|
||||
from stack import PRINT_STACKS
|
||||
DEBUG = False
|
||||
|
||||
class TokenIterator:
|
||||
|
||||
|
@ -161,7 +160,7 @@ class Emitter:
|
|||
self.emit(") {\n")
|
||||
next(tkn_iter) # Semi colon
|
||||
assert inst is not None
|
||||
assert inst.family is not None, inst
|
||||
assert inst.family is not None
|
||||
family_name = inst.family.name
|
||||
self.emit(f"UPDATE_MISS_STATS({family_name});\n")
|
||||
self.emit(f"assert(_PyOpcode_Deopt[opcode] == ({family_name}));\n")
|
||||
|
@ -242,6 +241,7 @@ class Emitter:
|
|||
next(tkn_iter)
|
||||
next(tkn_iter)
|
||||
next(tkn_iter)
|
||||
self._print_storage("DECREF_INPUTS", storage)
|
||||
try:
|
||||
storage.close_inputs(self.out)
|
||||
except StackError as ex:
|
||||
|
@ -249,7 +249,6 @@ class Emitter:
|
|||
except Exception as ex:
|
||||
ex.args = (ex.args[0] + str(tkn),)
|
||||
raise
|
||||
self._print_storage(storage)
|
||||
return True
|
||||
|
||||
def kill_inputs(
|
||||
|
@ -372,7 +371,7 @@ class Emitter:
|
|||
next(tkn_iter)
|
||||
storage.clear_inputs("when syncing stack")
|
||||
storage.flush(self.out)
|
||||
self._print_storage(storage)
|
||||
storage.stack.clear(self.out)
|
||||
return True
|
||||
|
||||
def stack_pointer(
|
||||
|
@ -406,7 +405,6 @@ class Emitter:
|
|||
def emit_save(self, storage: Storage) -> None:
|
||||
storage.flush(self.out)
|
||||
storage.save(self.out)
|
||||
self._print_storage(storage)
|
||||
|
||||
def save_stack(
|
||||
self,
|
||||
|
@ -424,7 +422,6 @@ class Emitter:
|
|||
|
||||
def emit_reload(self, storage: Storage) -> None:
|
||||
storage.reload(self.out)
|
||||
self._print_storage(storage)
|
||||
|
||||
def reload_stack(
|
||||
self,
|
||||
|
@ -453,9 +450,10 @@ class Emitter:
|
|||
self.out.emit(f" {uop.instruction_size} ")
|
||||
return True
|
||||
|
||||
def _print_storage(self, storage: Storage) -> None:
|
||||
if PRINT_STACKS:
|
||||
def _print_storage(self, reason:str, storage: Storage) -> None:
|
||||
if DEBUG:
|
||||
self.out.start_line()
|
||||
self.emit(f"/* {reason} */\n")
|
||||
self.emit(storage.as_comment())
|
||||
self.out.start_line()
|
||||
|
||||
|
@ -514,7 +512,6 @@ class Emitter:
|
|||
var.memory_offset = None
|
||||
break
|
||||
if tkn.text.startswith("DISPATCH"):
|
||||
self._print_storage(storage)
|
||||
reachable = False
|
||||
self.out.emit(tkn)
|
||||
else:
|
||||
|
@ -536,6 +533,8 @@ class Emitter:
|
|||
self.out.emit(stmt.condition)
|
||||
branch = stmt.else_ is not None
|
||||
reachable = True
|
||||
if branch:
|
||||
else_storage = storage.copy()
|
||||
for s in stmt.body:
|
||||
r, tkn, storage = self._emit_stmt(s, uop, storage, inst)
|
||||
if tkn is not None:
|
||||
|
@ -543,7 +542,6 @@ class Emitter:
|
|||
if not r:
|
||||
reachable = False
|
||||
if branch:
|
||||
else_storage = storage.copy()
|
||||
assert stmt.else_ is not None
|
||||
self.out.emit(stmt.else_)
|
||||
assert stmt.else_body is not None
|
||||
|
@ -553,7 +551,8 @@ class Emitter:
|
|||
self.out.emit(tkn)
|
||||
if not r:
|
||||
reachable = False
|
||||
storage.merge(else_storage, self.out)
|
||||
else_storage.merge(storage, self.out) # type: ignore[possibly-undefined]
|
||||
storage = else_storage
|
||||
self.out.emit(stmt.endif)
|
||||
return reachable, None, storage
|
||||
|
||||
|
@ -596,7 +595,6 @@ class Emitter:
|
|||
reachable = True
|
||||
return reachable, rbrace, storage
|
||||
except StackError as ex:
|
||||
self._print_storage(if_storage)
|
||||
assert rbrace is not None
|
||||
raise analysis_error(ex.args[0], rbrace) from None
|
||||
|
||||
|
@ -659,20 +657,18 @@ class Emitter:
|
|||
storage: Storage,
|
||||
inst: Instruction | None,
|
||||
emit_braces: bool = True
|
||||
) -> Storage:
|
||||
) -> tuple[bool, Storage]:
|
||||
self.out.start_line()
|
||||
reachable, tkn, storage = self.emit_BlockStmt(code.body, code, storage, inst, emit_braces)
|
||||
assert tkn is not None
|
||||
try:
|
||||
if reachable:
|
||||
self._print_storage(storage)
|
||||
storage.push_outputs()
|
||||
self._print_storage(storage)
|
||||
if emit_braces:
|
||||
self.out.emit(tkn)
|
||||
except StackError as ex:
|
||||
raise analysis_error(ex.args[0], tkn) from None
|
||||
return storage
|
||||
return reachable, storage
|
||||
|
||||
def emit(self, txt: str | Token) -> None:
|
||||
self.out.emit(txt)
|
||||
|
|
|
@ -145,7 +145,7 @@ def write_uop(
|
|||
# No reference management of inputs needed.
|
||||
for var in storage.inputs: # type: ignore[possibly-undefined]
|
||||
var.in_local = False
|
||||
storage = emitter.emit_tokens(override, storage, None, False)
|
||||
_, storage = emitter.emit_tokens(override, storage, None, False)
|
||||
out.start_line()
|
||||
storage.flush(out)
|
||||
else:
|
||||
|
|
|
@ -6,6 +6,8 @@ from typing import Iterator
|
|||
|
||||
UNUSED = {"unused"}
|
||||
|
||||
# Set this to true for voluminous output showing state of stack and locals
|
||||
PRINT_STACKS = False
|
||||
|
||||
def maybe_parenthesize(sym: str) -> str:
|
||||
"""Add parentheses around a string if it contains an operator
|
||||
|
@ -131,9 +133,6 @@ class PointerOffset:
|
|||
return None
|
||||
return self.numeric
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.numeric != 0 or bool(self.positive) or bool(self.negative)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.to_c()
|
||||
|
||||
|
@ -151,7 +150,7 @@ class Local:
|
|||
|
||||
def compact_str(self) -> str:
|
||||
mtag = "M" if self.memory_offset else ""
|
||||
dtag = "D" if self.in_local else ""
|
||||
dtag = "L" if self.in_local else ""
|
||||
atag = "A" if self.is_array() else ""
|
||||
return f"'{self.item.name}'{mtag}{dtag}{atag}"
|
||||
|
||||
|
@ -167,6 +166,11 @@ class Local:
|
|||
def from_memory(defn: StackItem, offset: PointerOffset) -> "Local":
|
||||
return Local(defn, offset, True)
|
||||
|
||||
@staticmethod
|
||||
def register(name: str) -> "Local":
|
||||
item = StackItem(name, None, "", False, True)
|
||||
return Local(item, None, True)
|
||||
|
||||
def kill(self) -> None:
|
||||
self.in_local = False
|
||||
self.memory_offset = None
|
||||
|
@ -230,20 +234,16 @@ class Stack:
|
|||
raise StackError(f"Dropping live value '{var.name}'")
|
||||
|
||||
def pop(self, var: StackItem, out: CWriter) -> Local:
|
||||
if self.variables:
|
||||
top = self.variables[-1]
|
||||
if var.is_array() != top.is_array() or top.size != var.size:
|
||||
# Mismatch in variables
|
||||
self.clear(out)
|
||||
self.logical_sp = self.logical_sp.pop(var)
|
||||
indirect = "&" if var.is_array() else ""
|
||||
if self.variables:
|
||||
popped = self.variables.pop()
|
||||
if var.is_array() ^ popped.is_array():
|
||||
raise StackError(
|
||||
f"Array mismatch when popping '{popped.name}' from stack to assign to '{var.name}'. "
|
||||
f"Expected {array_or_scalar(var)} got {array_or_scalar(popped)}"
|
||||
)
|
||||
if popped.size != var.size:
|
||||
raise StackError(
|
||||
f"Size mismatch when popping '{popped.name}' from stack to assign to '{var.name}'. "
|
||||
f"Expected {var_size(var)} got {var_size(popped.item)}"
|
||||
)
|
||||
assert var.is_array() == popped.is_array() and popped.size == var.size
|
||||
if not var.used:
|
||||
return popped
|
||||
if popped.name != var.name:
|
||||
|
@ -255,27 +255,33 @@ class Stack:
|
|||
if popped.memory_offset is None:
|
||||
popped.memory_offset = self.logical_sp
|
||||
assert popped.memory_offset == self.logical_sp, (popped, self.as_comment())
|
||||
offset = popped.memory_offset.to_c()
|
||||
offset = popped.memory_offset - self.physical_sp
|
||||
if var.is_array():
|
||||
defn = f"{var.name} = &stack_pointer[{offset}];\n"
|
||||
defn = f"{var.name} = &stack_pointer[{offset.to_c()}];\n"
|
||||
else:
|
||||
defn = f"{var.name} = stack_pointer[{offset}];\n"
|
||||
defn = f"{var.name} = stack_pointer[{offset.to_c()}];\n"
|
||||
popped.in_local = True
|
||||
else:
|
||||
defn = rename
|
||||
out.emit(defn)
|
||||
return popped
|
||||
|
||||
self.base_offset = self.logical_sp
|
||||
if var.name in UNUSED or not var.used:
|
||||
return Local.unused(var, self.base_offset)
|
||||
cast = f"({var.type})" if (not indirect and var.type) else ""
|
||||
bits = ".bits" if cast and self.extract_bits else ""
|
||||
offset = (self.base_offset - self.physical_sp).to_c()
|
||||
assign = f"{var.name} = {cast}{indirect}stack_pointer[{offset}]{bits};\n"
|
||||
c_offset = (self.base_offset - self.physical_sp).to_c()
|
||||
assign = f"{var.name} = {cast}{indirect}stack_pointer[{c_offset}]{bits};\n"
|
||||
out.emit(assign)
|
||||
self._print(out)
|
||||
return Local.from_memory(var, self.base_offset)
|
||||
|
||||
def clear(self, out: CWriter) -> None:
|
||||
"Flush to memory and clear variables stack"
|
||||
self.flush(out)
|
||||
self.variables = []
|
||||
self.base_offset = self.logical_sp
|
||||
|
||||
def push(self, var: Local) -> None:
|
||||
assert(var not in self.variables)
|
||||
self.variables.append(var)
|
||||
|
@ -298,10 +304,11 @@ class Stack:
|
|||
diff = self.logical_sp - self.physical_sp
|
||||
out.start_line()
|
||||
out.emit(f"stack_pointer += {diff.to_c()};\n")
|
||||
out.emit("assert(WITHIN_STACK_BOUNDS());\n")
|
||||
out.emit(f"assert(WITHIN_STACK_BOUNDS());\n")
|
||||
self.physical_sp = self.logical_sp
|
||||
self._print(out)
|
||||
|
||||
def flush(self, out: CWriter) -> None:
|
||||
def save_variables(self, out: CWriter) -> None:
|
||||
out.start_line()
|
||||
var_offset = self.base_offset
|
||||
for var in self.variables:
|
||||
|
@ -310,10 +317,15 @@ class Stack:
|
|||
not var.memory_offset and
|
||||
not var.is_array()
|
||||
):
|
||||
self._print(out)
|
||||
var.memory_offset = var_offset
|
||||
stack_offset = var_offset - self.physical_sp
|
||||
Stack._do_emit(out, var.item, stack_offset, self.cast_type, self.extract_bits)
|
||||
self._print(out)
|
||||
var_offset = var_offset.push(var.item)
|
||||
|
||||
def flush(self, out: CWriter) -> None:
|
||||
self.save_variables(out)
|
||||
self._save_physical_sp(out)
|
||||
out.start_line()
|
||||
|
||||
|
@ -329,9 +341,13 @@ class Stack:
|
|||
def as_comment(self) -> str:
|
||||
variables = ", ".join([v.compact_str() for v in self.variables])
|
||||
return (
|
||||
f"/* Variables: {variables}. base: {self.base_offset.to_c()}. sp: {self.physical_sp.to_c()}. logical_sp: {self.logical_sp.to_c()} */"
|
||||
f"/* Variables=[{variables}]; base={self.base_offset.to_c()}; sp={self.physical_sp.to_c()}; logical_sp={self.logical_sp.to_c()} */"
|
||||
)
|
||||
|
||||
def _print(self, out: CWriter) -> None:
|
||||
if PRINT_STACKS:
|
||||
out.emit(self.as_comment() + "\n")
|
||||
|
||||
def copy(self) -> "Stack":
|
||||
other = Stack(self.extract_bits, self.cast_type)
|
||||
other.base_offset = self.base_offset
|
||||
|
@ -358,7 +374,6 @@ class Stack:
|
|||
diff = other.physical_sp - self.physical_sp
|
||||
out.start_line()
|
||||
out.emit(f"stack_pointer += {diff.to_c()};\n")
|
||||
out.emit("assert(WITHIN_STACK_BOUNDS());\n")
|
||||
self.physical_sp = other.physical_sp
|
||||
|
||||
def merge(self, other: "Stack", out: CWriter) -> None:
|
||||
|
@ -621,10 +636,10 @@ class Storage:
|
|||
|
||||
def as_comment(self) -> str:
|
||||
stack_comment = self.stack.as_comment()
|
||||
next_line = "\n "
|
||||
next_line = "\n "
|
||||
inputs = ", ".join([var.compact_str() for var in self.inputs])
|
||||
outputs = ", ".join([var.compact_str() for var in self.outputs])
|
||||
return f"{stack_comment[:-2]}{next_line}inputs: {inputs}{next_line}outputs: {outputs}*/"
|
||||
return f"{stack_comment[:-2]}{next_line}inputs: {inputs} outputs: {outputs}*/"
|
||||
|
||||
def close_inputs(self, out: CWriter) -> None:
|
||||
|
||||
|
@ -637,7 +652,7 @@ class Storage:
|
|||
tmp_defined = True
|
||||
out.emit(f"tmp = {name};\n")
|
||||
out.emit(f"{name} = {overwrite};\n")
|
||||
self.stack.flush(out)
|
||||
self.stack.save_variables(out)
|
||||
out.emit(f"{close}(tmp);\n")
|
||||
else:
|
||||
out.emit(f"{close}({name});\n")
|
||||
|
@ -678,7 +693,6 @@ class Storage:
|
|||
if output is not None:
|
||||
raise StackError("Cannot call DECREF_INPUTS with more than one live output")
|
||||
output = var
|
||||
self.stack.flush(out)
|
||||
if output is not None:
|
||||
if output.is_array():
|
||||
assert len(self.inputs) == 1
|
||||
|
@ -691,6 +705,7 @@ class Storage:
|
|||
return
|
||||
if var_size(lowest.item) != var_size(output.item):
|
||||
raise StackError("Cannot call DECREF_INPUTS with live output not matching first input size")
|
||||
self.stack.flush(out)
|
||||
lowest.in_local = True
|
||||
close_variable(lowest, output.name)
|
||||
assert lowest.memory_offset is not None
|
||||
|
|
|
@ -9,6 +9,8 @@ from analyzer import (
|
|||
Analysis,
|
||||
Instruction,
|
||||
Uop,
|
||||
Label,
|
||||
CodeSection,
|
||||
Part,
|
||||
analyze_files,
|
||||
Skip,
|
||||
|
@ -22,9 +24,13 @@ from generators_common import (
|
|||
write_header,
|
||||
type_and_null,
|
||||
Emitter,
|
||||
TokenIterator,
|
||||
always_true,
|
||||
emit_to,
|
||||
)
|
||||
from cwriter import CWriter
|
||||
from typing import TextIO
|
||||
from lexer import Token
|
||||
from stack import Local, Stack, StackError, get_stack_effect, Storage
|
||||
|
||||
DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
|
||||
|
@ -69,23 +75,23 @@ def write_uop(
|
|||
stack: Stack,
|
||||
inst: Instruction,
|
||||
braces: bool,
|
||||
) -> tuple[int, Stack]:
|
||||
) -> tuple[bool, int, Stack]:
|
||||
# out.emit(stack.as_comment() + "\n")
|
||||
if isinstance(uop, Skip):
|
||||
entries = "entries" if uop.size > 1 else "entry"
|
||||
emitter.emit(f"/* Skip {uop.size} cache {entries} */\n")
|
||||
return (offset + uop.size), stack
|
||||
return True, (offset + uop.size), stack
|
||||
if isinstance(uop, Flush):
|
||||
emitter.emit(f"// flush\n")
|
||||
stack.flush(emitter.out)
|
||||
return offset, stack
|
||||
return True, offset, stack
|
||||
locals: dict[str, Local] = {}
|
||||
emitter.out.start_line()
|
||||
if braces:
|
||||
emitter.out.emit(f"// {uop.name}\n")
|
||||
emitter.emit("{\n")
|
||||
stack._print(emitter.out)
|
||||
storage = Storage.for_uop(stack, uop, emitter.out)
|
||||
emitter._print_storage(storage)
|
||||
|
||||
for cache in uop.caches:
|
||||
if cache.name != "unused":
|
||||
|
@ -102,12 +108,12 @@ def write_uop(
|
|||
emitter.emit(f"(void){cache.name};\n")
|
||||
offset += cache.size
|
||||
|
||||
storage = emitter.emit_tokens(uop, storage, inst, False)
|
||||
reachable, storage = emitter.emit_tokens(uop, storage, inst, False)
|
||||
if braces:
|
||||
emitter.out.start_line()
|
||||
emitter.emit("}\n")
|
||||
# emitter.emit(stack.as_comment() + "\n")
|
||||
return offset, storage.stack
|
||||
return reachable, offset, storage.stack
|
||||
|
||||
|
||||
def uses_this(inst: Instruction) -> bool:
|
||||
|
@ -204,6 +210,9 @@ def generate_tier1_labels(
|
|||
emitter.emit_tokens(label, storage, None)
|
||||
emitter.emit("\n\n")
|
||||
|
||||
def get_popped(inst: Instruction, analysis: Analysis) -> str:
|
||||
stack = get_stack_effect(inst)
|
||||
return (-stack.base_offset).to_c()
|
||||
|
||||
def generate_tier1_cases(
|
||||
analysis: Analysis, outfile: TextIO, lines: bool
|
||||
|
@ -214,6 +223,7 @@ def generate_tier1_cases(
|
|||
for name, inst in sorted(analysis.instructions.items()):
|
||||
out.emit("\n")
|
||||
out.emit(f"TARGET({name}) {{\n")
|
||||
popped = get_popped(inst, analysis)
|
||||
# We need to ifdef it because this breaks platforms
|
||||
# without computed gotos/tail calling.
|
||||
out.emit(f"#if Py_TAIL_CALL_INTERP\n")
|
||||
|
@ -251,11 +261,10 @@ def generate_tier1_cases(
|
|||
for part in inst.parts:
|
||||
# Only emit braces if more than one uop
|
||||
insert_braces = len([p for p in inst.parts if isinstance(p, Uop)]) > 1
|
||||
offset, stack = write_uop(part, emitter, offset, stack, inst, insert_braces)
|
||||
reachable, offset, stack = write_uop(part, emitter, offset, stack, inst, insert_braces)
|
||||
out.start_line()
|
||||
|
||||
stack.flush(out)
|
||||
if not inst.parts[-1].properties.always_exits:
|
||||
if reachable: # type: ignore[possibly-undefined]
|
||||
stack.flush(out)
|
||||
out.emit("DISPATCH();\n")
|
||||
out.start_line()
|
||||
out.emit("}")
|
||||
|
|
|
@ -154,7 +154,7 @@ def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack:
|
|||
cast = f"uint{cache.size*16}_t"
|
||||
emitter.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND{idx}();\n")
|
||||
idx += 1
|
||||
storage = emitter.emit_tokens(uop, storage, None, False)
|
||||
_, storage = emitter.emit_tokens(uop, storage, None, False)
|
||||
storage.flush(emitter.out)
|
||||
except StackError as ex:
|
||||
raise analysis_error(ex.args[0], uop.body.open) from None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue