Skip to content

Commit 5eea154

Browse files
committed
gh-87092: create new opcode_utils.h file and move macros from compile.c there, so they can be shared
1 parent f2e5a6e commit 5eea154

File tree

3 files changed

+112
-71
lines changed

3 files changed

+112
-71
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#ifndef Py_INTERNAL_OPCODE_UTILS_H
2+
#define Py_INTERNAL_OPCODE_UTILS_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
#include "pycore_opcode.h" // _PyOpcode_RelativeJump
12+
13+
14+
#define MAX_REAL_OPCODE 254
15+
16+
#define IS_WITHIN_OPCODE_RANGE(opcode) \
17+
(((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \
18+
IS_PSEUDO_OPCODE(opcode))
19+
20+
#define IS_JUMP_OPCODE(opcode) \
21+
is_bit_set_in_table(_PyOpcode_Jump, opcode)
22+
23+
#define IS_BLOCK_PUSH_OPCODE(opcode) \
24+
((opcode) == SETUP_FINALLY || \
25+
(opcode) == SETUP_WITH || \
26+
(opcode) == SETUP_CLEANUP)
27+
28+
#define HAS_TARGET(opcode) \
29+
(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
30+
31+
/* opcodes that must be last in the basicblock */
32+
#define IS_TERMINATOR_OPCODE(opcode) \
33+
(IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
34+
35+
/* opcodes which are not emitted in codegen stage, only by the assembler */
36+
#define IS_ASSEMBLER_OPCODE(opcode) \
37+
((opcode) == JUMP_FORWARD || \
38+
(opcode) == JUMP_BACKWARD || \
39+
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
40+
41+
#define IS_BACKWARDS_JUMP_OPCODE(opcode) \
42+
((opcode) == JUMP_BACKWARD || \
43+
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
44+
45+
#define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \
46+
((opcode) == JUMP || \
47+
(opcode) == JUMP_NO_INTERRUPT || \
48+
(opcode) == JUMP_FORWARD || \
49+
(opcode) == JUMP_BACKWARD || \
50+
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
51+
52+
#define IS_SCOPE_EXIT_OPCODE(opcode) \
53+
((opcode) == RETURN_VALUE || \
54+
(opcode) == RETURN_CONST || \
55+
(opcode) == RAISE_VARARGS || \
56+
(opcode) == RERAISE)
57+
58+
#define IS_SUPERINSTRUCTION_OPCODE(opcode) \
59+
((opcode) == LOAD_FAST__LOAD_FAST || \
60+
(opcode) == LOAD_FAST__LOAD_CONST || \
61+
(opcode) == LOAD_CONST__LOAD_FAST || \
62+
(opcode) == STORE_FAST__LOAD_FAST || \
63+
(opcode) == STORE_FAST__STORE_FAST)
64+
65+
#define IS_SCOPE_EXIT_OPCODE(opcode) \
66+
((opcode) == RETURN_VALUE || \
67+
(opcode) == RETURN_CONST || \
68+
(opcode) == RAISE_VARARGS || \
69+
(opcode) == RERAISE)
70+
71+
#define IS_SUPERINSTRUCTION_OPCODE(opcode) \
72+
((opcode) == LOAD_FAST__LOAD_FAST || \
73+
(opcode) == LOAD_FAST__LOAD_CONST || \
74+
(opcode) == LOAD_CONST__LOAD_FAST || \
75+
(opcode) == STORE_FAST__LOAD_FAST || \
76+
(opcode) == STORE_FAST__STORE_FAST)
77+
78+
79+
#define LOG_BITS_PER_INT 5
80+
#define MASK_LOW_LOG_BITS 31
81+
82+
static inline int
83+
is_bit_set_in_table(const uint32_t *table, int bitindex) {
84+
/* Is the relevant bit set in the relevant word? */
85+
/* 512 bits fit into 9 32-bits words.
86+
* Word is indexed by (bitindex>>ln(size of int in bits)).
87+
* Bit within word is the low bits of bitindex.
88+
*/
89+
if (bitindex >= 0 && bitindex < 512) {
90+
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
91+
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
92+
}
93+
else {
94+
return 0;
95+
}
96+
}
97+
98+
#undef LOG_BITS_PER_INT
99+
#undef MASK_LOW_LOG_BITS
100+
101+
#define IS_RELATIVE_JUMP(opcode) (is_bit_set_in_table(_PyOpcode_RelativeJump, opcode))
102+
103+
104+
105+
#ifdef __cplusplus
106+
}
107+
#endif
108+
#endif /* !Py_INTERNAL_OPCODE_UTILS_H */

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,8 @@ PYTHON_HEADERS= \
17021702
$(srcdir)/Include/internal/pycore_object_state.h \
17031703
$(srcdir)/Include/internal/pycore_obmalloc.h \
17041704
$(srcdir)/Include/internal/pycore_obmalloc_init.h \
1705+
$(srcdir)/Include/internal/pycore_opcode.h \
1706+
$(srcdir)/Include/internal/pycore_opcode_utils.h \
17051707
$(srcdir)/Include/internal/pycore_pathconfig.h \
17061708
$(srcdir)/Include/internal/pycore_pyarena.h \
17071709
$(srcdir)/Include/internal/pycore_pyerrors.h \

Python/compile.c

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "pycore_intrinsics.h"
3434
#include "pycore_long.h" // _PyLong_GetZero()
3535
#include "pycore_opcode.h" // _PyOpcode_Caches
36+
#include "pycore_opcode_utils.h"
3637
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
3738
#include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST()
3839

@@ -83,58 +84,6 @@
8384
*/
8485
#define MAX_ALLOWED_STACK_USE (STACK_USE_GUIDELINE * 100)
8586

86-
87-
#define MAX_REAL_OPCODE 254
88-
89-
#define IS_WITHIN_OPCODE_RANGE(opcode) \
90-
(((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \
91-
IS_PSEUDO_OPCODE(opcode))
92-
93-
#define IS_JUMP_OPCODE(opcode) \
94-
is_bit_set_in_table(_PyOpcode_Jump, opcode)
95-
96-
#define IS_BLOCK_PUSH_OPCODE(opcode) \
97-
((opcode) == SETUP_FINALLY || \
98-
(opcode) == SETUP_WITH || \
99-
(opcode) == SETUP_CLEANUP)
100-
101-
#define HAS_TARGET(opcode) \
102-
(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
103-
104-
/* opcodes that must be last in the basicblock */
105-
#define IS_TERMINATOR_OPCODE(opcode) \
106-
(IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
107-
108-
/* opcodes which are not emitted in codegen stage, only by the assembler */
109-
#define IS_ASSEMBLER_OPCODE(opcode) \
110-
((opcode) == JUMP_FORWARD || \
111-
(opcode) == JUMP_BACKWARD || \
112-
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
113-
114-
#define IS_BACKWARDS_JUMP_OPCODE(opcode) \
115-
((opcode) == JUMP_BACKWARD || \
116-
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
117-
118-
#define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \
119-
((opcode) == JUMP || \
120-
(opcode) == JUMP_NO_INTERRUPT || \
121-
(opcode) == JUMP_FORWARD || \
122-
(opcode) == JUMP_BACKWARD || \
123-
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
124-
125-
#define IS_SCOPE_EXIT_OPCODE(opcode) \
126-
((opcode) == RETURN_VALUE || \
127-
(opcode) == RETURN_CONST || \
128-
(opcode) == RAISE_VARARGS || \
129-
(opcode) == RERAISE)
130-
131-
#define IS_SUPERINSTRUCTION_OPCODE(opcode) \
132-
((opcode) == LOAD_FAST__LOAD_FAST || \
133-
(opcode) == LOAD_FAST__LOAD_CONST || \
134-
(opcode) == LOAD_CONST__LOAD_FAST || \
135-
(opcode) == STORE_FAST__LOAD_FAST || \
136-
(opcode) == STORE_FAST__STORE_FAST)
137-
13887
#define IS_TOP_LEVEL_AWAIT(C) ( \
13988
((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
14089
&& ((C)->u->u_ste->ste_type == ModuleBlock))
@@ -214,29 +163,11 @@ typedef struct exceptstack {
214163
int depth;
215164
} ExceptStack;
216165

217-
#define LOG_BITS_PER_INT 5
218-
#define MASK_LOW_LOG_BITS 31
219-
220-
static inline int
221-
is_bit_set_in_table(const uint32_t *table, int bitindex) {
222-
/* Is the relevant bit set in the relevant word? */
223-
/* 512 bits fit into 9 32-bits words.
224-
* Word is indexed by (bitindex>>ln(size of int in bits)).
225-
* Bit within word is the low bits of bitindex.
226-
*/
227-
if (bitindex >= 0 && bitindex < 512) {
228-
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
229-
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
230-
}
231-
else {
232-
return 0;
233-
}
234-
}
235166

236167
static inline int
237168
is_relative_jump(struct cfg_instr *i)
238169
{
239-
return is_bit_set_in_table(_PyOpcode_RelativeJump, i->i_opcode);
170+
return IS_RELATIVE_JUMP(i->i_opcode);
240171
}
241172

242173
static inline int

0 commit comments

Comments
 (0)