summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.h')
-rw-r--r--Zend/zend_compile.h195
1 files changed, 108 insertions, 87 deletions
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index a3bc17f425..fda7fe6014 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -31,16 +31,16 @@
#include "zend_llist.h"
-#define DEBUG_ZEND 0
-
#define SET_UNUSED(op) op ## _type = IS_UNUSED
#define MAKE_NOP(opline) do { \
- opline->opcode = ZEND_NOP; \
- memset(&opline->result, 0, sizeof(opline->result)); \
- memset(&opline->op1, 0, sizeof(opline->op1)); \
- memset(&opline->op2, 0, sizeof(opline->op2)); \
- opline->result_type = opline->op1_type = opline->op2_type = IS_UNUSED; \
+ (opline)->op1.num = 0; \
+ (opline)->op2.num = 0; \
+ (opline)->result.num = 0; \
+ (opline)->opcode = ZEND_NOP; \
+ (opline)->op1_type = IS_UNUSED; \
+ (opline)->op2_type = IS_UNUSED; \
+ (opline)->result_type = IS_UNUSED; \
} while (0)
#define RESET_DOC_COMMENT() do { \
@@ -109,18 +109,6 @@ typedef struct _zend_declarables {
zend_long ticks;
} zend_declarables;
-/* Compilation context that is different for each op array. */
-typedef struct _zend_oparray_context {
- uint32_t opcodes_size;
- int vars_size;
- int literals_size;
- int current_brk_cont;
- int backpatch_count;
- int in_finally;
- uint32_t fast_call_var;
- HashTable *labels;
-} zend_oparray_context;
-
/* Compilation context that is different for each file, but shared between op arrays. */
typedef struct _zend_file_context {
zend_declarables declarables;
@@ -183,6 +171,33 @@ typedef struct _zend_try_catch_element {
uint32_t finally_end;
} zend_try_catch_element;
+#define ZEND_LIVE_TMPVAR 0
+#define ZEND_LIVE_LOOP 1
+#define ZEND_LIVE_SILENCE 2
+#define ZEND_LIVE_ROPE 3
+#define ZEND_LIVE_MASK 3
+
+typedef struct _zend_live_range {
+ uint32_t var; /* low bits are used for variable type (ZEND_LIVE_* macros) */
+ uint32_t start;
+ uint32_t end;
+} zend_live_range;
+
+/* Compilation context that is different for each op array. */
+typedef struct _zend_oparray_context {
+ uint32_t opcodes_size;
+ int vars_size;
+ int literals_size;
+ int backpatch_count;
+ int in_finally;
+ uint32_t fast_call_var;
+ uint32_t try_catch_offset;
+ int current_brk_cont;
+ int last_brk_cont;
+ zend_brk_cont_element *brk_cont_array;
+ HashTable *labels;
+} zend_oparray_context;
+
/* method flags (types) */
#define ZEND_ACC_STATIC 0x01
#define ZEND_ACC_ABSTRACT 0x02
@@ -259,7 +274,7 @@ typedef struct _zend_try_catch_element {
/* class has magic methods __get/__set/__unset/__isset that use guards */
#define ZEND_ACC_USE_GUARDS 0x1000000
-/* function has arguments with type hinting */
+/* function has typed arguments */
#define ZEND_ACC_HAS_TYPE_HINTS 0x10000000
/* op_array has finally blocks */
@@ -268,7 +283,7 @@ typedef struct _zend_try_catch_element {
/* internal function is allocated at arena */
#define ZEND_ACC_ARENA_ALLOCATED 0x20000000
-/* Function has a return type hint (or class has such non-private function) */
+/* Function has a return type (or class has such non-private function) */
#define ZEND_ACC_HAS_RETURN_TYPE 0x40000000
/* op_array uses strict mode types */
@@ -294,6 +309,12 @@ typedef struct _zend_property_info {
#define OBJ_PROP_TO_NUM(offset) \
((offset - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval))
+typedef struct _zend_class_constant {
+ zval value; /* access flags are stored in reserved: zval.u2.access_flags */
+ zend_string *doc_comment;
+ zend_class_entry *ce;
+} zend_class_constant;
+
/* arg_info for internal functions */
typedef struct _zend_internal_arg_info {
const char *name;
@@ -317,7 +338,7 @@ typedef struct _zend_arg_info {
/* the following structure repeats the layout of zend_internal_arg_info,
* but its fields have different meaning. It's used as the first element of
* arg_info array to define properties of internal functions.
- * It's also used for return type hinting.
+ * It's also used for the return type.
*/
typedef struct _zend_internal_function_info {
zend_uintptr_t required_num_args;
@@ -352,9 +373,9 @@ struct _zend_op_array {
uint32_t T;
zend_string **vars;
- int last_brk_cont;
+ int last_live_range;
int last_try_catch;
- zend_brk_cont_element *brk_cont_array;
+ zend_live_range *live_range;
zend_try_catch_element *try_catch_array;
/* static variables support */
@@ -394,12 +415,14 @@ typedef struct _zend_internal_function {
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
struct _zend_module_entry *module;
+ void *reserved[ZEND_MAX_RESERVED_RESOURCES];
} zend_internal_function;
#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? ZSTR_VAL((function)->common.scope->name) : "")
union _zend_function {
zend_uchar type; /* MUST be the first element of this struct! */
+ uint32_t quick_arg_flags;
struct {
zend_uchar type; /* never used */
@@ -428,17 +451,16 @@ struct _zend_execute_data {
const zend_op *opline; /* executed opline */
zend_execute_data *call; /* current call */
zval *return_value;
- zend_function *func; /* executed op_array */
- zval This;
+ zend_function *func; /* executed funcrion */
+ zval This; /* this + call_info + num_args */
+ zend_execute_data *prev_execute_data;
+ zend_array *symbol_table;
#if ZEND_EX_USE_RUN_TIME_CACHE
- void **run_time_cache;
+ void **run_time_cache; /* cache op_array->run_time_cache */
#endif
#if ZEND_EX_USE_LITERALS
- zval *literals;
+ zval *literals; /* cache op_array->literals */
#endif
- zend_class_entry *called_scope;
- zend_execute_data *prev_execute_data;
- zend_array *symbol_table;
};
#define ZEND_CALL_FUNCTION (0 << 0)
@@ -447,13 +469,17 @@ struct _zend_execute_data {
#define ZEND_CALL_TOP (1 << 1)
#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) /* equal to IS_TYPE_REFCOUNTED */
#define ZEND_CALL_CTOR (1 << 3)
-#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4)
+#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 4)
#define ZEND_CALL_CLOSURE (1 << 5)
#define ZEND_CALL_RELEASE_THIS (1 << 6)
#define ZEND_CALL_ALLOCATED (1 << 7)
+#define ZEND_CALL_GENERATOR (1 << 8)
+#define ZEND_CALL_DYNAMIC (1 << 9)
+
+#define ZEND_CALL_INFO_SHIFT 16
#define ZEND_CALL_INFO(call) \
- (Z_TYPE_INFO((call)->This) >> 24)
+ (Z_TYPE_INFO((call)->This) >> ZEND_CALL_INFO_SHIFT)
#define ZEND_CALL_KIND_EX(call_info) \
(call_info & (ZEND_CALL_CODE | ZEND_CALL_TOP))
@@ -461,12 +487,12 @@ struct _zend_execute_data {
#define ZEND_CALL_KIND(call) \
ZEND_CALL_KIND_EX(ZEND_CALL_INFO(call))
-#define ZEND_SET_CALL_INFO(call, info) do { \
- Z_TYPE_INFO((call)->This) = IS_OBJECT_EX | ((info) << 24); \
+#define ZEND_SET_CALL_INFO(call, object, info) do { \
+ Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << ZEND_CALL_INFO_SHIFT); \
} while (0)
#define ZEND_ADD_CALL_FLAG_EX(call_info, flag) do { \
- call_info |= ((flag) << 24); \
+ call_info |= ((flag) << ZEND_CALL_INFO_SHIFT); \
} while (0)
#define ZEND_ADD_CALL_FLAG(call, flag) do { \
@@ -511,7 +537,10 @@ struct _zend_execute_data {
#define EX_VAR(n) ZEND_CALL_VAR(execute_data, n)
#define EX_VAR_NUM(n) ZEND_CALL_VAR_NUM(execute_data, n)
-#define EX_VAR_TO_NUM(n) (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
+#define EX_VAR_TO_NUM(n) ((uint32_t)(ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0)))
+
+#define ZEND_OPLINE_TO_OFFSET(opline, target) \
+ ((char*)(target) - (char*)(opline))
#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
@@ -528,6 +557,10 @@ struct _zend_execute_data {
# define OP_JMP_ADDR(opline, node) \
(node).jmp_addr
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+ (node).jmp_addr = (val); \
+ } while (0)
+
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
@@ -544,6 +577,10 @@ struct _zend_execute_data {
# define OP_JMP_ADDR(opline, node) \
ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+ (node).jmp_offset = ZEND_OPLINE_TO_OFFSET(opline, val); \
+ } while (0)
+
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
@@ -649,8 +686,6 @@ struct _zend_execute_data {
#define IS_UNUSED (1<<3) /* Unused variable */
#define IS_CV (1<<4) /* Compiled variable */
-#define EXT_TYPE_UNUSED (1<<5)
-
#include "zend_globals.h"
BEGIN_EXTERN_C()
@@ -691,11 +726,10 @@ ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API binary_op_type get_binary_op(int opcode);
void zend_stop_lexing(void);
-void zend_emit_final_return(zval *zv);
+void zend_emit_final_return(int return_one);
zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag);
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag);
-zend_ast *zend_ast_append_doc_comment(zend_ast *list);
void zend_handle_encoding_declaration(zend_ast *ast);
/* parser-driven code generators */
@@ -712,7 +746,7 @@ void zend_do_extended_fcall_end(void);
void zend_verify_namespace(void);
-void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2);
+void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline);
ZEND_API void function_add_ref(zend_function *function);
@@ -723,6 +757,7 @@ ZEND_API void function_add_ref(zend_function *function);
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type);
ZEND_API zend_op_array *compile_string(zval *source_string, char *filename);
ZEND_API zend_op_array *compile_filename(int type, zval *filename);
+ZEND_API void zend_try_exception_handler();
ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...);
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle);
ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size);
@@ -751,15 +786,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char
zend_op *get_next_op(zend_op_array *op_array);
void init_op(zend_op *op);
int get_next_op_number(zend_op_array *op_array);
-int print_class(zend_class_entry *class_entry);
-void print_op_array(zend_op_array *op_array, int optimizations);
ZEND_API int pass_two(zend_op_array *op_array);
-zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array);
+zend_brk_cont_element *get_next_brk_cont_element(void);
ZEND_API zend_bool zend_is_compiling(void);
ZEND_API char *zend_make_compiled_string_description(const char *name);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
uint32_t zend_get_class_fetch_type(zend_string *name);
-ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc);
+ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc);
typedef zend_bool (*zend_auto_global_callback)(zend_string *name);
typedef struct _zend_auto_global {
@@ -801,16 +834,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_FETCH_CLASS_SILENT 0x0100
#define ZEND_FETCH_CLASS_EXCEPTION 0x0200
-/* variable parsing type (compile-time) */
-#define ZEND_PARSED_MEMBER (1<<0)
-#define ZEND_PARSED_METHOD_CALL (1<<1)
-#define ZEND_PARSED_STATIC_MEMBER (1<<2)
-#define ZEND_PARSED_FUNCTION_CALL (1<<3)
-#define ZEND_PARSED_VARIABLE (1<<4)
-#define ZEND_PARSED_REFERENCE_VARIABLE (1<<5)
-#define ZEND_PARSED_NEW (1<<6)
-#define ZEND_PARSED_LIST_EXPR (1<<7)
-
#define ZEND_PARAM_REF (1<<0)
#define ZEND_PARAM_VARIADIC (1<<1)
@@ -818,8 +841,7 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_NAME_NOT_FQ 1
#define ZEND_NAME_RELATIVE 2
-/* unset types */
-#define ZEND_UNSET_REG 0
+#define ZEND_TYPE_NULLABLE (1<<8)
/* var status for backpatching */
#define BP_VAR_R 0
@@ -828,7 +850,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define BP_VAR_IS 3
#define BP_VAR_FUNC_ARG 4
#define BP_VAR_UNSET 5
-#define BP_VAR_REF 6 /* right-hand side of by-ref assignment */
/* Bottom 3 bits are the type, top bits are arg num for BP_VAR_FUNC_ARG */
#define BP_VAR_SHIFT 3
@@ -859,10 +880,7 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
/* global/local fetches */
#define ZEND_FETCH_GLOBAL 0x00000000
#define ZEND_FETCH_LOCAL 0x10000000
-#define ZEND_FETCH_STATIC 0x20000000
-#define ZEND_FETCH_STATIC_MEMBER 0x30000000
#define ZEND_FETCH_GLOBAL_LOCK 0x40000000
-#define ZEND_FETCH_LEXICAL 0x50000000
#define ZEND_FETCH_TYPE_MASK 0x70000000
@@ -875,17 +893,14 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_FETCH_ARG_MASK 0x000fffff
-#define ZEND_MEMBER_FUNC_CALL 1<<0
-
-#define ZEND_ARG_SEND_BY_REF (1<<0)
-#define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)
-#define ZEND_ARG_SEND_FUNCTION (1<<2)
-#define ZEND_ARG_SEND_SILENT (1<<3)
+#define ZEND_FREE_ON_RETURN (1<<0)
#define ZEND_SEND_BY_VAL 0
#define ZEND_SEND_BY_REF 1
#define ZEND_SEND_PREFER_REF 2
+#define ZEND_DIM_IS 1
+
static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask)
{
arg_num--;
@@ -912,16 +927,16 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
#ifdef WORDS_BIGENDIAN
# define ZEND_SET_ARG_FLAG(zf, arg_num, mask) do { \
- *(uint32_t*)&(zf)->type |= ((mask) << ((arg_num) - 1) * 2); \
+ (zf)->quick_arg_flags |= ((mask) << ((arg_num) - 1) * 2); \
} while (0)
# define ZEND_CHECK_ARG_FLAG(zf, arg_num, mask) \
- (((*((uint32_t*)&((zf)->type))) >> (((arg_num) - 1) * 2)) & (mask))
+ (((zf)->quick_arg_flags >> (((arg_num) - 1) * 2)) & (mask))
#else
# define ZEND_SET_ARG_FLAG(zf, arg_num, mask) do { \
- *(uint32_t*)&(zf)->type |= (((mask) << 6) << (arg_num) * 2); \
+ (zf)->quick_arg_flags |= (((mask) << 6) << (arg_num) * 2); \
} while (0)
# define ZEND_CHECK_ARG_FLAG(zf, arg_num, mask) \
- (((*(uint32_t*)&(zf)->type) >> (((arg_num) + 3) * 2)) & (mask))
+ (((zf)->quick_arg_flags >> (((arg_num) + 3) * 2)) & (mask))
#endif
#define QUICK_ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
@@ -940,19 +955,14 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
#define ZEND_RETURNS_FUNCTION 1<<0
#define ZEND_RETURNS_VALUE 1<<1
-#define ZEND_FAST_RET_TO_CATCH 1
-#define ZEND_FAST_RET_TO_FINALLY 2
-
-#define ZEND_FAST_CALL_FROM_CATCH 1
-#define ZEND_FAST_CALL_FROM_FINALLY 2
-
#define ZEND_ARRAY_ELEMENT_REF (1<<0)
#define ZEND_ARRAY_NOT_PACKED (1<<1)
#define ZEND_ARRAY_SIZE_SHIFT 2
/* Pseudo-opcodes that are used only temporarily during compilation */
-#define ZEND_BRK 254
-#define ZEND_CONT 255
+#define ZEND_GOTO 253
+#define ZEND_BRK 254
+#define ZEND_CONT 255
END_EXTERN_C()
@@ -975,37 +985,48 @@ END_EXTERN_C()
* to change the default compiler behavior */
/* generate extended debug information */
-#define ZEND_COMPILE_EXTENDED_INFO (1<<0)
+#define ZEND_COMPILE_EXTENDED_INFO (1<<0)
/* call op_array handler of extendions */
#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
-#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
+#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
/* don't perform early binding for classes inherited form internal ones;
* in namespaces assume that internal class that doesn't exist at compile-time
* may apper in run-time */
-#define ZEND_COMPILE_IGNORE_INTERNAL_CLASSES (1<<3)
+#define ZEND_COMPILE_IGNORE_INTERNAL_CLASSES (1<<3)
/* generate ZEND_DECLARE_INHERITED_CLASS_DELAYED opcode to delay early binding */
-#define ZEND_COMPILE_DELAYED_BINDING (1<<4)
+#define ZEND_COMPILE_DELAYED_BINDING (1<<4)
/* disable constant substitution at compile-time */
-#define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<5)
+#define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<5)
/* disable usage of builtin instruction for strlen() */
-#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<6)
+#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<6)
/* disable substitution of persistent constants at compile-time */
#define ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION (1<<7)
+/* generate ZEND_INIT_FCALL_BY_NAME for userland functions instead of ZEND_INIT_FCALL */
+#define ZEND_COMPILE_IGNORE_USER_FUNCTIONS (1<<8)
+
+/* force IS_OBJ_USE_GUARDS for all classes */
+#define ZEND_COMPILE_GUARDS (1<<9)
+
+/* disable builtin special case function calls */
+#define ZEND_COMPILE_NO_BUILTINS (1<<10)
+
/* The default value for CG(compiler_options) */
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY
/* The default value for CG(compiler_options) during eval() */
#define ZEND_COMPILE_DEFAULT_FOR_EVAL 0
+ZEND_API zend_bool zend_binary_op_produces_numeric_string_error(uint32_t opcode, zval *op1, zval *op2);
+
#endif /* ZEND_COMPILE_H */
/*