Skip to content

[depends on #2336] runtime: add the native Windows runtime core - #2338

Open
cpunion wants to merge 77 commits into
xgo-dev:mainfrom
cpunion:codex/windows-runtime-core-20260816
Open

[depends on #2336] runtime: add the native Windows runtime core#2338
cpunion wants to merge 77 commits into
xgo-dev:mainfrom
cpunion:codex/windows-runtime-core-20260816

Conversation

@cpunion

@cpunion cpunion commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Implements the native Windows runtime core described in #2325.

Depends on #2336 for the MSVC C ABI and COFF linker foundation. The runtime work is layered on the official-source reuse from #2331 rather than restoring superseded alternate runtime patches.

What this adds

  • adds hosted Windows thread, TLS, synchronization, timer, stdio, and setjmp primitives while keeping the existing Unix backend intact
  • implements the variable-width Windows syscall bridge for amd64 and arm64 with explicit COFF unwind metadata; Go 1.26 uses the official syscall wrappers and DLL helpers, while compatibility wrappers are selected only before Go 1.26
  • lowers Go's Windows //go:cgo_import_dynamic pointer aliases generically so the official standard-library syscall sources receive their imported DLL entry points
  • enables Windows reflection/libffi calls, including correctly allocated aggregate return buffers and Windows ABI selection
  • emits COFF-associated runtime PC metadata and keeps frame pointers so Windows hardware faults can become Go-compatible panic/recover events with source tracebacks
  • walks amd64 and arm64 frames through Windows SEH unwind metadata, using explicitly 16-byte-aligned CONTEXT storage, instead of treating the Win64 frame pointer as a linked Go frame
  • supplies target-correct 32-bit and 64-bit Windows libuv handle storage
  • enables BDWGC allocation, collection, finalizers, runtime-thread registration, and foreign-callback root retention on Windows
  • adds a native Windows CI smoke covering the runtime, standard-library syscalls, FFI, faults, GC, finalizers, and cross-thread/callback roots

Scope

This PR supplies the runtime core used by later Windows standard-library and process support. syscall.NewCallback remains explicitly unsupported and is not implemented here.

Validation

After rebasing the stack onto #2336 head e4c6ea7c1, the contribution head is bba71242f.

On macOS ARM64 with Go 1.26.5 and LLVM 19:

  • the focused Windows cgo import-pointer and pragma tests in ./internal/build pass
  • go test -count=1 ./internal/env ./internal/crosscompile ./internal/cabi ./ssa passes (internal/cabi: 141.025 seconds; ssa: 179.184 seconds)
  • from runtime, the internal runtime, libffi, synchronization, and thread packages compile and pass their host-side Go tests
  • the branch retains the prior Windows/386, Windows/amd64, and Windows/arm64 cross-build coverage and x86_64/aarch64 MSVC wrapper syntax checks

On a native Windows 11 ARM64 VM with Go 1.26.5, MSVC Build Tools, and LLVM 19.1.7, building directly from the macOS source worktree over the Parallels UNC share:

  • passed the metadata, architecture, LLVM, build, cross-compilation, SSA, and complete C ABI suites (internal/cabi: 175.828 seconds)
  • built and ran the native ARM64 LLGo host compiler (llgo (devel) windows/arm64)
  • built and passed the runtime, standard-library syscall, and reflection/libffi smoke programs
  • passed the runtime smoke 20/20 consecutive times
  • converted an unrecovered nil fault into a Go panic with the expected main.windowsNilFault function and source path in the traceback
  • exercised GC/finalizers, LLGo runtime threads, foreign callbacks, and cross-thread root retention

GitHub CI completed all 42 applicable checks successfully (with the normal release job skipped), including native Windows AMD64, Ubuntu, macOS, and codecov/patch at 98.20%.

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Windows runtime & toolchain support

This is a large, well-structured PR adding Windows support across the compiler and runtime. The platform split via build tags (_windows/_unix/_default) is consistent, new C shims validate pointers and manage matched free-on-error paths, the syscall ASM bridge is bounds-guarded from the Go side, and the meta parser adds solid hardening for mmap'd file-controlled input. Test coverage (goarch parsing, COFF COMDAT, setjmp ABI, cache fingerprints, lock release) is strong.

Findings below are inline. Highlights:

  • Perf (P1): llgo_nanotime queries QueryPerformanceFrequency on every call; the frequency is fixed for the lifetime of the system and should be cached once.
  • Correctness (P2): the process-global fault-traceback buffer is not thread-safe if concurrent recoverable faults are possible.
  • Docs (P2): the MutexAttr comment misdescribes where unsupported attributes are rejected.

No high-severity or blocking issues found. Nice work.

Comment thread runtime/internal/lib/runtime/_wrap/runtime_windows.c Outdated
Comment thread runtime/internal/clite/sync/sync_windows.go Outdated
Comment thread runtime/internal/lib/runtime/fault_windows_llgo.go Outdated
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown

LLGo baseline benchmarks

bba71242fb9e | workflow run | long-term charts

Program measurements

Platform Workload File size vs base Build vs base Run vs base
Linux cprintf 19464 B +0.4% (worse) 334.221 ms -2.2% (better) 1.353 ms +9.4% (worse)
Linux fmtprintf 1883936 B +0.2% (worse) 2.717 s +1.6% (worse) 3.233 ms -2.8% (better)
Linux println 69624 B +1.1% (worse) 340.812 ms +3.9% (worse) 1.809 ms +10.5% (worse)
macOS cprintf 84672 B +0.0% 503.318 ms +2.3% (worse) 3.739 ms +8.3% (worse)
macOS fmtprintf 1892928 B +0.0% (worse) 3.706 s -6.5% (better) 14.264 ms -9.9% (better)
macOS println 121856 B +0.4% (worse) 600.617 ms -4.8% (better) 8.025 ms +11.9% (worse)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 13.250 ns/op -0.1% (better)
Linux BenchmarkMergeCompilerFlags 151.200 ns/op -0.9% (better)
Linux BenchmarkMergeLinkerFlags 95.270 ns/op +0.3% (worse)
Linux BenchmarkChannelBuffered 34.790 ns/op +3.3% (worse)
Linux BenchmarkChannelHandoff 27670 ns/op -1.0% (better)
Linux BenchmarkDefer 45.900 ns/op +1.6% (worse)
Linux BenchmarkDirectCall 1.570 ns/op +0.8% (worse)
Linux BenchmarkGlobalRead 1.870 ns/op +20.2% (worse)
Linux BenchmarkGlobalWrite 2.500 ns/op +0.8% (worse)
Linux BenchmarkGoroutine 42913 ns/op +31.4% (worse)
Linux BenchmarkInterfaceCall 8.254 ns/op +1.9% (worse)
Linux BenchmarkRuntimeGetG 2.179 ns/op +16.6% (worse)
macOS BenchmarkLookupPCRandom 14.330 ns/op +8.3% (worse)
macOS BenchmarkMergeCompilerFlags 163.300 ns/op +14.9% (worse)
macOS BenchmarkMergeLinkerFlags 101.900 ns/op +15.8% (worse)
macOS BenchmarkChannelBuffered 26.040 ns/op -0.3% (better)
macOS BenchmarkChannelHandoff 9942 ns/op +7.7% (worse)
macOS BenchmarkDefer 40.690 ns/op +13.9% (worse)
macOS BenchmarkDirectCall 1.194 ns/op +6.1% (worse)
macOS BenchmarkGlobalRead 1.155 ns/op +2.9% (worse)
macOS BenchmarkGlobalWrite 1.263 ns/op +9.1% (worse)
macOS BenchmarkGoroutine 56829 ns/op +6.0% (worse)
macOS BenchmarkInterfaceCall 6.806 ns/op +6.4% (worse)
macOS BenchmarkRuntimeGetG 2.440 ns/op -17.9% (better)

Compared with 0f480253029a measured in the same runner job.

@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.19928% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/build/cgo_pragmas.go 84.31% 4 Missing and 4 partials ⚠️
internal/crosscompile/crosscompile.go 96.93% 2 Missing and 1 partial ⚠️
internal/build/build.go 96.82% 1 Missing and 1 partial ⚠️
ssa/eh.go 96.49% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@cpunion
cpunion force-pushed the codex/windows-runtime-core-20260816 branch 2 times, most recently from e3525d1 to 4932830 Compare August 16, 2026 13:47
@cpunion

cpunion commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator Author

@fennoai The full stack is now rebased onto current main at head 493283007d53. All 42 applicable CI checks pass (one normal skip), codecov/patch passes at 95.94%, GitHub Windows AMD64 passes, and the same head passes native Windows 11 ARM64/MSVC + LLVM 19 validation (complete C ABI suite, runtime 20/20, stdlib, FFI, GC/finalizers, foreign threads, and fault traceback). Since your earlier review, the PR also added generic Windows go:cgo_import_dynamic pointer lowering and Win64 SEH virtual unwinding, plus the fixes for your prior findings. Please re-review the current head, especially those substantive additions.

@fennoai

fennoai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Re-review complete

I re-reviewed the current head (493283007d53) across code quality, performance, security/memory-safety, and documentation accuracy, focusing on the generic //go:cgo_import_dynamic pointer lowering and the Win64 SEH virtual unwinding.

Findings are posted as a non-blocking PR review with 3 inline comments plus a couple of minor items in the review body. Most substantive point is the CONTEXT stack alignment (P2). No blocking correctness issues found.

➡️ View the review

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review: native Windows runtime core (head 493283007d53)

I re-reviewed the current head across code quality, performance, security/memory-safety, and documentation accuracy, focusing on the substantive additions you called out — the generic //go:cgo_import_dynamic pointer lowering (internal/build/cgo_pragmas.go) and the Win64 SEH virtual unwinding (runtime/internal/lib/runtime/unwind_windows_seh_llgo.go + fault_context_windows_*).

Overall this is solid, defensively-written systems code: the CONTEXT records carry compile-time size/offset assertions, build tags are complementary and mutually exclusive, the syscall bridge is //go:nosplit and allocation-free, the sync primitives map straight to SRW/CONDITION_VARIABLE, and the expensive per-frame RtlVirtualUnwind/VirtualQuery work is correctly confined to the fault/traceback cold path. The dynamic-import alias parsing validates the %argc suffix and flows names into LLVM symbol creation rather than a shell, so there's no injection surface there.

A few points worth addressing are left as inline comments. The most substantive is the CONTEXT stack alignment (P2). No blocking correctness issues were found.

Minor items (no reliable single inline anchor)

  • internal/build/cgo_pragmas.go — unused goos parameter. goCgoLinkArgs(goos string, files []*ast.File) never uses goos; it collects ldflags regardless of GOOS. Either drop the parameter or gate on it, for parity with the sibling lowerWindowsCgoImportPointers/buildGoCgoAliasObjects which do gate on GOOS.
  • internal/build/cgo_pragmas.go (buildGoCgoAliasObjects) — temp object cleanup / dropped Close error. After os.CreateTemp(..., "cgoimportalias-*.o"), the objFile.Close() error is discarded and objPath is only removed on the explicit Compile failure path. Consider defer-removing objPath until success is confirmed, matching the correctly-handled .s temp block just above it.

Verified as intentional / no action needed

  • TypeInfoWindowsArm64 embedding *TypeInfoArm64 with no overrides is a deliberate distinct-type guard (documented).
  • FLS lifecycle in thread_windows.c correctly mirrors pthread setspecific semantics; no leak/double-free.
  • MSVC aggregate ABI register-size classification (1/2/4/8, indirect fallback) matches the Microsoft x64/x86 rules.
  • CONTEXT layout offsets and libffi DefaultAbi values are correct for their targets.

Comment thread runtime/internal/lib/runtime/fault_context_windows_amd64.go
Comment thread runtime/internal/clite/libuv/sizes_windows.go
Comment thread runtime/internal/lib/runtime/unwind_windows_seh_llgo.go Outdated
@cpunion

cpunion commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator Author

The two review-body cleanup items are also addressed in 551e881: goCgoLinkArgs no longer carries the unused GOOS parameter, and the Darwin alias object now checks Close and remains under deferred cleanup until successful ownership transfer to the package archive builder.

@cpunion

cpunion commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

@fennoai All findings from the re-review are fixed at head 551e881b3: Win64 CONTEXT storage is explicitly 16-byte aligned, libuv sizes are split for 386 vs 64-bit Windows using measured LLVM 19/header values, the unwind comment is corrected, and both review-body cleanup items are addressed. All CI checks now pass, including Windows AMD64, and codecov/patch is 95.98% against a 90.30% target; the same head also passes the full native Windows 11 ARM64/MSVC validation. Please do a focused final confirmation of these fixes.

@fennoai

fennoai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Final confirmation — all prior findings fixed at 551e881b3

I re-fetched the head and diffed only the delta from the previously-reviewed head (493283007d53...551e881b3) — the changes are tightly scoped to exactly the files flagged. Each finding is confirmed fixed:

  • [P2] Win64 CONTEXT alignmentunwind_windows_seh_llgo.go now uses windowsFaultContextStorage ([size + 15]byte) and a context() accessor that rounds the base up to a 16-byte boundary via (-base) & 15. The math is the standard round-up idiom, the slack guarantees size bytes remain after alignment, and all four capture sites (platformCallers, platformFaultCallers, recoverFrameMarks, recoverFrameLive) were migrated — no var context windowsFaultContext stack declarations remain. platformFaultCallers correctly copies the OS-owned record into the aligned storage.
  • [P2] libuv 386 vs 64-bit splitsizes_windows.go is now tagged windows && (amd64 || arm64) (matching its "64-bit Windows" comment) and a new sizes_windows_386.go tagged windows && 386 supplies distinct 32-bit sizes. The two tags are mutually exclusive and jointly cover all Windows arches.
  • [P3] Garbled unwind comment — corrected to "Drop platformCallers and the return into fpCallers, matching framePointerCallers' first entry." (now grammatical).
  • Unused goos parameter — removed from goCgoLinkArgs; both call sites in build.go updated. Verified no stale callers with the old signature.
  • Temp-object cleanup / dropped Close errorbuildGoCgoAliasObjects now uses a keepObj flag with a defer os.Remove(objPath) that fires on any early return/panic, and the objFile.Close() error is checked and returned. os is imported.

Verification performed here: gofmt -l reports all five changed files clean; the goCgoLinkArgs signature has one definition and two updated callers only. A full go build couldn't run in this sandbox (missing LLVM cgo headers for the llvm dependency — unrelated to this PR), so I relied on gofmt/AST-level checks plus your reported green CI (Windows AMD64 passing, codecov/patch 95.98%) and native Windows 11 ARM64/MSVC validation.

All findings from the re-review are resolved. No new issues introduced by the fixes. LGTM. 👍

@cpunion
cpunion force-pushed the codex/windows-runtime-core-20260816 branch from 551e881 to bba7124 Compare August 17, 2026 21:10
@cpunion

cpunion commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

@fennoai Please do a focused confirmation review of the rebased current head bba71242f.

The 36 runtime commits were rebased from the previously approved 551e881b3 onto the current #2336 head e4c6ea7c1: range-diff shows 30 patch-equivalent commits, while the remaining six only needed base/module-path conflict adjustments. A follow-up commit then consistently updates the remaining Windows-only imports from the former github.com/goplus/llgo path to the repository's current github.com/xgo-dev/llgo module path. Please focus on those conflict resolutions—especially retaining the current generic internal/clite/thread and internal/clite/sync organization—and confirm that the previously reviewed fixes remain intact.

All 42 applicable GitHub checks now pass (one normal release skip), including Windows AMD64 and codecov/patch at 98.20%. The same head also passes the complete native Windows 11 ARM64/MSVC + LLVM 19 validation described in the PR body. One Ubuntu shard was initially cancelled after an anomalous 16-minute optional-dependency install; rerunning the unchanged head completed successfully with that install taking 59 seconds.

@fennoai

fennoai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Rebase confirmation — bba71242f on new #2336 base ✅

Focused confirmation of the rebase onto the current #2336 head (e4c6ea7c1; PR base now 0f4802530). Verified against the locked range 0f4802530...bba71242f.

Previously-approved fixes — all intact:

  • Win64 CONTEXT 16-byte alignmentwindowsFaultContextAlignment = 16, windowsFaultContextStorage, and the (-base) & 15 round-up accessor are present; all four capture sites use storage.context(); no var context windowsFaultContext stack declarations remain.
  • libuv 386/64-bit splitsizes_windows.go tagged windows && (amd64 || arm64), sizes_windows_386.go tagged windows && 386. Mutually exclusive, jointly complete.
  • Corrected unwind comment — "Drop platformCallers and the return into fpCallers…" present and grammatical.
  • Unused goos param removed from goCgoLinkArgs; both callers updated.
  • Temp-object cleanupkeepObj flag + defer os.Remove(objPath) + checked Close error retained.

Conflict resolutions — as described:

  • Generic internal/clite/thread and internal/clite/sync organization retained. Diffing the approved head (551e881b3) against this head restricted to the runtime tree shows the only change to those files (and every other Windows runtime file) is the module-path import rename — no logic changes.
  • Module-path update complete and consistentgithub.com/goplus/llgogithub.com/xgo-dev/llgo. No stale goplus/llgo reference remains anywhere in the source tree, and no added line in the PR's own diff introduces the old path. go.mod module is github.com/xgo-dev/llgo.

Integrity checks:

  • No merge-conflict markers anywhere in the tracked .go/.c/.h/.s/.S sources.
  • gofmt -l is clean across all changed .go files in the locked range.
  • Key Windows runtime files (SEH unwind, sync/thread + _wrap C, arch_msvc, cgo_pragmas) are all present in the diff; feature set is intact (166 files vs new base).

Note: go build couldn't run in this sandbox (missing LLVM cgo headers for the llvm dependency — unrelated to the PR), so I relied on AST/gofmt-level checks plus your reported green CI (Windows AMD64, codecov/patch 98.20%) and native Windows 11 ARM64/MSVC + LLVM 19 validation. The cancelled Ubuntu shard was an infra flake (anomalous 16-min optional-dep install) that passed on rerun — not a code issue.

The rebase preserved the approved state; conflict resolutions are limited to base/module-path adjustments as claimed. No new issues. LGTM. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants