windows: integrate OS and standard-library support (R6) - #2418
Conversation
|
@fennoai /review |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Review: Windows stdlib/runtime support
Reviewed the fixed range 6fe8bab...4e52fc7 (~15k lines, 381 files) across code-quality, performance, security, and documentation dimensions. This is a large, well-engineered addition of Windows support to the llgo runtime and toolchain. The new C/asm bridges (syscall_windows.S, fault_windows.c, profile_windows.c, thread_windows.c) are consistent across arches, free their handles/allocations on all paths, bound all PC-buffer writes, and the fault handler is defensively guarded (re-entrancy guard, null checks, parameter_count bounds). The SyscallN bridge enforces windowsSyscallMaxArgs before the call, print wrappers clamp chunk sizes against UINT32_MAX, and the build-time command construction uses exec.Command (no shell injection). Security review found nothing actionable.
One correctness finding is worth addressing (inline). A few minor/low-confidence items are listed below.
Minor / low-confidence (non-blocking):
runtime/internal/sync/_wrap/sync_windows.c:14—#pragma comment(lib, "synchronization.lib")is an MSVC-only linker directive that clang with a GNU-style driver ignores; linking is already handled bysync_windows.go(LLGoPackage = "link: -lsynchronization"). It's redundant and slightly misleading; consider removing it.- Build-tag inconsistency for a hypothetical
windows && baremetalbuild:thread_windows_gc.gouses//go:build windows && !nogcwhileforeign_thread_gc_windows.gouses//go:build llgo && windows && !nogc && !baremetal. Awindows+baremetalbuild would select the GC thread backend but the stub foreign-thread side. Not a shipped config today, but the guards should be made consistent. runtime/internal/runtime/z_print_write_windows.go:35-47—PrintStringre-queriesc_printStderrIsConsole()(two syscalls:GetStdHandle+GetConsoleMode) on every non-ASCII print. Console-ness is fixed for process lifetime; caching it once (e.g.sync.Once) would match upstream Go. Bounded to the print/diagnostic path.- The 386 fault-context variant (
fault_context_windows_386.go) lacks the compile-time size/offset assertions that the amd64/arm64 variants have; adding parallel[N-size]byteguards would make the three self-checking.
LLGo baseline benchmarks
Program measurements
Core language and compiler benchmarks
Compared with |
|
FennoAI is processing your request, please wait a moment... |
|
Review follow-up in
I did not cache the stderr console probe: Go 1.26's Validation for the follow-up: all three Windows MSVC C targets passed syntax checking, the Windows/386 runtime package compiled, and the Windows |
There was a problem hiding this comment.
Review summary
R6 Windows OS/standard-library integration. This is a large PR (381 files); I focused the review on the core runtime, SSA, internal/build, internal/abi/internal/cabi, and the C wrappers, skipping test fixtures and demos.
Overall the implementation is careful and high quality: platform build-tag partitions are correct and non-overlapping, hot paths avoid per-call allocation/locks (per-M state, cached callback closures, memoized symbolization), and doc comments accurately describe the platform-specific behavior. Several higher-risk spots I specifically scrutinized checked out correct — surrogate-pair encoding in the console writer, windowsSyscallMaxArgs = 42 fitting exactly within the amd64/arm64 assembly stack reservations, the PC-site record layout matching emitted asm across 386/amd64/arm64, and the intentional double processExitLock.Lock() teardown freeze (mirrors Go issue #18253).
The main item worth attention is the Windows runtime random source (see inline P1). The remaining findings are low-severity clarity/robustness notes.
No blocking issues. This is a COMMENT (non-blocking) review.
Additional findings
internal/build/cgo_pragmas.go:64: [P3] goCgoLinkArgs ignores its goos parameter:goCgoLinkArgs(goos string, files []*ast.File)never usesgoos; it just forwardsfilestocollectGoCgoPragmasand returns the ldflags. Both callers inbuild.gopassctx.buildConf.Goos, which suggests GOOS-conditional#cgo LDFLAGSblocks were meant to be filtered here. If GOOS filtering is intended, this is a latent correctness gap (ldflags from non-matching platforms would leak into link args); if not, drop the unused parameter for clarity. Worth confirming against how darwin/linux ldflags are gathered.
|
Second review follow-up is in
Focused validation passed for all three Windows architectures and the affected |
|
Windows native CI exposed a dual-build representation missed by the P3 cleanup. |
b067676 to
9f9d8f7
Compare
9f9d8f7 to
4db20e0
Compare
Summary
This is R6 of the Windows support series tracked by #2325. It integrates the Windows OS and standard-library layer while preserving the existing macOS and Linux paths.
test/std, demo, symbol, and GOROOT coverageBase and dependency boundary
This PR was rebased onto
xgo-dev/llgo:mainata91a36b5be53, which contains R4 (#2404), R5 (#2405), and #2416. Its effective diff is therefore limited to the R6 OS and standard-library layer plus its CI dependency fix.#2417 remains a separate contribution and is not duplicated here. In particular, the invalid receiver diagnostic remains owned by that PR.
The staging PR for this exact R6 work is cpunion#188.
Validation
The complete staging CI for cpunion#188 is green, including:
Native Windows ARM64 validation used Go 1.26.5 in Parallels. All 32 GOROOT coverage shards were exercised; this was not a sampled run.
The rebased upstream CI and coverage completed before merge.
Binary-size analysis
The benchmark compared
6886993dc80fwith basea91a36b5be53. The reported growth is small and has two distinct causes: pre-DCE function metadata for newly added shared-runtime functions, and reachableruntime.Cleanupsupport pulled in byfmtthroughos/internal/poll. It is not caused by Windows-only code being compiled on Linux or macOS.cprintf/ LTOprintln/ LTOmexitstartup-root release pathfmtprintf/ LTOcprintf/ LTO__TEXT,__constmetadataprintln/ LTOfmtprintffmtprintf-ltoOn Mach-O, the benchmark's “text” metric includes every section in
__TEXT, including read-only__const; it is therefore not a machine-code-only measurement.The fixed 288 B increase is 18 net-new symbol-index entries at 16 B each. These entries cover shared runtime support added by this PR: cancellable Cleanup handling, proc-pin linkname bridges, goroutine state reporting, startup-root release, and fat map lookup.
For
fmtprintf, the complete function-info table grows by 14 net records:LLGo currently collects function-info records before linker DCE and calls
prepareFuncInfoTableRecords(..., nil), so no post-DCE live-symbol set is available to remove metadata for discarded functions. This explains why evencprintf, which does not execute the new runtime paths, still gains 288 B of metadata.The larger Linux
fmtprintfexecutable-code delta is dominated by the Go-compatible, pointer-free and cancellable Cleanup implementation (newCancelableCleanup,registerCleanupPtr,freeCleanupSlot,StopCleanupPtr, and the expanded finalizer), with smaller contributions from the Linux poll-descriptor check and goroutine startup-root release. These paths are reachable through the standard library and cannot be treated as Windows-only code.A future post-DCE live-symbol filter for function metadata is the highest-leverage size optimization: it can remove the fixed 288 B from small programs and most of the 976 B metadata increase in
fmtprintf. On the current macOS non-LTO layout, removing that metadata would also likely movefmtprintfback below the 16 KiB segment boundary, although that file-size cliff is alignment-dependent.Benchmark details: #2418 (comment)