Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `sizeof` | yes | yes | yes | standard | |
| `sort` | yes | yes | yes | standard | |
| `sqrt` | yes | yes | yes | standard | |
| `str_contains` | yes | yes | yes | standard | |
| `str_contains` | yes | yes | yes | standard | AOT PHPT |
| `str_ends_with` | yes | yes | yes | standard | AOT PHPT |
| `str_pad` | yes | yes | yes | standard | AOT PHPT |
| `str_repeat` | yes | yes | yes | standard | AOT PHPT |
Expand Down
14 changes: 11 additions & 3 deletions src/llvm-env.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@
* putenv('LD_LIBRARY_PATH') does not affect in-process dlopen on glibc; preload bundled
* dependencies with dlopen(RTLD_GLOBAL) before libLLVM is opened via FFI.
*/
$llvmDir = dirname(__DIR__) . '/.llvm';
$repoRoot = dirname(__DIR__);
$llvmDir = '';
if (is_file($repoRoot.'/.llvm/libLLVM-9.so.1')) {
$llvmDir = $repoRoot.'/.llvm';
} elseif (getenv('PHP_COMPILER_LLVM_PATH') && is_file(getenv('PHP_COMPILER_LLVM_PATH').'/libLLVM-9.so.1')) {
$llvmDir = getenv('PHP_COMPILER_LLVM_PATH');
} elseif (is_file('/opt/llvm9/libLLVM-9.so.1')) {
$llvmDir = '/opt/llvm9';
}

/**
* @param list<string> $names Basenames under $dir (e.g. libffi.so.7).
Expand Down Expand Up @@ -50,15 +58,15 @@ function php_compiler_preload_llvm_deps(string $dir, array $names): void
}
}

if (is_file($llvmDir . '/libLLVM-9.so.1')) {
if ('' !== $llvmDir && is_file($llvmDir . '/libLLVM-9.so.1')) {
putenv('PHP_COMPILER_LLVM_PATH=' . $llvmDir);
$ldPath = getenv('LD_LIBRARY_PATH');
putenv('LD_LIBRARY_PATH=' . $llvmDir . (false === $ldPath || '' === $ldPath ? '' : ':' . $ldPath));
$_ENV['LD_LIBRARY_PATH'] = getenv('LD_LIBRARY_PATH');
$_SERVER['LD_LIBRARY_PATH'] = $_ENV['LD_LIBRARY_PATH'];
php_compiler_preload_llvm_deps($llvmDir, ['libffi.so.7']);
}
if (is_executable($llvmDir . '/clang-9')) {
if ('' !== $llvmDir && is_executable($llvmDir . '/clang-9')) {
$path = getenv('PATH');
putenv('PATH=' . $llvmDir . (false === $path ? '' : ':' . $path));
$_ENV['PATH'] = getenv('PATH');
Expand Down
28 changes: 2 additions & 26 deletions test/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,39 +235,15 @@ protected function normalize(string $string): string {
*/
protected static function applyLlvmToolchainEnv(array &$env): void
{
$llvmDir = dirname(__DIR__).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
return;
}
$prefix = realpath($llvmDir) ?: $llvmDir;
$env['PHP_COMPILER_LLVM_PATH'] = $prefix;
$ld = $env['LD_LIBRARY_PATH'] ?? '';
$env['LD_LIBRARY_PATH'] = '' === $ld ? $prefix : $prefix.':'.$ld;
$path = $env['PATH'] ?? '';
$env['PATH'] = '' === $path ? $prefix : $prefix.':'.$path;
LlvmToolchain::applyProcessEnv($env, dirname(__DIR__));
}

/**
* @return list<string>
*/
protected static function llvmEnvPrefix(): array
{
$llvmDir = dirname(__DIR__).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
return [];
}
$prefix = realpath($llvmDir) ?: $llvmDir;
$ld = getenv('LD_LIBRARY_PATH');
$ldVal = false === $ld || '' === $ld ? $prefix : $prefix.':'.$ld;
$path = getenv('PATH');
$pathVal = false === $path || '' === $path ? $prefix : $prefix.':'.$path;

return [
'env',
'LD_LIBRARY_PATH='.$ldVal,
'PATH='.$pathVal,
'PHP_COMPILER_LLVM_PATH='.$prefix,
];
return LlvmToolchain::envPrefix(dirname(__DIR__));
}

}
103 changes: 103 additions & 0 deletions test/LlvmToolchain.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

declare(strict_types=1);

namespace PHPCompiler;

