Skip to content

build: integrate naked LLVM assembly and dynamic import libraries - #2623

Merged
xushiwei merged 16 commits into
xgo-dev:mainfrom
zhouguangyuan0718:codex/tsgo-darwin-build-20260918
Sep 25, 2026
Merged

xushiwei merged 16 commits into
xgo-dev:mainfrom
zhouguangyuan0718:codex/tsgo-darwin-build-20260918

Conversation

@zhouguangyuan0718

@zhouguangyuan0718 zhouguangyuan0718 commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

TypeScript Go tsc's FSEvents backend contains raw C callbacks and register-shuffling assembly without Go declarations. Translate these bounded native entries to naked noinline LLVM functions with function-local inline asm. Both native and ordinary Plan 9 translation feed the same textual .ll output, configured IR compiler, object/bitcode, archive and final-link pipeline. Native carriers retain their physical-register interface and bypass signature-based aggregate/C ABI rewrites.

Honor libraries declared by go:cgo_import_dynamic on both Darwin and Linux. Darwin frameworks/system dylibs resolve through SDK linker options. Linux preserves explicit library paths and uses exact-name ELF library lookup for bare names, including versioned SONAMEs. Reject library fields beginning with - or @, validate assembly DATA against Go storage, and preserve quoted directive arguments. Windows and WebAssembly retain their existing import handling. This fixes the review reproducer where Linux compiled native assembly but omitted the shared library at final link.

Supported native targets are Linux and Darwin on amd64/arm64. Entries manage their own native frames, arguments and results; no unknown Go/C prototype is inferred. Use upstream plan9asm v0.6.1, which includes merged xgo-dev/plan9asm#42; no fork replacement is needed. No Go assembler object dependency is introduced. Unsupported forms fail explicitly.

Regression coverage:

  • New end-to-end shared-library test builds a library in a path containing spaces, links solely through the dynamic-import library directive, calls through the native assembly entry, and checks integer arguments/results. It runs with LTO off, ThinLTO and Full LTO, and also tests versioned bare library names on Linux.
  • The existing Go test batch runs the host-side regressions and uploads their coverage. The existing release-artifact matrix exercises shared-library links and native calls with the installed compiler on Linux/amd64, Linux/arm64, Darwin/amd64 and Darwin/arm64; no additional CI jobs are introduced. Cross-object/GenLL/DATA tests cover all four target pairs. Directive tests cover Linux/Darwin conversion, invalid option-like paths, deduplication, relative paths, and unchanged Windows/WebAssembly handling.
  • Local LLVM/LLD 22 + Go 1.27 validation: Linux/amd64 and Linux/arm64 containers reproduce undefined symbol: answer with the old library handling and pass with the fix in every tested path/LTO combination. Focused native/Plan 9/dynamic-import tests pass on both Linux architectures and Darwin/arm64.
  • Darwin/amd64 additionally passes a local cross-link/Rosetta execution probe using the LLGo assembly driver and dynamic-import linker arguments with all three LTO modes. The full LLGo shared-library test also passed on the Intel CI runner at 6d5b1bc. The release-artifact smoke script passes locally on Darwin/arm64 and Linux/amd64/arm64; the latest remote CI results must be checked separately.
  • Full forced Darwin/arm64 cmd/tsc build at c975de5011fb7dfb32a491cf3fcf02d4f811f50e passes. Version, strict ES2022 JS/declarations, cross-file imports, TS2322 diagnostics/exit status and generated JS execution match standard Go.

Assembly instructions remain opaque to IR optimization. Go ABI adapters, runtime transitions and unwind metadata are outside this contract. Full Linux tsc builds and the recorded watch-mode issue are not established by these tests.

fennoai[bot]

This comment was marked as outdated.

@zhouguangyuan0718 zhouguangyuan0718 changed the title build: preserve foreign ABI ARM64 assembly callbacks build: integrate native Darwin assembly and dynamic import libraries Sep 18, 2026
@codecov

codecov Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.65217% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/build/build.go 75.00% 2 Missing ⚠️
internal/build/plan9asm.go 81.81% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

LLGo baseline benchmarks

e747bf52d27e | workflow run | long-term charts

Program measurements

