Skip to content

feat(platform): add full Windows x86_64 PE32+ cross-compilation support#446

Draft
Guikingone wants to merge 1 commit into
illegalstudio:mainfrom
Guikingone:feat/windows-pe
Draft

feat(platform): add full Windows x86_64 PE32+ cross-compilation support#446
Guikingone wants to merge 1 commit into
illegalstudio:mainfrom
Guikingone:feat/windows-pe

Conversation

@Guikingone

@Guikingone Guikingone commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #379.

Summary

This pull request adds an experimental windows-x86_64 backend that produces
standalone PE32+ executables and brings the compiler, runtime, bridge crates,
Magician/eval, TLS, and web mode onto native Windows validation paths.

The implementation uses the GNU/MinGW Windows ABI. The accepted
x86_64-pc-windows-msvc spelling is a CLI compatibility alias only; it does not
claim MSVC ABI output. The branch is rebased on the current main and remains
one squashed commit. Windows stays experimental until every strict gate below
is green on the same revision.

What is included

Target, PE/COFF, and toolchain support

  • Adds windows-x86_64 / x86_64-pc-windows-gnu target selection.
  • Emits and links x86-64 PE/COFF executables through MinGW-w64.
  • Supports an opt-in Clang integrated-assembler + LLD path while retaining the
    GNU Windows ABI.
  • Emits PE startup/runtime data for argc/argv, process exit, exceptions,
    callbacks, fibers, refcounted values, unwind records, and loader mitigations.
  • Runs the compiler pipeline on a dedicated 64 MiB Windows worker stack.
  • Cross-builds and discovers GNU/COFF bridge archives even when the compiler is
    running under Rust's native MSVC host toolchain.
  • Keeps Control Flow Guard disabled until indirect-call instrumentation, GFIDS,
    and the PE load-configuration directory can be emitted as one validated unit.

Windows ABI and runtime

  • Centralizes the boundary between elephc's internal runtime-helper convention
    and Microsoft x64 ABI imports, including shadow space, integer/floating
    register classes, stack arguments, variadics, callbacks, and indirect calls.
  • Adds Win32/CRT/Winsock implementations for memory, Unicode filesystem paths,
    metadata, directory iteration, streams, processes, clocks, entropy, sockets,
    DNS, synchronization, and console/file I/O.
  • Implements PHP-compatible Windows realpath/stat/lstat/fstat
    metadata, readonly/link/executable modes, reparse-point probing, dangling
    symlinks, tempnam, tmpfile, loopback socketpair, stream_isatty, and
    stream timeout behavior.
  • Matches PHP's tempnam() contract for prefix basenames, Windows path
    separators, the 63-byte prefix limit, and the false failure sentinel.
  • Keeps chown()/chgrp() visible with Windows failure semantics while
    omitting lchown()/lchgrp() exactly as php-src does without HAVE_LCHOWN.
    Direct calls, namespace fallback, user redeclarations, first-class callables,
    dynamic dispatch, Reflection, eval, function_exists(), and is_callable()
    all use the same target-aware catalog.
  • Supports PHP's full fopen base-mode and suffix surface, Windows
    temporary-file deletion, complete 64-bit Winsock handles, and the correct
    close order for filters, TLS sessions, stream state, CRT descriptors, and
    sockets.
  • Preserves stream payloads and arguments across Windows slot lookups in
    ordinary I/O and zlib, bzip2, iconv, and user-filter paths; fseek() and
    rewind() use the same handle mapping.
  • Normalizes Windows verbatim canonical paths before exposing __FILE__,
    __DIR__, closure names, and EIR source metadata.
  • Uses native Winsock protocol/service lookup and advertises only transports
    the runtime can negotiate; Windows omits Unix-domain transports and all
    targets omit unavailable SSLv2/SSLv3 aliases.
  • Widens signed 32-bit CRT long results before 64-bit consumers and derives
    PHP_EOL, DIRECTORY_SEPARATOR, and PATH_SEPARATOR from the target.

Processes, shell behavior, eval, and web

  • Implements Windows proc_open() descriptor inheritance and sparse
    descriptor behavior, proc_close(), proc_terminate(), and
    proc_get_status(). Windows reports cached: false, while Unix preserves
    PHP's post-exit cached transition.
  • Accepts PHP command arrays with associative or numeric keys in insertion
    order, ignores the keys like php-src, and preserves raw numeric environment
    entries while skipping empty converted values.
  • Matches php-src's Windows shell escaping behavior and preserves arguments
    correctly through CRT argv construction.
  • Extends Magician/eval parity for filesystem, process, shell, network,
    randomness, time, string, callable, and target-specific builtin behavior.
  • Exercises --web as a PE program with exported ABI validation, HTTP
    success/error responses, Ctrl-C shutdown, watchdog termination, and clean
    --max-requests exit.

