Skip to content

Commit 8f18ac0

Browse files
GH-98831: Add macro and op and their implementation to DSL (#99495)
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 <[email protected]>
1 parent f1a4a6a commit 8f18ac0

File tree

7 files changed

+325
-135
lines changed

7 files changed

+325
-135
lines changed

Include/internal/pycore_code.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,12 @@ write_obj(uint16_t *p, PyObject *val)
293293
memcpy(p, &val, sizeof(val));
294294
}
295295

296+
static inline uint16_t
297+
read_u16(uint16_t *p)
298+
{
299+
return *p;
300+
}
301+
296302
static inline uint32_t
297303
read_u32(uint16_t *p)
298304
{

Python/bytecodes.c

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ do { \
7070
#define DISPATCH_SAME_OPARG() ((void)0)
7171

7272
#define inst(name, ...) case name:
73+
#define op(name, ...) /* NAME is ignored */
74+
#define macro(name) static int MACRO_##name
7375
#define super(name) static int SUPER_##name
7476
#define family(name, ...) static int family_##name
7577

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

8487
static PyObject *
8588
dummy_func(
@@ -156,10 +159,7 @@ dummy_func(
156159
res = NULL;
157160
}
158161

159-
inst(END_FOR, (value1, value2 --)) {
160-
Py_DECREF(value1);
161-
Py_DECREF(value2);
162-
}
162+
macro(END_FOR) = POP_TOP + POP_TOP;
163163

164164
inst(UNARY_POSITIVE, (value -- res)) {
165165
res = PyNumber_Positive(value);
@@ -2725,33 +2725,27 @@ dummy_func(
27252725
PUSH(res);
27262726
}
27272727

2728-
// stack effect: ( -- __0)
2729-
inst(WITH_EXCEPT_START) {
2728+
inst(WITH_EXCEPT_START, (exit_func, lasti, unused, val -- exit_func, lasti, unused, val, res)) {
27302729
/* At the top of the stack are 4 values:
2731-
- TOP = exc_info()
2732-
- SECOND = previous exception
2733-
- THIRD: lasti of exception in exc_info()
2734-
- FOURTH: the context.__exit__ bound method
2730+
- val: TOP = exc_info()
2731+
- unused: SECOND = previous exception
2732+
- lasti: THIRD = lasti of exception in exc_info()
2733+
- exit_func: FOURTH = the context.__exit__ bound method
27352734
We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
27362735
Then we push the __exit__ return value.
27372736
*/
2738-
PyObject *exit_func;
2739-
PyObject *exc, *val, *tb, *res;
2737+
PyObject *exc, *tb;
27402738

2741-
val = TOP();
27422739
assert(val && PyExceptionInstance_Check(val));
27432740
exc = PyExceptionInstance_Class(val);
27442741
tb = PyException_GetTraceback(val);
27452742
Py_XDECREF(tb);
2746-
assert(PyLong_Check(PEEK(3)));
2747-
exit_func = PEEK(4);
2743+
assert(PyLong_Check(lasti));
2744+
(void)lasti; // Shut up compiler warning if asserts are off
27482745
PyObject *stack[4] = {NULL, exc, val, tb};
27492746
res = PyObject_Vectorcall(exit_func, stack + 1,
27502747
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
2751-
if (res == NULL)
2752-
goto error;
2753-
2754-
PUSH(res);
2748+
ERROR_IF(res == NULL, error);
27552749
}
27562750

27572751
// stack effect: ( -- __0)

Python/generated_cases.c.h

Lines changed: 60 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
What's currently here:
44

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

0 commit comments

Comments
 (0)