Platform Workload File size vs base Text size vs base Build vs base Run vs base
Linux cprintf 7160 B 0 B / +0.0% 387 B 0 B / +0.0% 610.232 ms +48.09 ms / +8.6% (worse) 1.499 ms +100.8 us / +7.2% (worse)
Linux cprintf-lto 6912 B 0 B / +0.0% 368 B 0 B / +0.0% 597.422 ms +41.06 ms / +7.4% (worse) 1.450 ms +100.5 us / +7.5% (worse)
Linux fmtprintf 1637744 B -8 B / -0.0004885% (better) 484801 B 0 B / +0.0% 5.077 s -163.7 ms / -3.1% (better) 3.453 ms +98.17 us / +2.9% (worse)
Linux fmtprintf-lto 1478056 B 0 B / +0.0% 422422 B 0 B / +0.0% 13.173 s +345.8 ms / +2.7% (worse) 3.194 ms +98.4 us / +3.2% (worse)
Linux println 61344 B 0 B / +0.0% 14171 B 0 B / +0.0% 619.401 ms +32.77 ms / +5.6% (worse) 1.717 ms -44.62 us / -2.5% (better)
Linux println-lto 54152 B 0 B / +0.0% 12073 B 0 B / +0.0% 824.009 ms +3.726 ms / +0.5% (worse) 1.740 ms +17.82 us / +1.0% (worse)
macOS cprintf 68064 B 0 B / +0.0% 4429 B 0 B / +0.0% 876.402 ms +167.9 ms / +23.7% (worse) 5.482 ms +1.827 ms / +50.0% (worse)
macOS cprintf-lto 84288 B 0 B / +0.0% 193 B 0 B / +0.0% 797.213 ms +107.4 ms / +15.6% (worse) 3.831 ms -1.662 ms / -30.3% (better)
macOS fmtprintf 1483792 B 0 B / +0.0% 860028 B 0 B / +0.0% 4.090 s +95.03 ms / +2.4% (worse) 7.135 ms +822.2 us / +13.0% (worse)
macOS fmtprintf-lto 1175808 B 0 B / +0.0% 832668 B 0 B / +0.0% 10.812 s +104.2 ms / +1.0% (worse) 7.445 ms +1.566 ms / +26.6% (worse)
macOS println 114512 B 0 B / +0.0% 34330 B 0 B / +0.0% 784.391 ms -63.83 ms / -7.5% (better) 4.455 ms -871.2 us / -16.4% (better)
macOS println-lto 118720 B 0 B / +0.0% 32308 B 0 B / +0.0% 954.395 ms +34.12 ms / +3.7% (worse) 5.404 ms -2.943 ms / -35.3% (better)
Windows MinGW cprintf 19456 B 0 B / +0.0% 4550 B 0 B / +0.0% 1.291 s +2.834 ms / +0.2% (worse) 4.774 ms +445.3 us / +10.3% (worse)
Windows MinGW cprintf-lto 17920 B 0 B / +0.0% 4486 B 0 B / +0.0% 1.325 s -16.83 ms / -1.3% (better) 4.427 ms -424.1 us / -8.7% (better)
Windows MinGW fmtprintf 1910784 B 0 B / +0.0% 586422 B 0 B / +0.0% 4.757 s +64.96 ms / +1.4% (worse) 9.737 ms -814.1 us / -7.7% (better)
Windows MinGW fmtprintf-lto 1933824 B 0 B / +0.0% 535158 B 0 B / +0.0% 11.388 s +178.9 ms / +1.6% (worse) 10.165 ms -1.113 ms / -9.9% (better)
Windows MinGW println 70656 B 0 B / +0.0% 23062 B 0 B / +0.0% 1.340 s +32.61 ms / +2.5% (worse) 8.905 ms +1.55 ms / +21.1% (worse)
Windows MinGW println-lto 65024 B 0 B / +0.0% 20358 B 0 B / +0.0% 1.561 s +48.52 ms / +3.2% (worse) 8.283 ms -113 us / -1.3% (better)
Windows MinGW 386 cprintf 43008 B 0 B / +0.0% 5326 B 0 B / +0.0% 1.084 s +3.194 ms / +0.3% (worse) 4.996 ms -201.2 us / -3.9% (better)
Windows MinGW 386 cprintf-lto 20992 B 0 B / +0.0% 5094 B 0 B / +0.0% 1.092 s -6.128 ms / -0.6% (better) 4.949 ms -184 us / -3.6% (better)
Windows MinGW 386 fmtprintf 1875968 B 0 B / +0.0% 462622 B 0 B / +0.0% 4.116 s -293.7 ms / -6.7% (better) 9.958 ms -790 us / -7.3% (better)
Windows MinGW 386 fmtprintf-lto 2152448 B 0 B / +0.0% 440178 B 0 B / +0.0% 9.582 s -39.56 ms / -0.4% (better) 10.886 ms +389.3 us / +3.7% (worse)
Windows MinGW 386 println 91136 B 0 B / +0.0% 19814 B 0 B / +0.0% 1.079 s -18.58 ms / -1.7% (better) 8.465 ms -135.4 us / -1.6% (better)
Windows MinGW 386 println-lto 69120 B 0 B / +0.0% 17726 B 0 B / +0.0% 1.310 s +6.883 ms / +0.5% (worse) 8.136 ms -777.7 us / -8.7% (better)
Windows MinGW ARM64 cprintf 18944 B 0 B / +0.0% 4408 B 0 B / +0.0% 1.383 s +10.18 ms / +0.7% (worse) 6.990 ms +566.2 us / +8.8% (worse)
Windows MinGW ARM64 cprintf-lto 17920 B 0 B / +0.0% 4340 B 0 B / +0.0% 1.428 s +42.55 ms / +3.1% (worse) 6.696 ms +272.5 us / +4.2% (worse)
Windows MinGW ARM64 fmtprintf 1799168 B 0 B / +0.0% 499204 B 0 B / +0.0% 4.344 s +172.5 ms / +4.1% (worse) 13.417 ms +278.9 us / +2.1% (worse)
Windows MinGW ARM64 fmtprintf-lto 1857536 B 0 B / +0.0% 465312 B 0 B / +0.0% 9.612 s +302.8 ms / +3.3% (worse) 13.216 ms +474.4 us / +3.7% (worse)
Windows MinGW ARM64 println 67072 B 0 B / +0.0% 21816 B 0 B / +0.0% 1.397 s +42.66 ms / +3.2% (worse) 11.259 ms +591.2 us / +5.5% (worse)
Windows MinGW ARM64 println-lto 63488 B 0 B / +0.0% 19436 B 0 B / +0.0% 1.584 s +21.76 ms / +1.4% (worse) 11.492 ms +832.3 us / +7.8% (worse)
Windows MSVC cprintf 120320 B 0 B / +0.0% 65782 B 0 B / +0.0% 761.087 ms -25.71 ms / -3.3% (better) 2.758 ms -91.7 us / -3.2% (better)
Windows MSVC cprintf-lto 119808 B 0 B / +0.0% 65718 B 0 B / +0.0% 758.782 ms -53.24 ms / -6.6% (better) 2.707 ms -149.3 us / -5.2% (better)
Windows MSVC fmtprintf 1624576 B 0 B / +0.0% 681958 B 0 B / +0.0% 3.072 s -44.78 ms / -1.4% (better) 7.199 ms -464.4 us / -6.1% (better)
Windows MSVC fmtprintf-lto 1615872 B 0 B / +0.0% 635126 B 0 B / +0.0% 7.094 s -251.8 ms / -3.4% (better) 6.858 ms -526.5 us / -7.1% (better)
Windows MSVC println 192000 B 0 B / +0.0% 118486 B 0 B / +0.0% 736.596 ms -36.18 ms / -4.7% (better) 6.047 ms +315.7 us / +5.5% (worse)
Windows MSVC println-lto 189952 B 0 B / +0.0% 116326 B 0 B / +0.0% 890.432 ms -11.58 ms / -1.3% (better) 5.520 ms -649.9 us / -10.5% (better)
Windows MSVC 386 cprintf 9728 B 0 B / +0.0% 3931 B 0 B / +0.0% 975.317 ms +52 ms / +5.6% (worse) 4.619 ms -857.7 us / -15.7% (better)
Windows MSVC 386 cprintf-lto 9216 B 0 B / +0.0% 3853 B 0 B / +0.0% 1.007 s +71.78 ms / +7.7% (worse) 5.859 ms -1.131 ms / -16.2% (better)
Windows MSVC 386 fmtprintf 1189376 B 0 B / +0.0% 446005 B 0 B / +0.0% 4.020 s +99.65 ms / +2.5% (worse) 12.063 ms +986.3 us / +8.9% (worse)
Windows MSVC 386 fmtprintf-lto 1224192 B 0 B / +0.0% 416617 B 0 B / +0.0% 8.789 s +263.5 ms / +3.1% (worse) 13.063 ms +1.88 ms / +16.8% (worse)
Windows MSVC 386 println 34304 B 0 B / +0.0% 18641 B 0 B / +0.0% 971.805 ms -178.4 ms / -15.5% (better) 9.676 ms -195.9 us / -2.0% (better)
Windows MSVC 386 println-lto 32256 B 0 B / +0.0% 16839 B 0 B / +0.0% 1.169 s +34.09 ms / +3.0% (worse) 9.474 ms -381.2 us / -3.9% (better)
Windows MSVC ARM64 cprintf 11264 B 0 B / +0.0% 3976 B 0 B / +0.0% 1.091 s +9.11 ms / +0.8% (worse) 6.831 ms +346.7 us / +5.3% (worse)
Windows MSVC ARM64 cprintf-lto 10752 B 0 B / +0.0% 3868 B 0 B / +0.0% 1.119 s +20.67 ms / +1.9% (worse) 7.009 ms +521.3 us / +8.0% (worse)
Windows MSVC ARM64 fmtprintf 1370112 B 0 B / +0.0% 498868 B 0 B / +0.0% 3.832 s +7.677 ms / +0.2% (worse) 14.313 ms +262.7 us / +1.9% (worse)
Windows MSVC ARM64 fmtprintf-lto 1387008 B 0 B / +0.0% 465732 B 0 B / +0.0% 8.653 s +41.39 ms / +0.5% (worse) 14.305 ms +368.9 us / +2.6% (worse)
Windows MSVC ARM64 println 41472 B 0 B / +0.0% 21608 B 0 B / +0.0% 1.136 s +51.53 ms / +4.7% (worse) 11.925 ms -8.3 us / -0.1% (better)
Windows MSVC ARM64 println-lto 39424 B 0 B / +0.0% 19340 B 0 B / +0.0% 1.280 s +26.72 ms / +2.1% (worse) 12.440 ms +178.7 us / +1.5% (worse)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 14.770 ns/op -0.04 ns/op / -0.3% (better)
Linux BenchmarkMergeCompilerFlags 206.700 ns/op +0.9 ns/op / +0.4% (worse)
Linux BenchmarkMergeLinkerFlags 141.700 ns/op +3.3 ns/op / +2.4% (worse)
Linux BenchmarkChannelBuffered 55.970 ns/op 0 ns/op / +0.0%
Linux BenchmarkChannelHandoff 13016 ns/op +164 ns/op / +1.3% (worse)
Linux BenchmarkDefer 48.480 ns/op -11.5 ns/op / -19.2% (better)
Linux BenchmarkDirectCall 1.587 ns/op -0.008 ns/op / -0.5% (better)
Linux BenchmarkGlobalRead 1.573 ns/op -0.026 ns/op / -1.6% (better)
Linux BenchmarkGlobalWrite 7.792 ns/op -0.03 ns/op / -0.4% (better)
Linux BenchmarkGoroutine 23261 ns/op -2579 ns/op / -10.0% (better)
Linux BenchmarkInterfaceCall 6.115 ns/op +0.15 ns/op / +2.5% (worse)
Linux BenchmarkRuntimeGetG 2.442 ns/op -0.042 ns/op / -1.7% (better)
macOS BenchmarkLookupPCRandom 16.940 ns/op -0.42 ns/op / -2.4% (better)
macOS BenchmarkMergeCompilerFlags 149.100 ns/op -5 ns/op / -3.2% (better)
macOS BenchmarkMergeLinkerFlags 102.700 ns/op -14 ns/op / -12.0% (better)
macOS BenchmarkChannelBuffered 39.170 ns/op +0.98 ns/op / +2.6% (worse)
macOS BenchmarkChannelHandoff 12303 ns/op +3530 ns/op / +40.2% (worse)
macOS BenchmarkDefer 48.640 ns/op -2.32 ns/op / -4.6% (better)
macOS BenchmarkDirectCall 1.309 ns/op +0.031 ns/op / +2.4% (worse)
macOS BenchmarkGlobalRead 1.368 ns/op 0 ns/op / +0.0%
macOS BenchmarkGlobalWrite 1.479 ns/op +0.042 ns/op / +2.9% (worse)
macOS BenchmarkGoroutine 51920 ns/op +5640 ns/op / +12.2% (worse)
macOS BenchmarkInterfaceCall 4.943 ns/op -0.916 ns/op / -15.6% (better)
macOS BenchmarkRuntimeGetG 2.992 ns/op +0.445 ns/op / +17.5% (worse)
Windows MinGW BenchmarkLookupPCRandom 12.980 ns/op -0.06 ns/op / -0.5% (better)
Windows MinGW BenchmarkMergeCompilerFlags 688.800 ns/op +31 ns/op / +4.7% (worse)
Windows MinGW BenchmarkMergeLinkerFlags 594.500 ns/op +35.6 ns/op / +6.4% (worse)
Windows MinGW BenchmarkChannelBuffered 30.550 ns/op +0.41 ns/op / +1.4% (worse)
Windows MinGW BenchmarkChannelHandoff 961.200 ns/op -38.7 ns/op / -3.9% (better)
Windows MinGW BenchmarkDefer 64.160 ns/op -0.2 ns/op / -0.3% (better)
Windows MinGW BenchmarkDirectCall 1.551 ns/op +0.004 ns/op / +0.3% (worse)
Windows MinGW BenchmarkGlobalRead 1.555 ns/op +0.007 ns/op / +0.5% (worse)
Windows MinGW BenchmarkGlobalWrite 2.476 ns/op +0.006 ns/op / +0.2% (worse)
Windows MinGW BenchmarkGoroutine 83921 ns/op -5908 ns/op / -6.6% (better)
Windows MinGW BenchmarkInterfaceCall 8.098 ns/op +0.001 ns/op / +0.01235% (worse)
Windows MinGW BenchmarkRuntimeGetG 2.505 ns/op +0.014 ns/op / +0.6% (worse)
Windows MinGW 386 BenchmarkLookupPCRandom 26.480 ns/op -0.03 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkMergeCompilerFlags 758.500 ns/op -4.6 ns/op / -0.6% (better)
Windows MinGW 386 BenchmarkMergeLinkerFlags 706.300 ns/op +19.5 ns/op / +2.8% (worse)
Windows MinGW 386 BenchmarkChannelBuffered 39.340 ns/op -0.12 ns/op / -0.3% (better)
Windows MinGW 386 BenchmarkChannelHandoff 893 ns/op -96.4 ns/op / -9.7% (better)
Windows MinGW 386 BenchmarkDefer 42.770 ns/op -1.63 ns/op / -3.7% (better)
Windows MinGW 386 BenchmarkDirectCall 1.546 ns/op -0.001 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkGlobalRead 1.558 ns/op +0.011 ns/op / +0.7% (worse)
Windows MinGW 386 BenchmarkGlobalWrite 7.784 ns/op +0.012 ns/op / +0.2% (worse)
Windows MinGW 386 BenchmarkGoroutine 85195 ns/op -397 ns/op / -0.5% (better)
Windows MinGW 386 BenchmarkInterfaceCall 8.352 ns/op -0.012 ns/op / -0.1% (better)
Windows MinGW 386 BenchmarkRuntimeGetG 2.170 ns/op +0.002 ns/op / +0.1% (worse)
Windows MinGW ARM64 BenchmarkLookupPCRandom 12.080 ns/op +0.02 ns/op / +0.2% (worse)
Windows MinGW ARM64 BenchmarkMergeCompilerFlags 575.100 ns/op -2.3 ns/op / -0.4% (better)
Windows MinGW ARM64 BenchmarkMergeLinkerFlags 532.700 ns/op -7.5 ns/op / -1.4% (better)
Windows MinGW ARM64 BenchmarkChannelBuffered 37.570 ns/op -0.03 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkChannelHandoff 3201 ns/op +321 ns/op / +11.1% (worse)
Windows MinGW ARM64 BenchmarkDefer 57.230 ns/op +0.14 ns/op / +0.2% (worse)
Windows MinGW ARM64 BenchmarkDirectCall 0.590 ns/op -0.0005 ns/op / -0.1% (better)
Windows MinGW ARM64 BenchmarkGlobalRead 0.885 ns/op +0.0004 ns/op / +0.0452% (worse)
Windows MinGW ARM64 BenchmarkGlobalWrite 0.590 ns/op +0.0002 ns/op / +0.03392% (worse)
Windows MinGW ARM64 BenchmarkGoroutine 58691 ns/op -1796 ns/op / -3.0% (better)
Windows MinGW ARM64 BenchmarkInterfaceCall 4.207 ns/op +0.002 ns/op / +0.04756% (worse)
Windows MinGW ARM64 BenchmarkRuntimeGetG 2.250 ns/op +0.456 ns/op / +25.4% (worse)
Windows MSVC BenchmarkLookupPCRandom 9.615 ns/op -0.053 ns/op / -0.5% (better)
Windows MSVC BenchmarkMergeCompilerFlags 383.900 ns/op -3.4 ns/op / -0.9% (better)
Windows MSVC BenchmarkMergeLinkerFlags 338.800 ns/op -11 ns/op / -3.1% (better)
Windows MSVC BenchmarkChannelBuffered 24.950 ns/op -0.13 ns/op / -0.5% (better)
Windows MSVC BenchmarkChannelHandoff 1015 ns/op -122 ns/op / -10.7% (better)
Windows MSVC BenchmarkDefer 43.980 ns/op -0.55 ns/op / -1.2% (better)
Windows MSVC BenchmarkDirectCall 1.357 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkGlobalRead 1.356 ns/op -0.001 ns/op / -0.1% (better)
Windows MSVC BenchmarkGlobalWrite 2.164 ns/op 0 ns/op / +0.0%
Windows MSVC BenchmarkGoroutine 51188 ns/op +524 ns/op / +1.0% (worse)
Windows MSVC BenchmarkInterfaceCall 6.703 ns/op -0.004 ns/op / -0.1% (better)
Windows MSVC BenchmarkRuntimeGetG 1.899 ns/op 0 ns/op / +0.0%
Windows MSVC 386 BenchmarkLookupPCRandom 26.550 ns/op -0.16 ns/op / -0.6% (better)
Windows MSVC 386 BenchmarkMergeCompilerFlags 720.200 ns/op +25.5 ns/op / +3.7% (worse)
Windows MSVC 386 BenchmarkMergeLinkerFlags 698.200 ns/op +1.8 ns/op / +0.3% (worse)
Windows MSVC 386 BenchmarkChannelBuffered 39.140 ns/op +0.04 ns/op / +0.1% (worse)
Windows MSVC 386 BenchmarkChannelHandoff 883.400 ns/op -9.1 ns/op / -1.0% (better)
Windows MSVC 386 BenchmarkDefer 49.210 ns/op +1.11 ns/op / +2.3% (worse)
Windows MSVC 386 BenchmarkDirectCall 1.863 ns/op +0.007 ns/op / +0.4% (worse)
Windows MSVC 386 BenchmarkGlobalRead 1.860 ns/op -0.001 ns/op / -0.1% (better)
Windows MSVC 386 BenchmarkGlobalWrite 7.801 ns/op +0.003 ns/op / +0.03847% (worse)
Windows MSVC 386 BenchmarkGoroutine 86889 ns/op +833 ns/op / +1.0% (worse)
Windows MSVC 386 BenchmarkInterfaceCall 8.211 ns/op -0.022 ns/op / -0.3% (better)
Windows MSVC 386 BenchmarkRuntimeGetG 1.932 ns/op +0.003 ns/op / +0.2% (worse)
Windows MSVC ARM64 BenchmarkLookupPCRandom 12.060 ns/op -0.07 ns/op / -0.6% (better)
Windows MSVC ARM64 BenchmarkMergeCompilerFlags 570 ns/op -12.2 ns/op / -2.1% (better)
Windows MSVC ARM64 BenchmarkMergeLinkerFlags 546.200 ns/op +11.2 ns/op / +2.1% (worse)
Windows MSVC ARM64 BenchmarkChannelBuffered 37.560 ns/op -2.17 ns/op / -5.5% (better)
Windows MSVC ARM64 BenchmarkChannelHandoff 2384 ns/op +87 ns/op / +3.8% (worse)
Windows MSVC ARM64 BenchmarkDefer 62.560 ns/op -0.77 ns/op / -1.2% (better)
Windows MSVC ARM64 BenchmarkDirectCall 0.590 ns/op +0.0001 ns/op / +0.01697% (worse)
Windows MSVC ARM64 BenchmarkGlobalRead 0.886 ns/op +0.0011 ns/op / +0.1% (worse)
Windows MSVC ARM64 BenchmarkGlobalWrite 3.750 ns/op -0.006 ns/op / -0.2% (better)
Windows MSVC ARM64 BenchmarkGoroutine 55447 ns/op -521 ns/op / -0.9% (better)
Windows MSVC ARM64 BenchmarkInterfaceCall 4.142 ns/op 0 ns/op / +0.0%
Windows MSVC ARM64 BenchmarkRuntimeGetG 2.275 ns/op +0.081 ns/op / +3.7% (worse)
Timer runtime benchmarks
Platform Operation and runtime ns/op vs base
Linux AfterFuncZeroDelivery/Go 978.800 ns/op +23.3 ns/op / +2.4% (worse)
Linux AfterFuncZeroDelivery/LLGo 38671 ns/op -3160 ns/op / -7.6% (better)
Linux CreateStop/Go 317.700 ns/op +5.3 ns/op / +1.7% (worse)
Linux CreateStop/LLGo 1535 ns/op -136 ns/op / -8.1% (better)
Linux RearmStopped/Go 116.400 ns/op +1.8 ns/op / +1.6% (worse)
Linux RearmStopped/LLGo 1773 ns/op +423 ns/op / +31.3% (worse)
Linux ResetActive/Go 68.690 ns/op -0.42 ns/op / -0.6% (better)
Linux ResetActive/LLGo 969.800 ns/op -50.2 ns/op / -4.9% (better)
Linux ResetHeap1024/Go 67.220 ns/op +0.14 ns/op / +0.2% (worse)
Linux ResetHeap1024/LLGo 180 ns/op -13.4 ns/op / -6.9% (better)
macOS AfterFuncZeroDelivery/Go 520.100 ns/op -73.6 ns/op / -12.4% (better)
macOS AfterFuncZeroDelivery/LLGo 101267 ns/op -8586 ns/op / -7.8% (better)
macOS CreateStop/Go 193.100 ns/op +14.5 ns/op / +8.1% (worse)
macOS CreateStop/LLGo 934.600 ns/op -17.9 ns/op / -1.9% (better)
macOS RearmStopped/Go 71.360 ns/op -8.44 ns/op / -10.6% (better)
macOS RearmStopped/LLGo 789.600 ns/op +11.8 ns/op / +1.5% (worse)
macOS ResetActive/Go 58.400 ns/op +0.5 ns/op / +0.9% (worse)
macOS ResetActive/LLGo 246.300 ns/op -56.2 ns/op / -18.6% (better)
macOS ResetHeap1024/Go 49.590 ns/op -5.33 ns/op / -9.7% (better)
macOS ResetHeap1024/LLGo 93.710 ns/op -0.55 ns/op / -0.6% (better)
Windows MinGW AfterFuncZeroDelivery/Go 577.500 ns/op +15.8 ns/op / +2.8% (worse)
Windows MinGW AfterFuncZeroDelivery/LLGo 174214 ns/op +2271 ns/op / +1.3% (worse)
Windows MinGW CreateStop/Go 119.800 ns/op +0.7 ns/op / +0.6% (worse)
Windows MinGW CreateStop/LLGo 491.900 ns/op +17.8 ns/op / +3.8% (worse)
Windows MinGW RearmStopped/Go 31.660 ns/op +0.24 ns/op / +0.8% (worse)
Windows MinGW RearmStopped/LLGo 283.600 ns/op -8.4 ns/op / -2.9% (better)
Windows MinGW ResetActive/Go 20.280 ns/op +0.05 ns/op / +0.2% (worse)
Windows MinGW ResetActive/LLGo 160.500 ns/op -24.4 ns/op / -13.2% (better)
Windows MinGW ResetHeap1024/Go 20.550 ns/op +0.09 ns/op / +0.4% (worse)
Windows MinGW ResetHeap1024/LLGo 124.400 ns/op -1.6 ns/op / -1.3% (better)
Windows MinGW 386 AfterFuncZeroDelivery/Go 953.500 ns/op -2.4 ns/op / -0.3% (better)
Windows MinGW 386 AfterFuncZeroDelivery/LLGo 182604 ns/op +1949 ns/op / +1.1% (worse)
Windows MinGW 386 CreateStop/Go 190.100 ns/op -3.3 ns/op / -1.7% (better)
Windows MinGW 386 CreateStop/LLGo 517.900 ns/op +32.3 ns/op / +6.7% (worse)
Windows MinGW 386 RearmStopped/Go 63.340 ns/op +0.1 ns/op / +0.2% (worse)
Windows MinGW 386 RearmStopped/LLGo 345.500 ns/op +2.3 ns/op / +0.7% (worse)
Windows MinGW 386 ResetActive/Go 38.920 ns/op -0.2 ns/op / -0.5% (better)
Windows MinGW 386 ResetActive/LLGo 1002 ns/op +20.4 ns/op / +2.1% (worse)
Windows MinGW 386 ResetHeap1024/Go 39.350 ns/op -0.04 ns/op / -0.1% (better)
Windows MinGW 386 ResetHeap1024/LLGo 187.200 ns/op 0 ns/op / +0.0%
Windows MinGW ARM64 AfterFuncZeroDelivery/Go 659.200 ns/op -12.4 ns/op / -1.8% (better)
Windows MinGW ARM64 AfterFuncZeroDelivery/LLGo 131993 ns/op +1353 ns/op / +1.0% (worse)
Windows MinGW ARM64 CreateStop/Go 199.700 ns/op -0.7 ns/op / -0.3% (better)
Windows MinGW ARM64 CreateStop/LLGo 366.100 ns/op +3.9 ns/op / +1.1% (worse)
Windows MinGW ARM64 RearmStopped/Go 70.590 ns/op +0.05 ns/op / +0.1% (worse)
Windows MinGW ARM64 RearmStopped/LLGo 255.600 ns/op -2.5 ns/op / -1.0% (better)
Windows MinGW ARM64 ResetActive/Go 31.010 ns/op -0.17 ns/op / -0.5% (better)
Windows MinGW ARM64 ResetActive/LLGo 124 ns/op +1 ns/op / +0.8% (worse)
Windows MinGW ARM64 ResetHeap1024/Go 31.120 ns/op -0.03 ns/op / -0.1% (better)
Windows MinGW ARM64 ResetHeap1024/LLGo 127.400 ns/op +0.1 ns/op / +0.1% (worse)
Windows MSVC AfterFuncZeroDelivery/Go 371.500 ns/op -0.1 ns/op / -0.02691% (better)
Windows MSVC AfterFuncZeroDelivery/LLGo 105019 ns/op +137 ns/op / +0.1% (worse)
Windows MSVC CreateStop/Go 90.810 ns/op +1.03 ns/op / +1.1% (worse)
Windows MSVC CreateStop/LLGo 341.100 ns/op +7.2 ns/op / +2.2% (worse)
Windows MSVC RearmStopped/Go 24.550 ns/op +0.13 ns/op / +0.5% (worse)
Windows MSVC RearmStopped/LLGo 219.300 ns/op +6.9 ns/op / +3.2% (worse)
Windows MSVC ResetActive/Go 14.770 ns/op -0.04 ns/op / -0.3% (better)
Windows MSVC ResetActive/LLGo 115.800 ns/op -4.5 ns/op / -3.7% (better)
Windows MSVC ResetHeap1024/Go 14.930 ns/op -0.21 ns/op / -1.4% (better)
Windows MSVC ResetHeap1024/LLGo 102.100 ns/op -0.1 ns/op / -0.1% (better)
Windows MSVC 386 AfterFuncZeroDelivery/Go 958.900 ns/op +9.8 ns/op / +1.0% (worse)
Windows MSVC 386 AfterFuncZeroDelivery/LLGo 181691 ns/op +3401 ns/op / +1.9% (worse)
Windows MSVC 386 CreateStop/Go 192.700 ns/op +0.5 ns/op / +0.3% (worse)
Windows MSVC 386 CreateStop/LLGo 473.800 ns/op -32.9 ns/op / -6.5% (better)
Windows MSVC 386 RearmStopped/Go 63.680 ns/op +0.39 ns/op / +0.6% (worse)
Windows MSVC 386 RearmStopped/LLGo 328.900 ns/op -8.3 ns/op / -2.5% (better)
Windows MSVC 386 ResetActive/Go 40.210 ns/op +1.18 ns/op / +3.0% (worse)
Windows MSVC 386 ResetActive/LLGo 996.600 ns/op +72.4 ns/op / +7.8% (worse)
Windows MSVC 386 ResetHeap1024/Go 39.550 ns/op +0.08 ns/op / +0.2% (worse)
Windows MSVC 386 ResetHeap1024/LLGo 171.800 ns/op +0.3 ns/op / +0.2% (worse)
Windows MSVC ARM64 AfterFuncZeroDelivery/Go 676.700 ns/op +4.4 ns/op / +0.7% (worse)
Windows MSVC ARM64 AfterFuncZeroDelivery/LLGo 137189 ns/op -1879 ns/op / -1.4% (better)
Windows MSVC ARM64 CreateStop/Go 200.200 ns/op -0.7 ns/op / -0.3% (better)
Windows MSVC ARM64 CreateStop/LLGo 390.200 ns/op -18.8 ns/op / -4.6% (better)
Windows MSVC ARM64 RearmStopped/Go 70.600 ns/op +0.06 ns/op / +0.1% (worse)
Windows MSVC ARM64 RearmStopped/LLGo 269.200 ns/op +2.1 ns/op / +0.8% (worse)
Windows MSVC ARM64 ResetActive/Go 30.960 ns/op -0.06 ns/op / -0.2% (better)
Windows MSVC ARM64 ResetActive/LLGo 136 ns/op +2.8 ns/op / +2.1% (worse)
Windows MSVC ARM64 ResetHeap1024/Go 31.070 ns/op +0.02 ns/op / +0.1% (worse)
Windows MSVC ARM64 ResetHeap1024/LLGo 136.600 ns/op +0.7 ns/op / +0.5% (worse)

Compared with be496b2cc5c3 measured in the same runner job.

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

LLGo WebAssembly build benchmarks

e747bf52d27e | workflow run | long-term charts

WebAssembly output sizes
Example, profile and compiler Wasm module vs base Generated JS glue vs base
cprintf/j32-emscripten/LLGo 135613 B 0 B / +0.0% 70786 B 0 B / +0.0%
cprintf/j32-goos-js/LLGo 134099 B 0 B / +0.0% 69150 B 0 B / +0.0%
cprintf/j64-emscripten-memory64/LLGo 123995 B 0 B / +0.0% 73998 B 0 B / +0.0%
cprintf/w32-goos-wasip1/LLGo 138444 B 0 B / +0.0% 0 B 0 B / 0.0%
cprintf/w32-wasi/LLGo 138170 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/j32-emscripten/LLGo 3087670 B 0 B / +0.0% 114540 B 0 B / +0.0%
fmtprintf/j32-goos-js/Go 2526852 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/j32-goos-js/LLGo 3081650 B 0 B / +0.0% 98239 B 0 B / +0.0%
fmtprintf/j64-emscripten-memory64/LLGo 2826744 B 0 B / +0.0% 121521 B 0 B / +0.0%
fmtprintf/w32-goos-wasip1/Go 2500019 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/w32-goos-wasip1/LLGo 2827999 B 0 B / +0.0% 0 B 0 B / 0.0%
fmtprintf/w32-wasi/LLGo 2694467 B 0 B / +0.0% 0 B 0 B / 0.0%
j32-emscripten/LLGo 134887 B 0 B / +0.0% 70786 B 0 B / +0.0%
j32-goos-js/Go 1895533 B 0 B / +0.0% 0 B 0 B / 0.0%
j32-goos-js/LLGo 133541 B 0 B / +0.0% 69150 B 0 B / +0.0%
j64-emscripten-memory64/LLGo 123307 B 0 B / +0.0% 73998 B 0 B / +0.0%
reflectcall/j32-emscripten/LLGo 1479328 B 0 B / +0.0% 88949 B 0 B / +0.0%
reflectcall/j32-goos-js/Go 2191221 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/j32-goos-js/LLGo 1482091 B 0 B / +0.0% 87313 B 0 B / +0.0%
reflectcall/j64-emscripten-memory64/LLGo 1366457 B 0 B / +0.0% 94158 B 0 B / +0.0%
reflectcall/w32-goos-wasip1/Go 2205707 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/w32-goos-wasip1/LLGo 1533364 B 0 B / +0.0% 0 B 0 B / 0.0%
reflectcall/w32-wasi/LLGo 1458829 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-goos-wasip1/Go 1909947 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-goos-wasip1/LLGo 137725 B 0 B / +0.0% 0 B 0 B / 0.0%
w32-wasi/LLGo 137518 B 0 B / +0.0% 0 B 0 B / 0.0%
LLGo WebAssembly build measurements
Example and profile Build vs base
j32-emscripten 5.986 s -173.1 ms / -2.8% (better)
j32-goos-js 6.205 s -698 ms / -10.1% (better)
j64-emscripten-memory64 5.357 s -265.9 ms / -4.7% (better)
reflectcall/w32-wasi 27.382 s +178.8 ms / +0.7% (worse)
w32-goos-wasip1 4.739 s -552.9 ms / -10.4% (better)
w32-wasi 4.625 s -285.1 ms / -5.8% (better)