TLS and stream contexts

  • Cross-builds and validates the Rust TLS bridge on native and cross Windows
    paths.
  • Loads Windows native certificate roots by default so administrator-installed
    and enterprise trust anchors remain visible; other targets retain the
    deterministic bundled root set.
  • Uses bridge ABI v3 with a stable 88-byte ElephcTlsClientOptions structure
    (options layout ABI v1) shared by HTTPS connects and STARTTLS attachment.
  • Implements independent PHP stream-context policies for verify_peer,
    verify_peer_name, and allow_self_signed, plus peer_name, additive
    cafile/capath, and combinable local_cert/local_pk.
  • Treats local_pk as optional when the key is present in local_cert, and
    ignores local_pk without a client certificate, matching php-src.
  • Restricts allow_self_signed to a valid depth-zero genuinely self-signed
    leaf. It never accepts an arbitrary untrusted leaf, never bypasses hostname
    validation, and always verifies TLS 1.2/1.3 handshake signatures.
  • Applies PHP boolean truthiness to stream-context options (0 and "0" are
    false; any other non-zero integer is true).
  • Distinguishes an omitted/null STARTTLS crypto method from an explicit zero,
    enforces supported TLS 1.2/1.3 client masks, and reuses the source TLS
    configuration/session cache when session_stream is provided.
  • Completes HTTPS request and tempfile writes across partial I/O, treats only a
    zero-byte TLS read as clean EOF, and rejects oversized, truncated, or
    unrewindable response streams with balanced handle cleanup.
  • Validates Unix file descriptors and Winsock sockets before adopting them into
    Rust, preserving retryable WouldBlock/TimedOut results without marking
    streams as EOF.

Final php-src audit

The implementation was audited against the current official php-src Windows,
stream, TLS, process, shell, and filesystem paths:

The last comparison found and closed the remaining gaps around native Windows
trust roots, TLS policy independence and true self-signed handling, client key
fallback, STARTTLS crypto-method/session propagation, complete HTTPS I/O,
target-aware lchown/lchgrp visibility, namespace and callable resolution,
tempnam() failure/prefix semantics, proc_open() command/environment
marshalling, proc_get_status().cached, shell escaping, stream-filter register
preservation, Windows stream seeking, and target-path normalization.

CI and acceptance gates

Cross-compilation gate

Windows PE Cross-Compile Tests and the independent Windows PE LLVM/LLD Tests run on Ubuntu with MinGW-w64 and Wine. Together they:

  • build warning-free;
  • cross-build all supported Windows bridge archives;
  • verify the GNU and opt-in Clang integrated-assembler/LLD toolchain paths;
  • run the dedicated PE integration tests; and
  • compile, inspect, and execute representative PHP programs as PE32+
    binaries.

Native bridge gate

Windows Native PE & Bridge Tests runs on Windows Server 2025. It:

  • builds and tests bridge crates with the native MSVC Rust host;
  • cross-builds their GNU/COFF archives;
  • verifies every exported C ABI symbol;
  • runs the complete windows_pe integration module; and
  • validates native bridge, eval, TLS, and web behavior.

Strict native codegen gate

The runnable ci-profile codegen inventory is split into 16 deterministic
partitions and executed directly on Windows Server 2025. There is no allowlist
or known-failure exemption: each runnable fixture must appear exactly once and
every shard must succeed. The aggregate Windows gates are required by the
top-level Build & Test job.

Validation

Focused local validation performed during development includes:

  • 135 Windows-specific library tests;
  • focused magic-constant, process, TLS, stream, eval, ownership, and PE/Wine
    regressions;
  • MinGW assembly/link and PE inspection of representative programs;
  • bridge export and multi-archive link validation;
  • focused supported-target regressions discovered by CI; and
  • post-rebase cargo fmt --all -- --check, Cargo metadata validation,
    assembly-comment validation, git diff --check, ancestry, squash, and
    unmerged-file checks.

The complete supported-target and native-Windows matrices remain CI-owned.

Promotion criteria

Windows can move into the first-class supported-target matrix only when one
revision satisfies all of the following:

  • all 16 strict native codegen shards and the exact-coverage aggregate are
    green;
  • native PE, bridge, Magician/eval, TLS, and web suites are green;
  • GNU and LLVM/LLD cross-toolchain probes are green;
  • PHP's Windows-specific behavior has been audited against php-src; and
  • no Windows path silently reports success for unsupported behavior or retains
    reduced semantics that the project claims to support.

Until then, documentation and diagnostics deliberately label the target
experimental.

@Guikingone
Guikingone marked this pull request as draft July 1, 2026 10:12
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 2 times, most recently from 1a6888e to 4b7fd88 Compare July 1, 2026 15:43
@Guikingone Guikingone changed the title feat(windows-pe): Full Windows x86_64 PE32+ cross-compilation support feat(platform): add full Windows x86_64 PE32+ cross-compilation support Jul 1, 2026
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 2 times, most recently from aa5e6be to 2ac8b78 Compare July 2, 2026 17:30
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 6, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 2 times, most recently from a1b7fa8 to b0d4620 Compare July 7, 2026 07:11
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 7, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.

