Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1a81561
feat(windows-pe): Windows x86_64 PE32+ cross-compilation + random_byt…
Guikingone Jul 6, 2026
8b89ff9
feat(ci): curated Windows codegen no-regression gate
Guikingone Jul 6, 2026
7cd8d4f
feat(windows-pe): Winsock init + access/ftruncate shims + target-awar…
Guikingone Jul 7, 2026
51ff74b
feat(windows-pe): MinGW cross-built PCRE2/bzip2/zlib/iconv sysroot + …
Guikingone Jul 7, 2026
93a52a7
feat(windows-pe): target-aware bridge cross-compile for x86_64-pc-win…
Guikingone Jul 7, 2026
97d054f
feat(windows-pe): sleep/usleep + getrusage Win32 shims
Guikingone Jul 7, 2026
7ec2236
feat(windows-pe): popen/pclose/fileno/fgetc/system msvcrt shims + str…
Guikingone Jul 7, 2026
2a7a8f8
fix(windows-pe): correct mixed-size mov in pselect6 fd_set shim
Guikingone Jul 7, 2026
02c3e66
feat(windows-pe): proc_open/proc_close PHP surface + stub runtime
Guikingone Jul 7, 2026
fa9caa4
docs: re-apply Windows target policy to AGENTS.md
Guikingone Jul 7, 2026
77b42ae
docs: regenerate builtins docs for proc_open/proc_close
Guikingone Jul 7, 2026
9f108db
fix(windows-pe): resolve MinGW ar/ranlib via absolute paths for new r…
Guikingone Jul 7, 2026
9b47ebc
fix(windows-pe): skip pcre2posix_test in MinGW PCRE2 sysroot cross-build
Guikingone Jul 8, 2026
4d0cd5a
fix(windows-pe): alias CMake zlib static archive to libz.a for -lz link
Guikingone Jul 8, 2026
6cb893a
feat(windows-pe): eradicate SysV/MSx64 ABI mismatches across the x86_…
Guikingone Jul 10, 2026
7eddc16
feat(windows-pe): proc_open/proc_close real runtime (unix pipe-only)
Guikingone Jul 10, 2026
833469f
feat(windows-pe): proc_open/proc_close real Windows runtime (C1c Crea…
Guikingone Jul 10, 2026
a62dd5a
feat(windows-pe): correct 7 Windows builtin semantics (W8)
Guikingone Jul 11, 2026
fbe6343
feat(windows-pe): split win32 runtime into cohesive submodules + ABI …
Guikingone Jul 11, 2026
dccfd18
fix(windows-pe): correct __rt_array_get_mixed_key x86_64 hash-path va…
Guikingone Jul 11, 2026
2be216d
fix(windows-pe): accept Windows "Temp" spelling in test_sys_get_temp_dir
Guikingone Jul 11, 2026
a2c7807
fix(windows-pe): regenerate builtins docs after W8 filesystem line sh…
Guikingone Jul 11, 2026
f6b3c55
feat(windows-pe): resync TEB stack bounds in x86_64 fiber switch
Guikingone Jul 11, 2026
cb8a173
feat(windows-pe): SEH-free __rt_setjmp/__rt_longjmp for Windows x86_64
Guikingone Jul 11, 2026
511c854
feat(windows-pe): SysV arg registers for runtime-intrinsic __rt_* cal…
Guikingone Jul 11, 2026
24c5d66
feat(windows-pe): refresh codegen parity gate from green wine run
Guikingone Jul 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ relative-to = "target"
path = "debug/libelephc_web.a"
relative-to = "target"

# Emit a machine-readable JUnit report for every `--profile ci` run. This is
# purely additive (it writes `target/nextest/ci/junit.xml` and changes no test
# outcome or console output), so the native codegen/non-codegen jobs are
# unaffected. The Windows codegen no-regression gate parses this file per shard
# to recover the exact set of failing test names (see the `windows-codegen-parity`
# job in `.github/workflows/ci.yml` and `scripts/windows_codegen_gate_check.py`).
[profile.ci.junit]
path = "junit.xml"

# The `ir_backend_parity` first-class-callable case bundles 15 legacy-vs-EIR
# parity programs (several link the PCRE staticlib), each compiled and run twice.
# It legitimately runs ~65-70s, just over the global 60s cap, so it needs a
Expand Down
393 changes: 393 additions & 0 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

40 changes: 39 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Before contributing, read `CONTRIBUTING.md` in full. It holds the complete step-

## Supported target policy

All supported targets are first-class targets. The supported target matrix is currently `macos-aarch64`, `linux-aarch64`, and `linux-x86_64`.
All supported targets are first-class targets. The supported target matrix is currently `macos-aarch64`, `linux-aarch64`, and `linux-x86_64`, plus `windows-x86_64` as a newly added, experimental cross-compilation target (runtime shim coverage and end-to-end execution testing are not yet at parity with the other three).

Do not design or land codegen/runtime features as ARM64-first with x86_64 treated as a later port. New features, builtins, runtime helpers, optimizer assumptions that affect emitted code, ABI behavior, and ownership/GC paths must either support every supported target in the same change or clearly isolate an intentionally unsupported path with diagnostics, tests, and documentation. A feature is not considered done while any supported target has a missing runtime symbol, reduced semantics, stale documentation, or an untested target-specific lowering path.

Expand Down Expand Up @@ -401,6 +401,44 @@ Adding or updating function docblocks must not change code behavior. Do not alte
- **Labels**: use `ctx.next_label("prefix")` — global counter prevents collisions across functions
- **Mixed values**: `PhpType::Mixed` is an internal boxed runtime shape used for heterogeneous associative-array values; codegen/runtime must preserve the boxed cell contract instead of treating it like a plain scalar

### Windows x86_64 (MSx64) ABI reference

The Windows PE target reuses the SysV-shaped native codegen and bridges to the
Microsoft x64 ABI inside per-symbol shims under `src/codegen_support/runtime/win32/`.
When writing or reviewing a Win32 shim, hold these rules:

- **Integer args**: `rcx`, `rdx`, `r8`, `r9`, then the stack. Every call reserves a
32-byte **shadow space** the callee owns; the 5th and later integer args go at
`[rsp+32]`, `[rsp+40]`, … (above the shadow), never in more registers.
- **Callee-saved**: `rbx`, `rbp`, `rdi`, `rsi`, `r12`–`r15`. Note `rsi`/`rdi` are
**non-volatile** on MSx64 (unlike SysV), so a shim can stage the incoming SysV
path/buffer pointer in `rsi`/`rdi` and rely on it surviving every nested Win32 call.
- **Stack alignment**: a shim is entered at `rsp ≡ 8 (mod 16)` (the `call` pushed the
return address). Re-align with `sub rsp, N` where `N ≡ 8 (mod 16)` — i.e. **40 or 56**,
not 32 — so `rsp ≡ 0 (mod 16)` at the nested `call`. The unit test
`test_stack_alignment_16_bytes` enforces this; the only legitimate `sub rsp, 32` is
the exit shim, which first forces alignment with `and rsp, -16`.
- **Struct / out-param layout is UPWARD (C layout)**: the pointer you pass to an API is
the struct's **lowest** address, and a field at byte offset `F` lives at `base + F` —
higher offset ⇒ higher address ⇒ *less-negative* `rbp`/`rsp` offset. Never lay a struct
downward (`base − F`); a downward layout is invisible to the macOS/Linux tests and only
fails under wine. Canonical reference: the `pselect6` fd_set shim (`fd_count@base+0`,
`fd_array@base+8`). Zero a struct fully before filling it. This class of bug bit us on
the proc_open `STARTUPINFOA`/`PROCESS_INFORMATION` layout and on the `statfs`/`utsname`/
`FILETIME`/`BY_HANDLE_FILE_INFORMATION` fills.
- **Status-convention translation**: many Win32 APIs return a `BOOL` (nonzero = success).
A shim standing in for a POSIX C symbol whose consumer tests `== 0` for success
(`link`, `rename`, …) **must** translate the `BOOL` to POSIX (`0` = success,
`-1` = failure) inside the shim, or success and failure are reported inverted. Mirror
the `link`/`rename` shims: `test eax, eax; jz .Lfail; xor rax, rax` / `.Lfail: mov rax, -1`.
- **32-bit int-status sign extension (Class-3)**: a shim returning a 32-bit C `int` status
that a consumer sign-tests must `cdqe` before returning, so a negative status is not read
as a large positive `rax`.
- **Adding a shim**: declare the Win32 import in `WIN32_IMPORTS`, add the `emit_shim_*` and
its call in `emit_win32_shims`, and keep non-Windows emitters byte-identical (only the
Windows arm and `WIN32_IMPORTS` change). `ntdll`-only APIs (e.g. `RtlGetVersion`) are
**not** in the link set — do not import them; use a documented fallback instead.

### Assembly comment policy

Every `emitter.instruction(...)` call must have an inline `//` comment aligned to
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Releases are listed newest first.
`true` uses strict type-identical membership.
- Added `mb_ereg_match()`: a PCRE2-backed, start-anchored mbregex builtin with
the optional `$options` argument and support for `i` case-insensitive matching.
- Add an experimental Windows x86_64 (PE32+) cross-compilation target (`--target windows-x86_64`, alias `x86_64-pc-windows-gnu`): produces a GNU/MinGW-ABI `.exe` (`.dll` for `--emit cdylib`) via `x86_64-w64-mingw32-gcc`, and requires the MinGW-w64 cross toolchain on the host doing the build. Runtime shim coverage and end-to-end execution testing are still catching up to macOS/Linux, so treat it as cross-compilation support rather than a fully verified target.
- Add the `random_bytes(int $length): string` builtin: a cryptographically secure random byte string on every supported target (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a length below 1.
- Int-backed enum `from()` / `tryFrom()` now accept a dynamically-typed (`mixed`) argument (issue #449): a `foreach` value over a heterogeneous array, an untyped parameter, etc. are coerced on their runtime type before the enum lookup — integer/numeric-string resolve (or throw `ValueError`), float truncates, bool/null coerce, and array/object/resource/closure throw `TypeError` naming the given type. Previously any `mixed` argument was rejected at compile time. Target-aware on every supported backend.
- Int-backed enum `from()` / `tryFrom()` now accept a numeric string (issue #349): `Level::from("1")` coerces the string to the integer backing value (as a distinct EIR coercion lowered before the enum call) and returns the matching case, instead of being rejected at compile time. A numeric string with no matching case throws `ValueError`; a non-numeric string (e.g. `"x"`) throws `TypeError` with PHP's exact argument-type message — matching PHP's coercive typing on every supported target, including PHP-rejected libc `strtod` extensions such as hexadecimal `"0x1"`, `"INF"`, and `"NAN"`.
- Fixed an enum `from()` / `tryFrom()` refcount bug (surfaced while fixing #349): the returned case singleton was under-retained, so storing the result into a reassigned variable inside a loop drove the persistent singleton's refcount to zero and freed it — producing garbage reads or a heap crash after a few iterations. `from()`/`tryFrom()` now retain the matched singleton, keeping it alive like direct case access. Affected both backed-enum backings.
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
</p>

<p align="center">
<strong>3 native targets &middot; no Zend Engine &middot; zero runtime dependencies &middot; single standalone binary</strong>
<strong>4 native targets &middot; no Zend Engine &middot; zero runtime dependencies &middot; single standalone binary</strong>
</p>

<p align="center">
A PHP-to-native compiler that takes a subset of PHP and compiles it directly to native assembly, producing standalone binaries for <strong>macOS ARM64</strong>, <strong>Linux ARM64</strong>, and <strong>Linux x86_64</strong>. No opcode fallback, just real machine code.
A PHP-to-native compiler that takes a subset of PHP and compiles it directly to native assembly, producing standalone binaries for <strong>macOS ARM64</strong>, <strong>Linux ARM64</strong>, and <strong>Linux x86_64</strong>, plus an experimental <strong>Windows x86_64</strong> cross-compilation target. No opcode fallback, just real machine code.
</p>

<p align="center">
Expand Down Expand Up @@ -199,9 +199,10 @@ elephc app.php -l sqlite3 -L /opt/homebrew/lib --framework Cocoa
elephc app.php --with-pdo --with-crypto

# Explicit target selection
# Supported targets today: macos-aarch64, linux-aarch64, linux-x86_64
# Supported targets today: macos-aarch64, linux-aarch64, linux-x86_64, windows-x86_64 (experimental)
elephc --target linux-aarch64 hello.php
elephc --target linux-x86_64 hello.php
elephc --target windows-x86_64 hello.php # experimental cross-compilation, requires MinGW-w64

# Compile a standalone prefork HTTP server binary
elephc --web app.php
Expand Down
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,8 @@ and 0.x validation rather than by speculative pass work.
- [ ] Composite conditional include function variants — extend include-graph exclusivity from one direct `if` / `elseif` / `else` chain to nested/composed conditional paths where declarations are pairwise exclusive only after combining multiple branch decisions
- [ ] Switch-aware conditional include function variants — extend include-graph exclusivity beyond `if` / `elseif` / `else` to `switch` cases once fall-through, `break`, and terminating case bodies are modeled precisely; revisit `match` only if include-like statement lowering ever appears inside match arms
- [x] Runtime routine dead stripping — include or link only runtime helpers reachable from the generated program instead of carrying the whole target runtime slice
- [x] Windows x86_64 (PE32+) cross-compilation target (experimental, newly added) — `--target windows-x86_64` (alias `x86_64-pc-windows-gnu`) cross-compiles to a GNU/MinGW-ABI binary via `x86_64-w64-mingw32-gcc` (`msvcrt`), producing `<stem>.exe` (`<stem>.dll` for `--emit cdylib`); requires the MinGW-w64 cross toolchain (`x86_64-w64-mingw32-as`, `x86_64-w64-mingw32-gcc`) on the host doing the build. CI cross-compiles and validates PE32+ structure (assemble + link) with MinGW-w64, and additionally executes the cross-compiled binaries under Wine (`wine64`/`wine`) to assert stdout for echo, arithmetic, string concatenation, loops, and function calls — closing the prior compile-only testing gap; broader runtime shim coverage (files, sockets, process control, …) is still not at parity with macOS/Linux.
- [x] `random_bytes(int $length): string` — cryptographically secure random byte string on every supported target (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or length below 1
- [x] Statically-known catchable `Error` conditions (issue #383) — private/protected method access from an inaccessible scope and readonly property writes outside the declaring constructor raise a catchable `Error` at runtime instead of being rejected at compile time, matching PHP
- [ ] Tail-call optimization — direct tail self- and mutual-recursion lowering on top of EIR (`Br` to function entry with parameter rebinding)
- [ ] Performance within 2x of C -O0 on compute benchmarks
Expand Down
68 changes: 68 additions & 0 deletions docs/compiling/targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,71 @@ targets from a macOS host.
For the target-aware ABI and runtime details behind each platform, see
[Architecture](../internals/architecture.md) and
[The Code Generator](../internals/the-codegen.md).

## Windows codegen parity gate

`windows-x86_64` is an experimental cross-compilation target, not yet a
first-class supported target. CI cross-compiles every codegen fixture to
`windows-x86_64` and runs it under Wine to measure how much of the suite already
behaves correctly on Windows. To let that parity grow without silently
regressing, CI enforces a **curated no-regression gate**.

### How the gate works

Two lists live in the repository as the source of truth:

- `tests/codegen/support/windows_codegen_allowlist.txt` — the codegen tests that
currently **pass** on `windows-x86_64` under Wine (the known-good set).
- `tests/codegen/support/windows_codegen_known_failures.txt` — the companion list
of tests that currently **fail** on Windows.

Together they partition the `ci`-profile *runnable* codegen tests:

```
allow_list = (ci-profile runnable codegen tests) - known_failures
known_failures = (ci-profile runnable codegen tests) - allow_list
```

The sharded `windows-codegen-parity` CI job runs the full suite under Wine and,
per shard, computes `regressions = actual_failures ∩ allow_list`. The gate rule
is exact:

> **The gate fails if and only if a test in the allow-list failed on Windows.**

Tests that are **not** in the allow-list — the known failures **and** any
brand-new or native-only fixtures — never fail the gate. This protects the
known-good set while letting Windows-incompatible tests exist freely: parity can
only improve, never regress. The aggregating `windows-codegen-gate` job is green
only when all 16 shards are green, and it is the single Windows-codegen
dependency of the top-level `test` gate. Each shard also prints its
passed / failed / parity% to the job summary, so the informational parity picture
stays visible alongside the gate.

### Refreshing the allow-list as parity grows

When Windows fixes land and previously-failing tests start passing, move them
from the known-failures list into the allow-list by regenerating both files from
a real parity run:

1. Download the 16 `windows-codegen-junit-<shard>` artifacts from a
`windows-codegen-parity` CI run (each is that shard's `junit.xml`).
2. Produce the current runnable set:

```bash
cargo nextest list --profile ci --test codegen_tests \
--message-format json > nextest_list.json
```

3. Regenerate both lists deterministically:

```bash
python3 scripts/gen_windows_codegen_allowlist.py generate \
--list-json nextest_list.json \
--junit path/to/windows-codegen-junit-*/junit.xml
```

The script writes both files sorted and locale-independent, so the same inputs
always reproduce byte-identical lists. It errors if a supplied failing test is
not in the runnable set (a sign the inputs came from a different revision). Never
hand-edit the lists — always regenerate. The same script's `gate` subcommand is
what the CI job runs to perform the intersection check.
2 changes: 1 addition & 1 deletion docs/internals/builtins/_internal/__elephc_gmmktime_raw.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "__elephc_gmmktime_raw() — internals"
description: "Compiler internals for __elephc_gmmktime_raw(): lowering path, type checks, and runtime helpers."
sidebar:
order: 433
order: 436
---

## `__elephc_gmmktime_raw()` — internals
Expand Down
2 changes: 1 addition & 1 deletion docs/internals/builtins/_internal/__elephc_mktime_raw.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "__elephc_mktime_raw() — internals"
description: "Compiler internals for __elephc_mktime_raw(): lowering path, type checks, and runtime helpers."
sidebar:
order: 434
order: 437
---

## `__elephc_mktime_raw()` — internals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "__elephc_phar_bzip2_archive() — internals"
description: "Compiler internals for __elephc_phar_bzip2_archive(): lowering path, type checks, and runtime helpers."
sidebar:
order: 435
order: 438
---

## `__elephc_phar_bzip2_archive()` — internals

## Where it lives

- **Signature**: [`src/builtins/io/__elephc_phar_bzip2_archive.rs`](https://github.com/illegalstudio/elephc/blob/main/src/builtins/io/__elephc_phar_bzip2_archive.rs)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4120](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4120) (`lower_elephc_phar_bzip2_archive`)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4182](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4182) (`lower_elephc_phar_bzip2_archive`)
- **Function symbol**: `lower_elephc_phar_bzip2_archive()`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "__elephc_phar_decompress_archive() — internals"
description: "Compiler internals for __elephc_phar_decompress_archive(): lowering path, type checks, and runtime helpers."
sidebar:
order: 436
order: 439
---

## `__elephc_phar_decompress_archive()` — internals

## Where it lives

- **Signature**: [`src/builtins/io/__elephc_phar_decompress_archive.rs`](https://github.com/illegalstudio/elephc/blob/main/src/builtins/io/__elephc_phar_decompress_archive.rs)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4135](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4135) (`lower_elephc_phar_decompress_archive`)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4197](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4197) (`lower_elephc_phar_decompress_archive`)
- **Function symbol**: `lower_elephc_phar_decompress_archive()`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "__elephc_phar_get_file_metadata() — internals"
description: "Compiler internals for __elephc_phar_get_file_metadata(): lowering path, type checks, and runtime helpers."
sidebar:
order: 437
order: 440
---

## `__elephc_phar_get_file_metadata()` — internals

## Where it lives

- **Signature**: [`src/builtins/io/__elephc_phar_get_file_metadata.rs`](https://github.com/illegalstudio/elephc/blob/main/src/builtins/io/__elephc_phar_get_file_metadata.rs)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4074](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4074) (`lower_elephc_phar_get_file_metadata`)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4136](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4136) (`lower_elephc_phar_get_file_metadata`)
- **Function symbol**: `lower_elephc_phar_get_file_metadata()`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "__elephc_phar_get_metadata() — internals"
description: "Compiler internals for __elephc_phar_get_metadata(): lowering path, type checks, and runtime helpers."
sidebar:
order: 438
order: 441
---

## `__elephc_phar_get_metadata()` — internals

## Where it lives

- **Signature**: [`src/builtins/io/__elephc_phar_get_metadata.rs`](https://github.com/illegalstudio/elephc/blob/main/src/builtins/io/__elephc_phar_get_metadata.rs)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:3859](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L3859) (`lower_elephc_phar_get_metadata`)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:3921](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L3921) (`lower_elephc_phar_get_metadata`)
- **Function symbol**: `lower_elephc_phar_get_metadata()`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "__elephc_phar_get_signature_hash() — internals"
description: "Compiler internals for __elephc_phar_get_signature_hash(): lowering path, type checks, and runtime helpers."
sidebar:
order: 439
order: 442
---

## `__elephc_phar_get_signature_hash()` — internals

## Where it lives

- **Signature**: [`src/builtins/io/__elephc_phar_get_signature_hash.rs`](https://github.com/illegalstudio/elephc/blob/main/src/builtins/io/__elephc_phar_get_signature_hash.rs)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4192](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4192) (`lower_elephc_phar_get_signature_hash`)
- **Lowering**: [`src/codegen/lower_inst/builtins/io.rs`:4254](https://github.com/illegalstudio/elephc/blob/main/src/codegen/lower_inst/builtins/io.rs#L4254) (`lower_elephc_phar_get_signature_hash`)
- **Function symbol**: `lower_elephc_phar_get_signature_hash()`


Expand Down
Loading
Loading