Compared with be496b2cc5c3 measured in the same runner job.

@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/tsgo-darwin-build-20260918 branch from aaa2e97 to 858ed14 Compare September 23, 2026 08:19
@zhouguangyuan0718 zhouguangyuan0718 changed the title build: integrate native Darwin assembly and dynamic import libraries build: integrate native assembly backends and dynamic import libraries Sep 23, 2026
@zhouguangyuan0718 zhouguangyuan0718 changed the title build: integrate native assembly backends and dynamic import libraries build: integrate naked LLVM assembly and dynamic import libraries Sep 23, 2026
@zhouguangyuan0718

Copy link
Copy Markdown
Collaborator Author

/review Please review the current head 43ae165. The earlier review predates the removal of Go object parsing. Focus on correctness of the shared textual LLVM IR compilation path, native naked inline-asm ABI preservation, DATA binding and archive extraction, LTO, and dynamic import handling. Please report actionable findings against this head; this request is for review only, not code changes.

@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: native inline-asm compilation path (head 43ae165)

Reviewed the current head against base 3df0491. The Go-object parsing path is gone; this review covers the shared textual LLVM IR path, native naked inline-asm ABI preservation, DATA binding, dynamic import handling, and the darwin linker-flag translation.

Overall the design is sound. Module ownership is correct (native and non-native modules both reach mod.Dispose() at plan9asm.go:104, and the DATA-binding error path disposes before returning); externalizePlan9DataGlobals has solid guards (thread-local mismatch, size mismatch, and the "both Go initializer and DATA" conflict all reject before mutating the Go module); the native gate correctly skips lowerLargeAggregates/TransformModule so native carriers keep their physical-register ABI; and the darwin gating, dedup, and framework/dylib fallbacks are reasonable. Test coverage (LTO Off/Thin/Full, cross-compile object inspection, the Go 1.27 trailing-quote case) is strong.

