summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_gen.php
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_vm_gen.php')
-rwxr-xr-xZend/zend_vm_gen.php193
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:".