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
20 changes: 19 additions & 1 deletion ext/standard/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public function getFunctions(): array
new floor(),
new round(),
new sqrt(),
new pi(),
new deg2rad(),
new rad2deg(),
new log(),
new exp(),
new is_nan(),
new is_finite(),
new is_infinite(),
new pow(),
new fmod(),
new intval(),
Expand Down Expand Up @@ -70,7 +78,7 @@ public function jitInit(JIT\Context $context): void
$context->registerFunction('strtol', $fn);
}
$double = $context->getTypeFromString('double');
foreach (['ceil', 'floor', 'round', 'sqrt', 'pow', 'fmod'] as $name) {
foreach (['ceil', 'floor', 'round', 'sqrt', 'log', 'exp', 'pow', 'fmod'] as $name) {
try {
$context->lookupFunction($name);
} catch (\Throwable $e) {
Expand All @@ -80,5 +88,15 @@ public function jitInit(JIT\Context $context): void
$context->registerFunction($name, $fn);
}
}
$i32 = $context->getTypeFromString('int32');
foreach (['isnan', 'isfinite', 'isinf'] as $name) {
try {
$context->lookupFunction($name);
} catch (\Throwable $e) {
$ft = $context->context->functionType($i32, false, $double);
$fn = $context->module->addFunction($name, $ft);
$context->registerFunction($name, $fn);
}
}
}
}
65 changes: 65 additions & 0 deletions ext/standard/deg2rad.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-Compiler, a PHP CFG Compiler for PHP code
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\Variable;
use PHPLLVM\Value;

/**
* deg2rad() for integer or float arguments (subset of PHP standard library).
*/
final class deg2rad extends Internal
{
private const FACTOR = \M_PI / 180.0;

public function execute(Frame $frame): void
{
if (1 !== count($frame->calledArgs)) {
throw new \LogicException('deg2rad() requires exactly one argument');
}
$v = $frame->calledArgs[0]->resolveIndirect();
if (null === $frame->returnVar) {
return;
}
$frame->returnVar->float(self::FACTOR * self::toFloat($v));
}

public Context $context;

public function call(Context $context, JITVariable ...$args): Value
{
$this->context = $context;
if (1 !== count($args)) {
throw new \LogicException('deg2rad() requires exactly one argument');
}
$double = $context->getTypeFromString('double');
$asFloat = pow::toJitDouble($context, $args[0], $double);
$factor = $double->constReal(self::FACTOR);

return $context->builder->fMul($asFloat, $factor);
}

private static function toFloat(Variable $v): float
{
if (Variable::TYPE_INTEGER === $v->type) {
return (float) $v->toInt();
}
if (Variable::TYPE_FLOAT === $v->type) {
return $v->toFloat();
}
throw new \LogicException('deg2rad() only supports integers and floats in this compiler build');
}
}
63 changes: 63 additions & 0 deletions ext/standard/exp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-Compiler, a PHP CFG Compiler for PHP code
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\Variable;
use PHPLLVM\Value;

/**
* exp() for integer or float arguments (subset of PHP standard library).
*/
final class exp extends Internal
{
public function execute(Frame $frame): void
{
if (1 !== count($frame->calledArgs)) {
throw new \LogicException('exp() requires exactly one argument');
}
$v = $frame->calledArgs[0]->resolveIndirect();
if (null === $frame->returnVar) {
return;
}
$frame->returnVar->float(\exp(self::toFloat($v)));
}

public Context $context;

public function call(Context $context, JITVariable ...$args): Value
{
$this->context = $context;
if (1 !== count($args)) {
throw new \LogicException('exp() requires exactly one argument');
}
$double = $context->getTypeFromString('double');
$asFloat = pow::toJitDouble($context, $args[0], $double);
$fn = $context->lookupFunction('exp');

return $context->builder->call($fn, $asFloat);
}

private static function toFloat(Variable $v): float
{
if (Variable::TYPE_INTEGER === $v->type) {
return (float) $v->toInt();
}
if (Variable::TYPE_FLOAT === $v->type) {
return $v->toFloat();
}
throw new \LogicException('exp() only supports integers and floats in this compiler build');
}
}
70 changes: 70 additions & 0 deletions ext/standard/is_finite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-Compiler, a PHP CFG Compiler for PHP code
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\Variable;
use PHPLLVM\Builder;
use PHPLLVM\Value;

