forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pythongh-87092: move CFG related code from compile.c to flowgraph.c (p…
- Loading branch information
1 parent
b0422e1
commit 80163e1
Showing
14 changed files
with
2,580 additions
and
2,495 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#ifndef Py_INTERNAL_CFG_H | ||
#define Py_INTERNAL_CFG_H | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifndef Py_BUILD_CORE | ||
# error "this header requires Py_BUILD_CORE define" | ||
#endif | ||
|
||
#include "pycore_opcode_utils.h" | ||
|
||
static const _PyCompilerSrcLocation NO_LOCATION = {-1, -1, -1, -1}; | ||
|
||
typedef struct { | ||
int i_opcode; | ||
int i_oparg; | ||
_PyCompilerSrcLocation i_loc; | ||
struct _PyCfgBasicblock_ *i_target; /* target block (if jump instruction) */ | ||
struct _PyCfgBasicblock_ *i_except; /* target block when exception is raised */ | ||
} _PyCfgInstruction; | ||
|
||
typedef struct { | ||
int id; | ||
} _PyCfgJumpTargetLabel; | ||
|
||
|
||
typedef struct { | ||
struct _PyCfgBasicblock_ *handlers[CO_MAXBLOCKS+1]; | ||
int depth; | ||
} _PyCfgExceptStack; | ||
|
||
typedef struct _PyCfgBasicblock_ { | ||
/* Each basicblock in a compilation unit is linked via b_list in the | ||
reverse order that the block are allocated. b_list points to the next | ||
block, not to be confused with b_next, which is next by control flow. */ | ||
struct _PyCfgBasicblock_ *b_list; | ||
/* The label of this block if it is a jump target, -1 otherwise */ | ||
_PyCfgJumpTargetLabel b_label; | ||
/* Exception stack at start of block, used by assembler to create the exception handling table */ | ||
_PyCfgExceptStack *b_exceptstack; | ||
/* pointer to an array of instructions, initially NULL */ | ||
_PyCfgInstruction *b_instr; | ||
/* If b_next is non-NULL, it is a pointer to the next | ||
block reached by normal control flow. */ | ||
struct _PyCfgBasicblock_ *b_next; | ||
/* number of instructions used */ | ||
int b_iused; | ||
/* length of instruction array (b_instr) */ | ||
int b_ialloc; | ||
/* Used by add_checks_for_loads_of_unknown_variables */ | ||
uint64_t b_unsafe_locals_mask; | ||
/* Number of predecessors that a block has. */ | ||
int b_predecessors; | ||
/* depth of stack upon entry of block, computed by stackdepth() */ | ||
int b_startdepth; | ||
/* instruction offset for block, computed by assemble_jump_offsets() */ | ||
int b_offset; | ||
/* Basic block is an exception handler that preserves lasti */ | ||
unsigned b_preserve_lasti : 1; | ||
/* Used by compiler passes to mark whether they have visited a basic block. */ | ||
unsigned b_visited : 1; | ||
/* b_except_handler is used by the cold-detection algorithm to mark exception targets */ | ||
unsigned b_except_handler : 1; | ||
/* b_cold is true if this block is not perf critical (like an exception handler) */ | ||
unsigned b_cold : 1; | ||
/* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */ | ||
unsigned b_warm : 1; | ||
} _PyCfgBasicblock; | ||
|
||
int _PyBasicblock_InsertInstruction(_PyCfgBasicblock *block, int pos, _PyCfgInstruction *instr); | ||
|
||
typedef struct cfg_builder_ { | ||
/* The entryblock, at which control flow begins. All blocks of the | ||
CFG are reachable through the b_next links */ | ||
_PyCfgBasicblock *g_entryblock; | ||
/* Pointer to the most recently allocated block. By following | ||
b_list links, you can reach all allocated blocks. */ | ||
_PyCfgBasicblock *g_block_list; | ||
/* pointer to the block currently being constructed */ | ||
_PyCfgBasicblock *g_curblock; | ||
/* label for the next instruction to be placed */ | ||
_PyCfgJumpTargetLabel g_current_label; | ||
} _PyCfgBuilder; | ||
|
||
int _PyCfgBuilder_UseLabel(_PyCfgBuilder *g, _PyCfgJumpTargetLabel lbl); | ||
int _PyCfgBuilder_Addop(_PyCfgBuilder *g, int opcode, int oparg, _PyCompilerSrcLocation loc); | ||
|
||
int _PyCfgBuilder_Init(_PyCfgBuilder *g); | ||
void _PyCfgBuilder_Fini(_PyCfgBuilder *g); | ||
|
||
_PyCfgInstruction* _PyCfg_BasicblockLastInstr(const _PyCfgBasicblock *b); | ||
int _PyCfg_OptimizeCodeUnit(_PyCfgBuilder *g, PyObject *consts, PyObject *const_cache, | ||
int code_flags, int nlocals, int nparams); | ||
int _PyCfg_Stackdepth(_PyCfgBasicblock *entryblock, int code_flags); | ||
void _PyCfg_ConvertExceptionHandlersToNops(_PyCfgBasicblock *entryblock); | ||
int _PyCfg_ResolveLineNumbers(_PyCfgBuilder *g, int firstlineno); | ||
int _PyCfg_ResolveJumps(_PyCfgBuilder *g); | ||
int _PyCfg_InstrSize(_PyCfgInstruction *instruction); | ||
|
||
|
||
static inline int | ||
basicblock_nofallthrough(const _PyCfgBasicblock *b) { | ||
_PyCfgInstruction *last = _PyCfg_BasicblockLastInstr(b); | ||
return (last && | ||
(IS_SCOPE_EXIT_OPCODE(last->i_opcode) || | ||
IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode))); | ||
} | ||
|
||
#define BB_NO_FALLTHROUGH(B) (basicblock_nofallthrough(B)) | ||
#define BB_HAS_FALLTHROUGH(B) (!basicblock_nofallthrough(B)) | ||
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif /* !Py_INTERNAL_CFG_H */ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#ifndef Py_INTERNAL_OPCODE_UTILS_H | ||
#define Py_INTERNAL_OPCODE_UTILS_H | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifndef Py_BUILD_CORE | ||
# error "this header requires Py_BUILD_CORE define" | ||
#endif | ||
|
||
#include "pycore_opcode.h" // _PyOpcode_RelativeJump | ||
|
||
|
||
#define MAX_REAL_OPCODE 254 | ||
|
||
#define IS_WITHIN_OPCODE_RANGE(opcode) \ | ||
(((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \ | ||
IS_PSEUDO_OPCODE(opcode)) | ||
|
||
#define IS_JUMP_OPCODE(opcode) \ | ||
is_bit_set_in_table(_PyOpcode_Jump, opcode) | ||
|
||
#define IS_BLOCK_PUSH_OPCODE(opcode) \ | ||
((opcode) == SETUP_FINALLY || \ | ||
(opcode) == SETUP_WITH || \ | ||
(opcode) == SETUP_CLEANUP) | ||
|
||
#define HAS_TARGET(opcode) \ | ||
(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)) | ||
|
||
/* opcodes that must be last in the basicblock */ | ||
#define IS_TERMINATOR_OPCODE(opcode) \ | ||
(IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) | ||
|
||
/* opcodes which are not emitted in codegen stage, only by the assembler */ | ||
#define IS_ASSEMBLER_OPCODE(opcode) \ | ||
((opcode) == JUMP_FORWARD || \ | ||
(opcode) == JUMP_BACKWARD || \ | ||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT) | ||
|
||
#define IS_BACKWARDS_JUMP_OPCODE(opcode) \ | ||
((opcode) == JUMP_BACKWARD || \ | ||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT) | ||
|
||
#define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \ | ||
((opcode) == JUMP || \ | ||
(opcode) == JUMP_NO_INTERRUPT || \ | ||
(opcode) == JUMP_FORWARD || \ | ||
(opcode) == JUMP_BACKWARD || \ | ||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT) | ||
|
||
#define IS_SCOPE_EXIT_OPCODE(opcode) \ | ||
((opcode) == RETURN_VALUE || \ | ||
(opcode) == RETURN_CONST || \ | ||
(opcode) == RAISE_VARARGS || \ | ||
(opcode) == RERAISE) | ||
|
||
#define IS_SUPERINSTRUCTION_OPCODE(opcode) \ | ||
((opcode) == LOAD_FAST__LOAD_FAST || \ | ||
(opcode) == LOAD_FAST__LOAD_CONST || \ | ||
(opcode) == LOAD_CONST__LOAD_FAST || \ | ||
(opcode) == STORE_FAST__LOAD_FAST || \ | ||
(opcode) == STORE_FAST__STORE_FAST) | ||
|
||
|
||
#define LOG_BITS_PER_INT 5 | ||
#define MASK_LOW_LOG_BITS 31 | ||
|
||
static inline int | ||
is_bit_set_in_table(const uint32_t *table, int bitindex) { | ||
/* Is the relevant bit set in the relevant word? */ | ||
/* 512 bits fit into 9 32-bits words. | ||
* Word is indexed by (bitindex>>ln(size of int in bits)). | ||
* Bit within word is the low bits of bitindex. | ||
*/ | ||
if (bitindex >= 0 && bitindex < 512) { | ||
uint32_t word = table[bitindex >> LOG_BITS_PER_INT]; | ||
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1; | ||
} | ||
else { | ||
return 0; | ||
} | ||
} | ||
|
||
#undef LOG_BITS_PER_INT | ||
#undef MASK_LOW_LOG_BITS | ||
|
||
#define IS_RELATIVE_JUMP(opcode) (is_bit_set_in_table(_PyOpcode_RelativeJump, opcode)) | ||
|
||
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif /* !Py_INTERNAL_OPCODE_UTILS_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.