A few findings below, the first being the most important.

Findings

[P1] Raw library paths flow unvalidated into linker args (cgo_pragmas.go) — In goCgoLinkArgs, any //go:cgo_import_dynamic library value that doesn't match the framework or /usr/lib/lib*.dylib shapes is appended verbatim to the link command. A value beginning with - or @ (e.g. -Wl,..., -force_load,..., @file) is interpreted by clang/ld as an option rather than an input file. Since these directives are read straight from package source, this is new linker-flag injection surface (Go's own toolchain guards the equivalent LDFLAGS path via an allowlist / CGO_LDFLAGS_ALLOW). Consider rejecting lib values starting with -/@ and constraining the raw-path branch to absolute existing .dylib/.tbd/.a paths.

[P2] collectGoCgoPragmas(pkg.Syntax) recomputed per .s file — translateForeignNativeAsm re-scans every Go AST file/comment and rebuilds the imports map on each iteration of the compilePkgSFiles loop, though its input and output are package-invariant. For packages with many .s and .go files this is O(sfiles × gofiles) redundant comment scanning plus per-iteration allocations. shouldCheckDarwinDynimportTrampolineAsm already computes this once per package; consider hoisting/memoizing (matching the existing plan9asmSigs cache pattern). Bounded by the SupportsNativeTarget short-circuit, so darwin-only.

