From 5f14139acee1a5ed8224bae4ed36c60752a68430 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 7 Jan 2026 11:30:35 +0800 Subject: [PATCH] =?UTF-8?q?Native=20=E5=B8=B8=E9=87=8F=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.cc | 7 ++- src/Php/Translator.php | 124 ++++++++++++++++++++++++++++++++++++++--- tests/aot/const.phpt | 50 +++++++++++++++++ 3 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 tests/aot/const.phpt diff --git a/main.cc b/main.cc index 2a9bc7da..6c0167fc 100644 --- a/main.cc +++ b/main.cc @@ -8,7 +8,9 @@ void php_main(); extern php::Var argc; extern php::Var argv; -extern void php_unset_all_global_vars(); + +extern void php_init_constant_vars(); +extern void php_unset_global_vars(); static void throw_exception(zend_object *ex) { zend_bailout(); @@ -33,6 +35,7 @@ int main(int cpp_argc, char **cpp_argv) { zend_first_try { argc = php::global("argc"); argv = php::global("argv"); + php_init_constant_vars(); php_main(); } zend_catch { @@ -45,7 +48,7 @@ int main(int cpp_argc, char **cpp_argv) { #if PPROF_ON ProfilerStop(); #endif - php_unset_all_global_vars(); + php_unset_global_vars(); php::request_shutdown(); php_embed_shutdown(); return rc; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 44b714bd..4d785149 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -13,6 +13,7 @@ use PhpParser\NodeTraverser; use PhpParser\ParserFactory; use PhpParser\PrettyPrinter; use SimplePie\Exception; +use stdClass; class Translator extends \PhpAot\Core\Translator { @@ -99,6 +100,7 @@ class Translator extends \PhpAot\Core\Translator private array $nativeFunctions = []; private array $internalFunctions = []; + private array $nativeConstants = []; private int $optimizeLevel = 0; private int $floatPrecision = 17; private bool $debugInfo = true; @@ -293,6 +295,9 @@ class Translator extends \PhpAot\Core\Translator case 'Stmt_Function': $cppCode .= $this->parseFunctionDef($v) . PHP_EOL; break; + case 'Stmt_Const': + $this->parseConstDef($v) . PHP_EOL; + break; default: abort($v); } @@ -499,6 +504,7 @@ class Translator extends \PhpAot\Core\Translator $this->beforeStmtLines = []; $this->afterStmtLines = []; $this->writeLog('Line ' . $this->getLine($v) . ': ' . $class); + $lines[] = $this->getIndent() . '// ' . $class . ' [' . $v->getStartLine() . ':' . $v->getEndLine() . ']'; switch ($class) { case 'Stmt_Expression': $result = $this->parseExpr($v->expr) . ';'; @@ -819,14 +825,19 @@ class Translator extends \PhpAot\Core\Translator return implode("\n" . $this->getIndent(), $lines); } - private function isFloatStr(string $str) + private function isFloatStr(string $str): bool + { + return filter_var($str, FILTER_VALIDATE_FLOAT) !== false; + } + + private function isIntStr(string $str): bool { - return filter_var($str, FILTER_VALIDATE_FLOAT); + return filter_var($str, FILTER_VALIDATE_INT) !== false; } - private function isIntStr(string $str) + private function isBoolStr(string $str): bool { - return filter_var($str, FILTER_VALIDATE_INT); + return $str === 'true' || $str === 'false'; } private function isInternalFunction(string $fname): bool @@ -1172,7 +1183,7 @@ class Translator extends \PhpAot\Core\Translator if ($expr->getType() === 'Expr_Assign') { $left = $expr->var; $name = $this->parseIdentifier($left); - if (!$this->hasGlobalVar($name)) { + if ($this->hasGlobalVar($name)) { $this->fatalError($left, 'Cannot assign to global variable in for loop'); } if (!$this->hasVar($name)) { @@ -1755,6 +1766,9 @@ class Translator extends \PhpAot\Core\Translator case 'Stmt_Class': $code .= $this->parseClassDef($v2); break; + case 'Stmt_Const': + $this->parseConstDef($v2) . PHP_EOL; + break; case 'Stmt_Function': $code .= $this->parseFunctionDef($v2) . PHP_EOL; break; @@ -1815,7 +1829,13 @@ class Translator extends \PhpAot\Core\Translator private function parseConstFetch(Node $expr): string { + if ($expr->name->getType() != 'Name') { + abort($expr); + } $name = $this->parseIdentifier($expr->name); + if ($this->hasConstant($name)) { + return $this->getConstant($name); + } if ($name === 'null') { return 'nullptr'; } elseif ($name === 'true') { @@ -2049,6 +2069,9 @@ class Translator extends \PhpAot\Core\Translator private function detectConstType($expr): string { $name = $this->parseIdentifier($expr->name); + if ($this->hasConstant($name)) { + return $this->getConstantType($name); + } if ($name === 'true') { return self::TYPE_BOOL; } @@ -2219,20 +2242,52 @@ class Translator extends \PhpAot\Core\Translator $this->indentLevel--; $code .= '};' . PHP_EOL; + // 生成全局常量 + $this->indentLevel++; + foreach ($this->nativeConstants as $name => $constant) { + $code .= $constant->type . ' ' . $name . ';' . PHP_EOL; + } + $this->indentLevel--; + $code .= PHP_EOL; - $code .= 'void ' . self::PREFIX . 'unset_all_global_vars() {' . PHP_EOL; + $this->indentLevel++; $lines = []; + foreach ($this->nativeConstants as $name => $constant) { + $lines[] = $this->getIndent() . $name . ' = ' . $constant->value . ';'; + } + $this->indentLevel--; + $code .= $this->genFunction(self::PREFIX . 'init_constant_vars', 'void', [], $lines); + + $code .= PHP_EOL; $this->indentLevel++; + $lines = []; foreach ($this->globalVars as $name => $type) { $lines[] = $this->getIndent() . $name . '.unset();'; } + foreach ($this->nativeConstants as $name => $constant) { + if ($constant->type !== self::TYPE_VAR) { + continue; + } + $lines[] = $this->getIndent() . $name . '.unset();'; + } $this->indentLevel--; - $code .= implode(PHP_EOL, $lines) . PHP_EOL; - $code .= '}' . PHP_EOL; + $code .= $this->genFunction(self::PREFIX . 'unset_global_vars', 'void', [], $lines); file_put_contents($file, $code); } + private function genFunction(string $name, string $returnType, array $args = [], array $lines = []): string + { + $_args = []; + foreach ($args as $arg => $type) { + $_args[] = $type . ' ' . $arg; + } + $code = $returnType . ' ' . $name . '(' . implode(', ', $_args) . ') {' . PHP_EOL; + $code .= implode(PHP_EOL, $lines) . PHP_EOL; + $code .= '}' . PHP_EOL; + return $code; + } + private function parseCastDouble(mixed $expr): string { return $this->convertFloatExpr($this->parseIdentifier($expr->expr)); @@ -2312,6 +2367,12 @@ class Translator extends \PhpAot\Core\Translator } $code .= ');' . PHP_EOL; } + + $code .= PHP_EOL; + foreach ($this->nativeConstants as $name => $constant) { + $code .= 'extern ' . $constant->type . ' ' . $name . ';' . PHP_EOL; + } + file_put_contents($file, $code); } @@ -2461,4 +2522,51 @@ class Translator extends \PhpAot\Core\Translator $this->fatalError($v, 'Label statement is not supported'); return $v->name->name . ':'; } + + private function parseConstDef(mixed $v2): string + { + foreach($v2->consts as $const) { + $name = $this->parseIdentifier($const->name); + $value = $this->parseIdentifier($const->value); + $this->addConstant($name, $value); + } + return ''; + } + + private function addConstant(string $name, string $value): void + { + $constInfo = new stdClass(); + $constInfo->value = $value; + $constInfo->type = $this->detectStrValueType($value); + $this->nativeConstants[$name] = $constInfo; + } + + private function hasConstant(string $name) + { + return isset($this->nativeConstants[$name]); + } + + private function getConstant(string $name): string + { + return $this->nativeConstants[$name]->value; + } + + private function getConstantType(string $name): string + { + return $this->nativeConstants[$name]->type; + } + + private function detectStrValueType(mixed $constant): string + { + if ($this->isIntStr($constant)) { + return self::TYPE_INT; + } + if ($this->isFloatStr($constant)) { + return self::TYPE_FLOAT; + } + if ($this->isBoolStr($constant)) { + return self::TYPE_BOOL; + } + return self::TYPE_VAR; + } } diff --git a/tests/aot/const.phpt b/tests/aot/const.phpt new file mode 100644 index 00000000..6272f143 --- /dev/null +++ b/tests/aot/const.phpt @@ -0,0 +1,50 @@ +--TEST-- +consts +--FILE-- + +--EXPECTF-- +int(11) +float(1.1) +string(3) "str" +bool(true) +NULL +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(stdClass)#%d (0) { +} +int(-11) +float(2.2) +string(8) "strhello" +