/**
* Resolve LLVM 9 for JIT/AOT tests (mirrors script/php-env.sh).
*/
final class LlvmToolchain
{
private static ?bool $ready = null;

/**
* @return non-empty-string|null
*/
public static function resolveDir(?string $repoRoot = null): ?string
{
$candidates = [];
if (null !== $repoRoot) {
$candidates[] = $repoRoot.'/.llvm';
}
$fromEnv = getenv('PHP_COMPILER_LLVM_PATH');
if (false !== $fromEnv && '' !== $fromEnv) {
$candidates[] = $fromEnv;
}
$candidates[] = '/opt/llvm9';

foreach ($candidates as $dir) {
if (is_file($dir.'/libLLVM-9.so.1')) {
$resolved = realpath($dir);

return false !== $resolved ? $resolved : $dir;
}
}

return null;
}

public static function isReady(?string $repoRoot = null): bool
{
if (null !== self::$ready) {
return self::$ready;
}
$dir = self::resolveDir($repoRoot);
if (null === $dir) {
self::$ready = false;

return false;
}
if ('' === getenv('PHP_COMPILER_LLVM_PATH')) {
putenv('PHP_COMPILER_LLVM_PATH='.$dir);
$_ENV['PHP_COMPILER_LLVM_PATH'] = $dir;
$_SERVER['PHP_COMPILER_LLVM_PATH'] = $dir;
}
try {
\PHPLLVM\Chooser::choose();
self::$ready = true;
} catch (\Throwable $e) {
self::$ready = false;
}

return self::$ready;
}

/**
* @param array<string, string> $env
*/
public static function applyProcessEnv(array &$env, ?string $repoRoot = null): void
{
$dir = self::resolveDir($repoRoot);
if (null === $dir) {
return;
}
$env['PHP_COMPILER_LLVM_PATH'] = $dir;
$ld = $env['LD_LIBRARY_PATH'] ?? '';
$env['LD_LIBRARY_PATH'] = '' === $ld ? $dir : $dir.':'.$ld;
$path = $env['PATH'] ?? '';
$env['PATH'] = '' === $path ? $dir : $dir.':'.$path;
}

/**
* @return list<string>
*/
public static function envPrefix(?string $repoRoot = null): array
{
$dir = self::resolveDir($repoRoot);
if (null === $dir) {
return [];
}
$ld = getenv('LD_LIBRARY_PATH');
$ldVal = false === $ld || '' === $ld ? $dir : $dir.':'.$ld;
$path = getenv('PATH');
$pathVal = false === $path || '' === $path ? $dir : $dir.':'.$path;

return [
'env',
'LD_LIBRARY_PATH='.$ldVal,
'PATH='.$pathVal,
'PHP_COMPILER_LLVM_PATH='.$dir,
];
}
}
28 changes: 2 additions & 26 deletions test/aot/AotTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,7 @@ private static function isLlvmReady(): bool
if (null !== self::$llvmReady) {
return self::$llvmReady;
}
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
self::$llvmReady = false;

return false;
}
if ('' === getenv('PHP_COMPILER_LLVM_PATH')) {
putenv('PHP_COMPILER_LLVM_PATH='.$llvmDir);
$_ENV['PHP_COMPILER_LLVM_PATH'] = $llvmDir;
$_SERVER['PHP_COMPILER_LLVM_PATH'] = $llvmDir;
}
try {
\PHPLLVM\Chooser::choose();
self::$llvmReady = true;
} catch (\Throwable $e) {
self::$llvmReady = false;
}
self::$llvmReady = LlvmToolchain::isReady(dirname(__DIR__, 2));

return self::$llvmReady;
}
Expand Down Expand Up @@ -77,15 +61,7 @@ public function testCases(string $name, string $code, array $sections): void
$env[$key] = $value;
}
}
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (is_file($llvmDir.'/libLLVM-9.so.1')) {
$prefix = realpath($llvmDir) ?: $llvmDir;
$env['PHP_COMPILER_LLVM_PATH'] = $prefix;
$ld = $env['LD_LIBRARY_PATH'] ?? '';
$env['LD_LIBRARY_PATH'] = '' === $ld ? $prefix : $prefix.':'.$ld;
$path = $env['PATH'] ?? '';
$env['PATH'] = '' === $path ? $prefix : $prefix.':'.$path;
}
LlvmToolchain::applyProcessEnv($env, $repoRoot);
if (isset($sections['ENV'])) {
foreach (explode("\n", trim($sections['ENV'])) as $line) {
$line = trim($line);
Expand Down
43 changes: 3 additions & 40 deletions test/aot/ExampleWebAotTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,7 @@ private function llvmProcessEnv(string $repoRoot): array
$env[$key] = $value;
}
}
$llvmDir = $repoRoot.'/.llvm';
if (is_file($llvmDir.'/libLLVM-9.so.1')) {
$prefix = realpath($llvmDir) ?: $llvmDir;
$env['PHP_COMPILER_LLVM_PATH'] = $prefix;
$ld = $env['LD_LIBRARY_PATH'] ?? '';
$env['LD_LIBRARY_PATH'] = '' === $ld ? $prefix : $prefix.':'.$ld;
$path = $env['PATH'] ?? '';
$env['PATH'] = '' === $path ? $prefix : $prefix.':'.$path;
}
LlvmToolchain::applyProcessEnv($env, $repoRoot);

