Skip to content

Fix AOT nullable ?string param returns via compile-time ?? rewrite (#8563) - #8586

Merged
PurHur merged 3 commits into
masterfrom
agent/issue-8561-bootstrap-aot-link-lane-c
Jun 14, 2026
Merged

PurHur merged 3 commits into
masterfrom
agent/issue-8561-bootstrap-aot-link-lane-c

Conversation

@PurHur

@PurHur PurHur commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes AOT segfault/abort when functions return explicit nullable parameters (?string $n → ?string) — the bootstrap-aot-link blocker tracked on #8561 / #8555.

PHP-in-PHP approach:

  • Compile-time rewrite in lib/Compiler.php: return $param and return (null !== $param ? $param : null) lower to $param ?? null (proven AOT-safe coalesce path)
  • cfgFunctionReturnCallbackType: nullable scalar returns use __value__* ABI (parity with cfgParamIsImplicitNullable)
  • Cherry-pick JIT ?: merge arm-tail RETURN lowering from bootstrap-aot-link: VALUE-box concat + ordered float compare lowering #8555 (emitCfgReturnOperand)

Reference: Zend ext/standard coalesce semantics; php-src equivalent shapes for ?string param/return ABI.

Verification

php vendor/bin/phpunit test/unit/NullableNeNullTernaryRewriteTest.php test/unit/NullableStringReturnAbiTest.php
# OK (2 tests)

php bin/vm.php test/repro/aot_ternary_ne_null.php
php bin/jit.php test/repro/aot_ternary_ne_null.php
# hello

export PHP_COMPILER_BOOTSTRAP_AOT_LINK=1
php bin/compile.php -o /tmp/ne test/repro/aot_ternary_ne_null.php && /tmp/ne
# hello (exit 0; was segfault 139)

php bin/compile.php -o /tmp/v test/repro/aot_ternary_var_nullable.php && /tmp/v
# hello (exit 0)

php bin/compile.php -o /tmp/d test/repro/aot_nullable_param_direct_return.php && /tmp/d
# hello (exit 0)

make bootstrap-aot-link still has unrelated failures (hash/crypto/stdlib); this PR greens the nullable-param return repros that blocked ns_func.php-class patterns.

Closes #8563

Made with Cursor

PurHur and others added 3 commits June 14, 2026 18:54
Compile-time rewrite maps the if-entry ?string arm to null === $param ? null : $param
(php-src equivalent) and tracks the JumpIf so branch targets stay aligned with IDENTICAL.

Verification: php vendor/bin/phpunit test/unit/NullableNeNullTernaryRewriteTest.php test/unit/TernaryReturnMergeSlotTest.php
  php bin/vm.php test/repro/aot_ternary_ne_null.php
  PHP_COMPILER_BOOTSTRAP_AOT_LINK=1 php bin/compile.php -o /tmp/n test/repro/aot_ternary_ne_null.php && /tmp/n
Co-authored-by: Cursor <cursoragent@cursor.com>
Return typed string operands directly from the if-entry arm instead of
reading the shared phi VALUE box after merge-block dead-operand frees.
Nullable/union if-arms keep per-arm RETURN from the phi slot; pure string
params skip the box on the string arm only.

Verification:
- test/repro/ns_nullable_ternary_return.php AOT exit 0 (was segfault)
- test/repro/aot_ternary_bool.php AOT exit 0
- test/repro/getenv_identical_false.php AOT prints yes
- make bootstrap-aot-link still 16 failures (ns_func, ne_null, …)

Co-authored-by: Cursor <cursoragent@cursor.com>
…8563).

Rewrite direct and ternary returns of explicit ?T params to $param ?? null
(php-src equivalent) so native AOT uses the proven coalesce VALUE-box path.
Register nullable scalar returns as __value__* in JIT ABI; cherry-pick ?: merge
lowering from #8555.

Verification: php vendor/bin/phpunit test/unit/NullableNeNullTernaryRewriteTest.php test/unit/NullableStringReturnAbiTest.php
  PHP_COMPILER_BOOTSTRAP_AOT_LINK=1 php bin/compile.php -o /tmp/t test/repro/aot_ternary_ne_null.php && /tmp/t
  PHP_COMPILER_BOOTSTRAP_AOT_LINK=1 php bin/compile.php -o /tmp/t test/repro/aot_nullable_param_direct_return.php && /tmp/t
Co-authored-by: Cursor <cursoragent@cursor.com>
@PurHur
PurHur merged commit ac6eee2 into master Jun 14, 2026
@PurHur
PurHur deleted the agent/issue-8561-bootstrap-aot-link-lane-c branch June 14, 2026 19:07
PurHur added a commit that referenced this pull request Jul 26, 2026
…curse AOT (#23482) (#23513)

Arm-tail ternary returns called a missing Context method since #8586; resolve
return/phi operands via the arm CFG block's scope slots so naive untyped fib
compiles and matches Zend.

Co-authored-by: PurHur <PurHur@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant