1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 | Dmitry Stogov <dmitry@zend.com> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* $Id$ */
22
23 #include <stdio.h>
24
25 #include "zend.h"
26 #include "zend_alloc.h"
27 #include "zend_compile.h"
28 #include "zend_extensions.h"
29 #include "zend_API.h"
30
31 #include "zend_vm.h"
32
zend_extension_op_array_ctor_handler(zend_extension * extension,zend_op_array * op_array)33 static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array)
34 {
35 if (extension->op_array_ctor) {
36 extension->op_array_ctor(op_array);
37 }
38 }
39
zend_extension_op_array_dtor_handler(zend_extension * extension,zend_op_array * op_array)40 static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array)
41 {
42 if (extension->op_array_dtor) {
43 extension->op_array_dtor(op_array);
44 }
45 }
46
op_array_alloc_ops(zend_op_array * op_array,uint32_t size)47 static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
48 {
49 op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
50 }
51
init_op_array(zend_op_array * op_array,zend_uchar type,int initial_ops_size)52 void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
53 {
54 op_array->type = type;
55 op_array->arg_flags[0] = 0;
56 op_array->arg_flags[1] = 0;
57 op_array->arg_flags[2] = 0;
58
59 op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
60 *op_array->refcount = 1;
61 op_array->last = 0;
62 op_array->opcodes = NULL;
63 op_array_alloc_ops(op_array, initial_ops_size);
64
65 op_array->last_var = 0;
66 op_array->vars = NULL;
67
68 op_array->T = 0;
69
70 op_array->function_name = NULL;
71 op_array->filename = zend_get_compiled_filename();
72 op_array->doc_comment = NULL;
73
74 op_array->arg_info = NULL;
75 op_array->num_args = 0;
76 op_array->required_num_args = 0;
77
78 op_array->scope = NULL;
79 op_array->prototype = NULL;
80
81 op_array->live_range = NULL;
82 op_array->try_catch_array = NULL;
83 op_array->last_live_range = 0;
84
85 op_array->static_variables = NULL;
86 op_array->last_try_catch = 0;
87
88 op_array->fn_flags = 0;
89
90 op_array->early_binding = -1;
91
92 op_array->last_literal = 0;
93 op_array->literals = NULL;
94
95 op_array->run_time_cache = NULL;
96 op_array->cache_size = 0;
97
98 memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
99
100 if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR) {
101 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array);
102 }
103 }
104
destroy_zend_function(zend_function * function)105 ZEND_API void destroy_zend_function(zend_function *function)
106 {
107 if (function->type == ZEND_USER_FUNCTION) {
108 destroy_op_array(&function->op_array);
109 } else {
110 ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
111 ZEND_ASSERT(function->common.function_name);
112 zend_string_release(function->common.function_name);
113 }
114 }
115
zend_function_dtor(zval * zv)116 ZEND_API void zend_function_dtor(zval *zv)
117 {
118 zend_function *function = Z_PTR_P(zv);
119
120 if (function->type == ZEND_USER_FUNCTION) {
121 ZEND_ASSERT(function->common.function_name);
122 destroy_op_array(&function->op_array);
123 /* op_arrays are allocated on arena, so we don't have to free them */
124 } else {
125 ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
126 ZEND_ASSERT(function->common.function_name);
127 zend_string_release(function->common.function_name);
128 if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
129 pefree(function, 1);
130 }
131 }
132 }
133
zend_cleanup_op_array_data(zend_op_array * op_array)134 ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
135 {
136 if (op_array->static_variables &&
137 !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
138 zend_hash_clean(op_array->static_variables);
139 }
140 }
141
zend_cleanup_user_class_data(zend_class_entry * ce)142 ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce)
143 {
144 /* Clean all parts that can contain run-time data */
145 /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
146 not contain objects and thus are not probelmatic */
147 if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
148 zend_function *func;
149
150 ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
151 if (func->type == ZEND_USER_FUNCTION) {
152 zend_cleanup_op_array_data((zend_op_array *) func);
153 }
154 } ZEND_HASH_FOREACH_END();
155 }
156 if (ce->static_members_table) {
157 zval *static_members = ce->static_members_table;
158 zval *p = static_members;
159 zval *end = p + ce->default_static_members_count;
160
161
162 ce->default_static_members_count = 0;
163 ce->default_static_members_table = ce->static_members_table = NULL;
164 while (p != end) {
165 i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
166 p++;
167 }
168 efree(static_members);
169 }
170 }
171
zend_cleanup_internal_class_data(zend_class_entry * ce)172 ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
173 {
174 if (CE_STATIC_MEMBERS(ce)) {
175 zval *static_members = CE_STATIC_MEMBERS(ce);
176 zval *p = static_members;
177 zval *end = p + ce->default_static_members_count;
178
179 #ifdef ZTS
180 CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL;
181 #else
182 ce->static_members_table = NULL;
183 #endif
184 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
185 while (p != end) {
186 i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
187 p++;
188 }
189 efree(static_members);
190 }
191 }
192
_destroy_zend_class_traits_info(zend_class_entry * ce)193 void _destroy_zend_class_traits_info(zend_class_entry *ce)
194 {
195 if (ce->num_traits > 0 && ce->traits) {
196 efree(ce->traits);
197 }
198
199 if (ce->trait_aliases) {
200 size_t i = 0;
201 while (ce->trait_aliases[i]) {
202 if (ce->trait_aliases[i]->trait_method) {
203 if (ce->trait_aliases[i]->trait_method->method_name) {
204 zend_string_release(ce->trait_aliases[i]->trait_method->method_name);
205 }
206 if (ce->trait_aliases[i]->trait_method->class_name) {
207 zend_string_release(ce->trait_aliases[i]->trait_method->class_name);
208 }
209 efree(ce->trait_aliases[i]->trait_method);
210 }
211
212 if (ce->trait_aliases[i]->alias) {
213 zend_string_release(ce->trait_aliases[i]->alias);
214 }
215
216 efree(ce->trait_aliases[i]);
217 i++;
218 }
219
220 efree(ce->trait_aliases);
221 }
222
223 if (ce->trait_precedences) {
224 size_t i = 0;
225
226 while (ce->trait_precedences[i]) {
227 zend_string_release(ce->trait_precedences[i]->trait_method->method_name);
228 zend_string_release(ce->trait_precedences[i]->trait_method->class_name);
229 efree(ce->trait_precedences[i]->trait_method);
230
231 if (ce->trait_precedences[i]->exclude_from_classes) {
232 size_t j = 0;
233 zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
234 while (cur_precedence->exclude_from_classes[j].class_name) {
235 zend_string_release(cur_precedence->exclude_from_classes[j].class_name);
236 j++;
237 }
238 efree(ce->trait_precedences[i]->exclude_from_classes);
239 }
240 efree(ce->trait_precedences[i]);
241 i++;
242 }
243 efree(ce->trait_precedences);
244 }
245 }
246
destroy_zend_class(zval * zv)247 ZEND_API void destroy_zend_class(zval *zv)
248 {
249 zend_property_info *prop_info;
250 zend_class_entry *ce = Z_PTR_P(zv);
251
252 if (--ce->refcount > 0) {
253 return;
254 }
255 switch (ce->type) {
256 case ZEND_USER_CLASS:
257 if (ce->default_properties_table) {
258 zval *p = ce->default_properties_table;
259 zval *end = p + ce->default_properties_count;
260
261 while (p != end) {
262 i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
263 p++;
264 }
265 efree(ce->default_properties_table);
266 }
267 if (ce->default_static_members_table) {
268 zval *p = ce->default_static_members_table;
269 zval *end = p + ce->default_static_members_count;
270
271 while (p != end) {
272 i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
273 p++;
274 }
275 efree(ce->default_static_members_table);
276 }
277 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
278 if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
279 zend_string_release(prop_info->name);
280 if (prop_info->doc_comment) {
281 zend_string_release(prop_info->doc_comment);
282 }
283 }
284 } ZEND_HASH_FOREACH_END();
285 zend_hash_destroy(&ce->properties_info);
286 zend_string_release(ce->name);
287 zend_hash_destroy(&ce->function_table);
288 if (zend_hash_num_elements(&ce->constants_table)) {
289 zend_class_constant *c;
290
291 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
292 if (c->ce == ce) {
293 zval_ptr_dtor(&c->value);
294 if (c->doc_comment) {
295 zend_string_release(c->doc_comment);
296 }
297 }
298 } ZEND_HASH_FOREACH_END();
299 }
300 zend_hash_destroy(&ce->constants_table);
301 if (ce->num_interfaces > 0 && ce->interfaces) {
302 efree(ce->interfaces);
303 }
304 if (ce->info.user.doc_comment) {
305 zend_string_release(ce->info.user.doc_comment);
306 }
307
308 _destroy_zend_class_traits_info(ce);
309
310 break;
311 case ZEND_INTERNAL_CLASS:
312 if (ce->default_properties_table) {
313 zval *p = ce->default_properties_table;
314 zval *end = p + ce->default_properties_count;
315
316 while (p != end) {
317 zval_internal_ptr_dtor(p);
318 p++;
319 }
320 free(ce->default_properties_table);
321 }
322 if (ce->default_static_members_table) {
323 zval *p = ce->default_static_members_table;
324 zval *end = p + ce->default_static_members_count;
325
326 while (p != end) {
327 zval_internal_ptr_dtor(p);
328 p++;
329 }
330 free(ce->default_static_members_table);
331 }
332 zend_hash_destroy(&ce->properties_info);
333 zend_string_release(ce->name);
334 zend_hash_destroy(&ce->function_table);
335 if (zend_hash_num_elements(&ce->constants_table)) {
336 zend_class_constant *c;
337
338 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
339 zval_internal_ptr_dtor(&c->value);
340 if (c->doc_comment && c->ce == ce) {
341 zend_string_release(c->doc_comment);
342 }
343 } ZEND_HASH_FOREACH_END();
344 zend_hash_destroy(&ce->constants_table);
345 }
346 if (ce->num_interfaces > 0) {
347 free(ce->interfaces);
348 }
349 free(ce);
350 break;
351 }
352 }
353
zend_class_add_ref(zval * zv)354 void zend_class_add_ref(zval *zv)
355 {
356 zend_class_entry *ce = Z_PTR_P(zv);
357
358 ce->refcount++;
359 }
360
destroy_op_array(zend_op_array * op_array)361 ZEND_API void destroy_op_array(zend_op_array *op_array)
362 {
363 zval *literal = op_array->literals;
364 zval *end;
365 uint32_t i;
366
367 if (op_array->static_variables &&
368 !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
369 if (--GC_REFCOUNT(op_array->static_variables) == 0) {
370 zend_array_destroy(op_array->static_variables);
371 }
372 }
373
374 if (op_array->run_time_cache && !op_array->function_name) {
375 efree(op_array->run_time_cache);
376 op_array->run_time_cache = NULL;
377 }
378
379 if (!op_array->refcount || --(*op_array->refcount) > 0) {
380 return;
381 }
382
383 efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
384
385 if (op_array->vars) {
386 i = op_array->last_var;
387 while (i > 0) {
388 i--;
389 zend_string_release(op_array->vars[i]);
390 }
391 efree(op_array->vars);
392 }
393
394 if (literal) {
395 end = literal + op_array->last_literal;
396 while (literal < end) {
397 zval_ptr_dtor_nogc(literal);
398 literal++;
399 }
400 efree(op_array->literals);
401 }
402 efree(op_array->opcodes);
403
404 if (op_array->function_name) {
405 zend_string_release(op_array->function_name);
406 }
407 if (op_array->doc_comment) {
408 zend_string_release(op_array->doc_comment);
409 }
410 if (op_array->live_range) {
411 efree(op_array->live_range);
412 }
413 if (op_array->try_catch_array) {
414 efree(op_array->try_catch_array);
415 }
416 if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR) {
417 if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
418 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
419 }
420 }
421 if (op_array->arg_info) {
422 uint32_t num_args = op_array->num_args;
423 zend_arg_info *arg_info = op_array->arg_info;
424
425 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
426 arg_info--;
427 num_args++;
428 }
429 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
430 num_args++;
431 }
432 for (i = 0 ; i < num_args; i++) {
433 if (arg_info[i].name) {
434 zend_string_release(arg_info[i].name);
435 }
436 if (arg_info[i].class_name) {
437 zend_string_release(arg_info[i].class_name);
438 }
439 }
440 efree(arg_info);
441 }
442 }
443
init_op(zend_op * op)444 void init_op(zend_op *op)
445 {
446 memset(op, 0, sizeof(zend_op));
447 op->lineno = CG(zend_lineno);
448 SET_UNUSED(op->result);
449 }
450
get_next_op(zend_op_array * op_array)451 zend_op *get_next_op(zend_op_array *op_array)
452 {
453 uint32_t next_op_num = op_array->last++;
454 zend_op *next_op;
455
456 if (next_op_num >= CG(context).opcodes_size) {
457 CG(context).opcodes_size *= 4;
458 op_array_alloc_ops(op_array, CG(context).opcodes_size);
459 }
460
461 next_op = &(op_array->opcodes[next_op_num]);
462
463 init_op(next_op);
464
465 return next_op;
466 }
467
get_next_op_number(zend_op_array * op_array)468 uint32_t get_next_op_number(zend_op_array *op_array)
469 {
470 return op_array->last;
471 }
472
get_next_brk_cont_element(void)473 zend_brk_cont_element *get_next_brk_cont_element(void)
474 {
475 CG(context).last_brk_cont++;
476 CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
477 return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
478 }
479
zend_update_extended_info(zend_op_array * op_array)480 static void zend_update_extended_info(zend_op_array *op_array)
481 {
482 zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
483
484 while (opline<end) {
485 if (opline->opcode == ZEND_EXT_STMT) {
486 if (opline+1<end) {
487 if ((opline+1)->opcode == ZEND_EXT_STMT) {
488 opline->opcode = ZEND_NOP;
489 opline++;
490 continue;
491 }
492 if (opline+1<end) {
493 opline->lineno = (opline+1)->lineno;
494 }
495 } else {
496 opline->opcode = ZEND_NOP;
497 }
498 }
499 opline++;
500 }
501 }
502
zend_extension_op_array_handler(zend_extension * extension,zend_op_array * op_array)503 static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array)
504 {
505 if (extension->op_array_handler) {
506 extension->op_array_handler(op_array);
507 }
508 }
509
zend_check_finally_breakout(zend_op_array * op_array,uint32_t op_num,uint32_t dst_num)510 static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num)
511 {
512 int i;
513
514 for (i = 0; i < op_array->last_try_catch; i++) {
515 if ((op_num < op_array->try_catch_array[i].finally_op ||
516 op_num >= op_array->try_catch_array[i].finally_end)
517 && (dst_num >= op_array->try_catch_array[i].finally_op &&
518 dst_num <= op_array->try_catch_array[i].finally_end)) {
519 CG(in_compilation) = 1;
520 CG(active_op_array) = op_array;
521 CG(zend_lineno) = op_array->opcodes[op_num].lineno;
522 zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed");
523 } else if ((op_num >= op_array->try_catch_array[i].finally_op
524 && op_num <= op_array->try_catch_array[i].finally_end)
525 && (dst_num > op_array->try_catch_array[i].finally_end
526 || dst_num < op_array->try_catch_array[i].finally_op)) {
527 CG(in_compilation) = 1;
528 CG(active_op_array) = op_array;
529 CG(zend_lineno) = op_array->opcodes[op_num].lineno;
530 zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
531 }
532 }
533 }
534
zend_get_brk_cont_target(const zend_op_array * op_array,const zend_op * opline)535 static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
536 int nest_levels = opline->op2.num;
537 int array_offset = opline->op1.num;
538 zend_brk_cont_element *jmp_to;
539 do {
540 jmp_to = &CG(context).brk_cont_array[array_offset];
541 if (nest_levels > 1) {
542 array_offset = jmp_to->parent;
543 }
544 } while (--nest_levels > 0);
545
546 return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
547 }
548
pass_two(zend_op_array * op_array)549 ZEND_API int pass_two(zend_op_array *op_array)
550 {
551 zend_op *opline, *end;
552
553 if (!ZEND_USER_CODE(op_array->type)) {
554 return 0;
555 }
556 if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
557 zend_update_extended_info(op_array);
558 }
559 if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
560 if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) {
561 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array);
562 }
563 }
564
565 if (CG(context).vars_size != op_array->last_var) {
566 op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
567 CG(context).vars_size = op_array->last_var;
568 }
569 if (CG(context).opcodes_size != op_array->last) {
570 op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
571 CG(context).opcodes_size = op_array->last;
572 }
573 if (CG(context).literals_size != op_array->last_literal) {
574 op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
575 CG(context).literals_size = op_array->last_literal;
576 }
577 opline = op_array->opcodes;
578 end = opline + op_array->last;
579 while (opline < end) {
580 switch (opline->opcode) {
581 case ZEND_FAST_CALL:
582 opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op;
583 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
584 break;
585 case ZEND_BRK:
586 case ZEND_CONT:
587 {
588 uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
589
590 if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
591 zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target);
592 }
593 opline->opcode = ZEND_JMP;
594 opline->op1.opline_num = jmp_target;
595 opline->op2.num = 0;
596 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
597 }
598 break;
599 case ZEND_GOTO:
600 zend_resolve_goto_label(op_array, opline);
601 if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
602 zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num);
603 }
604 /* break omitted intentionally */
605 case ZEND_JMP:
606 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
607 break;
608 case ZEND_JMPZNZ:
609 /* absolute index to relative offset */
610 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
611 /* break omitted intentionally */
612 case ZEND_JMPZ:
613 case ZEND_JMPNZ:
614 case ZEND_JMPZ_EX:
615 case ZEND_JMPNZ_EX:
616 case ZEND_JMP_SET:
617 case ZEND_COALESCE:
618 case ZEND_FE_RESET_R:
619 case ZEND_FE_RESET_RW:
620 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
621 break;
622 case ZEND_ASSERT_CHECK:
623 {
624 /* If result of assert is unused, result of check is unused as well */
625 zend_op *call = &op_array->opcodes[opline->op2.opline_num - 1];
626 if (call->opcode == ZEND_EXT_FCALL_END) {
627 call--;
628 }
629 if (call->result_type == IS_UNUSED) {
630 opline->result_type = IS_UNUSED;
631 }
632 ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
633 break;
634 }
635 case ZEND_DECLARE_ANON_CLASS:
636 case ZEND_DECLARE_ANON_INHERITED_CLASS:
637 case ZEND_CATCH:
638 case ZEND_FE_FETCH_R:
639 case ZEND_FE_FETCH_RW:
640 /* absolute index to relative offset */
641 opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
642 break;
643 case ZEND_RETURN:
644 case ZEND_RETURN_BY_REF:
645 if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
646 opline->opcode = ZEND_GENERATOR_RETURN;
647 }
648 break;
649 }
650 if (opline->op1_type == IS_CONST) {
651 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
652 } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
653 opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
654 }
655 if (opline->op2_type == IS_CONST) {
656 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
657 } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
658 opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
659 }
660 if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
661 opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
662 }
663 ZEND_VM_SET_OPCODE_HANDLER(opline);
664 opline++;
665 }
666
667 if (op_array->live_range) {
668 int i;
669
670 for (i = 0; i < op_array->last_live_range; i++) {
671 op_array->live_range[i].var =
672 (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |
673 (op_array->live_range[i].var & ZEND_LIVE_MASK);
674 }
675 }
676
677 op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
678 return 0;
679 }
680
get_unary_op(int opcode)681 ZEND_API unary_op_type get_unary_op(int opcode)
682 {
683 switch (opcode) {
684 case ZEND_BW_NOT:
685 return (unary_op_type) bitwise_not_function;
686 case ZEND_BOOL_NOT:
687 return (unary_op_type) boolean_not_function;
688 default:
689 return (unary_op_type) NULL;
690 }
691 }
692
get_binary_op(int opcode)693 ZEND_API binary_op_type get_binary_op(int opcode)
694 {
695 switch (opcode) {
696 case ZEND_ADD:
697 case ZEND_ASSIGN_ADD:
698 return (binary_op_type) add_function;
699 case ZEND_SUB:
700 case ZEND_ASSIGN_SUB:
701 return (binary_op_type) sub_function;
702 case ZEND_MUL:
703 case ZEND_ASSIGN_MUL:
704 return (binary_op_type) mul_function;
705 case ZEND_POW:
706 return (binary_op_type) pow_function;
707 case ZEND_DIV:
708 case ZEND_ASSIGN_DIV:
709 return (binary_op_type) div_function;
710 case ZEND_MOD:
711 case ZEND_ASSIGN_MOD:
712 return (binary_op_type) mod_function;
713 case ZEND_SL:
714 case ZEND_ASSIGN_SL:
715 return (binary_op_type) shift_left_function;
716 case ZEND_SR:
717 case ZEND_ASSIGN_SR:
718 return (binary_op_type) shift_right_function;
719 case ZEND_FAST_CONCAT:
720 case ZEND_CONCAT:
721 case ZEND_ASSIGN_CONCAT:
722 return (binary_op_type) concat_function;
723 case ZEND_IS_IDENTICAL:
724 return (binary_op_type) is_identical_function;
725 case ZEND_IS_NOT_IDENTICAL:
726 return (binary_op_type) is_not_identical_function;
727 case ZEND_IS_EQUAL:
728 return (binary_op_type) is_equal_function;
729 case ZEND_IS_NOT_EQUAL:
730 return (binary_op_type) is_not_equal_function;
731 case ZEND_IS_SMALLER:
732 return (binary_op_type) is_smaller_function;
733 case ZEND_IS_SMALLER_OR_EQUAL:
734 return (binary_op_type) is_smaller_or_equal_function;
735 case ZEND_SPACESHIP:
736 return (binary_op_type) compare_function;
737 case ZEND_BW_OR:
738 case ZEND_ASSIGN_BW_OR:
739 return (binary_op_type) bitwise_or_function;
740 case ZEND_BW_AND:
741 case ZEND_ASSIGN_BW_AND:
742 return (binary_op_type) bitwise_and_function;
743 case ZEND_BW_XOR:
744 case ZEND_ASSIGN_BW_XOR:
745 return (binary_op_type) bitwise_xor_function;
746 case ZEND_BOOL_XOR:
747 return (binary_op_type) boolean_xor_function;
748 default:
749 return (binary_op_type) NULL;
750 }
751 }
752
753 /*
754 * Local variables:
755 * tab-width: 4
756 * c-basic-offset: 4
757 * indent-tabs-mode: t
758 * End:
759 */
760