Skip to content

Commit

Permalink
GH-98831: Add macro and op and their implementation to DSL (#99495)
Browse files Browse the repository at this point in the history
Newly supported interpreter definition syntax:
- `op(NAME, (input_stack_effects -- output_stack_effects)) { ... }`
- `macro(NAME) = OP1 + OP2;`

Also some other random improvements:
- Convert `WITH_EXCEPT_START` to use stack effects
- Fix lexer to balk at unrecognized characters, e.g. `@`
- Fix moved output names; support object pointers in cache
- Introduce `error()` method to print errors
- Introduce read_uint16(p) as equivalent to `*p`

Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
  • Loading branch information
gvanrossum and brandtbucher authored Nov 23, 2022
1 parent f1a4a6a commit 8f18ac0
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 135 deletions.
6 changes: 6 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ write_obj(uint16_t *p, PyObject *val)
memcpy(p, &val, sizeof(val));
}

static inline uint16_t
read_u16(uint16_t *p)
{
return *p;
}

static inline uint32_t
read_u32(uint16_t *p)
{
Expand Down
32 changes: 13 additions & 19 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ do { \
#define DISPATCH_SAME_OPARG() ((void)0)

#define inst(name, ...) case name:
#define op(name, ...) /* NAME is ignored */
#define macro(name) static int MACRO_##name
#define super(name) static int SUPER_##name
#define family(name, ...) static int family_##name

Expand All @@ -80,6 +82,7 @@ do { \
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
static PyObject *container, *start, *stop, *v, *lhs, *rhs;
static PyObject *list, *tuple, *dict;
static PyObject *exit_func, *lasti, *val;

static PyObject *
dummy_func(
Expand Down Expand Up @@ -156,10 +159,7 @@ dummy_func(
res = NULL;
}

inst(END_FOR, (value1, value2 --)) {
Py_DECREF(value1);
Py_DECREF(value2);
}
macro(END_FOR) = POP_TOP + POP_TOP;

inst(UNARY_POSITIVE, (value -- res)) {
res = PyNumber_Positive(value);
Expand Down Expand Up @@ -2725,33 +2725,27 @@ dummy_func(
PUSH(res);
}

// stack effect: ( -- __0)
inst(WITH_EXCEPT_START) {
inst(WITH_EXCEPT_START, (exit_func, lasti, unused, val -- exit_func, lasti, unused, val, res)) {
/* At the top of the stack are 4 values:
- TOP = exc_info()
- SECOND = previous exception
- THIRD: lasti of exception in exc_info()
- FOURTH: the context.__exit__ bound method
- val: TOP = exc_info()
- unused: SECOND = previous exception
- lasti: THIRD = lasti of exception in exc_info()
- exit_func: FOURTH = the context.__exit__ bound method
We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
Then we push the __exit__ return value.
*/
PyObject *exit_func;
PyObject *exc, *val, *tb, *res;
PyObject *exc, *tb;

val = TOP();
assert(val && PyExceptionInstance_Check(val));
exc = PyExceptionInstance_Class(val);
tb = PyException_GetTraceback(val);
Py_XDECREF(tb);
assert(PyLong_Check(PEEK(3)));
exit_func = PEEK(4);
assert(PyLong_Check(lasti));
(void)lasti; // Shut up compiler warning if asserts are off
PyObject *stack[4] = {NULL, exc, val, tb};
res = PyObject_Vectorcall(exit_func, stack + 1,
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
if (res == NULL)
goto error;

PUSH(res);
ERROR_IF(res == NULL, error);
}

// stack effect: ( -- __0)
Expand Down
103 changes: 60 additions & 43 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Tools/cases_generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

What's currently here:

- lexer.py: lexer for C, originally written by Mark Shannon
- plexer.py: OO interface on top of lexer.py; main class: `PLexer`
- parser.py: Parser for instruction definition DSL; main class `Parser`
- `lexer.py`: lexer for C, originally written by Mark Shannon
- `plexer.py`: OO interface on top of lexer.py; main class: `PLexer`
- `parser.py`: Parser for instruction definition DSL; main class `Parser`
- `generate_cases.py`: driver script to read `Python/bytecodes.c` and
write `Python/generated_cases.c.h`

Expand Down
Loading

0 comments on commit 8f18ac0

Please sign in to comment.