/**
* is_finite() for float arguments; integers are always finite (subset of PHP standard library).
*/
final class is_finite extends Internal
{
public function execute(Frame $frame): void
{
if (1 !== count($frame->calledArgs)) {
throw new \LogicException('is_finite() requires exactly one argument');
}
$v = $frame->calledArgs[0]->resolveIndirect();
if (null === $frame->returnVar) {
return;
}
if (Variable::TYPE_INTEGER === $v->type) {
$frame->returnVar->bool(true);

return;
}
if (Variable::TYPE_FLOAT === $v->type) {
$frame->returnVar->bool(\is_finite($v->toFloat()));

return;
}
throw new \LogicException('is_finite() only supports integers and floats in this compiler build');
}

public Context $context;

public function call(Context $context, JITVariable ...$args): Value
{
$this->context = $context;
if (1 !== count($args)) {
throw new \LogicException('is_finite() requires exactly one argument');
}
if (JITVariable::TYPE_NATIVE_LONG === $args[0]->type) {
return $context->constantFromBool(true);
}
if (JITVariable::TYPE_NATIVE_DOUBLE !== $args[0]->type) {
throw new \LogicException('is_finite() only supports integers and floats in this compiler build');
}
$asFloat = $context->helper->loadValue($args[0]);
$fn = $context->lookupFunction('isfinite');
$raw = $context->builder->call($fn, $asFloat);
$zero = $raw->typeOf()->constInt(0, false);

return $context->builder->icmp(Builder::INT_NE, $raw, $zero);
}
}
70 changes: 70 additions & 0 deletions ext/standard/is_infinite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-Compiler, a PHP CFG Compiler for PHP code
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\Variable;
use PHPLLVM\Builder;
use PHPLLVM\Value;

/**
* is_infinite() for float arguments; integers are never infinite (subset of PHP standard library).
*/
final class is_infinite extends Internal
{
public function execute(Frame $frame): void
{
if (1 !== count($frame->calledArgs)) {
throw new \LogicException('is_infinite() requires exactly one argument');
}
$v = $frame->calledArgs[0]->resolveIndirect();
if (null === $frame->returnVar) {
return;
}
if (Variable::TYPE_INTEGER === $v->type) {
$frame->returnVar->bool(false);

return;
}
if (Variable::TYPE_FLOAT === $v->type) {
$frame->returnVar->bool(\is_infinite($v->toFloat()));

return;
}
throw new \LogicException('is_infinite() only supports integers and floats in this compiler build');
}

public Context $context;

public function call(Context $context, JITVariable ...$args): Value
{
$this->context = $context;
if (1 !== count($args)) {
throw new \LogicException('is_infinite() requires exactly one argument');
}
if (JITVariable::TYPE_NATIVE_LONG === $args[0]->type) {
return $context->constantFromBool(false);
}
if (JITVariable::TYPE_NATIVE_DOUBLE !== $args[0]->type) {
throw new \LogicException('is_infinite() only supports integers and floats in this compiler build');
}
$asFloat = $context->helper->loadValue($args[0]);
$fn = $context->lookupFunction('isinf');
$raw = $context->builder->call($fn, $asFloat);
$zero = $raw->typeOf()->constInt(0, false);

return $context->builder->icmp(Builder::INT_NE, $raw, $zero);
}
}
70 changes: 70 additions & 0 deletions ext/standard/is_nan.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-Compiler, a PHP CFG Compiler for PHP code
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCompiler\ext\standard;

use PHPCompiler\Frame;
use PHPCompiler\Func\Internal;
use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\Variable;
use PHPLLVM\Builder;
use PHPLLVM\Value;

/**
* is_nan() for float arguments; integers are never NaN (subset of PHP standard library).
*/
final class is_nan extends Internal
{
public function execute(Frame $frame): void
{
if (1 !== count($frame->calledArgs)) {
throw new \LogicException('is_nan() requires exactly one argument');
}
$v = $frame->calledArgs[0]->resolveIndirect();
if (null === $frame->returnVar) {
return;
}
if (Variable::TYPE_INTEGER === $v->type) {
$frame->returnVar->bool(false);

return;
}
if (Variable::TYPE_FLOAT === $v->type) {
$frame->returnVar->bool(\is_nan($v->toFloat()));

return;
}
throw new \LogicException('is_nan() only supports integers and floats in this compiler build');
}

public Context $context;

public function call(Context $context, JITVariable ...$args): Value
{
$this->context = $context;
if (1 !== count($args)) {
throw new \LogicException('is_nan() requires exactly one argument');
}
if (JITVariable::TYPE_NATIVE_LONG === $args[0]->type) {
return $context->constantFromBool(false);
}
if (JITVariable::TYPE_NATIVE_DOUBLE !== $args[0]->type) {
throw new \LogicException('is_nan() only supports integers and floats in this compiler build');
}
$asFloat = $context->helper->loadValue($args[0]);
$fn = $context->lookupFunction('isnan');
$raw = $context->builder->call($fn, $asFloat);
$zero = $raw->typeOf()->constInt(0, false);

return $context->builder->icmp(Builder::INT_NE, $raw, $zero);
}
}
Loading