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