return $env;
}
Expand Down Expand Up @@ -147,21 +139,7 @@ private static function isLlvmReady(): bool
if (null !== self::$llvmReady) {
return self::$llvmReady;
}
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
self::$llvmReady = false;

return false;
}
if ('' === getenv('PHP_COMPILER_LLVM_PATH')) {
putenv('PHP_COMPILER_LLVM_PATH='.$llvmDir);
}
try {
\PHPLLVM\Chooser::choose();
self::$llvmReady = true;
} catch (\Throwable $e) {
self::$llvmReady = false;
}
self::$llvmReady = LlvmToolchain::isReady(dirname(__DIR__, 2));

return self::$llvmReady;
}
Expand All @@ -171,21 +149,6 @@ private static function isLlvmReady(): bool
*/
private static function llvmEnvPrefix(): array
{
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
return [];
}
$prefix = realpath($llvmDir) ?: $llvmDir;
$ld = getenv('LD_LIBRARY_PATH');
$ldVal = false === $ld || '' === $ld ? $prefix : $prefix.':'.$ld;
$path = getenv('PATH');
$pathVal = false === $path || '' === $path ? $prefix : $prefix.':'.$path;

return [
'env',
'LD_LIBRARY_PATH='.$ldVal,
'PATH='.$pathVal,
'PHP_COMPILER_LLVM_PATH='.$prefix,
];
return LlvmToolchain::envPrefix(dirname(__DIR__, 2));
}
}
43 changes: 3 additions & 40 deletions test/aot/NestedSuperglobalsAotTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,7 @@ private static function llvmEnvironment(string $repoRoot): array
$env[$key] = $value;
}
}
$llvmDir = $repoRoot.'/.llvm';
if (is_file($llvmDir.'/libLLVM-9.so.1')) {
$prefix = realpath($llvmDir) ?: $llvmDir;
$env['PHP_COMPILER_LLVM_PATH'] = $prefix;
$ld = $env['LD_LIBRARY_PATH'] ?? '';
$env['LD_LIBRARY_PATH'] = '' === $ld ? $prefix : $prefix.':'.$ld;
$path = $env['PATH'] ?? '';
$env['PATH'] = '' === $path ? $prefix : $prefix.':'.$path;
}
LlvmToolchain::applyProcessEnv($env, $repoRoot);

return $env;
}
Expand All @@ -120,21 +112,7 @@ private static function isLlvmReady(): bool
if (null !== self::$llvmReady) {
return self::$llvmReady;
}
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
self::$llvmReady = false;

return false;
}
if ('' === getenv('PHP_COMPILER_LLVM_PATH')) {
putenv('PHP_COMPILER_LLVM_PATH='.$llvmDir);
}
try {
\PHPLLVM\Chooser::choose();
self::$llvmReady = true;
} catch (\Throwable $e) {
self::$llvmReady = false;
}
self::$llvmReady = LlvmToolchain::isReady(dirname(__DIR__, 2));

return self::$llvmReady;
}
Expand Down Expand Up @@ -171,21 +149,6 @@ private static function phpCommand(): array
*/
private static function llvmEnvPrefix(): array
{
$llvmDir = dirname(__DIR__, 2).'/.llvm';
if (!is_file($llvmDir.'/libLLVM-9.so.1')) {
return [];
}
$prefix = realpath($llvmDir) ?: $llvmDir;
$ld = getenv('LD_LIBRARY_PATH');
$ldVal = false === $ld || '' === $ld ? $prefix : $prefix.':'.$ld;
$path = getenv('PATH');
$pathVal = false === $path || '' === $path ? $prefix : $prefix.':'.$path;

return [
'env',
'LD_LIBRARY_PATH='.$ldVal,
'PATH='.$pathVal,
'PHP_COMPILER_LLVM_PATH='.$prefix,
];
return LlvmToolchain::envPrefix(dirname(__DIR__, 2));
}
}
Loading
Loading