static int32_t qb_release_object_instances(qb_interpreter_context *cxt) { USE_TSRM uint32_t i; for(i = 0; i < QB_G(scope_count); i++) { qb_import_scope *scope = QB_G(scopes)[i]; if(scope->type == QB_IMPORT_SCOPE_OBJECT) { // release the object zval_ptr_dtor(&scope->object); scope->type = QB_IMPORT_SCOPE_FREED_OBJECT; } } return TRUE; }
static void qb_refresh_imported_variables(qb_interpreter_context *cxt) { USE_TSRM uint32_t i, j; for(i = 0; i < QB_G(scope_count); i++) { qb_import_scope *scope = QB_G(scopes)[i]; if(scope->type != QB_IMPORT_SCOPE_ABSTRACT_OBJECT) { for(j = 0; j < scope->variable_count; j++) { qb_variable *ivar = scope->variables[j]; qb_transfer_value_from_import_source(cxt, ivar, scope); } } } }
static int32_t qb_release_imported_segments(qb_interpreter_context *cxt) { USE_TSRM uint32_t i, j; for(i = 0; i < QB_G(scope_count); i++) { qb_import_scope *scope = QB_G(scopes)[i]; if(scope->type != QB_IMPORT_SCOPE_ABSTRACT_OBJECT) { for(j = QB_SELECTOR_ARRAY_START; j < scope->storage->segment_count; j++) { qb_memory_segment *segment = &scope->storage->segments[j]; qb_release_segment(segment); } } } return TRUE; }
void qb_generate_executables(qb_build_context *cxt) { USE_TSRM int32_t native_compile = FALSE; uint32_t i; for(i = 0; i < cxt->compiler_context_count; i++) { qb_compiler_context *compiler_cxt = cxt->compiler_contexts[i]; qb_encoder_context _encoder_cxt, *encoder_cxt = &_encoder_cxt; qb_initialize_encoder_context(encoder_cxt, compiler_cxt, TRUE TSRMLS_CC); // encode the instruction stream compiler_cxt->compiled_function = qb_encode_function(encoder_cxt); if(!compiler_cxt->compiled_function) { qb_dispatch_exceptions(TSRMLS_C); } // relocate the function now, so the base function won't be in the middle of relcoation while it's being copied qb_relocate_function(compiler_cxt->compiled_function, TRUE); // attach the function to the op array qb_attach_compiled_function(compiler_cxt->compiled_function, compiler_cxt->zend_op_array TSRMLS_CC); if(compiler_cxt->function_flags & QB_FUNCTION_NATIVE_IF_POSSIBLE) { native_compile = TRUE; } } #ifdef NATIVE_COMPILE_ENABLED // compile all functions inside build in one go if(native_compile) { if(QB_G(allow_native_compilation)) { qb_native_compiler_context _native_compiler_cxt, *native_compiler_cxt = &_native_compiler_cxt; qb_initialize_native_compiler_context(native_compiler_cxt, cxt TSRMLS_CC); qb_compile_to_native_code(native_compiler_cxt); qb_free_native_compiler_context(native_compiler_cxt); } } if(!QB_G(allow_bytecode_interpretation)) { for(i = 0; i < cxt->compiler_context_count; i++) { qb_compiler_context *compiler_cxt = cxt->compiler_contexts[i]; if(!compiler_cxt->compiled_function->native_proc) { qb_report_native_compilation_exception(compiler_cxt->compiled_function->line_id, compiler_cxt->compiled_function->name); qb_dispatch_exceptions(TSRMLS_C); } } } #endif }
static int32_t qb_sync_imported_variables(qb_interpreter_context *cxt) { USE_TSRM uint32_t i, j; for(i = 0; i < QB_G(scope_count); i++) { qb_import_scope *scope = QB_G(scopes)[i]; if(scope->type != QB_IMPORT_SCOPE_ABSTRACT_OBJECT && scope->type != QB_IMPORT_SCOPE_FREED_OBJECT) { for(j = 0; j < scope->variable_count; j++) { qb_variable *ivar = scope->variables[j]; if(!qb_transfer_value_to_import_source(cxt, ivar, scope)) { return FALSE; } } } } return TRUE; }
static int32_t qb_validate_operands_matrix_current_mode(qb_compiler_context *cxt, qb_op_factory *f, qb_primitive_type expr_type, uint32_t flags, qb_operand *operands, uint32_t operand_count, qb_result_destination *result_destination) { USE_TSRM qb_matrix_op_factory_selector *s = (qb_matrix_op_factory_selector *) f; if(QB_G(column_major_matrix)) { f = s->cm_factory; } else { f = s->rm_factory; } return f->validate_operands(cxt, f, expr_type, flags, operands, operand_count, result_destination); }
static int32_t qb_transfer_operands_matrix_current_mode(qb_compiler_context *cxt, qb_op_factory *f, uint32_t flags, qb_operand *operands, uint32_t operand_count, qb_operand *result, qb_operand *dest, uint32_t dest_count) { USE_TSRM qb_matrix_op_factory_selector *s = (qb_matrix_op_factory_selector *) f; if(QB_G(column_major_matrix)) { f = s->cm_factory; } else { f = s->rm_factory; } return f->transfer_operands(cxt, f, flags, operands, operand_count, result, dest, dest_count); }
NO_RETURN void qb_abort(const char *format, ...) { const char *filename; uint32_t lineno; va_list args; TSRMLS_FETCH(); if(QB_G(current_filename)) { filename = QB_G(current_filename); } else { filename = zend_get_executed_filename(TSRMLS_C); } if(QB_G(current_line_number)) { lineno = QB_G(current_line_number); } else { lineno = zend_get_executed_lineno(TSRMLS_C); } va_start(args, format); zend_error_cb(E_ERROR, filename, lineno, format, args); va_end(args); }
static int32_t qb_inline_function(qb_compiler_context *cxt, void *factory, qb_operand *operands, uint32_t operand_count, qb_operand *result, uint32_t *jump_target_indices, uint32_t jump_target_count, qb_result_prototype *result_prototype) { USE_TSRM qb_operand *func = &operands[0], *arguments = &operands[1], *argument_count = &operands[2]; qb_function *qfunc = qb_find_compiled_function(func->zend_function TSRMLS_CC); qb_compiler_context *callee_cxt = qb_find_compiler_context(QB_G(build_context), qfunc); qb_function_inliner_context _inliner_cxt, *inliner_cxt = &_inliner_cxt; int32_t succeeded; qb_initialize_function_inliner_context(inliner_cxt, cxt, callee_cxt, arguments->arguments, argument_count->number, result, result_prototype TSRMLS_CC); succeeded = qb_transfer_inlined_function_ops(inliner_cxt); qb_free_function_inliner_context(inliner_cxt); return succeeded; }
void qb_perform_translation(qb_build_context *cxt) { USE_TSRM uint32_t i; for(i = 0; i < cxt->compiler_context_count; i++) { qb_compiler_context *compiler_cxt = cxt->compiler_contexts[i]; switch(compiler_cxt->translation) { case QB_TRANSLATION_PHP: { qb_php_translator_context *translator_cxt = compiler_cxt->translator_context; // translate the zend ops to intermediate qb ops qb_translate_instructions(translator_cxt); } break; case QB_TRANSLATION_PBJ: { qb_pbj_translator_context *translator_cxt = compiler_cxt->translator_context; // create the main loop and translate the PB instructions qb_translate_pbj_instructions(translator_cxt); // free the binary qb_free_external_code(compiler_cxt); } break; } // display warning and bail out on fatal errors qb_dispatch_exceptions(TSRMLS_C); // make all jump target indices absolute qb_resolve_jump_targets(compiler_cxt); // fuse basic instructions into compound ones qb_fuse_instructions(compiler_cxt, 1); // assign storage space to variables qb_assign_storage_space(compiler_cxt); // make opcodes address-mode-specific qb_resolve_address_modes(compiler_cxt); // try to fuse more instructions qb_fuse_instructions(compiler_cxt, 2); // figure out how many references to relocatable segments there are qb_resolve_reference_counts(compiler_cxt); // show the qb opcodes if turned on if(QB_G(show_opcodes)) { qb_printer_context _printer_cxt, *printer_cxt = &_printer_cxt; qb_initialize_printer_context(printer_cxt, compiler_cxt TSRMLS_CC); qb_print_ops(printer_cxt); } } }
static qb_matrix_order qb_get_matrix_order(qb_compiler_context *cxt, qb_op_factory *f) { if(f->result_flags & QB_RESULT_IS_COLUMN_MAJOR) { return QB_MATRIX_ORDER_COLUMN_MAJOR; } else if(f->result_flags & QB_RESULT_IS_ROW_MAJOR) { return QB_MATRIX_ORDER_ROW_MAJOR; } else { USE_TSRM if(QB_G(column_major_matrix)) { return QB_MATRIX_ORDER_COLUMN_MAJOR; } else { return QB_MATRIX_ORDER_ROW_MAJOR; } } }
static void qb_initialize_build_environment(qb_build_context *cxt) { USE_TSRM uint32_t i; cxt->compiler_contexts = emalloc(sizeof(qb_compiler_context *) * cxt->function_declaration_count); for(i = 0; i < cxt->function_declaration_count; i++) { qb_compiler_context *compiler_cxt = cxt->compiler_contexts[cxt->compiler_context_count++] = emalloc(sizeof(qb_compiler_context)); qb_initialize_compiler_context(compiler_cxt, cxt->pool, cxt->function_declarations[i], i, cxt->function_declaration_count TSRMLS_CC); // add variables used within function if(!qb_add_variables(compiler_cxt)) { qb_dispatch_exceptions(TSRMLS_C); } // set up function prototypes so the functions can resolved against each other qb_initialize_function_prototype(compiler_cxt); // attach the appropriate translator if(!compiler_cxt->function_declaration->import_path) { qb_php_translator_context *translator_cxt = emalloc(sizeof(qb_php_translator_context)); qb_initialize_php_translator_context(translator_cxt, compiler_cxt TSRMLS_CC); compiler_cxt->translation = QB_TRANSLATION_PHP; compiler_cxt->translator_context = translator_cxt; } else { qb_pbj_translator_context *translator_cxt = emalloc(sizeof(qb_pbj_translator_context)); qb_initialize_pbj_translator_context(translator_cxt, compiler_cxt TSRMLS_CC); compiler_cxt->translation = QB_TRANSLATION_PBJ; compiler_cxt->translator_context = translator_cxt; // load the code into memory and decode the pbj data if(!qb_load_external_code(compiler_cxt, compiler_cxt->function_declaration->import_path) || !qb_decode_pbj_binary(translator_cxt)) { qb_dispatch_exceptions(TSRMLS_C); } } // show the zend/pbj opcodes if turned on if(QB_G(show_source_opcodes)) { qb_printer_context _printer_cxt, *printer_cxt = &_printer_cxt; qb_initialize_printer_context(printer_cxt, compiler_cxt TSRMLS_CC); qb_print_source_ops(printer_cxt); qb_free_printer_context(printer_cxt); } } for(i = 0; i < cxt->compiler_context_count; i++) { qb_compiler_context *compiler_cxt = cxt->compiler_contexts[i]; switch(compiler_cxt->translation) { case QB_TRANSLATION_PHP: { // run an initial pass over the opcode to gather info qb_php_translator_context *translator_cxt = compiler_cxt->translator_context; qb_survey_instructions(translator_cxt); } break; case QB_TRANSLATION_PBJ: { qb_pbj_translator_context *translator_cxt = compiler_cxt->translator_context; qb_survey_pbj_instructions(translator_cxt); } break; } } // display warning and bail out on fatal errors qb_dispatch_exceptions(TSRMLS_C); }