2024-04-15 04:24:36 +08:00
llgo - A Go compiler based on LLVM
=====
[](https://github.com/goplus/llgo/actions/workflows/go.yml)
[](https://goreportcard.com/report/github.com/goplus/llgo)
2024-04-22 01:04:38 +08:00
[](https://github.com/goplus/llgo/releases)
2024-04-15 04:24:36 +08:00
[](https://codecov.io/gh/goplus/llgo)
2024-04-25 07:29:45 +08:00
[](https://pkg.go.dev/github.com/goplus/llgo)
[](https://github.com/goplus/gop)
2024-05-16 00:02:10 +08:00
LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a subproject of [the Go+ project ](https://github.com/goplus/gop ).
2024-05-06 12:31:55 +08:00
2024-05-11 05:18:17 +08:00
## C standard libary support
2024-05-12 13:05:15 +08:00
```go
package main
import "github.com/goplus/llgo/c"
func main() {
c.Printf(c.Str("Hello world\n"))
}
```
2024-05-16 00:02:10 +08:00
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):
* [hello ](_demo/hello/hello.go ): call C `printf` to print `Hello world`
* [concat ](_demo/concat/concat.go ): call C `fprintf` with `stderr`
* [qsort ](_demo/qsort/qsort.go ): call C function with a callback (eg. `qsort` )
To run these demos (If you haven't installed `llgo` yet, please refer to [How to install ](#how-to-install )):
```sh
export LLGOROOT=`pwd`
2024-05-16 01:08:21 +08:00
cd <demo-directory> # eg. cd _demo/hello
2024-05-16 00:02:10 +08:00
llgo run .
```
2024-05-12 13:05:15 +08:00
See [github.com/goplus/llgo/c ](https://pkg.go.dev/github.com/goplus/llgo/c ) for more detials.
2024-05-11 05:18:17 +08:00
## Python support
2024-05-16 00:02:10 +08:00
You can import a Python library in LLGo!
2024-05-15 16:04:20 +08:00
2024-05-16 00:02:10 +08:00
And you can import any Python library into `llgo` through a program called `llpyg` . The currently imported libraries include:
2024-05-15 16:04:20 +08:00
* [sys ](https://pkg.go.dev/github.com/goplus/llgo/py/sys )
* [os ](https://pkg.go.dev/github.com/goplus/llgo/py/os )
* [math ](https://pkg.go.dev/github.com/goplus/llgo/py/math )
* [json ](https://pkg.go.dev/github.com/goplus/llgo/py/json )
* [inspect ](https://pkg.go.dev/github.com/goplus/llgo/py/inspect )
* [statistics ](https://pkg.go.dev/github.com/goplus/llgo/py/statistics )
* [numpy ](https://pkg.go.dev/github.com/goplus/llgo/py/numpy )
Here is an example using the Python `math` library:
2024-05-12 23:59:24 +08:00
```go
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/math"
)
func main() {
x := math.Sqrt(py.Float(2))
c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64())
}
```
2024-05-13 01:27:02 +08:00
Here, We call `py.Float(2)` to create a Python number 2, and pass it to Python’ s `math.sqrt` to get `x` . Then use `x.Float64()` to convert x to Go's `float64` type, and print the value through the C `printf` function.
2024-05-15 16:04:20 +08:00
Let's look at a slightly more complex example. For example, we use `numpy` to calculate:
```go
package main
import (
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/py"
"github.com/goplus/llgo/py/numpy"
)
func main() {
a := py.List(
py.List(1.0, 2.0, 3.0),
py.List(4.0, 5.0, 6.0),
py.List(7.0, 8.0, 9.0),
)
b := py.List(
py.List(9.0, 8.0, 7.0),
py.List(6.0, 5.0, 4.0),
py.List(3.0, 2.0, 1.0),
)
x := numpy.Add(a, b)
c.Printf(c.Str("a+b = %s\n"), x.Str().CStr())
}
```
Here we define two 3x3 matrices a and b, add them to get x, and then print the result.
2024-05-16 00:02:10 +08:00
The `_pydemo` directory contains some python related demos:
2024-05-11 05:18:17 +08:00
2024-05-16 00:02:10 +08:00
* [callpy ](_pydemo/callpy/callpy.go ): call Python standard library function `math.sqrt`
* [pi ](_pydemo/pi/pi.go ): print python constants `math.pi`
* [statistics ](_pydemo/statistics/statistics.go ): define a python list and call `statistics.mean` to get the mean
* [matrix ](_pydemo/matrix/matrix.go ): a basic `numpy` demo
2024-05-11 05:18:17 +08:00
2024-05-16 00:02:10 +08:00
To run these demos, you need to set the `LLGO_LIB_PYTHON` environment variable first.
2024-05-11 05:18:17 +08:00
2024-05-16 00:02:10 +08:00
If Python is in the search path for `clang` linking, then `LLGO_LIB_PYTHON` only needs to be set to the name of the Python library. For example:
2024-05-11 05:18:17 +08:00
2024-05-16 00:02:10 +08:00
```sh
export LLGO_LIB_PYTHON=python3.12
```
2024-05-11 05:18:17 +08:00
2024-05-16 00:02:10 +08:00
You can also specify the path to tell `llgo` where the Python library is located:
2024-05-06 12:31:55 +08:00
2024-05-16 00:02:10 +08:00
```sh
export LLGO_LIB_PYTHON=/foo/bar/python3.12
```
2024-05-06 12:31:55 +08:00
2024-05-16 00:02:10 +08:00
For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python library location under macOS. So we should set it like this:
2024-05-06 12:31:55 +08:00
```sh
2024-05-16 00:02:10 +08:00
export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12
2024-05-06 12:31:55 +08:00
```
2024-05-16 00:02:10 +08:00
Note that the file name must be written in a platform-independent format, using `python3.12` instead of `libpython3.12.dylib` .
Then you can run the demos:
2024-05-06 12:31:55 +08:00
```sh
2024-05-16 00:02:10 +08:00
export LLGOROOT=`pwd`
cd <demo-directory> # eg. cd _pydemo/callpy
llgo run .
2024-05-06 12:31:55 +08:00
```
2024-05-16 00:02:10 +08:00
See [github.com/goplus/llgo/py ](https://pkg.go.dev/github.com/goplus/llgo/py ) for more detials.
2024-05-09 07:19:13 +08:00
2024-05-16 00:02:10 +08:00
## Other frequently used libraries
2024-05-09 07:19:13 +08:00
2024-05-16 00:02:10 +08:00
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.
2024-05-06 12:31:55 +08:00
2024-05-16 00:02:10 +08:00
The currently imported libraries include:
* [llama2.c ](https://pkg.go.dev/github.com/goplus/llgo/x/llama2 )
* [cjson ](https://pkg.go.dev/github.com/goplus/llgo/x/cjson )
* [sqlite ](https://pkg.go.dev/github.com/goplus/llgo/x/sqlite )
Here are some examples related to them:
2024-05-06 12:31:55 +08:00
2024-05-07 18:44:51 +08:00
* [llama2-c ](_demo/llama2-c ): inference Llama 2 (It's the first llgo AI example)
2024-05-16 00:02:10 +08:00
* [mkjson ](x/cjson/_demo/mkjson/mkjson.go ): create a json object and print it
2024-05-16 01:08:21 +08:00
* [sqlitedemo ](x/sqlite/_demo/sqlitedemo/demo.go ): a basic sqlite demo
2024-05-11 05:04:02 +08:00
2024-05-12 23:59:24 +08:00
2024-05-16 00:02:10 +08:00
## Go syntax support
2024-05-11 05:04:02 +08:00
2024-05-16 00:02:10 +08:00
The priority of `llgo` feature iteration is:
2024-05-06 12:31:55 +08:00
2024-05-16 00:02:10 +08:00
* Popular C/Python libraries
* Full Go syntax
* Go standard libraries
* Popular Go packages
2024-05-06 12:31:55 +08:00
2024-05-16 00:02:10 +08:00
Common Go syntax is already supported. Except for the following, which needs to be improved:
2024-05-11 05:04:02 +08:00
2024-05-16 00:02:10 +08:00
* interface (Limited support)
* map (Very limited support)
* panic (Limited support)
* recover (Not supported yet)
* defer (Not supported yet)
* gc (Not supported yet)
* chan (Not supported yet)
* goroutine (Not supported yet)
* generics (Not supported yet)
2024-05-11 05:04:02 +08:00
2024-05-16 00:02:10 +08:00
Here are some examples related to Go syntax:
2024-05-11 05:04:02 +08:00
2024-05-16 00:02:10 +08:00
* [concat ](_demo/concat/concat.go ): define a variadic function
* [genints ](_demo/genints/genints.go ): various forms of closure usage (including C function, recv.method and anonymous function)
## How to install
Follow these steps to generate the `llgo` command (its usage is the same as the `go` command):
2024-05-11 05:04:02 +08:00
2024-05-16 00:02:10 +08:00
### on macOS
2024-05-11 05:04:02 +08:00
```sh
2024-05-16 00:02:10 +08:00
brew update # execute if needed
brew install llvm@17
go install -v ./...
2024-05-11 05:04:02 +08:00
```
2024-05-16 00:02:10 +08:00
### on Linux
2024-05-11 05:04:02 +08:00
```sh
2024-05-16 00:02:10 +08:00
echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-17 main' | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update # execute if needed
sudo apt-get install --no-install-recommends llvm-17-dev
go install -v ./...
2024-05-11 05:04:02 +08:00
```
2024-05-16 00:02:10 +08:00
### on Windows
TODO
2024-05-16 06:34:18 +08:00
## Development tools
* [pydump ](chore/_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` .
* [llpyg ](chore/llpyg ): It is used to automatically convert Python libraries into Go packages that `llgo` can import. It depends on `pydump` to accomplish the task.
* [llgen ](chore/llgen ): It is used to compile Go packages into LLVM IR files (*.ll).
* [ssadump ](chore/ssadump ): It is a Go SSA builder and interpreter.
How do I generate these tools?
```sh
go install -v ./... # compile all tools except pydump
cd chore/_xtool
llgo install ./... # compile pydump
```