From 9b31fbbe2d1f7ca5bb9eae6bd3df10159dda96aa Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 09:22:00 +0800 Subject: [PATCH 1/8] docs: add shared contributor validation guide --- AGENTS.md | 1 + CLAUDE.md | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 7 deletions(-) create mode 120000 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 0000000000..681311eb9c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 2451cf4c56..90c150aacb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ -# LLGo Project AI Assistant Guide +# LLGo Contributor and AI Assistant Guide -This document provides essential information for AI assistants to help fix bugs and implement features in the LLGo project. +This document provides essential information for contributors and AI assistants fixing bugs or implementing features in the LLGo project. `AGENTS.md` links to this file so every tool uses the same repository guidance. ## About LLGo @@ -21,6 +21,16 @@ LLGo is a Go compiler based on LLVM designed to better integrate Go with the C e For detailed dependency requirements and installation instructions, see the [Dependencies](README.md#dependencies) and [How to install](README.md#how-to-install) sections in the README. +CI uses LLVM 19 and pins exact Go patch releases; check [`.github/workflows/llgo.yml`](.github/workflows/llgo.yml) and [`.github/workflows/goroot.yml`](.github/workflows/goroot.yml) instead of guessing versions. Native development is supported on macOS and Linux. Native Windows support is still TODO; use WSL2 or Linux containers on Windows. + +## Repository and GitHub Safety + +- Treat `xgo-dev/*` as upstream. Do not push branches or tags directly to an `xgo-dev` repository, and do not merge its pull requests. +- Push code to your fork, then create or update a pull request against `xgo-dev/llgo:main`. Bug reports and proposals may be submitted as upstream issues. +- Do not publish upstream releases or change upstream repository settings. Inspect remotes before any write operation when ownership is unclear. +- Prefer `gh issue view`, `gh pr view`, and `gh pr checks` for GitHub state. Use `gh api` for review threads, inline comments, check-run details, or fields not exposed by the higher-level commands; avoid scraping the website. +- Keep changes scoped, preserve unrelated worktree edits, and review the complete diff against upstream before submission. Diagnose baseline failures instead of hiding them with skips, exclusions, or weakened checks. + ## Testing & Validation The following commands and workflows are essential when fixing bugs or implementing features in the LLGo project: @@ -36,6 +46,20 @@ go test ./... - C interop - Python integration (requires Python development headers) +The root command does not enter the nested `runtime` Go module. Test it separately when runtime code changes: + +```bash +(cd runtime && go test ./...) +``` + +Prefer the development wrapper for LLGo execution tests; it builds the current checkout and sets `LLGO_ROOT`: + +```bash +./dev/llgo.sh test ./path/to/package +``` + +After focused tests pass, `./dev/local_ci.sh` runs the main local build, test, LLGo, demo, target-build, and cache checks when the optional dependencies are available. See [`dev/README.md`](dev/README.md) for the maintained commands. + ### Write and run tests for your changes When adding new functionality or fixing bugs, create appropriate test cases: @@ -53,7 +77,7 @@ go test ./... ### Update out.ll files after modifying compiler IR generation -**CRITICAL:** When you modify the compiler's IR generation logic (especially in `ssa/` or `cl/` packages), you MUST update all out.ll test files under the `cl/` directory. +**CRITICAL:** When you modify compiler IR generation (especially in `ssa/` or `cl/`), update the affected expectations and review every generated diff. Do not regenerate or commit unrelated test output. #### Understanding out.ll files @@ -72,7 +96,7 @@ The `out.ll` files under the `cl/` directory are comparison IR files that serve 2. **Regenerate out.ll files**: - **For batch updates (recommended)** - Use `gentests` to regenerate all test files: + **For intentional batch updates** - Use `gentests` to regenerate all test files: ```bash gentests ``` @@ -94,6 +118,14 @@ The `out.ll` files under the `cl/` directory are comparison IR files that serve 4. **Commit the updated out.ll files** along with your compiler changes +Tests whose first line is `// LITTEST` keep FileCheck expectations in the Go source instead of `out.ll`. Refresh only the affected file or directory: + +```bash +go run ./chore/litgen cl/_testrt/litdemo/in.go +``` + +See [`dev/README.md`](dev/README.md#6-refresh-test-goldens) for the `gentests`/`litgen` split and marker rules. + #### Why this matters This process ensures that: @@ -101,16 +133,89 @@ This process ensures that: - Changes to IR generation are properly documented and reviewed - Future regressions can be detected by comparing against the reference output +### Go compatibility + +Compatibility means matching Go source and observable behavior; do not assume compatibility with the gc compiler's internal ABI. Tests under `test/std` should normally run with both compilers: + +```bash +go test ./test/std/... +./dev/llgo.sh test ./test/std/... +``` + +Use the external-GOROOT runner for official Go test cases. Start with the relevant case, then expand to the CI directive set: + +```bash +bash ./dev/test_goroot.sh -- -directive-mode ci -dirs . -case '^helloworld\.go$' +bash ./dev/test_goroot.sh -- -directive-mode ci +``` + +Pass multiple GOROOT paths before `--` to validate the supported Go generations. The full `coverage` mode is resource-intensive; its limits, sharding options, and classification rules are documented in [`test/goroot/README.md`](test/goroot/README.md). Do not skip, weaken, or reclassify a failing test merely to make a change pass. + +### Host and cross-platform validation + +Run native tests on the host platform whenever possible. Cross-compilation alone proves only that an artifact was produced; execute it on real hardware, a container, or an emulator when behavior is affected. + +| Development host | Practical local coverage | +| --- | --- | +| macOS arm64 | Native macOS arm64; macOS amd64 with Rosetta and a matching x86_64 Go/LLVM toolchain; Linux amd64/arm64 with Docker Desktop | +| macOS amd64 | Native macOS amd64; Linux amd64/arm64 with Docker Desktop; use a remote arm64 Mac for native macOS arm64 behavior | +| Linux amd64/arm64 | Native matching Linux architecture; the other Linux architecture with containers plus QEMU/binfmt | +| Windows amd64/arm64 | Linux validation through WSL2 or Docker; do not claim native Windows validation | + +Reusable Linux environments are provided for both main architectures: + +```bash +./dev/docker.sh amd64 bash -lc './dev/llgo.sh test ./test/...' +./dev/docker.sh arm64 bash -lc './dev/llgo.sh test ./test/...' +``` + +Docker Desktop provides emulation on macOS. Linux hosts must enable QEMU/binfmt before running a container for the other architecture. The primary CI source-build/test lanes cover macOS arm64 and Linux amd64; release artifact smoke tests additionally cover macOS amd64 and Linux arm64. Linux and Windows hosts cannot validate native macOS behavior. + +### WebAssembly + +Use the maintained wrapper for a build smoke test: + +```bash +./dev/llgo_wasm.sh build ./... +``` + +For execution, build the CI-compatible WAMR runner with `./dev/build_iwasm.sh`, add the printed directory to `PATH`, then compile and run a focused fixture: + +```bash +(cd _demo/c && ../../dev/llgo_wasm.sh build -o hello -tags=nogc ./helloc) +iwasm --stack-size=819200000 --heap-size=800000000 _demo/c/hello.wasm +``` + +Changes specific to `GOOS=js` should also compile an explicit `GOOS=js GOARCH=wasm` fixture. Validate Wasm output with a runtime (WAMR, Wasmtime, Node, or a browser as appropriate), not only LLVM IR generation. + +### Embedded targets + +Build smoke coverage for all configured targets is available through: + +```bash +(cd _demo/embed/targetsbuild && bash build.sh empty) +``` + +For ESP32 and ESP32-C3 execution tests, install the QEMU packages used by CI and run the existing fixtures: + +```bash +.github/workflows/install-esp-qemu.sh .cache/qemu +export PATH="$PWD/.cache/qemu/bin:$PATH" +bash _demo/embed/test-esp-serial-startup.sh +``` + +Install SDL2 and libslirp as shown in [`.github/actions/setup-embed-deps/action.yml`](.github/actions/setup-embed-deps/action.yml). ESP32-C3 startup/linker changes should also run `_demo/embed/test_esp32c3_startup.sh` with `esptool==5.1.0`. When no emulator exists, build a focused `-target=` fixture and state clearly that execution was not validated. + ## Code Quality Before submitting any code updates, you must run the following formatting and validation commands: ### Format code ```bash -go fmt ./... +gofmt -w path/to/changed.go ``` -**Important:** Always run `go fmt ./...` before committing code changes. This ensures consistent code formatting across the project. +**Important:** Format every changed Go file before committing, but do not rewrite unrelated files in a shared or dirty worktree. ### Run static analysis ```bash @@ -179,4 +284,3 @@ LLGO_ROOT=/path/to/llgo llgo run . 3. **Defer in Loops:** LLGo now supports `defer` within loops, matching Go's semantics of executing defers in LIFO order for every iteration. Be mindful of loop-heavy defer usage as it allocates per iteration. 4. **C Ecosystem Integration:** LLGo uses `go:linkname` directive to link external symbols through ABI 5. **Python Integration:** Third-party Python libraries require separate installation of library files - From 5ce3a2d95b7905aadadb3d1c60ce7493aac309ac Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 10:45:12 +0800 Subject: [PATCH 2/8] docs: mention OrbStack for macOS validation --- CLAUDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 90c150aacb..ef36812bfd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -157,8 +157,8 @@ Run native tests on the host platform whenever possible. Cross-compilation alone | Development host | Practical local coverage | | --- | --- | -| macOS arm64 | Native macOS arm64; macOS amd64 with Rosetta and a matching x86_64 Go/LLVM toolchain; Linux amd64/arm64 with Docker Desktop | -| macOS amd64 | Native macOS amd64; Linux amd64/arm64 with Docker Desktop; use a remote arm64 Mac for native macOS arm64 behavior | +| macOS arm64 | Native macOS arm64; macOS amd64 with Rosetta and a matching x86_64 Go/LLVM toolchain; Linux amd64/arm64 with Docker Desktop or OrbStack | +| macOS amd64 | Native macOS amd64; Linux amd64/arm64 with Docker Desktop or OrbStack; use a remote arm64 Mac for native macOS arm64 behavior | | Linux amd64/arm64 | Native matching Linux architecture; the other Linux architecture with containers plus QEMU/binfmt | | Windows amd64/arm64 | Linux validation through WSL2 or Docker; do not claim native Windows validation | @@ -169,7 +169,7 @@ Reusable Linux environments are provided for both main architectures: ./dev/docker.sh arm64 bash -lc './dev/llgo.sh test ./test/...' ``` -Docker Desktop provides emulation on macOS. Linux hosts must enable QEMU/binfmt before running a container for the other architecture. The primary CI source-build/test lanes cover macOS arm64 and Linux amd64; release artifact smoke tests additionally cover macOS amd64 and Linux arm64. Linux and Windows hosts cannot validate native macOS behavior. +On macOS, use Docker Desktop or [OrbStack](https://docs.orbstack.dev/) for the Linux container lanes. Both expose Docker Compose, so the `dev/docker.sh` commands stay the same. Linux hosts must enable QEMU/binfmt before running a container for the other architecture. The primary CI source-build/test lanes cover macOS arm64 and Linux amd64; release artifact smoke tests additionally cover macOS amd64 and Linux arm64. Linux and Windows hosts cannot validate native macOS behavior. ### WebAssembly From 59da5a3f638fb69c6bc144d6e50b19b10d630640 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 10:46:48 +0800 Subject: [PATCH 3/8] docs: clarify coverage expectations --- CLAUDE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index ef36812bfd..9e4bd8c97a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,13 @@ Prefer the development wrapper for LLGo execution tests; it builds the current c After focused tests pass, `./dev/local_ci.sh` runs the main local build, test, LLGo, demo, target-build, and cache checks when the optional dependencies are available. See [`dev/README.md`](dev/README.md) for the maintained commands. +### Coverage + +- The Codecov patch check must pass; new deterministic logic and error paths should normally be fully covered. +- Check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. Run it inside `runtime/` for that nested module. +- Coverage from Linux and macOS is combined because each has platform-specific paths. Validate host-specific changes on the matching host when possible. +- [`.github/codecov.yml`](.github/codecov.yml) lists paths excluded from coverage. Add an exclusion only for generated, tooling, fixture, or otherwise non-meaningful code; never exclude production logic merely to make a PR pass, and explain every ignore change in the PR. + ### Write and run tests for your changes When adding new functionality or fixing bugs, create appropriate test cases: From 5f47ace8c0dcc48e4df02002c4492dc0d8de8bd3 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 11:10:55 +0800 Subject: [PATCH 4/8] dev: add target validation wrappers --- CLAUDE.md | 137 +++++----------------------------------------- dev/README.md | 61 +++++++++++++++++++-- dev/test_embed.sh | 43 +++++++++++++++ dev/test_wasm.sh | 56 +++++++++++++++++++ 4 files changed, 168 insertions(+), 129 deletions(-) create mode 100755 dev/test_embed.sh create mode 100755 dev/test_wasm.sh diff --git a/CLAUDE.md b/CLAUDE.md index 9e4bd8c97a..925a45122e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # LLGo Contributor and AI Assistant Guide -This document provides essential information for contributors and AI assistants fixing bugs or implementing features in the LLGo project. `AGENTS.md` links to this file so every tool uses the same repository guidance. +This document provides essential information for contributors and AI assistants fixing bugs or implementing features in the LLGo project. ## About LLGo @@ -63,7 +63,7 @@ After focused tests pass, `./dev/local_ci.sh` runs the main local build, test, L ### Coverage - The Codecov patch check must pass; new deterministic logic and error paths should normally be fully covered. -- Check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. Run it inside `runtime/` for that nested module. +- From the module containing the target package, check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. - Coverage from Linux and macOS is combined because each has platform-specific paths. Validate host-specific changes on the matching host when possible. - [`.github/codecov.yml`](.github/codecov.yml) lists paths excluded from coverage. Add an exclusion only for generated, tooling, fixture, or otherwise non-meaningful code; never exclude production logic merely to make a PR pass, and explain every ignore change in the PR. @@ -82,136 +82,25 @@ go test ./... **Important:** The `LLGO_ROOT` environment variable must be set to the repository root when running llgo commands during development. -### Update out.ll files after modifying compiler IR generation +### Update IR test expectations -**CRITICAL:** When you modify compiler IR generation (especially in `ssa/` or `cl/`), update the affected expectations and review every generated diff. Do not regenerate or commit unrelated test output. - -#### Understanding out.ll files - -The `out.ll` files under the `cl/` directory are comparison IR files that serve as reference outputs for the test suite: -- They are generated by `llgen` from the corresponding `in.go` files in the same directory -- They reflect the current compiler's LLVM IR representation of the Go source code -- They are used by tests to verify that the compiler generates correct and consistent IR output - -#### Required steps after modifying IR generation logic - -1. **Reinstall the tools** to apply your compiler changes: - ```bash - go install -v ./chore/gentests - go install -v ./chore/llgen - ``` - -2. **Regenerate out.ll files**: - - **For intentional batch updates** - Use `gentests` to regenerate all test files: - ```bash - gentests - ``` - This will automatically regenerate all out.ll files in these directories: - - `cl/_testlibc` - - `cl/_testlibgo` - - `cl/_testrt` - - `cl/_testgo` - - `cl/_testpy` - - `cl/_testdata` - - **For individual test inspection** - Use `llgen` to regenerate specific test directories: - ```bash - llgen cl/_testgo/interface - llgen cl/_testrt/tpmethod - ``` - -3. **Verify the changes** make sense by reviewing the diff in the out.ll files - -4. **Commit the updated out.ll files** along with your compiler changes - -Tests whose first line is `// LITTEST` keep FileCheck expectations in the Go source instead of `out.ll`. Refresh only the affected file or directory: +When `ssa/` or `cl/` changes generated IR, refresh only the affected expectations and review every generated diff: ```bash -go run ./chore/litgen cl/_testrt/litdemo/in.go +go run ./chore/litgen path/to/LITTEST/in.go # default +go run ./chore/llgen path/to/legacy/case # remaining out.ll cases only ``` -See [`dev/README.md`](dev/README.md#6-refresh-test-goldens) for the `gentests`/`litgen` split and marker rules. - -#### Why this matters - -This process ensures that: -- The test suite reflects the current compiler behavior -- Changes to IR generation are properly documented and reviewed -- Future regressions can be detected by comparing against the reference output - -### Go compatibility - -Compatibility means matching Go source and observable behavior; do not assume compatibility with the gc compiler's internal ABI. Tests under `test/std` should normally run with both compilers: - -```bash -go test ./test/std/... -./dev/llgo.sh test ./test/std/... -``` - -Use the external-GOROOT runner for official Go test cases. Start with the relevant case, then expand to the CI directive set: - -```bash -bash ./dev/test_goroot.sh -- -directive-mode ci -dirs . -case '^helloworld\.go$' -bash ./dev/test_goroot.sh -- -directive-mode ci -``` - -Pass multiple GOROOT paths before `--` to validate the supported Go generations. The full `coverage` mode is resource-intensive; its limits, sharding options, and classification rules are documented in [`test/goroot/README.md`](test/goroot/README.md). Do not skip, weaken, or reclassify a failing test merely to make a change pass. - -### Host and cross-platform validation - -Run native tests on the host platform whenever possible. Cross-compilation alone proves only that an artifact was produced; execute it on real hardware, a container, or an emulator when behavior is affected. - -| Development host | Practical local coverage | -| --- | --- | -| macOS arm64 | Native macOS arm64; macOS amd64 with Rosetta and a matching x86_64 Go/LLVM toolchain; Linux amd64/arm64 with Docker Desktop or OrbStack | -| macOS amd64 | Native macOS amd64; Linux amd64/arm64 with Docker Desktop or OrbStack; use a remote arm64 Mac for native macOS arm64 behavior | -| Linux amd64/arm64 | Native matching Linux architecture; the other Linux architecture with containers plus QEMU/binfmt | -| Windows amd64/arm64 | Linux validation through WSL2 or Docker; do not claim native Windows validation | +Do not regenerate unrelated output. The legacy batch tooling, supported scopes, and marker format are documented in [`dev/README.md`](dev/README.md#6-refresh-test-goldens). -Reusable Linux environments are provided for both main architectures: +### Compatibility and target validation -```bash -./dev/docker.sh amd64 bash -lc './dev/llgo.sh test ./test/...' -./dev/docker.sh arm64 bash -lc './dev/llgo.sh test ./test/...' -``` - -On macOS, use Docker Desktop or [OrbStack](https://docs.orbstack.dev/) for the Linux container lanes. Both expose Docker Compose, so the `dev/docker.sh` commands stay the same. Linux hosts must enable QEMU/binfmt before running a container for the other architecture. The primary CI source-build/test lanes cover macOS arm64 and Linux amd64; release artifact smoke tests additionally cover macOS amd64 and Linux arm64. Linux and Windows hosts cannot validate native macOS behavior. - -### WebAssembly - -Use the maintained wrapper for a build smoke test: - -```bash -./dev/llgo_wasm.sh build ./... -``` - -For execution, build the CI-compatible WAMR runner with `./dev/build_iwasm.sh`, add the printed directory to `PATH`, then compile and run a focused fixture: - -```bash -(cd _demo/c && ../../dev/llgo_wasm.sh build -o hello -tags=nogc ./helloc) -iwasm --stack-size=819200000 --heap-size=800000000 _demo/c/hello.wasm -``` - -Changes specific to `GOOS=js` should also compile an explicit `GOOS=js GOARCH=wasm` fixture. Validate Wasm output with a runtime (WAMR, Wasmtime, Node, or a browser as appropriate), not only LLVM IR generation. - -### Embedded targets - -Build smoke coverage for all configured targets is available through: - -```bash -(cd _demo/embed/targetsbuild && bash build.sh empty) -``` - -For ESP32 and ESP32-C3 execution tests, install the QEMU packages used by CI and run the existing fixtures: - -```bash -.github/workflows/install-esp-qemu.sh .cache/qemu -export PATH="$PWD/.cache/qemu/bin:$PATH" -bash _demo/embed/test-esp-serial-startup.sh -``` +- Go compatibility covers source and observable behavior, not the gc compiler's internal ABI. Run standard-library tests with both `go test ./test/std/...` and `./dev/llgo.sh test ./test/std/...`. +- Run official Go cases with `bash ./dev/test_goroot.sh -- -directive-mode ci`; see [`test/goroot/README.md`](test/goroot/README.md) for filtering, multiple toolchains, full coverage, and sharding. +- Run native tests on the matching host. Use `dev/docker.sh` for Linux amd64/arm64 validation, `dev/test_wasm.sh` for Wasm, and `dev/test_embed.sh` for embedded build plus emulator smoke. +- Cross-compilation alone is not execution validation. Do not weaken or reclassify failures to make a change pass, and state any target that could not be run. -Install SDL2 and libslirp as shown in [`.github/actions/setup-embed-deps/action.yml`](.github/actions/setup-embed-deps/action.yml). ESP32-C3 startup/linker changes should also run `_demo/embed/test_esp32c3_startup.sh` with `esptool==5.1.0`. When no emulator exists, build a focused `-target=` fixture and state clearly that execution was not validated. +The host matrix, CI coverage, dependencies, and target-specific follow-up commands are in [`dev/README.md`](dev/README.md#platform-and-target-validation). ## Code Quality diff --git a/dev/README.md b/dev/README.md index f831633577..34650205b5 100644 --- a/dev/README.md +++ b/dev/README.md @@ -72,14 +72,65 @@ You can control demo parallelism via `LLGO_DEMO_JOBS` (defaults to up to 4 jobs) - If `[command...]` is provided, it runs that command and exits. - You must run it from within the repo (within `LLGO_ROOT`), and it will start in the matching repo subdirectory inside the container. +## Platform and target validation + +Cross-compilation proves that an artifact was produced; run it on a matching host, container, or emulator when behavior changes. + +| Development host | Practical local coverage | +| --- | --- | +| macOS arm64 | Native macOS arm64; macOS amd64 with Rosetta and an x86_64 toolchain; Linux amd64/arm64 with Docker Desktop or OrbStack | +| macOS amd64 | Native macOS amd64; Linux amd64/arm64 with Docker Desktop or OrbStack; use a remote arm64 Mac for native macOS arm64 behavior | +| Linux amd64/arm64 | Native matching Linux architecture; the other Linux architecture with containers plus QEMU/binfmt | +| Windows amd64/arm64 | Linux through WSL2 or Docker; native Windows is not currently supported | + +Use the same container commands with Docker Desktop or OrbStack on macOS. Linux hosts must enable QEMU/binfmt before running the other architecture: + +```bash +./dev/docker.sh amd64 bash -lc './dev/llgo.sh test ./test/...' +./dev/docker.sh arm64 bash -lc './dev/llgo.sh test ./test/...' +``` + +The primary CI source-build/test lanes cover macOS arm64 and Linux amd64. Release artifact smoke tests additionally cover macOS amd64 and Linux arm64. Linux and Windows hosts cannot validate native macOS behavior. + +### Official Go compatibility + +Run the current GOROOT with the CI directive set: + +```bash +bash ./dev/test_goroot.sh -- -directive-mode ci +``` + +Pass GOROOT paths before `--` for multiple Go versions. See [`test/goroot/README.md`](../test/goroot/README.md) for case filters, full coverage, resource limits, and sharding. + +### WebAssembly + +Run the WASI build and WAMR execution smoke test: + +```bash +./dev/test_wasm.sh +``` + +The script builds the pinned WAMR runner through `dev/build_iwasm.sh` when it is not cached. Changes specific to `GOOS=js` still need an explicit `GOOS=js GOARCH=wasm` build and an appropriate Node or browser test. + +### Embedded + +After installing SDL2 and libslirp as shown in [the CI setup action](../.github/actions/setup-embed-deps/action.yml), run: + +```bash +./dev/test_embed.sh +``` + +The script caches the pinned ESP QEMU binaries outside the worktree, then builds and runs the ESP32/ESP32-C3 serial smoke tests. Target-table changes should also run `(cd _demo/embed/targetsbuild && bash build.sh empty)`. Startup/linker changes should additionally run `_demo/embed/test_esp32c3_startup.sh` with `esptool==5.1.0`. If a target has no emulator, report build-only validation explicitly. + ## 6) Refresh test goldens -LLGo currently has two different golden-test refresh flows: +Use source-embedded `// LITTEST` checks and `litgen` for new and migrated IR tests. The remaining `out.ll` cases use `llgen`; `gentests` exists only for intentional legacy batch maintenance. -- `gentests` for directory-based golden files such as `out.ll` and `expect.txt` -- `litgen` for source-embedded `// LITTEST` FileCheck directives +- `litgen` is the default for source-embedded FileCheck directives. +- `llgen` refreshes an individual legacy `out.ll` case. +- `gentests` batch-refreshes legacy `out.ll` and `expect.txt`; do not use it for routine focused changes. -### `gentests` +### `gentests` (legacy batch only) Run: @@ -94,7 +145,7 @@ Behavior: - Preserves the existing skip convention where `out.ll` or `expect.txt` containing only `;` means "do not refresh". - New behavior: if a test case directory contains a non-test Go source file whose first line is exactly `// LITTEST`, `gentests` skips `llgen` for that directory and does not regenerate `out.ll` there. -Use `gentests` when the test still stores LLVM IR in `out.ll`. +Use `gentests` only when an intentional change requires a repository-wide refresh of legacy `out.ll` or `expect.txt`. For one `out.ll` case, use `go run ./chore/llgen path/to/case` instead. ### `litgen` diff --git a/dev/test_embed.sh b/dev/test_embed.sh new file mode 100755 index 0000000000..bd01b7d937 --- /dev/null +++ b/dev/test_embed.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +if [[ $# -ne 0 ]]; then + if [[ $# -eq 1 && ("$1" == "-h" || "$1" == "--help") ]]; then + echo "usage: dev/test_embed.sh" + exit 0 + fi + echo "usage: dev/test_embed.sh" >&2 + exit 2 +fi + +case "$(uname -s)" in + Darwin | Linux) ;; + *) + echo "error: dev/test_embed.sh supports macOS and Linux; use WSL2 on Windows" >&2 + exit 2 + ;; +esac + +if [[ "$(uname -s)" == "Darwin" ]]; then + cache_root="${HOME}/Library/Caches/llgo" +else + cache_root="${XDG_CACHE_HOME:-$HOME/.cache}/llgo" +fi +qemu_installer="$repo_root/.github/workflows/install-esp-qemu.sh" +qemu_cache_key="$(cksum "$qemu_installer" | awk '{print $1}')" +qemu_dir="$cache_root/esp-qemu/$(uname -m)-$qemu_cache_key" +if [[ ! -x "$qemu_dir/bin/qemu-system-riscv32" || ! -x "$qemu_dir/bin/qemu-system-xtensa" ]]; then + "$qemu_installer" "$qemu_dir" +fi +export PATH="$qemu_dir/bin:$PATH" + +export LLGO_CALLER_PWD="$repo_root" +# shellcheck source=dev/_llgo_setup.sh +source "$repo_root/dev/_llgo_setup.sh" +_llgo_ensure_llgo_cli +llgo_bin_dir="$(dirname "$LLGO_BIN")" +export PATH="$llgo_bin_dir:$PATH" + +bash "$repo_root/_demo/embed/test-esp-serial-startup.sh" diff --git a/dev/test_wasm.sh b/dev/test_wasm.sh new file mode 100755 index 0000000000..28ac00ad22 --- /dev/null +++ b/dev/test_wasm.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +if [[ $# -ne 0 ]]; then + if [[ $# -eq 1 && ("$1" == "-h" || "$1" == "--help") ]]; then + echo "usage: dev/test_wasm.sh" + exit 0 + fi + echo "usage: dev/test_wasm.sh" >&2 + exit 2 +fi + +case "$(uname -s)" in + Darwin | Linux) ;; + *) + echo "error: dev/test_wasm.sh supports macOS and Linux; use WSL2 on Windows" >&2 + exit 2 + ;; +esac + +if [[ "$(uname -s)" == "Darwin" ]]; then + iwasm_bin="${HOME}/Library/Caches/llgo/bin/iwasm" +else + iwasm_bin="${XDG_CACHE_HOME:-$HOME/.cache}/llgo/bin/iwasm" +fi +if [[ ! -x "$iwasm_bin" ]]; then + "$repo_root/dev/build_iwasm.sh" +fi +if [[ ! -x "$iwasm_bin" ]]; then + echo "error: iwasm was not installed at $iwasm_bin" >&2 + exit 1 +fi + +tmp_dir="$(mktemp -d)" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT + +( + cd "$repo_root/_demo/c" + "$repo_root/dev/llgo_wasm.sh" build -o "$tmp_dir/hello" -tags=nogc ./helloc +) + +wasm_file="$tmp_dir/hello.wasm" +if [[ ! -f "$wasm_file" && -f "$tmp_dir/hello" ]]; then + wasm_file="$tmp_dir/hello" +fi +if [[ ! -f "$wasm_file" ]]; then + echo "error: wasm output not found under $tmp_dir" >&2 + exit 1 +fi + +"$iwasm_bin" --stack-size=819200000 --heap-size=800000000 "$wasm_file" From 2031532b3b281dd3bca7e392ba7f76e52b358530 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 11:12:22 +0800 Subject: [PATCH 5/8] docs: clarify embedded host dependencies --- dev/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/README.md b/dev/README.md index 34650205b5..c82b4f632d 100644 --- a/dev/README.md +++ b/dev/README.md @@ -114,7 +114,7 @@ The script builds the pinned WAMR runner through `dev/build_iwasm.sh` when it is ### Embedded -After installing SDL2 and libslirp as shown in [the CI setup action](../.github/actions/setup-embed-deps/action.yml), run: +After installing SDL2 and, on Linux, libslirp as shown in [the CI setup action](../.github/actions/setup-embed-deps/action.yml), run: ```bash ./dev/test_embed.sh From 3a155c5816f727ac4d7c593452dbb3b81432c730 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 11:33:13 +0800 Subject: [PATCH 6/8] docs: streamline contributor guidance --- CLAUDE.md | 137 ++++++++++++++++-------------------------------------- 1 file changed, 39 insertions(+), 98 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 925a45122e..8cbc983032 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,27 +1,23 @@ -# LLGo Contributor and AI Assistant Guide +# LLGo Contributor Guide -This document provides essential information for contributors and AI assistants fixing bugs or implementing features in the LLGo project. - -## About LLGo - -LLGo is a Go compiler based on LLVM designed to better integrate Go with the C ecosystem, including Python and JavaScript. It's a subproject of the XGo project that aims to expand the boundaries of Go/XGo for game development, AI and data science, WebAssembly, and embedded development. +LLGo is an LLVM-based Go compiler with C, Python, JavaScript, WebAssembly, and embedded integrations. This guide covers repository-specific contribution rules; see the [README](README.md) for installation and usage. ## Project Structure -- `cmd/llgo` - Main llgo compiler command (usage similar to `go` command) -- `cl/` - Core compiler logic that converts Go packages to LLVM IR -- `ssa/` - LLVM IR file generation using Go SSA semantics -- `internal/build/` - Build process orchestration +- `cmd/llgo` - Main compiler command +- `cl/` - Go package to LLVM IR compilation +- `ssa/` - LLVM IR generation with Go SSA semantics +- `internal/build/` - Build orchestration - `runtime/` - LLGo runtime library - `chore/` - Development tools (llgen, llpyg, ssadump, etc.) -- `_demo/` - Example programs demonstrating C/C++ interop (`c/hello`, `c/qsort`) and Python integration (`py/callpy`, `py/numpy`) -- `_cmptest/` - Comparison tests to verify the same program gets the same output with Go and LLGo +- `_demo/` - C/C++, Python, and other integration examples +- `_cmptest/` - Go/LLGo output comparison tests ## Development Environment For detailed dependency requirements and installation instructions, see the [Dependencies](README.md#dependencies) and [How to install](README.md#how-to-install) sections in the README. -CI uses LLVM 19 and pins exact Go patch releases; check [`.github/workflows/llgo.yml`](.github/workflows/llgo.yml) and [`.github/workflows/goroot.yml`](.github/workflows/goroot.yml) instead of guessing versions. Native development is supported on macOS and Linux. Native Windows support is still TODO; use WSL2 or Linux containers on Windows. +CI uses LLVM 19 and pinned Go patch releases; check [`.github/workflows/llgo.yml`](.github/workflows/llgo.yml) and [`.github/workflows/goroot.yml`](.github/workflows/goroot.yml) for exact versions. Native development supports macOS and Linux; use WSL2 or Linux containers on Windows. ## Repository and GitHub Safety @@ -33,55 +29,32 @@ CI uses LLVM 19 and pins exact Go patch releases; check [`.github/workflows/llgo ## Testing & Validation -The following commands and workflows are essential when fixing bugs or implementing features in the LLGo project: +Behavior changes require focused regression tests; documentation-only and mechanical changes do not need artificial tests. Start with the affected package, then broaden validation: -### Run all tests ```bash +go test ./path/to/package go test ./... ``` -**Note:** Some tests may fail if optional dependencies (like Python) are not properly configured. The test suite includes comprehensive tests for: -- Compiler functionality -- SSA generation -- C interop -- Python integration (requires Python development headers) +The nested `runtime` Go module is not covered by root-level `go test`, `go build`, or `go vet`; run the corresponding command there when it is affected, for example `(cd runtime && go test ./...)`. -The root command does not enter the nested `runtime` Go module. Test it separately when runtime code changes: - -```bash -(cd runtime && go test ./...) -``` +Install the [documented dependencies](README.md#dependencies), including development libraries for Python and other integrations. If one is unavailable, report the exact omitted tests and reason; omission is not a pass. -Prefer the development wrapper for LLGo execution tests; it builds the current checkout and sets `LLGO_ROOT`: +Prefer the development wrapper for LLGo execution tests; it builds the current checkout and selects its runtime tree: ```bash ./dev/llgo.sh test ./path/to/package ``` -After focused tests pass, `./dev/local_ci.sh` runs the main local build, test, LLGo, demo, target-build, and cache checks when the optional dependencies are available. See [`dev/README.md`](dev/README.md) for the maintained commands. +After focused tests pass, `./dev/local_ci.sh` runs the main local checks when dependencies are available. See [`dev/README.md`](dev/README.md) for details. ### Coverage -- The Codecov patch check must pass; new deterministic logic and error paths should normally be fully covered. +- The Codecov patch check must pass; new deterministic logic and error paths should normally be covered. - From the module containing the target package, check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. -- Coverage from Linux and macOS is combined because each has platform-specific paths. Validate host-specific changes on the matching host when possible. +- Linux and macOS coverage is combined; validate host-specific changes on the matching host when possible. - [`.github/codecov.yml`](.github/codecov.yml) lists paths excluded from coverage. Add an exclusion only for generated, tooling, fixture, or otherwise non-meaningful code; never exclude production logic merely to make a PR pass, and explain every ignore change in the PR. -### Write and run tests for your changes - -When adding new functionality or fixing bugs, create appropriate test cases: - -```bash -# Add your test to the relevant package's *_test.go file -# Then run tests for that package -go test ./path/to/package - -# Or run all tests -go test ./... -``` - -**Important:** The `LLGO_ROOT` environment variable must be set to the repository root when running llgo commands during development. - ### Update IR test expectations When `ssa/` or `cl/` changes generated IR, refresh only the affected expectations and review every generated diff: @@ -95,88 +68,56 @@ Do not regenerate unrelated output. The legacy batch tooling, supported scopes, ### Compatibility and target validation -- Go compatibility covers source and observable behavior, not the gc compiler's internal ABI. Run standard-library tests with both `go test ./test/std/...` and `./dev/llgo.sh test ./test/std/...`. +- Go compatibility covers source and observable behavior, not gc's internal ABI. Run standard-library tests with both `go test ./test/std/...` and `./dev/llgo.sh test ./test/std/...`. - Run official Go cases with `bash ./dev/test_goroot.sh -- -directive-mode ci`; see [`test/goroot/README.md`](test/goroot/README.md) for filtering, multiple toolchains, full coverage, and sharding. - Run native tests on the matching host. Use `dev/docker.sh` for Linux amd64/arm64 validation, `dev/test_wasm.sh` for Wasm, and `dev/test_embed.sh` for embedded build plus emulator smoke. -- Cross-compilation alone is not execution validation. Do not weaken or reclassify failures to make a change pass, and state any target that could not be run. +- Cross-compilation is not execution validation. Do not weaken failures to make a change pass, and state any target that could not be run. +- Changes to runtime ABI, archive/link metadata, target selection, or generated IR need focused multi-target tests. Use `// LITTEST` checks where IR shape matters and describe compatibility implications in the pull request. The host matrix, CI coverage, dependencies, and target-specific follow-up commands are in [`dev/README.md`](dev/README.md#platform-and-target-validation). -## Code Quality +### Performance, size, and validation record -Before submitting any code updates, you must run the following formatting and validation commands: +- For compiler, runtime, linker, ABI, or hot-path changes, run focused benchmarks and inspect the paired Linux/macOS results. Repeat material differences because small changes may be runner noise. See [`benchmark/baseline/README.md`](benchmark/baseline/README.md). +- For changes that may affect binary layout or size, use `llgo build -size` as described in [`doc/size-report.md`](doc/size-report.md). +- In the pull request, record commands and targets, distinguish execution from build-only checks, and identify gaps. Required Linux/macOS checks must pass; a `continue-on-error` lane is not authoritative. + +## Code Quality ### Format code + ```bash gofmt -w path/to/changed.go ``` **Important:** Format every changed Go file before committing, but do not rewrite unrelated files in a shared or dirty worktree. -### Run static analysis -```bash -go vet ./... -``` +For changed shell scripts, run `bash -n path/to/changed.sh` and `shellcheck path/to/changed.sh` when ShellCheck is available. -**Note:** Currently reports some issues related to lock passing by value in `ssa/type_cvt.go` and a possible unsafe.Pointer misuse in `cl/builtin_test.go`. These are known issues. +### Run static analysis +Run `go vet ./path/to/package` for affected packages. Repository-wide vet currently reports lock-copy diagnostics in `ssa/type_cvt.go` and possible `unsafe.Pointer` misuse in `cl/builtin_test.go`; do not claim a clean run, suppress new diagnostics, or silently expand this baseline. ## Common Development Tasks -### Build the entire project -```bash -go build -v ./... -``` - -### Build llgo command specifically -```bash -go build -o llgo ./cmd/llgo -``` - -### Check llgo version -```bash -llgo version -``` - -### Install llgo for system-wide use -```bash -./install.sh -``` - -### Build development tools -```bash -go install -v ./cmd/... -go install -v ./chore/... -``` - -## Key Modules for Understanding - -- `ssa` - Generates LLVM IR using Go SSA semantics -- `cl` - Core compiler converting Go to LLVM IR -- `internal/build` - Orchestrates the compilation process +Use `./dev/llgo.sh version` to build the current checkout with the development configuration and check the resulting command. Installation and tool-building commands are maintained in the [README](README.md#how-to-install). ## Debugging ### Disable Garbage Collection -For testing purposes, you can disable GC: + +The `nogc` build tag is a targeted diagnostic mode that changes runtime semantics; it does not replace validation with the default GC configuration: + ```bash -LLGO_ROOT=/path/to/llgo llgo run -tags nogc . +./dev/llgo.sh run -tags nogc . ``` -## LLGO_ROOT Environment Variable +See [Garbage Collection](README.md#garbage-collection-gc) and [`doc/defer-tls-gc.md`](doc/defer-tls-gc.md) for the supported modes and runtime design. -**CRITICAL:** Always set `LLGO_ROOT` to the repository root when running llgo during development: +### `LLGO_ROOT` -```bash -export LLGO_ROOT=/path/to/llgo -# or -LLGO_ROOT=/path/to/llgo llgo run . -``` +Do not set `LLGO_ROOT` unconditionally. Development wrappers derive it for the current checkout, and an installed `llgo` does not necessarily require it. Set it explicitly only to select a non-standard source/runtime tree. ## Important Notes -1. **Testing Requirement:** All bug fixes and features MUST include tests -2. **Demo Directory:** Examples in `_demo` are prefixed with `_` to prevent standard `go` command from trying to compile them -3. **Defer in Loops:** LLGo now supports `defer` within loops, matching Go's semantics of executing defers in LIFO order for every iteration. Be mindful of loop-heavy defer usage as it allocates per iteration. -4. **C Ecosystem Integration:** LLGo uses `go:linkname` directive to link external symbols through ABI -5. **Python Integration:** Third-party Python libraries require separate installation of library files +Examples live under `_demo/`, whose underscore keeps ordinary `go` package discovery from including them. C and C++ integration uses LLGo directives and target ABIs, including `go:linkname` where appropriate; follow [`doc/How-to-support-a-C&C++-Library.md`](doc/How-to-support-a-C&C++-Library.md) instead of assuming every binding uses the same mechanism. From 9119dafca29ea9671b3d6a51efe8918115a09999 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 12:14:23 +0800 Subject: [PATCH 7/8] docs: make litgen the sole IR check workflow --- CLAUDE.md | 7 +++---- README.md | 2 -- dev/README.md | 29 ++++------------------------- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8cbc983032..1e15d29968 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ LLGo is an LLVM-based Go compiler with C, Python, JavaScript, WebAssembly, and e - `ssa/` - LLVM IR generation with Go SSA semantics - `internal/build/` - Build orchestration - `runtime/` - LLGo runtime library -- `chore/` - Development tools (llgen, llpyg, ssadump, etc.) +- `chore/` - Development tools (litgen, llpyg, ssadump, etc.) - `_demo/` - C/C++, Python, and other integration examples - `_cmptest/` - Go/LLGo output comparison tests @@ -60,11 +60,10 @@ After focused tests pass, `./dev/local_ci.sh` runs the main local checks when de When `ssa/` or `cl/` changes generated IR, refresh only the affected expectations and review every generated diff: ```bash -go run ./chore/litgen path/to/LITTEST/in.go # default -go run ./chore/llgen path/to/legacy/case # remaining out.ll cases only +go run ./chore/litgen path/to/LITTEST/in.go ``` -Do not regenerate unrelated output. The legacy batch tooling, supported scopes, and marker format are documented in [`dev/README.md`](dev/README.md#6-refresh-test-goldens). +Do not regenerate unrelated output. Supported scopes and the marker format are documented in [`dev/README.md`](dev/README.md#6-refresh-ir-checks). ### Compatibility and target validation diff --git a/README.md b/README.md index a8185aec21..a40367c836 100644 --- a/README.md +++ b/README.md @@ -422,8 +422,6 @@ cd llgo * [pydump](_xtool/pydump): It's the first program compiled by `llgo` (NOT `go`) in a production environment. It outputs symbol information (functions, variables, and constants) from a Python library in JSON format, preparing for the generation of corresponding packages in `llgo`. * [pysigfetch](https://github.com/goplus/hdq/tree/main/chore/pysigfetch): It generates symbol information by extracting information from Python's documentation site. This tool is not part of the `llgo` project, but we depend on it. * [llpyg](chore/llpyg): It is used to automatically convert Python libraries into Go packages that `llgo` can import. It depends on `pydump` and `pysigfetch` to accomplish the task. -* [llgen](chore/llgen): It is used to compile Go packages into LLVM IR files (*.ll). -* [gentests](chore/gentests): It refreshes the built-in golden test data under `cl/_test*`, including `out.ll` and `expect.txt`. Directories that use source-embedded `// LITTEST` checks are skipped for `out.ll` regeneration. * [litgen](chore/litgen): It generates and refreshes source-embedded `// LITTEST` FileCheck directives from the current LLVM IR for marked Go source files. * [ssadump](chore/ssadump): It is a Go SSA builder and interpreter. diff --git a/dev/README.md b/dev/README.md index c82b4f632d..0d9e459148 100644 --- a/dev/README.md +++ b/dev/README.md @@ -122,30 +122,9 @@ After installing SDL2 and, on Linux, libslirp as shown in [the CI setup action]( The script caches the pinned ESP QEMU binaries outside the worktree, then builds and runs the ESP32/ESP32-C3 serial smoke tests. Target-table changes should also run `(cd _demo/embed/targetsbuild && bash build.sh empty)`. Startup/linker changes should additionally run `_demo/embed/test_esp32c3_startup.sh` with `esptool==5.1.0`. If a target has no emulator, report build-only validation explicitly. -## 6) Refresh test goldens +## 6) Refresh IR checks -Use source-embedded `// LITTEST` checks and `litgen` for new and migrated IR tests. The remaining `out.ll` cases use `llgen`; `gentests` exists only for intentional legacy batch maintenance. - -- `litgen` is the default for source-embedded FileCheck directives. -- `llgen` refreshes an individual legacy `out.ll` case. -- `gentests` batch-refreshes legacy `out.ll` and `expect.txt`; do not use it for routine focused changes. - -### `gentests` (legacy batch only) - -Run: - -```bash -go run ./chore/gentests -``` - -Behavior: - -- Refreshes `out.ll` for the built-in test suites under `cl/_testlibc`, `cl/_testlibgo`, `cl/_testrt`, `cl/_testgo`, `cl/_testpy`, and `cl/_testdata`. -- Refreshes `expect.txt` for the same directories using the existing runtime execution flow. -- Preserves the existing skip convention where `out.ll` or `expect.txt` containing only `;` means "do not refresh". -- New behavior: if a test case directory contains a non-test Go source file whose first line is exactly `// LITTEST`, `gentests` skips `llgen` for that directory and does not regenerate `out.ll` there. - -Use `gentests` only when an intentional change requires a repository-wide refresh of legacy `out.ll` or `expect.txt`. For one `out.ll` case, use `go run ./chore/llgen path/to/case` instead. +Use source-embedded `// LITTEST` FileCheck directives and `litgen` for IR tests. Refresh only the affected files and review every generated change. ### `litgen` @@ -168,9 +147,9 @@ Behavior: - If the path is a `.go` file, it refreshes only that file. The file must start with `// LITTEST`. - If the path is a directory, it walks that directory recursively, finds marked source files, and refreshes each marked test in place. - Rewrites embedded `CHECK-LABEL`, `CHECK-NEXT`, `CHECK-EMPTY`, and referenced constant `CHECK-LINE` directives from the current generated IR. -- Does not update `expect.txt` and does not write `out.ll`. +- Does not update runtime-output expectations in `expect.txt`. -Use `litgen` when the test case stores its IR expectations directly in the Go source instead of `out.ll`. +Use `litgen` when a test case needs LLVM IR expectations. ### Marker convention From c370aebee583ef36096a6e5fe7078b475e0a93c8 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 4 Aug 2026 17:28:08 +0800 Subject: [PATCH 8/8] docs: split contributor and agent guidance --- CLAUDE.md | 131 +++++++----------------------------------------- CONTRIBUTING.md | 121 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 3 files changed, 142 insertions(+), 112 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CLAUDE.md b/CLAUDE.md index 1e15d29968..fc63934632 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,122 +1,29 @@ -# LLGo Contributor Guide +# LLGo Agent Guide -LLGo is an LLVM-based Go compiler with C, Python, JavaScript, WebAssembly, and embedded integrations. This guide covers repository-specific contribution rules; see the [README](README.md) for installation and usage. +Automated contributors must read and follow the shared [contribution guide](CONTRIBUTING.md). It defines the development environment, testing expectations, platform validation, code quality rules, and pull request record required for every contributor. -## Project Structure +The rules below are additional safeguards for AI agents and other repository automation. -- `cmd/llgo` - Main compiler command -- `cl/` - Go package to LLVM IR compilation -- `ssa/` - LLVM IR generation with Go SSA semantics -- `internal/build/` - Build orchestration -- `runtime/` - LLGo runtime library -- `chore/` - Development tools (litgen, llpyg, ssadump, etc.) -- `_demo/` - C/C++, Python, and other integration examples -- `_cmptest/` - Go/LLGo output comparison tests +## Scope and working tree safety -## Development Environment +- Keep changes within the requested scope and preserve unrelated edits, untracked files, and active worktrees. +- Inspect the complete diff against upstream before submission. Do not overwrite or discard existing work unless explicitly authorized. +- Use focused edits and tests first. Do not rewrite unrelated files, regenerate unrelated fixtures, or broaden a change merely to make validation pass. +- Diagnose baseline failures instead of hiding them with skips, exclusions, weakened checks, or undocumented environment changes. -For detailed dependency requirements and installation instructions, see the [Dependencies](README.md#dependencies) and [How to install](README.md#how-to-install) sections in the README. - -CI uses LLVM 19 and pinned Go patch releases; check [`.github/workflows/llgo.yml`](.github/workflows/llgo.yml) and [`.github/workflows/goroot.yml`](.github/workflows/goroot.yml) for exact versions. Native development supports macOS and Linux; use WSL2 or Linux containers on Windows. - -## Repository and GitHub Safety +## Repository and GitHub safety - Treat `xgo-dev/*` as upstream. Do not push branches or tags directly to an `xgo-dev` repository, and do not merge its pull requests. -- Push code to your fork, then create or update a pull request against `xgo-dev/llgo:main`. Bug reports and proposals may be submitted as upstream issues. -- Do not publish upstream releases or change upstream repository settings. Inspect remotes before any write operation when ownership is unclear. -- Prefer `gh issue view`, `gh pr view`, and `gh pr checks` for GitHub state. Use `gh api` for review threads, inline comments, check-run details, or fields not exposed by the higher-level commands; avoid scraping the website. -- Keep changes scoped, preserve unrelated worktree edits, and review the complete diff against upstream before submission. Diagnose baseline failures instead of hiding them with skips, exclusions, or weakened checks. - -## Testing & Validation - -Behavior changes require focused regression tests; documentation-only and mechanical changes do not need artificial tests. Start with the affected package, then broaden validation: - -```bash -go test ./path/to/package -go test ./... -``` - -The nested `runtime` Go module is not covered by root-level `go test`, `go build`, or `go vet`; run the corresponding command there when it is affected, for example `(cd runtime && go test ./...)`. - -Install the [documented dependencies](README.md#dependencies), including development libraries for Python and other integrations. If one is unavailable, report the exact omitted tests and reason; omission is not a pass. - -Prefer the development wrapper for LLGo execution tests; it builds the current checkout and selects its runtime tree: - -```bash -./dev/llgo.sh test ./path/to/package -``` - -After focused tests pass, `./dev/local_ci.sh` runs the main local checks when dependencies are available. See [`dev/README.md`](dev/README.md) for details. - -### Coverage - -- The Codecov patch check must pass; new deterministic logic and error paths should normally be covered. -- From the module containing the target package, check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. -- Linux and macOS coverage is combined; validate host-specific changes on the matching host when possible. -- [`.github/codecov.yml`](.github/codecov.yml) lists paths excluded from coverage. Add an exclusion only for generated, tooling, fixture, or otherwise non-meaningful code; never exclude production logic merely to make a PR pass, and explain every ignore change in the PR. - -### Update IR test expectations - -When `ssa/` or `cl/` changes generated IR, refresh only the affected expectations and review every generated diff: - -```bash -go run ./chore/litgen path/to/LITTEST/in.go -``` - -Do not regenerate unrelated output. Supported scopes and the marker format are documented in [`dev/README.md`](dev/README.md#6-refresh-ir-checks). - -### Compatibility and target validation - -- Go compatibility covers source and observable behavior, not gc's internal ABI. Run standard-library tests with both `go test ./test/std/...` and `./dev/llgo.sh test ./test/std/...`. -- Run official Go cases with `bash ./dev/test_goroot.sh -- -directive-mode ci`; see [`test/goroot/README.md`](test/goroot/README.md) for filtering, multiple toolchains, full coverage, and sharding. -- Run native tests on the matching host. Use `dev/docker.sh` for Linux amd64/arm64 validation, `dev/test_wasm.sh` for Wasm, and `dev/test_embed.sh` for embedded build plus emulator smoke. -- Cross-compilation is not execution validation. Do not weaken failures to make a change pass, and state any target that could not be run. -- Changes to runtime ABI, archive/link metadata, target selection, or generated IR need focused multi-target tests. Use `// LITTEST` checks where IR shape matters and describe compatibility implications in the pull request. - -The host matrix, CI coverage, dependencies, and target-specific follow-up commands are in [`dev/README.md`](dev/README.md#platform-and-target-validation). - -### Performance, size, and validation record - -- For compiler, runtime, linker, ABI, or hot-path changes, run focused benchmarks and inspect the paired Linux/macOS results. Repeat material differences because small changes may be runner noise. See [`benchmark/baseline/README.md`](benchmark/baseline/README.md). -- For changes that may affect binary layout or size, use `llgo build -size` as described in [`doc/size-report.md`](doc/size-report.md). -- In the pull request, record commands and targets, distinguish execution from build-only checks, and identify gaps. Required Linux/macOS checks must pass; a `continue-on-error` lane is not authoritative. - -## Code Quality - -### Format code - -```bash -gofmt -w path/to/changed.go -``` - -**Important:** Format every changed Go file before committing, but do not rewrite unrelated files in a shared or dirty worktree. - -For changed shell scripts, run `bash -n path/to/changed.sh` and `shellcheck path/to/changed.sh` when ShellCheck is available. - -### Run static analysis - -Run `go vet ./path/to/package` for affected packages. Repository-wide vet currently reports lock-copy diagnostics in `ssa/type_cvt.go` and possible `unsafe.Pointer` misuse in `cl/builtin_test.go`; do not claim a clean run, suppress new diagnostics, or silently expand this baseline. - -## Common Development Tasks - -Use `./dev/llgo.sh version` to build the current checkout with the development configuration and check the resulting command. Installation and tool-building commands are maintained in the [README](README.md#how-to-install). - -## Debugging - -### Disable Garbage Collection - -The `nogc` build tag is a targeted diagnostic mode that changes runtime semantics; it does not replace validation with the default GC configuration: - -```bash -./dev/llgo.sh run -tags nogc . -``` - -See [Garbage Collection](README.md#garbage-collection-gc) and [`doc/defer-tls-gc.md`](doc/defer-tls-gc.md) for the supported modes and runtime design. - -### `LLGO_ROOT` +- Push code to the contributor's fork, then create or update a pull request against `xgo-dev/llgo:main`. Upstream issues may be created when requested. +- Do not publish upstream releases or change upstream repository settings. Inspect remotes and exact refs before any write operation when ownership is unclear. +- Prefer `gh issue view`, `gh pr view`, and `gh pr checks` for GitHub state. Use `gh api` for review threads, inline comments, check-run details, or fields not exposed by higher-level commands; do not scrape the website. +- Use explicit force-with-lease protection when a requested rebase requires rewriting a fork branch. Stop if the remote head changed unexpectedly. -Do not set `LLGO_ROOT` unconditionally. Development wrappers derive it for the current checkout, and an installed `llgo` does not necessarily require it. Set it explicitly only to select a non-standard source/runtime tree. +## Validation and reporting -## Important Notes +- Follow [CONTRIBUTING.md](CONTRIBUTING.md#testing-and-validation) for the affected package, nested runtime module, GOROOT cases, and target-specific validation. +- Report the exact commands and platforms exercised. Distinguish execution from build-only checks and state every omitted test with its reason; omission is not a pass. +- Do not claim repository-wide success from a focused test. When a required check cannot run locally, leave it to CI and say so explicitly. +- For generated IR, use the repository's `// LITTEST` and `chore/litgen` workflow described in the contribution guide; do not hand-edit or bulk-regenerate unrelated expectations. -Examples live under `_demo/`, whose underscore keeps ordinary `go` package discovery from including them. C and C++ integration uses LLGo directives and target ABIs, including `go:linkname` where appropriate; follow [`doc/How-to-support-a-C&C++-Library.md`](doc/How-to-support-a-C&C++-Library.md) instead of assuming every binding uses the same mechanism. +`AGENTS.md` links to this file so supported agents receive the same automation-specific rules. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..fa6476d56b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,121 @@ +# Contributing to LLGo + +LLGo is an LLVM-based Go compiler with C, Python, JavaScript, WebAssembly, and embedded integrations. This guide covers the repository-specific workflow for code contributors. See the [README](README.md) for installation and usage. + +## Contribution workflow + +- Fork the repository, create a focused branch, and open a pull request against `xgo-dev/llgo:main`. +- Keep changes scoped and avoid rewriting unrelated files. Diagnose baseline failures instead of hiding them with skips, exclusions, or weakened checks. +- Describe the behavior change, compatibility implications, tests run, platforms exercised, and any validation gaps in the pull request. +- Use an issue to discuss substantial proposals or behavior changes before investing in a large implementation. + +## Project structure + +- `cmd/llgo` - Main compiler command +- `cl/` - Go package to LLVM IR compilation +- `ssa/` - LLVM IR generation with Go SSA semantics +- `internal/build/` - Build orchestration +- `runtime/` - LLGo runtime library +- `chore/` - Development tools (litgen, llpyg, ssadump, etc.) +- `_demo/` - C/C++, Python, and other integration examples +- `_cmptest/` - Go/LLGo output comparison tests + +## Development environment + +For detailed dependency requirements and installation instructions, see the [Dependencies](README.md#dependencies) and [How to install](README.md#how-to-install) sections in the README. + +CI uses LLVM 19 and pinned Go patch releases; check [`.github/workflows/llgo.yml`](.github/workflows/llgo.yml) and [`.github/workflows/goroot.yml`](.github/workflows/goroot.yml) for exact versions. Native development supports macOS and Linux; use WSL2 or Linux containers on Windows. + +## Testing and validation + +Behavior changes require focused regression tests; documentation-only and mechanical changes do not need artificial tests. Start with the affected package, then broaden validation: + +```bash +go test ./path/to/package +go test ./... +``` + +The nested `runtime` Go module is not covered by root-level `go test`, `go build`, or `go vet`; run the corresponding command there when it is affected, for example `(cd runtime && go test ./...)`. + +Install the [documented dependencies](README.md#dependencies), including development libraries for Python and other integrations. If one is unavailable, report the exact omitted tests and reason; omission is not a pass. + +Prefer the development wrapper for LLGo execution tests; it builds the current checkout and selects its runtime tree: + +```bash +./dev/llgo.sh test ./path/to/package +``` + +After focused tests pass, `./dev/local_ci.sh` runs the main local checks when dependencies are available. See [`dev/README.md`](dev/README.md) for details. + +### Coverage + +- The Codecov patch check must pass; new deterministic logic and error paths should normally be covered. +- From the module containing the target package, check focused coverage with `go test -coverprofile=coverage.out ./path/to/package` and `go tool cover -func=coverage.out`. +- Linux and macOS coverage is combined; validate host-specific changes on the matching host when possible. +- [`.github/codecov.yml`](.github/codecov.yml) lists paths excluded from coverage. Add an exclusion only for generated, tooling, fixture, or otherwise non-meaningful code; never exclude production logic merely to make a PR pass, and explain every ignore change in the PR. + +### Update IR test expectations + +When `ssa/` or `cl/` changes generated IR, refresh only the affected expectations and review every generated diff: + +```bash +go run ./chore/litgen path/to/LITTEST/in.go +``` + +Do not regenerate unrelated output. Supported scopes and the marker format are documented in [`dev/README.md`](dev/README.md#6-refresh-ir-checks). + +### Compatibility and target validation + +- Go compatibility covers source and observable behavior, not gc's internal ABI. Run standard-library tests with both `go test ./test/std/...` and `./dev/llgo.sh test ./test/std/...`. +- Run official Go cases with `bash ./dev/test_goroot.sh -- -directive-mode ci`; see [`test/goroot/README.md`](test/goroot/README.md) for filtering, multiple toolchains, full coverage, and sharding. +- Run native tests on the matching host. Use `dev/docker.sh` for Linux amd64/arm64 validation, `dev/test_wasm.sh` for Wasm, and `dev/test_embed.sh` for embedded build plus emulator smoke. +- Cross-compilation is not execution validation. Do not weaken failures to make a change pass, and state any target that could not be run. +- Changes to runtime ABI, archive/link metadata, target selection, or generated IR need focused multi-target tests. Use `// LITTEST` checks where IR shape matters and describe compatibility implications in the pull request. + +The host matrix, CI coverage, dependencies, and target-specific follow-up commands are in [`dev/README.md`](dev/README.md#platform-and-target-validation). + +### Performance, size, and validation record + +- For compiler, runtime, linker, ABI, or hot-path changes, run focused benchmarks and inspect the paired Linux/macOS results. Repeat material differences because small changes may be runner noise. See [`benchmark/baseline/README.md`](benchmark/baseline/README.md). +- For changes that may affect binary layout or size, use `llgo build -size` as described in [`doc/size-report.md`](doc/size-report.md). +- In the pull request, record commands and targets, distinguish execution from build-only checks, and identify gaps. Required Linux/macOS checks must pass; a `continue-on-error` lane is not authoritative. + +## Code quality + +### Format code + +```bash +gofmt -w path/to/changed.go +``` + +Format every changed Go file before committing, but do not rewrite unrelated files. + +For changed shell scripts, run `bash -n path/to/changed.sh` and `shellcheck path/to/changed.sh` when ShellCheck is available. + +### Run static analysis + +Run `go vet ./path/to/package` for affected packages. Repository-wide vet currently reports lock-copy diagnostics in `ssa/type_cvt.go` and possible `unsafe.Pointer` misuse in `cl/builtin_test.go`; do not claim a clean run, suppress new diagnostics, or silently expand this baseline. + +## Common development tasks + +Use `./dev/llgo.sh version` to build the current checkout with the development configuration and check the resulting command. Installation and tool-building commands are maintained in the [README](README.md#how-to-install). + +## Debugging + +### Disable garbage collection + +The `nogc` build tag is a targeted diagnostic mode that changes runtime semantics; it does not replace validation with the default GC configuration: + +```bash +./dev/llgo.sh run -tags nogc . +``` + +See [Garbage Collection](README.md#garbage-collection-gc) and [`doc/defer-tls-gc.md`](doc/defer-tls-gc.md) for the supported modes and runtime design. + +### `LLGO_ROOT` + +Do not set `LLGO_ROOT` unconditionally. Development wrappers derive it for the current checkout, and an installed `llgo` does not necessarily require it. Set it explicitly only to select a non-standard source/runtime tree. + +## Important notes + +Examples live under `_demo/`, whose underscore keeps ordinary `go` package discovery from including them. C and C++ integration uses LLGo directives and target ABIs, including `go:linkname` where appropriate; follow [`doc/How-to-support-a-C&C++-Library.md`](doc/How-to-support-a-C&C++-Library.md) instead of assuming every binding uses the same mechanism. diff --git a/README.md b/README.md index a40367c836..4ada055b81 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ llgo - A Go compiler based on LLVM LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python and JavaScript. It's a subproject of [the XGo project](https://github.com/goplus/gop). +See [CONTRIBUTING.md](CONTRIBUTING.md) for the development, testing, and pull request workflow. + LLGo aims to expand the boundaries of Go/XGo, providing limitless possibilities such as: * Game development