pycore_flowgraph.h 4.5 KB

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