github.com/goplus/llgo@v0.8.3/README.md (about) 1 llgo - A Go compiler based on LLVM 2 ===== 3 4 [![Build Status](https://github.com/goplus/llgo/actions/workflows/go.yml/badge.svg)](https://github.com/goplus/llgo/actions/workflows/go.yml) 5 [![Go Report Card](https://goreportcard.com/badge/github.com/goplus/llgo)](https://goreportcard.com/report/github.com/goplus/llgo) 6 [![GitHub release](https://img.shields.io/github/v/tag/goplus/llgo.svg?label=release)](https://github.com/goplus/llgo/releases) 7 [![Coverage Status](https://codecov.io/gh/goplus/llgo/branch/main/graph/badge.svg)](https://codecov.io/gh/goplus/llgo) 8 [![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo) 9 [![Language](https://img.shields.io/badge/language-Go+-blue.svg)](https://github.com/goplus/gop) 10 11 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). 12 13 14 ## C standard libary support 15 16 ```go 17 package main 18 19 import "github.com/goplus/llgo/c" 20 21 func main() { 22 c.Printf(c.Str("Hello world\n")) 23 } 24 ``` 25 26 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. 27 28 The `_demo` directory contains some C standard libary related demos (it start with `_` to prevent the `go` command from compiling it): 29 30 * [hello](_demo/hello/hello.go): call C `printf` to print `Hello world` 31 * [concat](_demo/concat/concat.go): call C `fprintf` with `stderr` 32 * [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. `qsort`) 33 34 To run these demos (If you haven't installed `llgo` yet, please refer to [How to install](#how-to-install)): 35 36 ```sh 37 export LLGOROOT=`pwd` 38 cd <demo-directory> # eg. cd _demo/hello 39 llgo run . 40 ``` 41 42 See [github.com/goplus/llgo/c](https://pkg.go.dev/github.com/goplus/llgo/c) for more detials. 43 44 45 ## Python support 46 47 You can import a Python library in LLGo! 48 49 And you can import any Python library into `llgo` through a program called `llpyg` (see [Development tools](#development-tools)). The currently imported libraries include: 50 51 * [sys](https://pkg.go.dev/github.com/goplus/llgo/py/sys) 52 * [os](https://pkg.go.dev/github.com/goplus/llgo/py/os) 53 * [math](https://pkg.go.dev/github.com/goplus/llgo/py/math) 54 * [json](https://pkg.go.dev/github.com/goplus/llgo/py/json) 55 * [inspect](https://pkg.go.dev/github.com/goplus/llgo/py/inspect) 56 * [statistics](https://pkg.go.dev/github.com/goplus/llgo/py/statistics) 57 * [numpy](https://pkg.go.dev/github.com/goplus/llgo/py/numpy) 58 59 Here is an example using the Python `math` library: 60 61 ```go 62 package main 63 64 import ( 65 "github.com/goplus/llgo/c" 66 "github.com/goplus/llgo/py" 67 "github.com/goplus/llgo/py/math" 68 ) 69 70 func main() { 71 x := math.Sqrt(py.Float(2)) 72 c.Printf(c.Str("sqrt(2) = %f\n"), x.Float64()) 73 } 74 ``` 75 76 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. 77 78 Let's look at a slightly more complex example. For example, we use `numpy` to calculate: 79 80 ```go 81 package main 82 83 import ( 84 "github.com/goplus/llgo/c" 85 "github.com/goplus/llgo/py" 86 "github.com/goplus/llgo/py/numpy" 87 ) 88 89 func main() { 90 a := py.List( 91 py.List(1.0, 2.0, 3.0), 92 py.List(4.0, 5.0, 6.0), 93 py.List(7.0, 8.0, 9.0), 94 ) 95 b := py.List( 96 py.List(9.0, 8.0, 7.0), 97 py.List(6.0, 5.0, 4.0), 98 py.List(3.0, 2.0, 1.0), 99 ) 100 x := numpy.Add(a, b) 101 c.Printf(c.Str("a+b = %s\n"), x.Str().CStr()) 102 } 103 ``` 104 105 Here we define two 3x3 matrices a and b, add them to get x, and then print the result. 106 107 The `_pydemo` directory contains some python related demos: 108 109 * [callpy](_pydemo/callpy/callpy.go): call Python standard library function `math.sqrt` 110 * [pi](_pydemo/pi/pi.go): print python constants `math.pi` 111 * [statistics](_pydemo/statistics/statistics.go): define a python list and call `statistics.mean` to get the mean 112 * [matrix](_pydemo/matrix/matrix.go): a basic `numpy` demo 113 114 To run these demos, you need to set the `LLGO_LIB_PYTHON` environment variable first. 115 116 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: 117 118 ```sh 119 export LLGO_LIB_PYTHON=python3.12 120 ``` 121 122 You can also specify the path to tell `llgo` where the Python library is located: 123 124 ```sh 125 export LLGO_LIB_PYTHON=/foo/bar/python3.12 126 ``` 127 128 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: 129 130 ```sh 131 export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12 132 ``` 133 134 Note that the file name must be written in a platform-independent format, using `python3.12` instead of `libpython3.12.dylib`. 135 136 Then you can run the demos: 137 138 ```sh 139 export LLGOROOT=`pwd` 140 cd <demo-directory> # eg. cd _pydemo/callpy 141 llgo run . 142 ``` 143 144 See [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py) for more detials. 145 146 147 ## Other frequently used libraries 148 149 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. 150 151 The currently imported libraries include: 152 153 * [llama2.c](https://pkg.go.dev/github.com/goplus/llgo/c/llama2) 154 * [cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson) 155 * [sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite) 156 157 Here are some examples related to them: 158 159 * [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example) 160 * [mkjson](c/cjson/_demo/mkjson/mkjson.go): create a json object and print it 161 * [sqlitedemo](c/sqlite/_demo/sqlitedemo/demo.go): a basic sqlite demo 162 163 164 ## Go syntax support 165 166 The priority of `llgo` feature iteration is: 167 168 * Popular C/Python libraries 169 * Full Go syntax 170 * Go standard libraries 171 * Popular Go packages 172 173 Common Go syntax is already supported. Except for the following, which needs to be improved: 174 175 * interface (Limited support) 176 * map (Very limited support) 177 * panic (Limited support) 178 * recover (Not supported yet) 179 * defer (Not supported yet) 180 * gc (Not supported yet) 181 * chan (Not supported yet) 182 * goroutine (Not supported yet) 183 * generics (Not supported yet) 184 185 Here are some examples related to Go syntax: 186 187 * [concat](_demo/concat/concat.go): define a variadic function 188 * [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function) 189 190 191 ## How to install 192 193 Follow these steps to generate the `llgo` command (its usage is the same as the `go` command): 194 195 ### on macOS 196 197 ```sh 198 brew update # execute if needed 199 brew install llvm@17 200 go install -v ./... 201 ``` 202 203 ### on Linux 204 205 ```sh 206 echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-17 main' | sudo tee /etc/apt/sources.list.d/llvm.list 207 wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 208 sudo apt-get update # execute if needed 209 sudo apt-get install --no-install-recommends llvm-17-dev 210 go install -v ./... 211 ``` 212 213 ### on Windows 214 215 TODO 216 217 218 ## Development tools 219 220 * [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`. 221 * [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. 222 * [llgen](chore/llgen): It is used to compile Go packages into LLVM IR files (*.ll). 223 * [ssadump](chore/ssadump): It is a Go SSA builder and interpreter. 224 225 How do I generate these tools? 226 227 ```sh 228 go install -v ./... # compile all tools except pydump 229 cd chore/_xtool 230 llgo install ./... # compile pydump 231 ``` 232 233 ## Key modules 234 235 Below are the key modules for understanding the implementation principles of `llgo`: 236 237 * [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`. 238 * [llgo/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`. 239 * [llgo/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`.