diff options
Diffstat (limited to 'Zend/zend_vm_gen.php')
-rwxr-xr-x | Zend/zend_vm_gen.php | 193 |
1 files changed, 106 insertions, 87 deletions
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 0795822f96..c7a0df936d 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -138,10 +138,10 @@ $vm_ext_decode = array( ); $vm_kind_name = array( - ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL", - ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH", - ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO", - ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID", + ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL", + ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH", + ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO", + ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID", ); $op_types = array( @@ -150,7 +150,7 @@ $op_types = array( "TMP", "VAR", "UNUSED", - "CV" + "CV", ); $op_types_ex = array( @@ -590,9 +590,9 @@ function is_hot_helper($name) { if (isset($helpers[$name]["hot"])) { return $helpers[$name]["hot"]; - } else { - return false; } + + return false; } // Returns name of specialized helper @@ -637,7 +637,8 @@ function helper_name($name, $spec, $op1, $op2, $extra_spec) { $extra = extra_spec_name(array_intersect_key($extra_spec, $helpers[$name]["spec"])); } } - return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].$extra; + + return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra; } function opcode_name($name, $spec, $op1, $op2, $extra_spec) { @@ -688,7 +689,8 @@ function opcode_name($name, $spec, $op1, $op2, $extra_spec) { $extra = extra_spec_name(array_intersect_key($extra_spec, $opcode["spec"])); } } - return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].$extra; + + return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra; } // Formats condition, protecting it by parentheses when needed. @@ -701,7 +703,7 @@ function format_condition($condition) { return $condition; } - return "(".$condition.")"; + return "(" . $condition . ")"; } // Generates code for opcode handler or helper @@ -811,7 +813,7 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) $code = "{\n\tfprintf(stderr, \"$name\\n\");\n" . substr($code, 1); } // Updating code according to selected threading model - switch($kind) { + switch ($kind) { case ZEND_VM_KIND_HYBRID: $code = preg_replace_callback( array( @@ -1071,7 +1073,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, // Generate opcode handler's entry point according to selected threading model $additional_func = false; $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):""); - switch($kind) { + switch ($kind) { case ZEND_VM_KIND_HYBRID: if (is_inline_hybrid_handler($name, $opcode["hot"], $op1, $op2, $extra_spec)) { $out = fopen('php://memory', 'w+'); @@ -1164,7 +1166,7 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):""); // Generate helper's entry point according to selected threading model - switch($kind) { + switch ($kind) { case ZEND_VM_KIND_HYBRID: out($f, $spec_name . "_LABEL:\n"); break; @@ -1226,7 +1228,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() // Emit labels for specialized executor // For each opcode in opcode number order - foreach($opcodes as $num => $dsc) { + foreach ($opcodes as $num => $dsc) { if (isset($dsc['alias'])) { $specs[$num] = $specs[$opnames[$dsc['alias']]]; continue; @@ -1276,7 +1278,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() $foreach_op1 = function($do) use ($dsc, $op_types) { return function($_, $op2) use ($do, $dsc, $op_types) { // For each op1.op_type except ANY - foreach($op_types as $op1) { + foreach ($op_types as $op1) { if ($op1 != "ANY") { if (!isset($dsc["op1"][$op1])) { if ($op1 == "TMP" || $op1 == "VAR") { @@ -1302,7 +1304,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() $foreach_op2 = function($do) use ($dsc, $op_types) { return function($op1, $_) use ($do, $dsc, $op_types) { // For each op2.op_type except ANY - foreach($op_types as $op2) { + foreach ($op_types as $op2) { if ($op2 != "ANY") { if (!isset($dsc["op2"][$op2])) { if ($op2 == "TMP" || $op2 == "VAR") { @@ -1328,7 +1330,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() $foreach_op_data = function($do) use ($dsc, $op_types) { return function($op1, $op2, $extra_spec = array()) use ($do, $dsc, $op_types) { // For each op_data.op_type except ANY - foreach($op_types as $op_data) { + foreach ($op_types as $op_data) { if ($op_data != "ANY") { if (!isset($dsc["spec"]["OP_DATA"][$op_data])) { if ($op_data == "TMP" || $op_data == "VAR") { @@ -1448,7 +1450,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() // Emit labels for unspecialized executor // For each opcode in opcode number order - foreach($opcodes as $num => $dsc) { + foreach ($opcodes as $num => $dsc) { while ($next != $num) { // If some opcode numbers are not used then fill hole with pointers // to handler of undefined opcode @@ -1529,7 +1531,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() $l = fopen(__DIR__ . "/zend_vm_handlers.h", "w+") or die("ERROR: Cannot create zend_vm_handlers.h\n"); out($l, "#define VM_HANDLERS(_) \\\n"); foreach ($list as $n => $name) { - if (!is_null($name)) { + if (null !== $name) { out($l, "\t_($n, $name) \\\n"); } } @@ -1644,7 +1646,7 @@ function extra_spec_handler($dsc) { if (isset($specs["OP_DATA"])) { $op_data_specs = $specs["OP_DATA"]; $specs["OP_DATA"] = array(); - foreach($op_types_ex as $op_data) { + foreach ($op_types_ex as $op_data) { if (isset($dsc["spec"]["OP_DATA"][$op_data])) { $specs["OP_DATA"][] = $op_data; } @@ -1694,10 +1696,10 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) // Produce specialized executor $op1t = $op_types_ex; // for each op1.op_type - foreach($op1t as $op1) { + foreach ($op1t as $op1) { $op2t = $op_types_ex; // for each op2.op_type - foreach($op2t as $op2) { + foreach ($op2t as $op2) { // for each handlers in helpers in original order foreach ($list as $lineno => $dsc) { if (isset($dsc["handler"])) { @@ -2255,7 +2257,7 @@ function parse_operand_spec($def, $lineno, $str, &$flags) { $flags = 0; $a = explode("|",$str); - foreach($a as $val) { + foreach ($a as $val) { if (isset($vm_op_decode[$val])) { $flags |= $vm_op_decode[$val]; } else { @@ -2276,7 +2278,7 @@ function parse_ext_spec($def, $lineno, $str) { $flags = 0; $a = explode("|",$str); - foreach($a as $val) { + foreach ($a as $val) { if (isset($vm_ext_decode[$val])) { $flags |= $vm_ext_decode[$val]; } else { @@ -2291,7 +2293,7 @@ function parse_spec_rules($def, $lineno, $str) { $ret = array(); $a = explode(",", $str); - foreach($a as $rule) { + foreach ($a as $rule) { $n = strpos($rule, "="); if ($n !== false) { $id = trim(substr($rule, 0, $n)); @@ -2336,6 +2338,62 @@ function parse_spec_rules($def, $lineno, $str) { return $ret; } +function gen_vm_opcodes_header( + array $opcodes, int $max_opcode, int $max_opcode_len, array $vm_op_flags +): string { + $str = HEADER_TEXT; + $str .= "#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n"; + $str .= "#define ZEND_VM_SPEC\t\t" . ZEND_VM_SPEC . "\n"; + $str .= "#define ZEND_VM_LINES\t\t" . ZEND_VM_LINES . "\n"; + $str .= "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n"; + $str .= "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n"; + $str .= "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n"; + $str .= "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n"; + if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") { + $str .= "/* HYBRID requires support for computed GOTO and global register variables*/\n"; + $str .= "#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n"; + $str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n"; + $str .= "#else\n"; + $str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n"; + $str .= "#endif\n"; + } else { + $str .= "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n"; + } + $str .= "\n"; + $str .= "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n"; + $str .= "# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n"; + $str .= "# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16\n"; + $str .= "# endif\n"; + $str .= "#endif\n"; + $str .= "\n"; + foreach ($vm_op_flags as $name => $val) { + $str .= sprintf("#define %-24s 0x%08x\n", $name, $val); + } + $str .= "#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff)\n"; + $str .= "#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff)\n"; + $str .= "\n"; + $str .= "BEGIN_EXTERN_C()\n\n"; + $str .= "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode);\n"; + $str .= "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(zend_uchar opcode);\n\n"; + $str .= "END_EXTERN_C()\n\n"; + + $code_len = strlen((string) $max_opcode); + foreach ($opcodes as $code => $dsc) { + $code = str_pad((string)$code, $code_len, " ", STR_PAD_LEFT); + $op = str_pad($dsc["op"], $max_opcode_len); + if ($code <= $max_opcode) { + $str .= "#define $op $code\n"; + } + } + + $code = str_pad((string)$max_opcode, $code_len, " ", STR_PAD_LEFT); + $op = str_pad("ZEND_VM_LAST_OPCODE", $max_opcode_len); + $str .= "\n#define $op $code\n"; + + $str .= "\n#endif\n"; + return $str; +} + function gen_vm($def, $skel) { global $definition_file, $skeleton_file, $executor_file, $op_types, $list, $opcodes, $helpers, $params, $opnames, @@ -2446,8 +2504,8 @@ function gen_vm($def, $skel) { $opcodes[$orig_code]['type_spec'][$code] = $condition; } $op = $m[4]; - $op1 = parse_operand_spec($def, $lineno, $m[5], $flags1); - $op2 = parse_operand_spec($def, $lineno, $m[6], $flags2); + $op1 = parse_operand_spec($def, $lineno, $m[5], $flags1); + $op2 = parse_operand_spec($def, $lineno, $m[6], $flags2); $flags = $flags1 | ($flags2 << 8); if (!empty($m[8])) { $flags |= parse_ext_spec($def, $lineno, $m[8]); @@ -2494,10 +2552,11 @@ function gen_vm($def, $skel) { } // Store parameters - if (ZEND_VM_KIND == ZEND_VM_KIND_GOTO + if ((ZEND_VM_KIND == ZEND_VM_KIND_GOTO || ZEND_VM_KIND == ZEND_VM_KIND_SWITCH - || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && $hot)) { - foreach (explode(",", $param) as $p) { + || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && $hot)) + && $param) { + foreach (explode(",", $param ) as $p) { $p = trim($p); if ($p !== "") { $params[$p] = 1; @@ -2574,60 +2633,8 @@ function gen_vm($def, $skel) { } // Generate opcode #defines (zend_vm_opcodes.h) - $code_len = strlen((string)$max_opcode); - $f = fopen(__DIR__ . "/zend_vm_opcodes.h", "w+") or die("ERROR: Cannot create zend_vm_opcodes.h\n"); - - // Insert header - out($f, HEADER_TEXT); - fputs($f, "#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n"); - fputs($f, "#define ZEND_VM_SPEC\t\t" . ZEND_VM_SPEC . "\n"); - fputs($f, "#define ZEND_VM_LINES\t\t" . ZEND_VM_LINES . "\n"); - fputs($f, "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n"); - fputs($f, "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n"); - fputs($f, "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n"); - fputs($f, "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n"); - if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") { - fputs($f, "/* HYBRID requires support for computed GOTO and global register variables*/\n"); - fputs($f, "#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n"); - fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n"); - fputs($f, "#else\n"); - fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n"); - fputs($f, "#endif\n"); - } else { - fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n"); - } - fputs($f, "\n"); - fputs($f, "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n"); - fputs($f, "# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n"); - fputs($f, "# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16\n"); - fputs($f, "# endif\n"); - fputs($f, "#endif\n"); - fputs($f, "\n"); - foreach($vm_op_flags as $name => $val) { - fprintf($f, "#define %-24s 0x%08x\n", $name, $val); - } - fputs($f, "#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff)\n"); - fputs($f, "#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff)\n"); - fputs($f, "\n"); - fputs($f, "BEGIN_EXTERN_C()\n\n"); - fputs($f, "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode);\n"); - fputs($f, "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(zend_uchar opcode);\n\n"); - fputs($f, "END_EXTERN_C()\n\n"); - - foreach ($opcodes as $code => $dsc) { - $code = str_pad((string)$code,$code_len," ",STR_PAD_LEFT); - $op = str_pad($dsc["op"],$max_opcode_len); - if ($code <= $max_opcode) { - fputs($f,"#define $op $code\n"); - } - } - - $code = str_pad((string)$max_opcode,$code_len," ",STR_PAD_LEFT); - $op = str_pad("ZEND_VM_LAST_OPCODE",$max_opcode_len); - fputs($f,"\n#define $op $code\n"); - - fputs($f, "\n#endif\n"); - fclose($f); + $str = gen_vm_opcodes_header($opcodes, $max_opcode, $max_opcode_len, $vm_op_flags); + write_file_if_changed(__DIR__ . "/zend_vm_opcodes.h", $str); echo "zend_vm_opcodes.h generated successfully.\n"; // zend_vm_opcodes.c @@ -2847,7 +2854,7 @@ function gen_vm($def, $skel) { out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); if (isset($used_extra_spec["TYPE"])) { out($f, "\tswitch (opcode) {\n"); - foreach($opcodes as $code => $dsc) { + foreach ($opcodes as $code => $dsc) { if (isset($dsc['type_spec'])) { $orig_op = $dsc['op']; out($f, "\t\tcase $orig_op:\n"); @@ -2857,7 +2864,7 @@ function gen_vm($def, $skel) { out($f, "\t\t\t}\n"); } $first = true; - foreach($dsc['type_spec'] as $code => $condition) { + foreach ($dsc['type_spec'] as $code => $condition) { $condition = format_condition($condition); if ($first) { out($f, "\t\t\tif $condition {\n"); @@ -2885,7 +2892,7 @@ function gen_vm($def, $skel) { } } $has_commutative = false; - foreach($opcodes as $code => $dsc) { + foreach ($opcodes as $code => $dsc) { if (!isset($dsc['is_type_spec']) && !isset($dsc['type_spec']) && isset($dsc["spec"]["COMMUTATIVE"])) { @@ -2980,6 +2987,18 @@ function gen_vm($def, $skel) { echo "zend_vm_execute.h generated successfully.\n"; } +function write_file_if_changed(string $filename, string $contents) { + if (file_exists($filename)) { + $orig_contents = file_get_contents($filename); + if ($orig_contents === $contents) { + // Unchanged, no need to write. + return; + } + } + + file_put_contents($filename, $contents); +} + function usage() { echo("\nUsage: php zend_vm_gen.php [options]\n". "\nOptions:". |