Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 43 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
llgo - A Go compiler based on LLVM
LLGo - A Go compiler based on LLVM
=====

[![Build Status](https://github.com/xgo-dev/llgo/actions/workflows/go.yml/badge.svg)](https://github.com/xgo-dev/llgo/actions/workflows/go.yml)
Expand All @@ -7,7 +7,7 @@ llgo - A Go compiler based on LLVM
[![GoDoc](https://pkg.go.dev/badge/github.com/xgo-dev/llgo.svg)](https://pkg.go.dev/github.com/xgo-dev/llgo)
[![XGo](https://img.shields.io/badge/project-XGo-blue.svg)](https://github.com/goplus/xgo)

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

LLGo aims to expand the boundaries of Go/XGo, providing limitless possibilities such as:

Expand All @@ -23,10 +23,25 @@ How can these be achieved?
LLGo := Go * C ecosystem
```

LLGo is compatible with C ecosystem through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**. C ecosystem includes all languages that are ABI compatible with C (eg. C/C++, Python, JavaScript, Objective-C, Swift, etc).
LLGo is compatible with the C ecosystem through the C **Application Binary Interface (ABI)**, while LLGo is compatible with Go at the **source-code level**. The C ecosystem includes languages that expose C-compatible interfaces (e.g. C/C++, Python, JavaScript, Objective-C, and Swift).


## C/C++ standard libary support
## Project status

LLGo is compatible with Go 1.20+ source code and supports the complete Go 1.26 language syntax. Compatibility is checked against applicable upstream [`GOROOT/test`](test/goroot/README.md) cases using pinned Go 1.24 and Go 1.26 toolchains. Remaining applicable differences are recorded in [`xfail.yaml`](test/goroot/xfail.yaml); gc-specific mechanisms outside LLGo's compatibility goals are documented in [`notapplicable.yaml`](test/goroot/notapplicable.yaml).

LLGo fully supports the Go standard library on supported native platforms; see [Go standard library support](#go-standard-library-support) for validation and target-specific details.
Comment thread
cpunion marked this conversation as resolved.

LLGo uses a different runtime from the standard Go toolchain. Native goroutines map 1:1 to OS threads with fixed native stacks, so direct C calls require no Go-to-C stack or scheduler transition, avoiding the cgo overhead that makes frequent C calls costly in standard Go. The default garbage collector is conservative BDWGC.

| Target | Current coverage |
| --- | --- |
| Native | Linux amd64/arm64 and macOS amd64/arm64 [release artifacts](https://github.com/xgo-dev/llgo/releases); primary CI on Linux amd64 and macOS arm64 |
| WebAssembly | `js/wasm` and `wasip1/wasm` builds; WASI and Emscripten CI coverage |
| Embedded | [`-target`](doc/Embedded_Cmd.md) configurations for supported boards and MCUs, with selected QEMU/emulator smoke tests |


## C/C++ standard library support

You can import a C/C++ standard library in LLGo!

Expand Down Expand Up @@ -60,7 +75,7 @@ func main() {

This is a simple example of calling the C `printf` function to print `Hello world`. Here, `c.Str` is not a function for converting a Go string to a C string, but a built-in instruction supported by `llgo` for generating a C string constant.

The `_demo` directory contains some C standard libary related demos (it start with `_` to prevent the `go` command from compiling it):
The `_demo` directory contains C library demos (it starts with `_` to prevent the `go` command from compiling it):

* [hello](_demo/c/hello/hello.go): call C `printf` to print `Hello world`
* [concat](_demo/c/concat/concat.go): call C `fprintf` with `stderr`
Expand All @@ -76,7 +91,7 @@ llgo run .

## How to support C/C++ and Python

LLGo use `go:linkname` to link an extern symbol througth its ABI:
LLGo uses `go:linkname` to link an external symbol through the C ABI:

<!-- embedme doc/_readme/llgo_call_c/call_c.go#L3-L6 -->

Expand Down Expand Up @@ -123,7 +138,7 @@ func main() {

You can import a Python library in LLGo!

And you can import any Python library into `llgo` through a program called `llpyg` (see [Development tools](#development-tools)). The following libraries have been included in `llgo`:
You can import Python libraries into `llgo` through `llpyg` (see [Development tools](#development-tools)). Available bindings include:

* [py](https://pkg.go.dev/github.com/goplus/lib/py) (abi)
* [py/std](https://pkg.go.dev/github.com/goplus/lib/py/std) (builtins)
Expand All @@ -138,7 +153,7 @@ And you can import any Python library into `llgo` through a program called `llpy
* [py/torch](https://pkg.go.dev/github.com/goplus/lib/py/torch)
* [py/matplotlib](https://pkg.go.dev/github.com/goplus/lib/py/matplotlib)

Note: For third-party libraries (such as pandas and pytorch), you still need to install the library files.
Third-party libraries such as pandas and PyTorch must be installed separately.

Here is an example:

Expand Down Expand Up @@ -220,9 +235,9 @@ llgo run .

## Other frequently used libraries

LLGo can easily import any libraries from the C ecosystem. Currently, this import process is still manual, but in the future, it will be automated similar to Python library imports.
LLGo can easily import libraries from the C ecosystem. C/C++ bindings are maintained manually, but the import process will be automated in the future, as with Python library imports.

The currently supported libraries include:
Available bindings include:

* [c/bdwgc](https://pkg.go.dev/github.com/goplus/lib/c/bdwgc)
* [c/cjson](https://pkg.go.dev/github.com/goplus/lib/c/cjson)
Expand All @@ -241,15 +256,15 @@ The currently supported libraries include:

Here are some examples related to them:

* [llama2-c](_demo/c/llama2-c): inference Llama 2 (It's the first llgo AI example)
* [llama2-c](_demo/c/llama2-c): inference Llama 2 (the first LLGo AI example)
* [mkjson](https://github.com/goplus/lib/tree/main/c/cjson/_demo/mkjson/mkjson.go): create a json object and print it
* [sqlitedemo](https://github.com/goplus/lib/tree/main/c/sqlite/_demo/sqlitedemo/demo.go): a basic sqlite demo
* [tetris](https://github.com/goplus/lib/tree/main/c/raylib/_demo/tetris/tetris.go): a tetris game based on raylib


## Go syntax support

All Go syntax (including `cgo`) is already supported. Here are some examples:
LLGo supports the complete Go 1.26 language syntax and `cgo`. Here are some examples:

* [concat](_demo/c/concat/concat.go): define a variadic function
* [genints](_demo/c/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
Expand All @@ -258,101 +273,41 @@ All Go syntax (including `cgo`) is already supported. Here are some examples:
* [goroutine](_demo/go/goroutine/goroutine.go): goroutine demo


### Defer

LLGo now supports `defer` within loops, matching Go's semantics of executing defers in LIFO order for every iteration. The usual caveat from Go still applies: be mindful of loop-heavy defer usage because it allocates per iteration.


### Garbage Collection (GC)

By default, LLGo implements `gc` based on [bdwgc](https://www.hboehm.info/gc/) (also known as [libgc](https://www.hboehm.info/gc/)).
By default, LLGo implements garbage collection with [BDWGC](https://www.hboehm.info/gc/) (also known as libgc). Bare-metal embedded targets instead use a TinyGo-derived conservative mark-and-sweep collector.

However, you can disable gc by specifying the `nogc` tag. For example:
Garbage collection can be disabled with the `nogc` build tag. For example:

```sh
llgo run -tags nogc .
```


## Go packages support

Here are the Go packages that can be imported correctly:

* [unsafe](https://pkg.go.dev/unsafe)
* [unicode](https://pkg.go.dev/unicode)
* [unicode/utf8](https://pkg.go.dev/unicode/utf8)
* [unicode/utf16](https://pkg.go.dev/unicode/utf16)
* [math](https://pkg.go.dev/math)
* [math/big](https://pkg.go.dev/math/big) (partially)
* [math/bits](https://pkg.go.dev/math/bits)
* [math/cmplx](https://pkg.go.dev/math/cmplx)
* [math/rand](https://pkg.go.dev/math/rand)
* [net/url](https://pkg.go.dev/net/url)
* [errors](https://pkg.go.dev/errors)
* [context](https://pkg.go.dev/context)
* [io](https://pkg.go.dev/io)
* [io/fs](https://pkg.go.dev/io/fs)
* [io/ioutil](https://pkg.go.dev/io/ioutil)
* [log](https://pkg.go.dev/log)
* [flag](https://pkg.go.dev/flag)
* [sort](https://pkg.go.dev/sort)
* [bytes](https://pkg.go.dev/bytes)
* [bufio](https://pkg.go.dev/bufio)
* [strings](https://pkg.go.dev/strings)
* [strconv](https://pkg.go.dev/strconv)
* [path](https://pkg.go.dev/path)
* [path/filepath](https://pkg.go.dev/path/filepath)
* [sync/atomic](https://pkg.go.dev/sync/atomic)
* [sync](https://pkg.go.dev/sync) (partially)
* [syscall](https://pkg.go.dev/syscall) (partially)
* [runtime](https://pkg.go.dev/runtime) (partially)
* [os](https://pkg.go.dev/os) (partially)
* [os/exec](https://pkg.go.dev/os/exec) (partially)
* [fmt](https://pkg.go.dev/fmt) (partially)
* [reflect](https://pkg.go.dev/reflect) (partially)
* [time](https://pkg.go.dev/time) (partially)
* [encoding](https://pkg.go.dev/encoding)
* [encoding/binary](https://pkg.go.dev/encoding/binary)
* [encoding/hex](https://pkg.go.dev/encoding/hex)
* [encoding/base32](https://pkg.go.dev/encoding/base32)
* [encoding/base64](https://pkg.go.dev/encoding/base64)
* [encoding/csv](https://pkg.go.dev/encoding/csv)
* [net/textproto](https://pkg.go.dev/net/textproto)
* [hash](https://pkg.go.dev/hash)
* [hash/adler32](https://pkg.go.dev/hash/adler32)
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
* [hash/crc64](https://pkg.go.dev/hash/crc64)
* [hash/maphash](https://pkg.go.dev/hash/maphash) (partially)
* [crypto](https://pkg.go.dev/crypto)
* [crypto/md5](https://pkg.go.dev/crypto/md5)
* [crypto/sha1](https://pkg.go.dev/crypto/sha1)
* [crypto/sha256](https://pkg.go.dev/crypto/sha256)
* [crypto/sha512](https://pkg.go.dev/crypto/sha512) (partially)
* [crypto/hmac](https://pkg.go.dev/crypto/hmac) (partially)
* [crypto/rand](https://pkg.go.dev/crypto/rand) (partially)
* [crypto/subtle](https://pkg.go.dev/crypto/subtle) (partially)
* [regexp](https://pkg.go.dev/regexp)
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
* [go/token](https://pkg.go.dev/go/token)
* [go/scanner](https://pkg.go.dev/go/scanner)
* [go/parser](https://pkg.go.dev/go/parser)
## Go standard library support

LLGo fully supports the Go standard library on supported native platforms. CI requires compatibility coverage for every public package and exported symbol in the primary Go toolchain, and runs [`test/std`](test/std/README.md) with both supported toolchains.

Other targets may not provide every OS service or implementation-specific runtime behavior.


## Dependencies

- [Go 1.21+](https://go.dev)
- [LLVM 18](https://llvm.org)
- [Clang 18](https://clang.llvm.org)
- [LLD 18](https://lld.llvm.org)
- [Go 1.24+](https://go.dev) (to build LLGo; CI also validates user packages with pinned Go 1.24 and Go 1.26 toolchains)
- [LLVM 19](https://llvm.org)
- [Clang 19](https://clang.llvm.org)
- [LLD 19](https://lld.llvm.org)
- [pkg-config 0.29+](https://gitlab.freedesktop.org/pkg-config/pkg-config)
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
- [libffi](https://sourceware.org/libffi/)
- [libuv](https://libuv.org/)
- [OpenSSL 3.0+](https://www.openssl.org/)
- [zlib 1.2+](https://github.com/madler/zlib)
- [Python 3.12+](https://www.python.org) (optional, for [github.com/goplus/lib/py](https://pkg.go.dev/github.com/goplus/lib/py))

## How to install

Follow these steps to generate the `llgo` command (its usage is the same as the `go` command):
Follow these steps to install the `llgo` command, whose usage is similar to the `go` command:

### on macOS

Expand Down Expand Up @@ -419,7 +374,7 @@ cd llgo

## Development tools

* [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`.
* [pydump](_xtool/pydump): It is the first production program compiled with `llgo` rather than `go`. 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).
Expand Down Expand Up @@ -449,6 +404,6 @@ go install github.com/goplus/hdq/chore/pysigfetch@v0.8.1 # compile pysigfetch

Below are the key modules for understanding the implementation principles of `llgo`:

* [ssa](https://pkg.go.dev/github.com/goplus/llgo/ssa): It generates LLVM IR files (LLVM SSA) using the semantics (interfaces) of Go SSA. Although `LLVM SSA` and `Go SSA` are both IR languages, they work at completely different levels. `LLVM SSA` is closer to machine code, which abstracts different instruction sets. While `Go SSA` is closer to a high-level language. We can think of it as the instruction set of the `Go computer`. `llgo/ssa` is not just limited to the `llgo` compiler. If we view it as the high-level expressive power of `LLVM`, you'll find it very useful. Prior to `llgo/ssa`, you had to operate `LLVM` using machine code semantics. But now, with the advanced SSA form (in the semantics of Go SSA), you can conveniently utilize `LLVM`.
* [ssa](https://pkg.go.dev/github.com/goplus/llgo/ssa): It generates LLVM IR files (LLVM SSA) using the semantics and interfaces of Go SSA. Although `LLVM SSA` and `Go SSA` are both IR languages, they work at completely different levels. `LLVM SSA` is closer to machine code and abstracts over different instruction sets, while `Go SSA` is closer to a high-level language. We can think of it as the instruction set of the `Go computer`. `llgo/ssa` is not limited to the `llgo` compiler. If we view it as providing the high-level expressive power of `LLVM`, it is very useful. Its advanced SSA form lets clients use LLVM without operating directly on machine-code semantics.
* [cl](https://pkg.go.dev/github.com/goplus/llgo/cl): It is the core of the llgo compiler. It converts a Go package into LLVM IR files. It depends on `llgo/ssa`.
* [internal/build](https://pkg.go.dev/github.com/goplus/llgo/internal/build): It strings together the entire compilation process of `llgo`. It depends on `llgo/ssa` and `llgo/cl`.
Loading