Skip to content

Latest commit

 

History

History
206 lines (152 loc) · 7.41 KB

CLAUDE.md

File metadata and controls

206 lines (152 loc) · 7.41 KB

LLGo Project AI Assistant Guide

This document provides essential information for AI assistants to help fix bugs and implement 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.

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
  • 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

Development Environment

For detailed dependency requirements and installation instructions, see the Dependencies and How to install sections in the README.

Testing & Validation

The following commands and workflows are essential when fixing bugs or implementing features in the LLGo project:

Run all tests

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)

Write and run tests for your changes

When adding new functionality or fixing bugs, create appropriate test cases:

# 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.

Maintain LLVM IR checks by test intent

Do not refresh every FileCheck assertion after an IR change. First identify the single compiler property a test is intended to protect, then keep the smallest handwritten assertions that prove that property. Runtime output and focused IR checks protect different contracts; avoid only the redundant full IR snapshot.

Treat 100 FileCheck directive lines as a review threshold, not a hard limit. Above that threshold, verify that each handwritten group protects a distinct, named semantic contract. If the test instead needs a long contiguous IR shape, make that region reproducible with litgen.

The repository keeps a curated set of source-embedded autogenerated checks for cases where a broad function or module shape is itself the contract. They remain in the Go source and carry a reproducible UTC_ARGS note:

// LITTEST
// NOTE: Assertions have been autogenerated by chore/litgen UTC_ARGS: --function=run --check-globals=smart

Declare known platform differences with a target matrix and exact FileCheck prefixes instead of regular-expression alternatives. The ordinary marker uses the historical pre-ABI stage; only checks after target ABI lowering need an explicit stage:

// LITTEST darwin/arm64 linux/amd64
// LITTEST: POST-ABI linux/amd64 linux/arm64

The harness cross-compiles IR for every listed target, independent of the host. It also always checks the fixture's current effective target; listed targets are additional coverage and are deduplicated against the current target. FileCheck enables CHECK, the GOARCH prefix, and the exact target prefix (for example CHECK,ARM64,DARWIN-ARM64). Put assertions shared by targets with the same architecture under ARM64, AMD64, and similar architecture prefixes. Fixtures that depend on cgo still require the corresponding target C toolchain and sysroot, so keep them on plain // LITTEST unless CI provides those inputs.

Refresh and verify all opted-in snapshots with:

go run ./chore/litgen -u cl
go run ./chore/litgen -u --check cl

litgen will not replace a handwritten test during update-only operation. When creating an autogenerated test, pass one or more --function expressions; use --all-functions only for a deliberate whole-module contract. See dev/README.md for the complete options and marker conventions.

Code Quality

Before submitting any code updates, you must run the following formatting and validation commands:

Format code

go fmt ./...

Important: Always run go fmt ./... before committing code changes. This ensures consistent code formatting across the project.

Run static analysis

go vet ./...

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.

Documentation checks (README.md)

Any modification to README.md must keep the checks in .github/workflows/doc-link-checker.yml (the doc_verify job) passing. That job runs two tools against README.md:

  • embedme --verify README.md — verifies embedded code blocks. embedme treats the first line of a fenced code block as an embedme <file> reference when it is a single-token //-style comment (for example //llgo:cdecl), and fails if that file does not exist. When a Go example must lead with such a directive, start the block with a real statement (an import, declaration, or a comment that contains spaces, e.g. //go:linkname Name sym) so the first line is not mistaken for a filename.
  • lychee README.md — checks that every link in README.md is reachable. Avoid adding dead or private links.

Verify locally before pushing a README change:

npm install -g embedme   # or: npx embedme ...
embedme --verify README.md

Common Development Tasks

Build the entire project

go build -v ./...

Build llgo command specifically

go build -o llgo ./cmd/llgo

Check llgo version

llgo version

Install llgo for system-wide use

./install.sh

Build development tools

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

Debugging

Disable Garbage Collection

For testing purposes, you can disable GC:

LLGO_ROOT=/path/to/llgo llgo run -tags nogc .

LLGO_ROOT Environment Variable

CRITICAL: Always set LLGO_ROOT to the repository root when running llgo during development:

export LLGO_ROOT=/path/to/llgo
# or
LLGO_ROOT=/path/to/llgo llgo run .

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