Skip to content

Commit b5244da

Browse files
committed
gh-87092: move CFG related code from compile.c to cfg.c
1 parent 5eea154 commit b5244da

File tree

9 files changed

+2430
-2358
lines changed

9 files changed

+2430
-2358
lines changed

Include/internal/pycore_cfg.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#ifndef Py_INTERNAL_CFG_H
2+
#define Py_INTERNAL_CFG_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 "Include/Python.h"
12+
#include "pycore_opcode_utils.h"
13+
14+
static _PyCompilerSrcLocation NO_LOCATION = {-1, -1, -1, -1};
15+
16+
typedef struct {
17+
int i_opcode;
18+
int i_oparg;
19+
_PyCompilerSrcLocation i_loc;
20+
struct _PyCfgBasicblock_ *i_target; /* target block (if jump instruction) */
21+
struct _PyCfgBasicblock_ *i_except; /* target block when exception is raised */
22+
} _PyCfgInstruction;
23+
24+
typedef struct {
25+
int id;
26+
} _PyCfgJumpTargetLabel;
27+
28+
29+
typedef struct {
30+
struct _PyCfgBasicblock_ *handlers[CO_MAXBLOCKS+1];
31+
int depth;
32+
} _PyCfgExceptStack;
33+
34+
typedef struct _PyCfgBasicblock_ {
35+
/* Each basicblock in a compilation unit is linked via b_list in the
36+
reverse order that the block are allocated. b_list points to the next
37+
block, not to be confused with b_next, which is next by control flow. */
38+
struct _PyCfgBasicblock_ *b_list;
39+
/* The label of this block if it is a jump target, -1 otherwise */
40+
_PyCfgJumpTargetLabel b_label;
41+
/* Exception stack at start of block, used by assembler to create the exception handling table */
42+
_PyCfgExceptStack *b_exceptstack;
43+
/* pointer to an array of instructions, initially NULL */
44+
_PyCfgInstruction *b_instr;
45+
/* If b_next is non-NULL, it is a pointer to the next
46+
block reached by normal control flow. */
47+
struct _PyCfgBasicblock_ *b_next;
48+
/* number of instructions used */
49+
int b_iused;
50+
/* length of instruction array (b_instr) */
51+
int b_ialloc;
52+
/* Used by add_checks_for_loads_of_unknown_variables */
53+
uint64_t b_unsafe_locals_mask;
54+
/* Number of predecessors that a block has. */
55+
int b_predecessors;
56+
/* depth of stack upon entry of block, computed by stackdepth() */
57+
int b_startdepth;
58+
/* instruction offset for block, computed by assemble_jump_offsets() */
59+
int b_offset;
60+
/* Basic block is an exception handler that preserves lasti */
61+
unsigned b_preserve_lasti : 1;
62+
/* Used by compiler passes to mark whether they have visited a basic block. */
63+
unsigned b_visited : 1;
64+
/* b_except_handler is used by the cold-detection algorithm to mark exception targets */
65+
unsigned b_except_handler : 1;
66+
/* b_cold is true if this block is not perf critical (like an exception handler) */
67+
unsigned b_cold : 1;
68+
/* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */
69+
unsigned b_warm : 1;
70+
} _PyCfgBasicblock;
71+
72+
int _PyBasicblock_InsertInstruction(_PyCfgBasicblock *block, int pos, _PyCfgInstruction *instr);
73+
74+
typedef struct cfg_builder_ {
75+
/* The entryblock, at which control flow begins. All blocks of the
76+
CFG are reachable through the b_next links */
77+
_PyCfgBasicblock *g_entryblock;
78+
/* Pointer to the most recently allocated block. By following
79+
b_list links, you can reach all allocated blocks. */
80+
_PyCfgBasicblock *g_block_list;
81+
/* pointer to the block currently being constructed */
82+
_PyCfgBasicblock *g_curblock;
83+
/* label for the next instruction to be placed */
84+
_PyCfgJumpTargetLabel g_current_label;
85+
} _PyCfgBuilder;
86+
87+
int _PyCfgBuilder_UseLabel(_PyCfgBuilder *g, _PyCfgJumpTargetLabel lbl);
88+
int _PyCfgBuilder_Addop(_PyCfgBuilder *g, int opcode, int oparg, _PyCompilerSrcLocation loc);
89+
90+
int _PyCfgBuilder_Init(_PyCfgBuilder *g);
91+
void _PyCfgBuilder_Fini(_PyCfgBuilder *g);
92+
93+
_PyCfgInstruction* _PyCfg_BasicblockLastInstr(const _PyCfgBasicblock *b);
94+
int _PyCfg_OptimizeCodeUnit(_PyCfgBuilder *g, PyObject *consts, PyObject *const_cache,
95+
int code_flags, int nlocals, int nparams);
96+
int _PyCfg_Stackdepth(_PyCfgBasicblock *entryblock, int code_flags);
97+
void _PyCfg_ConvertExceptionHandlersToNops(_PyCfgBasicblock *entryblock);
98+
int _PyCfg_ResolveLineNumbers(_PyCfgBuilder *g, int firstlineno);
99+
void _PyCfg_ResolveJumpOffsets(_PyCfgBasicblock *entryblock);
100+
int _PyCfg_NormalizeJumps(_PyCfgBuilder *g);
101+
int _PyCfg_InstrSize(_PyCfgInstruction *instruction);
102+
103+
104+
static inline int
105+
basicblock_nofallthrough(const _PyCfgBasicblock *b) {
106+
_PyCfgInstruction *last = _PyCfg_BasicblockLastInstr(b);
107+
return (last &&
108+
(IS_SCOPE_EXIT_OPCODE(last->i_opcode) ||
109+
IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)));
110+
}
111+
112+
#define BB_NO_FALLTHROUGH(B) (basicblock_nofallthrough(B))
113+
#define BB_HAS_FALLTHROUGH(B) (!basicblock_nofallthrough(B))
114+
115+
116+
#ifdef __cplusplus
117+
}
118+
#endif
119+
#endif /* !Py_INTERNAL_CFG_H */

Include/internal/pycore_compile.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ extern int _PyAST_Optimize(
3333
struct _arena *arena,
3434
_PyASTOptimizeState *state);
3535

36+
/* Utility for a number of growing arrays used in the compiler */
37+
int _PyCompile_EnsureArrayLargeEnough(
38+
int idx,
39+
void **arr_,
40+
int *alloc,
41+
int default_alloc,
42+
size_t item_size);
43+
44+
int _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj);
45+
3646
/* Access compiler internals for unit testing */
3747

3848
PyAPI_FUNC(PyObject*) _PyCompile_CodeGen(

Include/internal/pycore_opcode.h

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

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ PYTHON_OBJS= \
374374
Python/ast_unparse.o \
375375
Python/bltinmodule.o \
376376
Python/ceval.o \
377+
Python/cfg.o \
377378
Python/codecs.o \
378379
Python/compile.o \
379380
Python/context.o \

0 commit comments

Comments
 (0)