# Conflicts:
#	CHANGELOG.md
#	CLAUDE.md
#	docs/internals/builtins/math/mt_rand.md
#	docs/internals/builtins/math/rand.md
#	docs/internals/builtins/math/random_int.md
#	src/codegen/abi/mod.rs
#	src/codegen/builtins/arrays/call_user_func_array.rs
#	src/codegen/builtins/system/exit.rs
#	src/codegen/callable_dispatch.rs
#	src/codegen/prescan.rs
#	src/codegen/runtime_callable_invoker.rs
#	src/codegen_support/abi/bootstrap.rs
#	src/codegen_support/platform/windows_transform.rs
#	src/codegen_support/runtime/arrays/random_bytes.rs
#	src/codegen_support/runtime/emitters.rs
#	src/pipeline.rs
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 2 times, most recently from d2bb042 to d31d8bf Compare July 8, 2026 07:58
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 10, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 2 times, most recently from 735ae01 to d1e9c08 Compare July 10, 2026 16:54
Guikingone added a commit to Guikingone/elephc that referenced this pull request Jul 10, 2026
…es builtin

Reconstruct PR illegalstudio#446's feature set on top of current main.

Windows x86_64 PE target:
- Platform::Windows with the MSx64 ABI (rcx/rdx/r8/r9, 32-byte shadow, 16-byte
  alignment) and ~40 Win32 shim wrappers converting SysV->MSx64 (WriteFile/ReadFile,
  sockets, file/dir ops, VirtualAlloc/Heap, BCryptGenRandom, ...).
- Syscall->shim transform wired into the pipeline + runtime cache (Windows-only) so
  PE binaries contain no raw Linux syscalls; unmapped syscalls route to
  __rt_unsupported_syscall instead of a silent trap.
- Entry wrapper (MSx64->SysV), MinGW-w64 assembler/linker, kernel32/msvcrt/winmm/
  ws2_32/bcrypt/shlwapi link set. --target windows-x86_64 (alias
  x86_64-pc-windows-gnu); .exe / .dll outputs. CI windows-pe-cross-compile job
  (MinGW + Wine) wired into the gate.

Fix the implicit end-of-main exit code on Windows: emit_exit and
emit_exit_with_result_reg now load the code into edi and call the __rt_sys_exit
(ExitProcess) shim directly, identical to an explicit exit($n), instead of returning
through the MinGW CRT. The CRT's exit() reaches the same rdi-consuming shim, so the
old return path left rdi holding leftover data and exited with a garbage nonzero code.

random_bytes(int $length): string:
- Cryptographically secure random byte string on every supported target
  (arc4random_buf / getrandom / BCryptGenRandom), fatal on entropy failure or a
  constant length below 1.
- Expressed as a single-source registry home file (src/builtins/math/random_bytes.rs)
  instead of the legacy hand-maintained tables; excluded from the legacy
  runtime-callable wrapper as an EIR-only builtin. Builtin docs + registry JSON
  regenerated.

Callable-invoker ABI on Windows x86_64:
- The descriptor-based runtime callable invoker read its descriptor from a
  hardcoded rdi, but on Windows the caller passes it in the MSx64 first arg
  (rcx); read it from int_arg_reg_name(target, 0) instead.
- The invoker clone helpers passed arguments to the __rt_array_clone_shallow /
  __rt_array_to_mixed / __rt_hash_clone_shallow / __rt_hash_to_mixed /
  __rt_array_new runtime helpers via int_arg_reg_name, which returns the target
  user-call ABI (rcx/rdx on Windows); those helpers use the System V AMD64 ABI on
  every x86_64 target and read rdi/rsi. Add runtime_int_arg_reg_name (SysV on all
  x86_64, platform ABI on AArch64) and route the four helper call sites through
  it. No-op on Linux and AArch64.
@github-actions github-actions Bot added area:codegen Touches target-aware assembly or backend lowering. area:platform Touches targets, object formats, linking, or platform support. area:runtime Touches runtime helpers, GC, ownership, or bridge runtimes. scope:multi-area Touches more compiler areas than the automatic area-label cap. size:xl Very large pull request that needs deliberate review planning. target:windows-x86_64 Contains behavior specific to the Windows x86_64 target. type:feature Introduces new user-visible behavior or capabilities. labels Jul 13, 2026
@Guikingone Guikingone self-assigned this Jul 21, 2026
@github-actions github-actions Bot added area:magician Touches eval, include execution, or elephc-magician. area:web Touches --web mode, its prelude, or elephc-web. and removed area:codegen Touches target-aware assembly or backend lowering. area:runtime Touches runtime helpers, GC, ownership, or bridge runtimes. labels Jul 23, 2026
@Guikingone
Guikingone force-pushed the feat/windows-pe branch 8 times, most recently from d3c8bd9 to bbab487 Compare July 24, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:magician Touches eval, include execution, or elephc-magician. area:platform Touches targets, object formats, linking, or platform support. area:web Touches --web mode, its prelude, or elephc-web. scope:multi-area Touches more compiler areas than the automatic area-label cap. size:xl Very large pull request that needs deliberate review planning. target:windows-x86_64 Contains behavior specific to the Windows x86_64 target. type:feature Introduces new user-visible behavior or capabilities.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support PE file (windows)

1 participant