1 /* 2 +----------------------------------------------------------------------+ 3 | Zend Engine, CFG - Control Flow Graph | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1998-2018 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Dmitry Stogov <dmitry@zend.com> | 16 +----------------------------------------------------------------------+ 17 */ 18 19 #ifndef ZEND_CFG_H 20 #define ZEND_CFG_H 21 22 /* zend_basic_bloc.flags */ 23 #define ZEND_BB_START (1<<0) /* fist block */ 24 #define ZEND_BB_FOLLOW (1<<1) /* follows the next block */ 25 #define ZEND_BB_TARGET (1<<2) /* jump taget */ 26 #define ZEND_BB_EXIT (1<<3) /* without successors */ 27 #define ZEND_BB_ENTRY (1<<4) /* stackless entry */ 28 #define ZEND_BB_TRY (1<<5) /* start of try block */ 29 #define ZEND_BB_CATCH (1<<6) /* start of catch block */ 30 #define ZEND_BB_FINALLY (1<<7) /* start of finally block */ 31 #define ZEND_BB_FINALLY_END (1<<8) /* end of finally block */ 32 #define ZEND_BB_GEN_VAR (1<<9) /* start of live range */ 33 #define ZEND_BB_KILL_VAR (1<<10) /* end of live range */ 34 #define ZEND_BB_UNREACHABLE_FREE (1<<11) /* unreachable loop free */ 35 #define ZEND_BB_RECV_ENTRY (1<<12) /* RECV entry */ 36 37 #define ZEND_BB_LOOP_HEADER (1<<16) 38 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17) 39 40 #define ZEND_BB_REACHABLE (1<<31) 41 42 #define ZEND_BB_PROTECTED (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR) 43 44 typedef struct _zend_basic_block { 45 int *successors; /* successor block indices */ 46 uint32_t flags; 47 uint32_t start; /* first opcode number */ 48 uint32_t len; /* number of opcodes */ 49 int successors_count; /* number of successors */ 50 int predecessors_count; /* number of predecessors */ 51 int predecessor_offset; /* offset of 1-st predecessor */ 52 int idom; /* immediate dominator block */ 53 int loop_header; /* closest loop header, or -1 */ 54 int level; /* steps away from the entry in the dom. tree */ 55 int children; /* list of dominated blocks */ 56 int next_child; /* next dominated block */ 57 int successors_storage[2]; /* up to 2 successor blocks */ 58 } zend_basic_block; 59 60 /* 61 +------------+---+---+---+---+---+ 62 | |OP1|OP2|EXT| 0 | 1 | 63 +------------+---+---+---+---+---+ 64 |JMP |ADR| | |OP1| - | 65 |JMPZ | |ADR| |OP2|FOL| 66 |JMPNZ | |ADR| |OP2|FOL| 67 |JMPZNZ | |ADR|ADR|OP2|EXT| 68 |JMPZ_EX | |ADR| |OP2|FOL| 69 |JMPNZ_EX | |ADR| |OP2|FOL| 70 |JMP_SET | |ADR| |OP2|FOL| 71 |COALESCE | |ADR| |OP2|FOL| 72 |ASSERT_CHK | |ADR| |OP2|FOL| 73 |NEW | |ADR| |OP2|FOL| 74 |DCL_ANON* |ADR| | |OP1|FOL| 75 |FE_RESET_* | |ADR| |OP2|FOL| 76 |FE_FETCH_* | | |ADR|EXT|FOL| 77 |CATCH | | |ADR|EXT|FOL| 78 |FAST_CALL |ADR| | |OP1|FOL| 79 |FAST_RET | | | | - | - | 80 |RETURN* | | | | - | - | 81 |EXIT | | | | - | - | 82 |THROW | | | | - | - | 83 |* | | | |FOL| - | 84 +------------+---+---+---+---+---+ 85 */ 86 87 typedef struct _zend_cfg { 88 int blocks_count; /* number of basic blocks */ 89 int edges_count; /* number of edges */ 90 zend_basic_block *blocks; /* array of basic blocks */ 91 int *predecessors; 92 uint32_t *map; 93 unsigned int split_at_live_ranges : 1; 94 unsigned int split_at_calls : 1; 95 unsigned int split_at_recv : 1; 96 unsigned int dynamic : 1; /* accesses varables by name */ 97 unsigned int vararg : 1; /* uses func_get_args() */ 98 } zend_cfg; 99 100 /* Build Flags */ 101 #define ZEND_RT_CONSTANTS (1<<31) 102 #define ZEND_CFG_STACKLESS (1<<30) 103 #define ZEND_SSA_DEBUG_LIVENESS (1<<29) 104 #define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28) 105 #define ZEND_SSA_RC_INFERENCE (1<<27) 106 #define ZEND_CFG_SPLIT_AT_LIVE_RANGES (1<<26) 107 #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25) 108 #define ZEND_CFG_RECV_ENTRY (1<<24) 109 #define ZEND_CALL_TREE (1<<23) 110 #define ZEND_SSA_USE_CV_RESULTS (1<<22) 111 112 #define CRT_CONSTANT_EX(op_array, node, rt_constants) \ 113 ((rt_constants) ? \ 114 RT_CONSTANT(op_array, (node)) \ 115 : \ 116 CT_CONSTANT_EX(op_array, (node).constant) \ 117 ) 118 119 #define CRT_CONSTANT(node) \ 120 CRT_CONSTANT_EX(op_array, node, (build_flags & ZEND_RT_CONSTANTS)) 121 122 #define RETURN_VALUE_USED(opline) \ 123 ((opline)->result_type != IS_UNUSED) 124 125 BEGIN_EXTERN_C() 126 127 int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg, uint32_t *func_flags); 128 void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg); 129 int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg); 130 int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg); 131 int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32_t *flags); 132 133 END_EXTERN_C() 134 135 #endif /* ZEND_CFG_H */ 136 137 /* 138 * Local variables: 139 * tab-width: 4 140 * c-basic-offset: 4 141 * indent-tabs-mode: t 142 * End: 143 */ 144