1/* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1998-2013 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 +----------------------------------------------------------------------+ 18*/ 19 20/* $Id$ */ 21 22#include <stdio.h> 23 24#include "zend.h" 25#include "zend_alloc.h" 26#include "zend_compile.h" 27#include "zend_extensions.h" 28#include "zend_API.h" 29 30#include "zend_vm.h" 31 32static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 33{ 34 if (extension->op_array_ctor) { 35 extension->op_array_ctor(op_array); 36 } 37} 38 39static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 40{ 41 if (extension->op_array_dtor) { 42 extension->op_array_dtor(op_array); 43 } 44} 45 46static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size) 47{ 48 op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op)); 49} 50 51void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC) 52{ 53 op_array->type = type; 54 55 if (CG(interactive)) { 56 /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants 57 * will become invalid 58 */ 59 initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE; 60 } 61 62 op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint)); 63 *op_array->refcount = 1; 64 op_array->last = 0; 65 op_array->opcodes = NULL; 66 op_array_alloc_ops(op_array, initial_ops_size); 67 68 op_array->last_var = 0; 69 op_array->vars = NULL; 70 71 op_array->T = 0; 72 73 op_array->nested_calls = 0; 74 op_array->used_stack = 0; 75 76 op_array->function_name = NULL; 77 op_array->filename = zend_get_compiled_filename(TSRMLS_C); 78 op_array->doc_comment = NULL; 79 op_array->doc_comment_len = 0; 80 81 op_array->arg_info = NULL; 82 op_array->num_args = 0; 83 op_array->required_num_args = 0; 84 85 op_array->scope = NULL; 86 87 op_array->brk_cont_array = NULL; 88 op_array->try_catch_array = NULL; 89 op_array->last_brk_cont = 0; 90 91 op_array->static_variables = NULL; 92 op_array->last_try_catch = 0; 93 op_array->has_finally_block = 0; 94 95 op_array->this_var = -1; 96 97 op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0; 98 99 op_array->early_binding = -1; 100 101 op_array->last_literal = 0; 102 op_array->literals = NULL; 103 104 op_array->run_time_cache = NULL; 105 op_array->last_cache_slot = 0; 106 107 memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*)); 108 109 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC); 110} 111 112ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC) 113{ 114 switch (function->type) { 115 case ZEND_USER_FUNCTION: 116 destroy_op_array((zend_op_array *) function TSRMLS_CC); 117 break; 118 case ZEND_INTERNAL_FUNCTION: 119 /* do nothing */ 120 break; 121 } 122} 123 124ZEND_API void zend_function_dtor(zend_function *function) 125{ 126 TSRMLS_FETCH(); 127 128 destroy_zend_function(function TSRMLS_CC); 129} 130 131static void zend_cleanup_op_array_data(zend_op_array *op_array) 132{ 133 if (op_array->static_variables) { 134 zend_hash_clean(op_array->static_variables); 135 } 136} 137 138ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC) 139{ 140 if (function->type == ZEND_USER_FUNCTION) { 141 zend_cleanup_op_array_data((zend_op_array *) function); 142 return ZEND_HASH_APPLY_KEEP; 143 } else { 144 return ZEND_HASH_APPLY_STOP; 145 } 146} 147 148ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC) 149{ 150 if (function->type == ZEND_USER_FUNCTION) { 151 zend_cleanup_op_array_data((zend_op_array *) function); 152 } 153 return 0; 154} 155 156static inline void cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC) 157{ 158 /* Clean all parts that can contain run-time data */ 159 /* Note that only run-time accessed data need to be cleaned up, pre-defined data can 160 not contain objects and thus are not probelmatic */ 161 if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { 162 zend_hash_apply(&ce->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); 163 } 164 if (ce->static_members_table) { 165 int i; 166 167 for (i = 0; i < ce->default_static_members_count; i++) { 168 if (ce->static_members_table[i]) { 169 zval *p = ce->static_members_table[i]; 170 ce->static_members_table[i] = NULL; 171 zval_ptr_dtor(&p); 172 } 173 } 174 ce->static_members_table = NULL; 175 } 176} 177 178static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC) 179{ 180 if (CE_STATIC_MEMBERS(ce)) { 181 int i; 182 183 for (i = 0; i < ce->default_static_members_count; i++) { 184 zval_ptr_dtor(&CE_STATIC_MEMBERS(ce)[i]); 185 } 186 efree(CE_STATIC_MEMBERS(ce)); 187#ifdef ZTS 188 CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; 189#else 190 ce->static_members_table = NULL; 191#endif 192 } 193} 194 195ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC) 196{ 197 cleanup_internal_class_data(ce TSRMLS_CC); 198} 199 200ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC) 201{ 202 if ((*pce)->type == ZEND_USER_CLASS) { 203 cleanup_user_class_data(*pce TSRMLS_CC); 204 return ZEND_HASH_APPLY_KEEP; 205 } else { 206 return ZEND_HASH_APPLY_STOP; 207 } 208} 209 210ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC) 211{ 212 if ((*pce)->type == ZEND_USER_CLASS) { 213 cleanup_user_class_data(*pce TSRMLS_CC); 214 } else { 215 cleanup_internal_class_data(*pce TSRMLS_CC); 216 } 217 return 0; 218} 219 220void _destroy_zend_class_traits_info(zend_class_entry *ce) 221{ 222 if (ce->num_traits > 0 && ce->traits) { 223 efree(ce->traits); 224 } 225 226 if (ce->trait_aliases) { 227 size_t i = 0; 228 while (ce->trait_aliases[i]) { 229 if (ce->trait_aliases[i]->trait_method) { 230 if (ce->trait_aliases[i]->trait_method->method_name) { 231 efree((char*)ce->trait_aliases[i]->trait_method->method_name); 232 } 233 if (ce->trait_aliases[i]->trait_method->class_name) { 234 efree((char*)ce->trait_aliases[i]->trait_method->class_name); 235 } 236 efree(ce->trait_aliases[i]->trait_method); 237 } 238 239 if (ce->trait_aliases[i]->alias) { 240 efree((char*)ce->trait_aliases[i]->alias); 241 } 242 243 efree(ce->trait_aliases[i]); 244 i++; 245 } 246 247 efree(ce->trait_aliases); 248 } 249 250 if (ce->trait_precedences) { 251 size_t i = 0; 252 253 while (ce->trait_precedences[i]) { 254 efree((char*)ce->trait_precedences[i]->trait_method->method_name); 255 efree((char*)ce->trait_precedences[i]->trait_method->class_name); 256 efree(ce->trait_precedences[i]->trait_method); 257 258 if (ce->trait_precedences[i]->exclude_from_classes) { 259 efree(ce->trait_precedences[i]->exclude_from_classes); 260 } 261 262 efree(ce->trait_precedences[i]); 263 i++; 264 } 265 efree(ce->trait_precedences); 266 } 267} 268 269ZEND_API void destroy_zend_class(zend_class_entry **pce) 270{ 271 zend_class_entry *ce = *pce; 272 273 if (--ce->refcount > 0) { 274 return; 275 } 276 switch (ce->type) { 277 case ZEND_USER_CLASS: 278 if (ce->default_properties_table) { 279 int i; 280 281 for (i = 0; i < ce->default_properties_count; i++) { 282 if (ce->default_properties_table[i]) { 283 zval_ptr_dtor(&ce->default_properties_table[i]); 284 } 285 } 286 efree(ce->default_properties_table); 287 } 288 if (ce->default_static_members_table) { 289 int i; 290 291 for (i = 0; i < ce->default_static_members_count; i++) { 292 if (ce->default_static_members_table[i]) { 293 zval_ptr_dtor(&ce->default_static_members_table[i]); 294 } 295 } 296 efree(ce->default_static_members_table); 297 } 298 zend_hash_destroy(&ce->properties_info); 299 str_efree(ce->name); 300 zend_hash_destroy(&ce->function_table); 301 zend_hash_destroy(&ce->constants_table); 302 if (ce->num_interfaces > 0 && ce->interfaces) { 303 efree(ce->interfaces); 304 } 305 if (ce->info.user.doc_comment) { 306 efree((char*)ce->info.user.doc_comment); 307 } 308 309 _destroy_zend_class_traits_info(ce); 310 311 efree(ce); 312 break; 313 case ZEND_INTERNAL_CLASS: 314 if (ce->default_properties_table) { 315 int i; 316 317 for (i = 0; i < ce->default_properties_count; i++) { 318 if (ce->default_properties_table[i]) { 319 zval_internal_ptr_dtor(&ce->default_properties_table[i]); 320 } 321 } 322 free(ce->default_properties_table); 323 } 324 if (ce->default_static_members_table) { 325 int i; 326 327 for (i = 0; i < ce->default_static_members_count; i++) { 328 zval_internal_ptr_dtor(&ce->default_static_members_table[i]); 329 } 330 free(ce->default_static_members_table); 331 } 332 zend_hash_destroy(&ce->properties_info); 333 str_free(ce->name); 334 zend_hash_destroy(&ce->function_table); 335 zend_hash_destroy(&ce->constants_table); 336 if (ce->num_interfaces > 0) { 337 free(ce->interfaces); 338 } 339 free(ce); 340 break; 341 } 342} 343 344void zend_class_add_ref(zend_class_entry **ce) 345{ 346 (*ce)->refcount++; 347} 348 349ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) 350{ 351 zend_literal *literal = op_array->literals; 352 zend_literal *end; 353 zend_uint i; 354 355 if (op_array->static_variables) { 356 zend_hash_destroy(op_array->static_variables); 357 FREE_HASHTABLE(op_array->static_variables); 358 } 359 360 if (op_array->run_time_cache) { 361 efree(op_array->run_time_cache); 362 } 363 364 if (--(*op_array->refcount)>0) { 365 return; 366 } 367 368 efree(op_array->refcount); 369 370 if (op_array->vars) { 371 i = op_array->last_var; 372 while (i > 0) { 373 i--; 374 str_efree(op_array->vars[i].name); 375 } 376 efree(op_array->vars); 377 } 378 379 if (literal) { 380 end = literal + op_array->last_literal; 381 while (literal < end) { 382 zval_dtor(&literal->constant); 383 literal++; 384 } 385 efree(op_array->literals); 386 } 387 efree(op_array->opcodes); 388 389 if (op_array->function_name) { 390 efree((char*)op_array->function_name); 391 } 392 if (op_array->doc_comment) { 393 efree((char*)op_array->doc_comment); 394 } 395 if (op_array->brk_cont_array) { 396 efree(op_array->brk_cont_array); 397 } 398 if (op_array->try_catch_array) { 399 efree(op_array->try_catch_array); 400 } 401 if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) { 402 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC); 403 } 404 if (op_array->arg_info) { 405 for (i=0; i<op_array->num_args; i++) { 406 str_efree(op_array->arg_info[i].name); 407 if (op_array->arg_info[i].class_name) { 408 str_efree(op_array->arg_info[i].class_name); 409 } 410 } 411 efree(op_array->arg_info); 412 } 413} 414 415void init_op(zend_op *op TSRMLS_DC) 416{ 417 memset(op, 0, sizeof(zend_op)); 418 op->lineno = CG(zend_lineno); 419 SET_UNUSED(op->result); 420} 421 422zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC) 423{ 424 zend_uint next_op_num = op_array->last++; 425 zend_op *next_op; 426 427 if (next_op_num >= CG(context).opcodes_size) { 428 if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { 429 /* we messed up */ 430 zend_printf("Ran out of opcode space!\n" 431 "You should probably consider writing this huge script into a file!\n"); 432 zend_bailout(); 433 } 434 CG(context).opcodes_size *= 4; 435 op_array_alloc_ops(op_array, CG(context).opcodes_size); 436 } 437 438 next_op = &(op_array->opcodes[next_op_num]); 439 440 init_op(next_op TSRMLS_CC); 441 442 return next_op; 443} 444 445int get_next_op_number(zend_op_array *op_array) 446{ 447 return op_array->last; 448} 449 450zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) 451{ 452 op_array->last_brk_cont++; 453 op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont); 454 return &op_array->brk_cont_array[op_array->last_brk_cont-1]; 455} 456 457static void zend_update_extended_info(zend_op_array *op_array TSRMLS_DC) 458{ 459 zend_op *opline = op_array->opcodes, *end=opline+op_array->last; 460 461 while (opline<end) { 462 if (opline->opcode == ZEND_EXT_STMT) { 463 if (opline+1<end) { 464 if ((opline+1)->opcode == ZEND_EXT_STMT) { 465 opline->opcode = ZEND_NOP; 466 opline++; 467 continue; 468 } 469 if (opline+1<end) { 470 opline->lineno = (opline+1)->lineno; 471 } 472 } else { 473 opline->opcode = ZEND_NOP; 474 } 475 } 476 opline++; 477 } 478} 479 480static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 481{ 482 if (extension->op_array_handler) { 483 extension->op_array_handler(op_array); 484 } 485} 486 487static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) 488{ 489 zend_uint i; 490 491 for (i = 0; i < op_array->last_try_catch; i++) { 492 if (op_array->try_catch_array[i].try_op > op_num) { 493 break; 494 } 495 if ((op_num >= op_array->try_catch_array[i].finally_op 496 && op_num <= op_array->try_catch_array[i].finally_end) 497 && (dst_num > op_array->try_catch_array[i].finally_end 498 || dst_num < op_array->try_catch_array[i].finally_op)) { 499 CG(in_compilation) = 1; 500 CG(active_op_array) = op_array; 501 CG(zend_lineno) = op_array->opcodes[op_num].lineno; 502 zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed"); 503 } 504 } 505} 506 507static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) 508{ 509 zend_uint start_op; 510 zend_op *opline; 511 zend_uint i = op_array->last_try_catch; 512 513 if (dst_num != (zend_uint)-1) { 514 zend_check_finally_breakout(op_array, op_num, dst_num TSRMLS_CC); 515 } 516 517 /* the backward order is mater */ 518 while (i > 0) { 519 i--; 520 if (op_array->try_catch_array[i].finally_op && 521 op_num >= op_array->try_catch_array[i].try_op && 522 op_num < op_array->try_catch_array[i].finally_op - 1 && 523 (dst_num < op_array->try_catch_array[i].try_op || 524 dst_num > op_array->try_catch_array[i].finally_end)) { 525 /* we have a jump out of try block that needs executing finally */ 526 527 /* generate a FAST_CALL to finally block */ 528 start_op = get_next_op_number(op_array); 529 530 opline = get_next_op(op_array TSRMLS_CC); 531 opline->opcode = ZEND_FAST_CALL; 532 SET_UNUSED(opline->op1); 533 SET_UNUSED(opline->op2); 534 opline->op1.opline_num = op_array->try_catch_array[i].finally_op; 535 if (op_array->try_catch_array[i].catch_op) { 536 opline->extended_value = 1; 537 opline->op2.opline_num = op_array->try_catch_array[i].catch_op; 538 } 539 540 /* generate a sequence of FAST_CALL to upward finally block */ 541 while (i > 0) { 542 i--; 543 if (op_array->try_catch_array[i].finally_op && 544 op_num >= op_array->try_catch_array[i].try_op && 545 op_num < op_array->try_catch_array[i].finally_op - 1 && 546 (dst_num < op_array->try_catch_array[i].try_op || 547 dst_num > op_array->try_catch_array[i].finally_end)) { 548 549 opline = get_next_op(op_array TSRMLS_CC); 550 opline->opcode = ZEND_FAST_CALL; 551 SET_UNUSED(opline->op1); 552 SET_UNUSED(opline->op2); 553 opline->op1.opline_num = op_array->try_catch_array[i].finally_op; 554 } 555 } 556 557 /* Finish the sequence with original opcode */ 558 opline = get_next_op(op_array TSRMLS_CC); 559 *opline = op_array->opcodes[op_num]; 560 561 /* Replace original opcode with jump to this sequence */ 562 opline = op_array->opcodes + op_num; 563 opline->opcode = ZEND_JMP; 564 SET_UNUSED(opline->op1); 565 SET_UNUSED(opline->op2); 566 opline->op1.opline_num = start_op; 567 568 break; 569 } 570 } 571} 572 573static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num TSRMLS_DC) 574{ 575 int i; 576 zend_uint catch_op_num = 0, finally_op_num = 0; 577 578 for (i = 0; i < op_array->last_try_catch; i++) { 579 if (op_array->try_catch_array[i].try_op > op_num) { 580 break; 581 } 582 if (op_num < op_array->try_catch_array[i].finally_op) { 583 finally_op_num = op_array->try_catch_array[i].finally_op; 584 } 585 if (op_num < op_array->try_catch_array[i].catch_op) { 586 catch_op_num = op_array->try_catch_array[i].catch_op; 587 } 588 } 589 590 if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { 591 /* in case of unhandled exception return to upward finally block */ 592 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY; 593 op_array->opcodes[op_num].op2.opline_num = finally_op_num; 594 } else if (catch_op_num) { 595 /* in case of unhandled exception return to upward catch block */ 596 op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH; 597 op_array->opcodes[op_num].op2.opline_num = catch_op_num; 598 } 599} 600 601static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) 602{ 603 zend_uint i; 604 zend_op *opline; 605 606 for (i = 0; i < op_array->last; i++) { 607 opline = op_array->opcodes + i; 608 switch (opline->opcode) { 609 case ZEND_RETURN: 610 case ZEND_RETURN_BY_REF: 611 case ZEND_GENERATOR_RETURN: 612 zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC); 613 break; 614 case ZEND_BRK: 615 case ZEND_CONT: 616 { 617 int nest_levels, array_offset; 618 zend_brk_cont_element *jmp_to; 619 620 nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant); 621 array_offset = opline->op1.opline_num; 622 do { 623 jmp_to = &op_array->brk_cont_array[array_offset]; 624 if (nest_levels > 1) { 625 array_offset = jmp_to->parent; 626 } 627 } while (--nest_levels > 0); 628 zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC); 629 break; 630 } 631 case ZEND_GOTO: 632 if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) { 633 zend_uint num = opline->op2.constant; 634 opline->op2.zv = &op_array->literals[opline->op2.constant].constant; 635 zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); 636 opline->op2.constant = num; 637 } 638 /* break omitted intentionally */ 639 case ZEND_JMP: 640 zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC); 641 break; 642 case ZEND_FAST_RET: 643 zend_resolve_finally_ret(op_array, i TSRMLS_CC); 644 break; 645 default: 646 break; 647 } 648 } 649} 650 651ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) 652{ 653 zend_op *opline, *end; 654 655 if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) { 656 return 0; 657 } 658 if (op_array->has_finally_block) { 659 zend_resolve_finally_calls(op_array TSRMLS_CC); 660 } 661 if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) { 662 zend_update_extended_info(op_array TSRMLS_CC); 663 } 664 if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) { 665 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC); 666 } 667 668 if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) { 669 op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var); 670 CG(context).vars_size = op_array->last_var; 671 } 672 if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) { 673 op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); 674 CG(context).opcodes_size = op_array->last; 675 } 676 if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) { 677 op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal); 678 CG(context).literals_size = op_array->last_literal; 679 } 680 681 opline = op_array->opcodes; 682 end = opline + op_array->last; 683 while (opline < end) { 684 if (opline->op1_type == IS_CONST) { 685 opline->op1.zv = &op_array->literals[opline->op1.constant].constant; 686 } 687 if (opline->op2_type == IS_CONST) { 688 opline->op2.zv = &op_array->literals[opline->op2.constant].constant; 689 } 690 switch (opline->opcode) { 691 case ZEND_GOTO: 692 if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { 693 zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); 694 } 695 /* break omitted intentionally */ 696 case ZEND_JMP: 697 case ZEND_FAST_CALL: 698 opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; 699 break; 700 case ZEND_JMPZ: 701 case ZEND_JMPNZ: 702 case ZEND_JMPZ_EX: 703 case ZEND_JMPNZ_EX: 704 case ZEND_JMP_SET: 705 case ZEND_JMP_SET_VAR: 706 opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; 707 break; 708 case ZEND_RETURN: 709 case ZEND_RETURN_BY_REF: 710 if (op_array->fn_flags & ZEND_ACC_GENERATOR) { 711 if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) { 712 CG(zend_lineno) = opline->lineno; 713 zend_error(E_COMPILE_ERROR, "Generators cannot return values using \"return\""); 714 } 715 716 opline->opcode = ZEND_GENERATOR_RETURN; 717 } 718 break; 719 } 720 ZEND_VM_SET_OPCODE_HANDLER(opline); 721 opline++; 722 } 723 724 op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; 725 return 0; 726} 727 728int print_class(zend_class_entry *class_entry TSRMLS_DC) 729{ 730 printf("Class %s:\n", class_entry->name); 731 zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC); 732 printf("End of class %s.\n\n", class_entry->name); 733 return 0; 734} 735 736ZEND_API unary_op_type get_unary_op(int opcode) 737{ 738 switch (opcode) { 739 case ZEND_BW_NOT: 740 return (unary_op_type) bitwise_not_function; 741 break; 742 case ZEND_BOOL_NOT: 743 return (unary_op_type) boolean_not_function; 744 break; 745 default: 746 return (unary_op_type) NULL; 747 break; 748 } 749} 750 751ZEND_API binary_op_type get_binary_op(int opcode) 752{ 753 switch (opcode) { 754 case ZEND_ADD: 755 case ZEND_ASSIGN_ADD: 756 return (binary_op_type) add_function; 757 break; 758 case ZEND_SUB: 759 case ZEND_ASSIGN_SUB: 760 return (binary_op_type) sub_function; 761 break; 762 case ZEND_MUL: 763 case ZEND_ASSIGN_MUL: 764 return (binary_op_type) mul_function; 765 break; 766 case ZEND_DIV: 767 case ZEND_ASSIGN_DIV: 768 return (binary_op_type) div_function; 769 break; 770 case ZEND_MOD: 771 case ZEND_ASSIGN_MOD: 772 return (binary_op_type) mod_function; 773 break; 774 case ZEND_SL: 775 case ZEND_ASSIGN_SL: 776 return (binary_op_type) shift_left_function; 777 break; 778 case ZEND_SR: 779 case ZEND_ASSIGN_SR: 780 return (binary_op_type) shift_right_function; 781 break; 782 case ZEND_CONCAT: 783 case ZEND_ASSIGN_CONCAT: 784 return (binary_op_type) concat_function; 785 break; 786 case ZEND_IS_IDENTICAL: 787 return (binary_op_type) is_identical_function; 788 break; 789 case ZEND_IS_NOT_IDENTICAL: 790 return (binary_op_type) is_not_identical_function; 791 break; 792 case ZEND_IS_EQUAL: 793 return (binary_op_type) is_equal_function; 794 break; 795 case ZEND_IS_NOT_EQUAL: 796 return (binary_op_type) is_not_equal_function; 797 break; 798 case ZEND_IS_SMALLER: 799 return (binary_op_type) is_smaller_function; 800 break; 801 case ZEND_IS_SMALLER_OR_EQUAL: 802 return (binary_op_type) is_smaller_or_equal_function; 803 break; 804 case ZEND_BW_OR: 805 case ZEND_ASSIGN_BW_OR: 806 return (binary_op_type) bitwise_or_function; 807 break; 808 case ZEND_BW_AND: 809 case ZEND_ASSIGN_BW_AND: 810 return (binary_op_type) bitwise_and_function; 811 break; 812 case ZEND_BW_XOR: 813 case ZEND_ASSIGN_BW_XOR: 814 return (binary_op_type) bitwise_xor_function; 815 break; 816 case ZEND_BOOL_XOR: 817 return (binary_op_type) boolean_xor_function; 818 break; 819 default: 820 return (binary_op_type) NULL; 821 break; 822 } 823} 824 825/* 826 * Local variables: 827 * tab-width: 4 828 * c-basic-offset: 4 829 * indent-tabs-mode: t 830 * End: 831 */ 832