[P3] splitDirectiveArgs does not handle backslash-escaped quotes — The manual scanner treats every " as a field boundary regardless of a preceding \. For input like "a\"b" it mis-splits before strconv.Unquote runs. The comment claims to "match cmd/compile's pragma field boundaries," and cmd/compile respects backslash escapes. Real cgo directives don't contain escaped quotes, so impact is low, but consider skipping \-escaped quotes inside a quoted region (or documenting the divergence with a test).

[P3] Supply-chain: fork pin in go.mod — replace github.com/xgo-dev/plan9asm => github.com/zhouguangyuan0718/plan9asm v0.2.2-... redirects the asm→LLVM backend (high-trust, emitted into user binaries) to a personal fork by pseudo-version pending PR #42. Fine as a temporary pin (covered by go.sum), but track moving it back to an org-owned tagged release, and note the pinned v0.2.2-... is lower than the required xgo-dev/plan9asm v0.5.3.

name := strings.TrimSuffix(strings.TrimPrefix(path.Base(lib), "lib"), ".dylib")
ldflags = append(ldflags, "-l"+name)
} else {
ldflags = append(ldflags, lib)

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.

Linker-flag injection via raw library path. Any //go:cgo_import_dynamic library that doesn't match the framework or /usr/lib/lib*.dylib shapes is appended verbatim here. A value beginning with - or @ (e.g. -Wl,..., -force_load,..., @file) is treated by clang/ld as an option, not an input file. These directives come from package source, so this is new linker-flag injection surface — Go's toolchain guards the equivalent LDFLAGS path with an allowlist. Suggest rejecting values starting with -/@ and constraining this branch to absolute existing .dylib/.tbd/.a paths.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 95e0da8: the dynamic-import library field now rejects leading - and @, and propagates the diagnostic from both ordinary and alternate packages. Added regression cases for linker-option/response-file values and valid relative, literal ./@, and space-containing library paths. Kept SDK-based framework/dylib resolution and did not require files to exist on the host: system dylibs may only be available through SDK stubs. Focused native/Plan 9/dynamic-import tests, including real callback links with LTO off/Thin/Full, pass.

if !extplan9asm.SupportsNativeTarget(ctx.buildConf.Goos, ctx.buildConf.Goarch) {
return llvm.Module{}, false, nil
}
_, decls := collectGoCgoPragmas(pkg.Syntax)

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.

collectGoCgoPragmas(pkg.Syntax) (and the imports map built below) is recomputed on every .s file in the compilePkgSFiles loop, but its input and output are package-invariant. For packages with many .s/.go files this is O(sfiles × gofiles) redundant AST/comment scanning plus repeated allocations. shouldCheckDarwinDynimportTrampolineAsm already computes this once per package; consider hoisting or memoizing (matching the plan9asmSigs cache pattern). Bounded by the SupportsNativeTarget short-circuit, so darwin-only.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The repeated per-file scan is real, but is a non-blocking optimization for these small callback files; keeping the focused correctness fix separate. SupportsNativeTarget covers both Linux and Darwin (amd64/arm64), so it is not Darwin-only. The personal-fork dependency is an immutable go.sum-verified pin explicitly pending plan9asm #42; the go.mod comment tracks removal once the upstream change is available.


func splitDirectiveArgs(s string) []string {
fields := strings.Fields(strings.TrimSpace(s))
// Match cmd/compile's pragma field boundaries: quoted regions are single

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.

The comment claims to "Match cmd/compile's pragma field boundaries," but the scanner treats every " as a field boundary regardless of a preceding backslash, so a backslash-escaped quote (e.g. "a\"b") mis-splits before strconv.Unquote runs. cmd/compile respects backslash escapes. Real cgo directives don't contain escaped quotes so impact is low; consider skipping \-escaped quotes inside a quoted region, or documenting the divergence with a test.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Checked this against Go 1.27.0: pragmaFields also toggles its quoted state on every double quote and does not special-case backslashes. See https://github.com/golang/go/blob/go1.27.0/src/cmd/compile/internal/noder/lex.go#L151 . The field-boundary behavior here is intentional, including ignoring an unmatched trailing quote (needed by runtime/sys_darwin.go). I am keeping compatibility with that parser rather than introducing different escaped-quote boundaries.

@cpunion

cpunion commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Confirmed on Linux/amd64 at this PR's head (95e0da88b, LLVM 22): the native assembly compiles, but the final link omits the library named by //go:cgo_import_dynamic and fails with an unresolved symbol.

Minimal reproducer (paths below are inside the Linux container):

go.mod:

module example.com/llgo-dynimport-repro

go 1.27.0

main.go:

package main

//go:cgo_import_dynamic imported answer "/repro/libprobe.so"
var entry uintptr

func main() { println(entry) }

bridge_amd64.s:

#include "textflag.h"

TEXT bridge<>(SB), NOSPLIT, $0
    JMP imported(SB)

GLOBL ·entry(SB), RODATA, $8
DATA ·entry(SB)/8, $bridge<>(SB)

libprobe.c:

int answer(void) { return 42; }

From /repro, run clang -shared -fPIC libprobe.c -o libprobe.so, then from /repro/app run llgo build -o repro .. The actual error is:

ld.lld: error: undefined symbol: answer
>>> referenced by native-main
>>>               plan9asm-bridge_amd64.s-797705208.o:(__plan9_native_0) in archive /tmp/pkg-3521799947.a
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
example.com/llgo-dynimport-repro: exit status 1

I also checked the cause with a control build: a separate imported cgo package supplying #cgo LDFLAGS: -L/repro -lprobe made this same program link and run (it printed a nonzero entry address). goCgoLinkArgs currently returns only ldflags for every non-Darwin target, so the dynamic import's library field is not forwarded on Linux. Could we translate that field into an ELF linker input and add an end-to-end Linux shared-library link test?

Update: I repeated the failing build with a go.work workspace containing LLGo #2623 at 95e0da88b and plan9asm #42 at its current head 35531cc directly. go list -m -json github.com/xgo-dev/plan9asm confirmed the workspace module directory /repro/plan9asm; the rebuilt LLGo still failed at final link with ld.lld: error: undefined symbol: answer, referenced from __plan9_native_0. The initial run used #2623's go.mod replace pin (66e8f32), so this verifies the same issue against the latest #42 head as well.

@xushiwei
xushiwei merged commit 75fbba7 into xgo-dev:main Sep 25, 2026
88 checks passed
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.

3 participants