1 /* 2 +----------------------------------------------------------------------+ 3 | Zend Engine, CFG - Control Flow Graph | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 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 | https://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@php.net> | 16 +----------------------------------------------------------------------+ 17 */ 18 19 #ifndef ZEND_CFG_H 20 #define ZEND_CFG_H 21 22 /* zend_basic_block.flags */ 23 #define ZEND_BB_START (1<<0) /* first block */ 24 #define ZEND_BB_FOLLOW (1<<1) /* follows the next block */ 25 #define ZEND_BB_TARGET (1<<2) /* jump target */ 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_UNREACHABLE_FREE (1<<11) /* unreachable loop free */ 33 #define ZEND_BB_RECV_ENTRY (1<<12) /* RECV entry */ 34 35 #define ZEND_BB_LOOP_HEADER (1<<16) 36 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17) 37 38 #define ZEND_BB_REACHABLE (1U<<31) 39 40 #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_UNREACHABLE_FREE) 41 42 typedef struct _zend_basic_block { 43 int *successors; /* successor block indices */ 44 uint32_t flags; 45 uint32_t start; /* first opcode number */ 46 uint32_t len; /* number of opcodes */ 47 int successors_count; /* number of successors */ 48 int predecessors_count; /* number of predecessors */ 49 int predecessor_offset; /* offset of 1-st predecessor */ 50 int idom; /* immediate dominator block */ 51 int loop_header; /* closest loop header, or -1 */ 52 int level; /* steps away from the entry in the dom. tree */ 53 int children; /* list of dominated blocks */ 54 int next_child; /* next dominated block */ 55 int successors_storage[2]; /* up to 2 successor blocks */ 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 |JMPZ_EX | |ADR| |OP2|FOL| 66 |JMPNZ_EX | |ADR| |OP2|FOL| 67 |JMP_SET | |ADR| |OP2|FOL| 68 |COALESCE | |ADR| |OP2|FOL| 69 |ASSERT_CHK | |ADR| |OP2|FOL| 70 |NEW | |ADR| |OP2|FOL| 71 |DCL_ANON* |ADR| | |OP1|FOL| 72 |FE_RESET_* | |ADR| |OP2|FOL| 73 |FE_FETCH_* | | |ADR|EXT|FOL| 74 |CATCH | | |ADR|EXT|FOL| 75 |FAST_CALL |ADR| | |OP1|FOL| 76 |FAST_RET | | | | - | - | 77 |RETURN* | | | | - | - | 78 |EXIT | | | | - | - | 79 |THROW | | | | - | - | 80 |* | | | |FOL| - | 81 +------------+---+---+---+---+---+ 82 */ 83 84 typedef struct _zend_cfg { 85 int blocks_count; /* number of basic blocks */ 86 int edges_count; /* number of edges */ 87 zend_basic_block *blocks; /* array of basic blocks */ 88 int *predecessors; 89 uint32_t *map; 90 uint32_t flags; 91 } zend_cfg; 92 93 /* Build Flags */ 94 #define ZEND_CFG_STACKLESS (1<<30) 95 #define ZEND_SSA_DEBUG_LIVENESS (1<<29) 96 #define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28) 97 #define ZEND_SSA_RC_INFERENCE (1<<27) 98 #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25) 99 #define ZEND_CFG_RECV_ENTRY (1<<24) 100 #define ZEND_CALL_TREE (1<<23) 101 #define ZEND_SSA_USE_CV_RESULTS (1<<22) 102 103 #define CRT_CONSTANT_EX(op_array, opline, node) \ 104 (((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) ? \ 105 RT_CONSTANT(opline, (node)) \ 106 : \ 107 CT_CONSTANT_EX(op_array, (node).constant) \ 108 ) 109 110 #define CRT_CONSTANT(node) \ 111 CRT_CONSTANT_EX(op_array, opline, node) 112 113 #define RETURN_VALUE_USED(opline) \ 114 ((opline)->result_type != IS_UNUSED) 115 116 BEGIN_EXTERN_C() 117 118 ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg); 119 void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg); 120 ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg); 121 ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg); 122 ZEND_API void zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg); 123 124 END_EXTERN_C() 125 126 #endif /* ZEND_CFG_H */ 127