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 uint32_t flags; 46 uint32_t start; /* first opcode number */ 47 uint32_t len; /* number of opcodes */ 48 int successors[2]; /* up to 2 successor blocks */ 49 int predecessors_count; /* number of predecessors */ 50 int predecessor_offset; /* offset of 1-st predecessor */ 51 int idom; /* immediate dominator block */ 52 int loop_header; /* closest loop header, or -1 */ 53 int level; /* steps away from the entry in the dom. tree */ 54 int children; /* list of dominated blocks */ 55 int next_child; /* next dominated block */ 56 } zend_basic_block; 57 58 /* 59 +------------+---+---+---+---+---+ 60 | |OP1|OP2|EXT| 0 | 1 | 61 +------------+---+---+---+---+---+ 62 |JMP |ADR| | |OP1| - | 63 |JMPZ | |ADR| |OP2|FOL| 64 |JMPNZ | |ADR| |OP2|FOL| 65 |JMPZNZ | |ADR|ADR|OP2|EXT| 66 |JMPZ_EX | |ADR| |OP2|FOL| 67 |JMPNZ_EX | |ADR| |OP2|FOL| 68 |JMP_SET | |ADR| |OP2|FOL| 69 |COALESCE | |ADR| |OP2|FOL| 70 |ASSERT_CHK | |ADR| |OP2|FOL| 71 |NEW | |ADR| |OP2|FOL| 72 |DCL_ANON* |ADR| | |OP1|FOL| 73 |FE_RESET_* | |ADR| |OP2|FOL| 74 |FE_FETCH_* | | |ADR|EXT|FOL| 75 |CATCH | | |ADR|EXT|FOL| 76 |FAST_CALL |ADR| | |OP1|FOL| 77 |FAST_RET | | | | - | - | 78 |RETURN* | | | | - | - | 79 |EXIT | | | | - | - | 80 |THROW | | | | - | - | 81 |* | | | |FOL| - | 82 +------------+---+---+---+---+---+ 83 */ 84 85 typedef struct _zend_cfg { 86 int blocks_count; /* number of basic blocks */ 87 zend_basic_block *blocks; /* array of basic blocks */ 88 int *predecessors; 89 uint32_t *map; 90 unsigned int split_at_live_ranges : 1; 91 unsigned int split_at_calls : 1; 92 unsigned int split_at_recv : 1; 93 } zend_cfg; 94 95 /* Build Flags */ 96 #define ZEND_RT_CONSTANTS (1<<31) 97 #define ZEND_CFG_STACKLESS (1<<30) 98 #define ZEND_SSA_DEBUG_LIVENESS (1<<29) 99 #define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28) 100 #define ZEND_SSA_RC_INFERENCE (1<<27) 101 #define ZEND_CFG_SPLIT_AT_LIVE_RANGES (1<<26) 102 #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25) 103 #define ZEND_CFG_RECV_ENTRY (1<<24) 104 #define ZEND_CALL_TREE (1<<23) 105 106 #define CRT_CONSTANT_EX(op_array, node, rt_constants) \ 107 ((rt_constants) ? \ 108 RT_CONSTANT(op_array, (node)) \ 109 : \ 110 CT_CONSTANT_EX(op_array, (node).constant) \ 111 ) 112 113 #define CRT_CONSTANT(node) \ 114 CRT_CONSTANT_EX(op_array, node, (build_flags & ZEND_RT_CONSTANTS)) 115 116 #define RETURN_VALUE_USED(opline) \ 117 ((opline)->result_type != IS_UNUSED) 118 119 BEGIN_EXTERN_C() 120 121 int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg, uint32_t *func_flags); 122 void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg); 123 int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg); 124 int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg); 125 int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32_t *flags); 126 127 END_EXTERN_C() 128 129 #endif /* ZEND_CFG_H */ 130 131 /* 132 * Local variables: 133 * tab-width: 4 134 * c-basic-offset: 4 135 * indent-tabs-mode: t 136 * End: 137 */ 138