Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
028c6cdf50 | ||
|
|
b08ae1dff3 | ||
|
|
37e7d66343 | ||
|
|
e6d06cc278 | ||
|
|
017fd150cd | ||
|
|
ea7e1de833 | ||
|
|
c2767be178 | ||
|
|
c60be43ac6 | ||
|
|
c373a5b505 | ||
|
|
da20aea408 | ||
|
|
973b5b90dc | ||
|
|
cffb5e9539 | ||
|
|
4b35586566 | ||
|
|
1e075d4830 | ||
|
|
c81b5b5df9 | ||
|
|
80b2b8d061 | ||
|
|
d1a7f63797 | ||
|
|
92359dd03b | ||
|
|
d1430c9f5a | ||
|
|
7feca4478e | ||
|
|
02b1d5ed84 | ||
|
|
99d74ce4b6 | ||
|
|
355094c7e2 | ||
|
|
7f61989869 | ||
|
|
7223ff004a | ||
|
|
df333fb144 | ||
|
|
5c08c55957 | ||
|
|
26b812a62a | ||
|
|
cd3d9c709f | ||
|
|
9da90e7ecf | ||
|
|
f17a4ca1de | ||
|
|
8ab662b373 | ||
|
|
fb839da81e | ||
|
|
244da4b10a | ||
|
|
c0c5271172 | ||
|
|
0066f8bd3f | ||
|
|
be9d209622 | ||
|
|
2bbd828f3a | ||
|
|
4f1b6e95a1 | ||
|
|
87ca3a39dc | ||
|
|
d7df46d578 | ||
|
|
489cbc4782 | ||
|
|
3c33a1d05e | ||
|
|
067cf0cba6 | ||
|
|
03a194a514 | ||
|
|
bdf45c0fcb | ||
|
|
6f679c05a3 | ||
|
|
0b131bd957 | ||
|
|
ebf4c80aff | ||
|
|
18a63e226a | ||
|
|
92f56a2f90 | ||
|
|
926e2d4a2e | ||
|
|
5d1d51dd58 | ||
|
|
52018cd424 | ||
|
|
e9153defee | ||
|
|
889fc8b6a9 | ||
|
|
9b9da3133d | ||
|
|
1c8edb0387 | ||
|
|
c0ef1598c9 | ||
|
|
bc1acee6f5 | ||
|
|
9f25d73826 | ||
|
|
f07a62d136 | ||
|
|
06d6b447e4 | ||
|
|
1cff02e4cc | ||
|
|
809a400f57 | ||
|
|
f1bb42f554 | ||
|
|
4fd8f84536 | ||
|
|
223c24450e | ||
|
|
8a7ddf4dc2 | ||
|
|
08217e5a5a | ||
|
|
424dbd9261 | ||
|
|
b615ada2c3 | ||
|
|
20a47873d0 | ||
|
|
d87ce1a124 | ||
|
|
91d012d33d | ||
|
|
330cb22351 | ||
|
|
236debab33 | ||
|
|
13a1c8ac4b | ||
|
|
29fad7b397 | ||
|
|
8eeac8a26d | ||
|
|
133d41d748 | ||
|
|
d444123062 | ||
|
|
4a5c8d3fbb | ||
|
|
afd3d40348 | ||
|
|
85da86a4f1 | ||
|
|
72d4f0f7f8 | ||
|
|
192b479f18 | ||
|
|
3e6dfa3c05 | ||
|
|
5bd28a1e9e | ||
|
|
a23a2601e4 | ||
|
|
3220b629c7 | ||
|
|
9cf122c31a | ||
|
|
75d513a78a | ||
|
|
3cbe4aac87 | ||
|
|
3e47a977e4 | ||
|
|
40855c2d2a | ||
|
|
b2319eda66 | ||
|
|
5c5b8e62e5 | ||
|
|
fbb1f89ab3 | ||
|
|
25b104cf13 | ||
|
|
be1599b418 | ||
|
|
d462e548b1 | ||
|
|
df1e4708f5 | ||
|
|
cf02f4a34f | ||
|
|
480cf09177 | ||
|
|
52a64a7770 | ||
|
|
8d3cb246c2 | ||
|
|
8f15fd45f2 | ||
|
|
afd02b3d78 | ||
|
|
aa1d0b307b | ||
|
|
8a09d8b442 | ||
|
|
7b99470bfa | ||
|
|
30192da7cf | ||
|
|
66337e0975 | ||
|
|
6e4a44438b | ||
|
|
3cc3b864af | ||
|
|
62f6542ca9 | ||
|
|
8c25848e1b | ||
|
|
e112d8277f | ||
|
|
014d0262da | ||
|
|
8ae97f73d0 | ||
|
|
666808b427 | ||
|
|
f208db48a1 | ||
|
|
673b9d9a5c | ||
|
|
ed8ffb228b | ||
|
|
d5a3ff6fb9 | ||
|
|
d3fddfb634 | ||
|
|
f7a54e3377 | ||
|
|
d62bf858dd | ||
|
|
ae0906d322 | ||
|
|
c6cb2931e1 | ||
|
|
0eac576171 | ||
|
|
0ee96db260 | ||
|
|
40a9e00d4c | ||
|
|
d8615330ad | ||
|
|
02afd1d73a | ||
|
|
4eedb4fb69 | ||
|
|
2d6869bdbd | ||
|
|
c0a9848cfb | ||
|
|
40cc7b2a85 | ||
|
|
dfaae24fea | ||
|
|
839ad8ba2b | ||
|
|
e757c66354 | ||
|
|
3ec6da002a | ||
|
|
190b029154 | ||
|
|
0bfc269652 | ||
|
|
b5961f0807 | ||
|
|
a792e312db | ||
|
|
04f81f3dbb | ||
|
|
91401c4571 | ||
|
|
18fe26e853 | ||
|
|
f895ca1fe6 | ||
|
|
ad28ed3154 | ||
|
|
f64abf37ab | ||
|
|
acc5de8d14 | ||
|
|
85bb1302ca | ||
|
|
fc893ba498 | ||
|
|
7527b326d7 | ||
|
|
a6d31ad8b8 | ||
|
|
664c3fcce3 | ||
|
|
e1d1d6a2d9 | ||
|
|
8c1b8ad945 | ||
|
|
ae5efdf16c | ||
|
|
2b82af519c | ||
|
|
7a347d4563 | ||
|
|
1610894a80 | ||
|
|
4eb2ddaf15 | ||
|
|
99a86d8d4e | ||
|
|
637db665c3 | ||
|
|
bb1da81a01 | ||
|
|
d4ddc61a9f | ||
|
|
6ebbc92c4f | ||
|
|
b45172bef1 | ||
|
|
695d3f3327 | ||
|
|
7979cfcb06 | ||
|
|
2986cb0c5f | ||
|
|
5a175955a9 | ||
|
|
cb507f43a7 | ||
|
|
8b148d72c2 | ||
|
|
616596e571 | ||
|
|
2849fe4841 | ||
|
|
98065e80d0 | ||
|
|
286b520d83 | ||
|
|
769b93a277 | ||
|
|
c30ed1b3c8 | ||
|
|
78d7f984d1 | ||
|
|
e88f7e6659 | ||
|
|
e8ff879943 | ||
|
|
f09d5bd155 | ||
|
|
53e73fc622 | ||
|
|
ba94d6f04e | ||
|
|
449f91ab14 | ||
|
|
70623dd554 | ||
|
|
35dc6dcd85 | ||
|
|
41dfafe957 | ||
|
|
2cc1bdee19 | ||
|
|
eb4146d80d | ||
|
|
0d68066086 | ||
|
|
7039cb3bc2 | ||
|
|
510f2f4769 | ||
|
|
5415f68c1b | ||
|
|
475f0fa2ff | ||
|
|
c58b1140d8 | ||
|
|
c97c1e97b9 | ||
|
|
ba3d82e5e5 | ||
|
|
d432899b42 | ||
|
|
08da38a609 | ||
|
|
6a3eb2f2f9 | ||
|
|
6a02c3ac4c | ||
|
|
f1761c0c9c | ||
|
|
39076c75cf | ||
|
|
3be8cacc24 | ||
|
|
46a9df47e4 | ||
|
|
d44a31cc62 | ||
|
|
00b2fd1479 | ||
|
|
5f08e7a612 | ||
|
|
5c8725373a | ||
|
|
c455f6e730 | ||
|
|
3cc83b8ec4 | ||
|
|
f74de76d70 | ||
|
|
ea8ddc6451 | ||
|
|
5f36c37cf2 | ||
|
|
2ad2873278 | ||
|
|
3855895808 | ||
|
|
f86cd74a98 | ||
|
|
1e6ecbadcd | ||
|
|
33716a3385 | ||
|
|
252f0bf967 | ||
|
|
2c3e1d1055 | ||
|
|
aafa639bf1 | ||
|
|
815a8a74fc | ||
|
|
840ea80e20 | ||
|
|
773ae2c8c6 | ||
|
|
4aadb4b86f | ||
|
|
91d1d71f6d | ||
|
|
a3d6a94600 | ||
|
|
43ae7a23b2 | ||
|
|
b6005886fa | ||
|
|
28dd34a136 | ||
|
|
3a3c263203 | ||
|
|
87b7ecd1d6 | ||
|
|
f5a309b5ad | ||
|
|
0f00add402 | ||
|
|
1014fa53dd | ||
|
|
04568835bd | ||
|
|
e4f8edc07c | ||
|
|
a8533d1677 | ||
|
|
edcb66afb7 |
8
.github/workflows/go.yml
vendored
8
.github/workflows/go.yml
vendored
@@ -60,4 +60,10 @@ jobs:
|
|||||||
run: go build -v ./...
|
run: go build -v ./...
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -v ./...
|
run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./...
|
||||||
|
|
||||||
|
- name: Upload coverage reports to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
slug: goplus/llgo
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -8,6 +8,11 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
err.log
|
||||||
|
|
||||||
|
_go/
|
||||||
|
_runtime/
|
||||||
_tinygo/
|
_tinygo/
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
|
|||||||
45
README.md
45
README.md
@@ -4,7 +4,46 @@ llgo - A Go compiler based on LLVM
|
|||||||
[](https://github.com/goplus/llgo/actions/workflows/go.yml)
|
[](https://github.com/goplus/llgo/actions/workflows/go.yml)
|
||||||
[](https://goreportcard.com/report/github.com/goplus/llgo)
|
[](https://goreportcard.com/report/github.com/goplus/llgo)
|
||||||
[](https://github.com/goplus/llgo/releases)
|
[](https://github.com/goplus/llgo/releases)
|
||||||
[](https://pkg.go.dev/github.com/goplus/llgo)
|
|
||||||
<!--
|
|
||||||
[](https://codecov.io/gh/goplus/llgo)
|
[](https://codecov.io/gh/goplus/llgo)
|
||||||
-->
|
[](https://pkg.go.dev/github.com/goplus/llgo)
|
||||||
|
[](https://github.com/goplus/gop)
|
||||||
|
|
||||||
|
This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem. It's a subproject of [the Go+ project](https://github.com/goplus/gop).
|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
Follow these steps to generate the `llgo` command (its usage is the same as the `go` command):
|
||||||
|
|
||||||
|
### on macOS
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew update # execute if needed
|
||||||
|
brew install llvm@17
|
||||||
|
go install -v ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Linux
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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 ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
The `_demo` directory contains our 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, and Go variadic function
|
||||||
|
* [qsort](_demo/qsort/qsort.go): call C function with a callback (eg. qsort)
|
||||||
|
* [genints](_demo/genints/genints.go): various forms of closure usage (including C function, recv.method and anonymous function)
|
||||||
|
|
||||||
|
### How to run demos
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd <demo-directory> # eg. cd _demo/genints
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
|
|||||||
21
_demo/concat/concat.go
Normal file
21
_demo/concat/concat.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func concat(args ...string) (ret string) {
|
||||||
|
for _, v := range args {
|
||||||
|
ret += v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := concat("Hello", " ", "World")
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output (stderr):
|
||||||
|
Hi, Hello World
|
||||||
|
*/
|
||||||
63
_demo/genints/gen_ints.go
Normal file
63
_demo/genints/gen_ints.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type generator struct {
|
||||||
|
val c.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *generator) next() c.Int {
|
||||||
|
g.val++
|
||||||
|
return g.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func genInts(n int, gen func() c.Int) []c.Int {
|
||||||
|
a := make([]c.Int, n)
|
||||||
|
for i := range a {
|
||||||
|
a[i] = gen()
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// generate 5 random integers
|
||||||
|
for _, v := range genInts(5, c.Rand) {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate 5 integers, each is double of the previous one
|
||||||
|
initVal := c.Int(1)
|
||||||
|
ints := genInts(5, func() c.Int {
|
||||||
|
initVal *= 2
|
||||||
|
return initVal
|
||||||
|
})
|
||||||
|
for _, v := range ints {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate 5 integers, each is incremented by 1
|
||||||
|
g := &generator{val: 1}
|
||||||
|
for _, v := range genInts(5, g.next) {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Posible output:
|
||||||
|
16807
|
||||||
|
282475249
|
||||||
|
1622650073
|
||||||
|
984943658
|
||||||
|
1144108930
|
||||||
|
2
|
||||||
|
4
|
||||||
|
8
|
||||||
|
16
|
||||||
|
32
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
*/
|
||||||
13
_demo/hello/hello.go
Normal file
13
_demo/hello/hello.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello world\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
Hello World
|
||||||
|
*/
|
||||||
25
_demo/qsort/qsort.go
Normal file
25
_demo/qsort/qsort.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := [...]int{100, 8, 23, 2, 7}
|
||||||
|
c.Qsort(c.Pointer(&a), 5, unsafe.Sizeof(0), func(a, b c.Pointer) c.Int {
|
||||||
|
return c.Int(*(*int)(a) - *(*int)(b))
|
||||||
|
})
|
||||||
|
for _, v := range a {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expected output:
|
||||||
|
2
|
||||||
|
7
|
||||||
|
8
|
||||||
|
23
|
||||||
|
100
|
||||||
|
*/
|
||||||
76
c/c.go
Normal file
76
c/c.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package c
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Char = int8
|
||||||
|
Int = C.int
|
||||||
|
Pointer = unsafe.Pointer
|
||||||
|
FilePtr = unsafe.Pointer
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Stdin __stdinp
|
||||||
|
var Stdin FilePtr
|
||||||
|
|
||||||
|
//go:linkname Stdout __stdoutp
|
||||||
|
var Stdout FilePtr
|
||||||
|
|
||||||
|
//go:linkname Stderr __stderrp
|
||||||
|
var Stderr FilePtr
|
||||||
|
|
||||||
|
//go:linkname Str llgo.cstr
|
||||||
|
func Str(string) *Char
|
||||||
|
|
||||||
|
//go:linkname Advance llgo.advance
|
||||||
|
func Advance(ptr Pointer, offset int) Pointer
|
||||||
|
|
||||||
|
//go:linkname Alloca llgo.alloca
|
||||||
|
func Alloca(size uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname AllocaCStr llgo.allocaCStr
|
||||||
|
func AllocaCStr(s string) *Char
|
||||||
|
|
||||||
|
//go:linkname Unreachable llgo.unreachable
|
||||||
|
func Unreachable()
|
||||||
|
|
||||||
|
//go:linkname Rand C.rand
|
||||||
|
func Rand() Int
|
||||||
|
|
||||||
|
//go:linkname Malloc C.malloc
|
||||||
|
func Malloc(size uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Memcpy C.memcpy
|
||||||
|
func Memcpy(dst, src Pointer, n uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Memset C.memset
|
||||||
|
func Memset(s Pointer, c Int, n uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Printf C.printf
|
||||||
|
func Printf(format *Char, __llgo_va_list ...any) Int
|
||||||
|
|
||||||
|
//go:linkname Fprintf C.fprintf
|
||||||
|
func Fprintf(fp FilePtr, format *Char, __llgo_va_list ...any) Int
|
||||||
|
|
||||||
|
//go:linkname Qsort C.qsort
|
||||||
|
func Qsort(base Pointer, count, elem uintptr, compar func(a, b Pointer) Int)
|
||||||
71
chore/clangast/clangast.go
Normal file
71
chore/clangast/clangast.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/x/clang/parser"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dump = flag.Bool("dump", false, "dump AST")
|
||||||
|
)
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: clangast [-dump] source.i\n")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Usage = usage
|
||||||
|
flag.Parse()
|
||||||
|
if flag.NArg() < 1 {
|
||||||
|
usage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var file = flag.Arg(0)
|
||||||
|
var err error
|
||||||
|
if *dump {
|
||||||
|
doc, _, e := parser.DumpAST(file, nil)
|
||||||
|
if e == nil {
|
||||||
|
os.Stdout.Write(doc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = e
|
||||||
|
} else {
|
||||||
|
doc, _, e := parser.ParseFile(file, 0)
|
||||||
|
if e == nil {
|
||||||
|
enc := json.NewEncoder(os.Stdout)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
check(enc.Encode(doc))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
41
chore/clangpp/clangpp.go
Normal file
41
chore/clangpp/clangpp.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/x/clang/preprocessor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: clangpp source.c\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
usage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
infile := os.Args[1]
|
||||||
|
outfile := infile + ".i"
|
||||||
|
if err := preprocessor.Do(infile, outfile, nil); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
57
chore/gentests/gentests.go
Normal file
57
chore/gentests/gentests.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/llgen"
|
||||||
|
"github.com/goplus/mod"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
dir, _, err := mod.FindGoMod(".")
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
llgen.Verbose = false
|
||||||
|
|
||||||
|
llgenDir(dir + "/cl/_testrt")
|
||||||
|
llgenDir(dir+"/cl/_testdata", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func llgenDir(dir string, pkgPath ...string) {
|
||||||
|
fis, err := os.ReadDir(dir)
|
||||||
|
check(err)
|
||||||
|
for _, fi := range fis {
|
||||||
|
name := fi.Name()
|
||||||
|
if !fi.IsDir() || strings.HasPrefix(name, "_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
testDir := dir + "/" + name
|
||||||
|
fmt.Fprintln(os.Stderr, "llgen", testDir)
|
||||||
|
os.Chdir(testDir)
|
||||||
|
llgen.SmartDoFile("in.go", pkgPath...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,29 +19,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/llgen"
|
"github.com/goplus/llgo/internal/llgen"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go [pkgPath]")
|
fmt.Fprintln(os.Stderr, "Usage: llgen <pkg> [pkgPath]")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inFile := os.Args[1]
|
|
||||||
|
|
||||||
dir, _ := filepath.Split(inFile)
|
|
||||||
outFile := dir + "out.ll"
|
|
||||||
|
|
||||||
pkgPath := ""
|
|
||||||
if len(os.Args) == 3 {
|
|
||||||
pkgPath = os.Args[2]
|
|
||||||
} else {
|
|
||||||
pkgPath = llgen.PkgPath(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
llgen.Init()
|
llgen.Init()
|
||||||
llgen.Do(pkgPath, inFile, outFile)
|
llgen.SmartDoFile(os.Args[1], os.Args[2:]...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,18 @@ source_filename = "apkg"
|
|||||||
|
|
||||||
@"apkg.init$guard" = global ptr null
|
@"apkg.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define double @apkg.Max(double %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fcmp ogt double %0, %1
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret double %0
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret double %1
|
||||||
|
}
|
||||||
|
|
||||||
define void @apkg.init() {
|
define void @apkg.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"apkg.init$guard", align 1
|
%0 = load i1, ptr @"apkg.init$guard", align 1
|
||||||
@@ -15,15 +27,3 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define double @apkg.Max(double %0, double %1) {
|
|
||||||
_llgo_0:
|
|
||||||
%2 = fcmp ogt double %0, %1
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret double %0
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret double %1
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call i64 @main.max(i64 1, i64 2)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
define i64 @main.max(i64 %0, i64 %1) {
|
define i64 @main.max(i64 %0, i64 %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = icmp sgt i64 %0, %1
|
%2 = icmp sgt i64 %0, %1
|
||||||
@@ -28,9 +36,4 @@ _llgo_2: ; preds = %_llgo_0
|
|||||||
ret i64 %1
|
ret i64 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
_llgo_0:
|
|
||||||
call void @main.init()
|
|
||||||
%0 = call i64 @main.max(i64 1, i64 2)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
|
||||||
@main.hello = global ptr null
|
@main.hello = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -27,6 +27,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
|
|
||||||
define void @main() {
|
define void @main() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = call i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64 2, i64 100)
|
%0 = call i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64 2, i64 100)
|
||||||
call void (ptr, ...) @printf(ptr @main.hello)
|
call void (ptr, ...) @printf(ptr @main.hello)
|
||||||
@@ -35,6 +36,8 @@ _llgo_0:
|
|||||||
|
|
||||||
declare void @"github.com/goplus/llgo/cl/internal/stdio.init"()
|
declare void @"github.com/goplus/llgo/cl/internal/stdio.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64, i64)
|
declare i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64, i64)
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
19
cl/_testdata/method/in.go
Normal file
19
cl/_testdata/method/in.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
type T int
|
||||||
|
|
||||||
|
func (a T) Add(b T) T {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := T(1)
|
||||||
|
printf(&format[0], a.Add(2))
|
||||||
|
}
|
||||||
54
cl/_testdata/method/out.ll
Normal file
54
cl/_testdata/method/out.ll
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define i64 @"(main.T).Add"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*main.T).Add"(ptr %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = load i64, ptr %0, align 4
|
||||||
|
%3 = call i64 @"(main.T).Add"(i64 %2, i64 %1)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call i64 @"(main.T).Add"(i64 1, i64 2)
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i64 %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
174
cl/_testdata/print/in.go
Normal file
174
cl/_testdata/print/in.go
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func gwrite(b []byte) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range b {
|
||||||
|
c.Printf(c.Str("%c"), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// func printfloat(v float64) {
|
||||||
|
// switch {
|
||||||
|
// case v != v:
|
||||||
|
// printstring("NaN")
|
||||||
|
// return
|
||||||
|
// case v+v == v && v > 0:
|
||||||
|
// printstring("+Inf")
|
||||||
|
// return
|
||||||
|
// case v+v == v && v < 0:
|
||||||
|
// printstring("-Inf")
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const n = 7 // digits printed
|
||||||
|
// var buf [n + 7]byte
|
||||||
|
// buf[0] = '+'
|
||||||
|
// e := 0 // exp
|
||||||
|
// if v == 0 {
|
||||||
|
// if 1/v < 0 {
|
||||||
|
// buf[0] = '-'
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if v < 0 {
|
||||||
|
// v = -v
|
||||||
|
// buf[0] = '-'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // normalize
|
||||||
|
// for v >= 10 {
|
||||||
|
// e++
|
||||||
|
// v /= 10
|
||||||
|
// }
|
||||||
|
// for v < 1 {
|
||||||
|
// e--
|
||||||
|
// v *= 10
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // round
|
||||||
|
// h := 5.0
|
||||||
|
// for i := 0; i < n; i++ {
|
||||||
|
// h /= 10
|
||||||
|
// }
|
||||||
|
// v += h
|
||||||
|
// if v >= 10 {
|
||||||
|
// e++
|
||||||
|
// v /= 10
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // format +d.dddd+edd
|
||||||
|
// for i := 0; i < n; i++ {
|
||||||
|
// s := int(v)
|
||||||
|
// buf[i+2] = byte(s + '0')
|
||||||
|
// v -= float64(s)
|
||||||
|
// v *= 10
|
||||||
|
// }
|
||||||
|
// buf[1] = buf[2]
|
||||||
|
// buf[2] = '.'
|
||||||
|
|
||||||
|
// buf[n+2] = 'e'
|
||||||
|
// buf[n+3] = '+'
|
||||||
|
// if e < 0 {
|
||||||
|
// e = -e
|
||||||
|
// buf[n+3] = '-'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// buf[n+4] = byte(e/100) + '0'
|
||||||
|
// buf[n+5] = byte(e/10)%10 + '0'
|
||||||
|
// buf[n+6] = byte(e%10) + '0'
|
||||||
|
// gwrite(buf[:])
|
||||||
|
// }
|
||||||
|
|
||||||
|
func printuint(v uint64) {
|
||||||
|
var buf [100]byte
|
||||||
|
i := len(buf)
|
||||||
|
for i--; i > 0; i-- {
|
||||||
|
buf[i] = byte(v%10 + '0')
|
||||||
|
if v < 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v /= 10
|
||||||
|
}
|
||||||
|
gwrite(buf[i:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// func printint(v int64) {
|
||||||
|
// if v < 0 {
|
||||||
|
// printstring("-")
|
||||||
|
// v = -v
|
||||||
|
// }
|
||||||
|
// printuint(uint64(v))
|
||||||
|
// }
|
||||||
|
|
||||||
|
var minhexdigits = 0
|
||||||
|
|
||||||
|
func printhex(v uint64) {
|
||||||
|
const dig = "0123456789abcdef"
|
||||||
|
var buf [100]byte
|
||||||
|
i := len(buf)
|
||||||
|
for i--; i > 0; i-- {
|
||||||
|
buf[i] = dig[v%16]
|
||||||
|
if v < 16 && len(buf)-i >= minhexdigits {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v /= 16
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
buf[i] = 'x'
|
||||||
|
i--
|
||||||
|
buf[i] = '0'
|
||||||
|
gwrite(buf[i:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func printsp() {
|
||||||
|
printstring(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printnl() {
|
||||||
|
printstring("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printstring(s string) {
|
||||||
|
gwrite(bytes(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
type slice struct {
|
||||||
|
array unsafe.Pointer
|
||||||
|
len int
|
||||||
|
cap int
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringStruct struct {
|
||||||
|
str unsafe.Pointer
|
||||||
|
len int
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringStructOf(sp *string) *stringStruct {
|
||||||
|
return (*stringStruct)(unsafe.Pointer(sp))
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytes(s string) (ret []byte) {
|
||||||
|
rp := (*slice)(unsafe.Pointer(&ret))
|
||||||
|
sp := stringStructOf(&s)
|
||||||
|
rp.array = sp.str
|
||||||
|
rp.len = sp.len
|
||||||
|
rp.cap = sp.len
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
printstring("llgo")
|
||||||
|
printnl()
|
||||||
|
printuint(1024)
|
||||||
|
printnl()
|
||||||
|
printhex(0x1234abcf)
|
||||||
|
printnl()
|
||||||
|
}
|
||||||
213
cl/_testdata/print/out.ll
Normal file
213
cl/_testdata/print/out.ll
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%main.stringStruct = type { ptr, i64 }
|
||||||
|
%main.slice = type { ptr, i64, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@main.minhexdigits = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [3 x i8] c"%c\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.bytes(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %1, align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 24)
|
||||||
|
%3 = call ptr @main.stringStructOf(ptr %1)
|
||||||
|
%4 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 0
|
||||||
|
%5 = load ptr, ptr %4, align 8
|
||||||
|
%6 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 0
|
||||||
|
store ptr %5, ptr %6, align 8
|
||||||
|
%7 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 1
|
||||||
|
%8 = load i64, ptr %7, align 4
|
||||||
|
%9 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 1
|
||||||
|
store i64 %8, ptr %9, align 4
|
||||||
|
%10 = getelementptr inbounds %main.stringStruct, ptr %3, i32 0, i32 1
|
||||||
|
%11 = load i64, ptr %10, align 4
|
||||||
|
%12 = getelementptr inbounds %main.slice, ptr %2, i32 0, i32 2
|
||||||
|
store i64 %11, ptr %12, align 4
|
||||||
|
%13 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.Slice" %13
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%2 = icmp eq i64 %1, 0
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
%3 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_4, %_llgo_2
|
||||||
|
%4 = phi i64 [ -1, %_llgo_2 ], [ %5, %_llgo_4 ]
|
||||||
|
%5 = add i64 %4, 1
|
||||||
|
%6 = icmp slt i64 %5, %3
|
||||||
|
br i1 %6, label %_llgo_4, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_3
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%8 = getelementptr inbounds i8, ptr %7, i64 %5
|
||||||
|
%9 = load i8, ptr %8, align 1
|
||||||
|
%10 = call i32 (ptr, ...) @printf(ptr @0, i8 %9)
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_3
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i64 0, ptr @main.minhexdigits, align 4
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 4)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.printuint(i64 1024)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.printhex(i64 305441743)
|
||||||
|
call void @main.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printhex(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 100)
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_3
|
||||||
|
%2 = urem i64 %14, 16
|
||||||
|
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 16)
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
||||||
|
%5 = getelementptr inbounds i8, ptr %4, i64 %2
|
||||||
|
%6 = load i8, ptr %5, align 1
|
||||||
|
%7 = getelementptr inbounds i8, ptr %1, i64 %15
|
||||||
|
store i8 %6, ptr %7, align 1
|
||||||
|
%8 = icmp ult i64 %14, 16
|
||||||
|
br i1 %8, label %_llgo_5, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_5, %_llgo_3
|
||||||
|
%9 = sub i64 %15, 1
|
||||||
|
%10 = getelementptr inbounds i8, ptr %1, i64 %9
|
||||||
|
store i8 120, ptr %10, align 1
|
||||||
|
%11 = sub i64 %9, 1
|
||||||
|
%12 = getelementptr inbounds i8, ptr %1, i64 %11
|
||||||
|
store i8 48, ptr %12, align 1
|
||||||
|
%13 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %11, i64 100, i64 100)
|
||||||
|
call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %13)
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_4, %_llgo_0
|
||||||
|
%14 = phi i64 [ %0, %_llgo_0 ], [ %17, %_llgo_4 ]
|
||||||
|
%15 = phi i64 [ 99, %_llgo_0 ], [ %18, %_llgo_4 ]
|
||||||
|
%16 = icmp sgt i64 %15, 0
|
||||||
|
br i1 %16, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_5, %_llgo_1
|
||||||
|
%17 = udiv i64 %14, 16
|
||||||
|
%18 = sub i64 %15, 1
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_1
|
||||||
|
%19 = sub i64 100, %15
|
||||||
|
%20 = load i64, ptr @main.minhexdigits, align 4
|
||||||
|
%21 = icmp sge i64 %19, %20
|
||||||
|
br i1 %21, label %_llgo_2, label %_llgo_4
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printnl() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 1)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printsp() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 1)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.bytes(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printuint(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 100)
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_3
|
||||||
|
%2 = urem i64 %8, 10
|
||||||
|
%3 = add i64 %2, 48
|
||||||
|
%4 = trunc i64 %3 to i8
|
||||||
|
%5 = getelementptr inbounds i8, ptr %1, i64 %9
|
||||||
|
store i8 %4, ptr %5, align 1
|
||||||
|
%6 = icmp ult i64 %8, 10
|
||||||
|
br i1 %6, label %_llgo_2, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3, %_llgo_1
|
||||||
|
%7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %9, i64 100, i64 100)
|
||||||
|
call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_4, %_llgo_0
|
||||||
|
%8 = phi i64 [ %0, %_llgo_0 ], [ %11, %_llgo_4 ]
|
||||||
|
%9 = phi i64 [ 99, %_llgo_0 ], [ %12, %_llgo_4 ]
|
||||||
|
%10 = icmp sgt i64 %9, 0
|
||||||
|
br i1 %10, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_1
|
||||||
|
%11 = udiv i64 %8, 10
|
||||||
|
%12 = sub i64 %9, 1
|
||||||
|
br label %_llgo_3
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @main.stringStructOf(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import _ "unsafe"
|
import _ "unsafe"
|
||||||
|
|
||||||
//go:linkname printf printf
|
//go:linkname printf C.printf
|
||||||
func printf(format *int8, __llgo_va_list ...any)
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0}
|
var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
|
||||||
@main.hello = global ptr null
|
@main.hello = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -24,11 +24,14 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
|
||||||
|
|
||||||
define void @main() {
|
define void @main() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
call void (ptr, ...) @printf(ptr @main.hello)
|
call void (ptr, ...) @printf(ptr @main.hello)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
12
cl/_testdata/printval/in.go
Normal file
12
cl/_testdata/printval/in.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
printf(&format[0], 100)
|
||||||
|
}
|
||||||
40
cl/_testdata/printval/out.ll
Normal file
40
cl/_testdata/printval/out.ll
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i64 100)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
19
cl/_testdata/ptrmthd/in.go
Normal file
19
cl/_testdata/ptrmthd/in.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
type T int8
|
||||||
|
|
||||||
|
func (f *T) Print(v int) {
|
||||||
|
printf((*int8)(f), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var format = [...]T{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := &format[0]
|
||||||
|
f.Print(100)
|
||||||
|
}
|
||||||
46
cl/_testdata/ptrmthd/out.ll
Normal file
46
cl/_testdata/ptrmthd/out.ll
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @"(*main.T).Print"(ptr %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
call void (ptr, ...) @printf(ptr %0, i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @"(*main.T).Print"(ptr @main.format, i64 100)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
11
cl/_testdata/untyped/in.go
Normal file
11
cl/_testdata/untyped/in.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const c = 100
|
||||||
|
|
||||||
|
var a float64 = 1
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if c > 100 {
|
||||||
|
a = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
35
cl/_testdata/untyped/out.ll
Normal file
35
cl/_testdata/untyped/out.ll
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.a = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store double 1.000000e+00, ptr @main.a, align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
br i1 false, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store double 0.000000e+00, ptr @main.a, align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
|
||||||
@main.a = global ptr null
|
@main.a = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -20,6 +20,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
|
|
||||||
define void @main() {
|
define void @main() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = load i64, ptr @main.a, align 4
|
%0 = load i64, ptr @main.a, align 4
|
||||||
%1 = add i64 %0, 1
|
%1 = add i64 %0, 1
|
||||||
@@ -27,3 +28,5 @@ _llgo_0:
|
|||||||
%2 = load i64, ptr @main.a, align 4
|
%2 = load i64, ptr @main.a, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|||||||
12
cl/_testrt/alloca/in.go
Normal file
12
cl/_testrt/alloca/in.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := c.Str("Hi\n")
|
||||||
|
s2 := c.Alloca(4)
|
||||||
|
c.Memcpy(s2, c.Pointer(s), 4)
|
||||||
|
c.Printf(c.Str("%s"), s2)
|
||||||
|
}
|
||||||
35
cl/_testrt/alloca/out.ll
Normal file
35
cl/_testrt/alloca/out.ll
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"Hi\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca i8, i64 4, align 1
|
||||||
|
%1 = call ptr @memcpy(ptr %0, ptr @0, i64 4)
|
||||||
|
%2 = call i32 (ptr, ...) @printf(ptr @1, ptr %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @memcpy(ptr, ptr, i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
13
cl/_testrt/allocstr/in.go
Normal file
13
cl/_testrt/allocstr/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func hello() string {
|
||||||
|
return "Hello world\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.AllocaCStr(hello()))
|
||||||
|
}
|
||||||
49
cl/_testrt/allocstr/out.ll
Normal file
49
cl/_testrt/allocstr/out.ll
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [13 x i8] c"Hello world\0A\00", align 1
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.String" @main.hello() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 12)
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello()
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
%2 = add i64 %1, 1
|
||||||
|
%3 = alloca i8, i64 %2, align 1
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %3, %"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
%5 = call i32 (ptr, ...) @printf(ptr %4)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
13
cl/_testrt/any/in.go
Normal file
13
cl/_testrt/any/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func incVal(a any) int {
|
||||||
|
return a.(int) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello %d\n"), incVal(100))
|
||||||
|
}
|
||||||
49
cl/_testrt/any/out.ll
Normal file
49
cl/_testrt/any/out.ll
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
|
define i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%2 = call i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
|
||||||
|
%3 = add i64 %2, 1
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 100)
|
||||||
|
%2 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %1)
|
||||||
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i64 %2)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
51
cl/_testrt/builtin/in.go
Normal file
51
cl/_testrt/builtin/in.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
var a int64 = 1<<63 - 1
|
||||||
|
var b int64 = -1 << 63
|
||||||
|
var n uint64 = 1<<64 - 1
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var s = []int{1, 2, 3, 4}
|
||||||
|
var a = [...]int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
out(len(s))
|
||||||
|
out(len([]int{1, 2, 3, 4}))
|
||||||
|
out(len(a))
|
||||||
|
out(len(&a))
|
||||||
|
out(len([4]int{1, 2, 3, 4}))
|
||||||
|
|
||||||
|
out(cap(s))
|
||||||
|
out(cap(a))
|
||||||
|
out(cap(&a))
|
||||||
|
|
||||||
|
out(len(s[1:]))
|
||||||
|
out(cap(s[1:]))
|
||||||
|
out(len(s[1:2]))
|
||||||
|
out(cap(s[1:2]))
|
||||||
|
out(len(s[1:2:2]))
|
||||||
|
out(cap(s[1:2:2]))
|
||||||
|
|
||||||
|
out(len(a[1:]))
|
||||||
|
out(cap(a[1:]))
|
||||||
|
out(len(a[1:2]))
|
||||||
|
out(cap(a[1:2]))
|
||||||
|
out(len(a[1:2:2]))
|
||||||
|
out(cap(a[1:2:2]))
|
||||||
|
|
||||||
|
string_len("hello")
|
||||||
|
string_len("hello"[1:])
|
||||||
|
string_len("hello"[1:2])
|
||||||
|
string_len("hello"[5:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func string_len(s string) {
|
||||||
|
out(len(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func out(n int) {
|
||||||
|
c.Printf(c.Str("%d\n"), n)
|
||||||
|
}
|
||||||
174
cl/_testrt/builtin/out.ll
Normal file
174
cl/_testrt/builtin/out.ll
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
|
||||||
|
@main.a = global ptr null
|
||||||
|
@main.b = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@main.n = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i64 9223372036854775807, ptr @main.a, align 4
|
||||||
|
store i64 -9223372036854775808, ptr @main.b, align 4
|
||||||
|
store i64 -1, ptr @main.n, align 4
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
|
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
||||||
|
store i64 1, ptr %1, align 4
|
||||||
|
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
||||||
|
store i64 2, ptr %2, align 4
|
||||||
|
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
||||||
|
store i64 3, ptr %3, align 4
|
||||||
|
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
||||||
|
store i64 4, ptr %4, align 4
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4)
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
|
%7 = getelementptr inbounds i64, ptr %6, i64 0
|
||||||
|
%8 = getelementptr inbounds i64, ptr %6, i64 1
|
||||||
|
%9 = getelementptr inbounds i64, ptr %6, i64 2
|
||||||
|
%10 = getelementptr inbounds i64, ptr %6, i64 3
|
||||||
|
store i64 1, ptr %7, align 4
|
||||||
|
store i64 2, ptr %8, align 4
|
||||||
|
store i64 3, ptr %9, align 4
|
||||||
|
store i64 4, ptr %10, align 4
|
||||||
|
%11 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
call void @main.out(i64 %11)
|
||||||
|
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
|
%13 = getelementptr inbounds i64, ptr %12, i64 0
|
||||||
|
store i64 1, ptr %13, align 4
|
||||||
|
%14 = getelementptr inbounds i64, ptr %12, i64 1
|
||||||
|
store i64 2, ptr %14, align 4
|
||||||
|
%15 = getelementptr inbounds i64, ptr %12, i64 2
|
||||||
|
store i64 3, ptr %15, align 4
|
||||||
|
%16 = getelementptr inbounds i64, ptr %12, i64 3
|
||||||
|
store i64 4, ptr %16, align 4
|
||||||
|
%17 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %12, i64 8, i64 4, i64 0, i64 4, i64 4)
|
||||||
|
%18 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %17)
|
||||||
|
call void @main.out(i64 %18)
|
||||||
|
call void @main.out(i64 4)
|
||||||
|
call void @main.out(i64 4)
|
||||||
|
call void @main.out(i64 4)
|
||||||
|
%19 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
call void @main.out(i64 %19)
|
||||||
|
call void @main.out(i64 4)
|
||||||
|
call void @main.out(i64 4)
|
||||||
|
%20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%23 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %22, i64 8, i64 %20, i64 1, i64 %21, i64 %20)
|
||||||
|
%24 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %23)
|
||||||
|
call void @main.out(i64 %24)
|
||||||
|
%25 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%28 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %27, i64 8, i64 %25, i64 1, i64 %26, i64 %25)
|
||||||
|
%29 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %28)
|
||||||
|
call void @main.out(i64 %29)
|
||||||
|
%30 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%32 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %31, i64 8, i64 %30, i64 1, i64 2, i64 %30)
|
||||||
|
%33 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %32)
|
||||||
|
call void @main.out(i64 %33)
|
||||||
|
%34 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%36 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %35, i64 8, i64 %34, i64 1, i64 2, i64 %34)
|
||||||
|
%37 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %36)
|
||||||
|
call void @main.out(i64 %37)
|
||||||
|
%38 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%39 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%40 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %39, i64 8, i64 %38, i64 1, i64 2, i64 2)
|
||||||
|
%41 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %40)
|
||||||
|
call void @main.out(i64 %41)
|
||||||
|
%42 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%44 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %43, i64 8, i64 %42, i64 1, i64 2, i64 2)
|
||||||
|
%45 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %44)
|
||||||
|
call void @main.out(i64 %45)
|
||||||
|
%46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4)
|
||||||
|
%47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %46)
|
||||||
|
call void @main.out(i64 %47)
|
||||||
|
%48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4)
|
||||||
|
%49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %48)
|
||||||
|
call void @main.out(i64 %49)
|
||||||
|
%50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4)
|
||||||
|
%51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %50)
|
||||||
|
call void @main.out(i64 %51)
|
||||||
|
%52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4)
|
||||||
|
%53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %52)
|
||||||
|
call void @main.out(i64 %53)
|
||||||
|
%54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2)
|
||||||
|
%55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %54)
|
||||||
|
call void @main.out(i64 %55)
|
||||||
|
%56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2)
|
||||||
|
%57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %56)
|
||||||
|
call void @main.out(i64 %57)
|
||||||
|
%58 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
|
||||||
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %58)
|
||||||
|
%59 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
||||||
|
%60 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %59)
|
||||||
|
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %59, i64 1, i64 %60)
|
||||||
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
||||||
|
%62 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
||||||
|
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %62, i64 1, i64 2)
|
||||||
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
||||||
|
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
|
%65 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %64)
|
||||||
|
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 5, i64 %65)
|
||||||
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.out(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
call void @main.out(i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
18
cl/_testrt/callback/in.go
Normal file
18
cl/_testrt/callback/in.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func callback(msg *c.Char, f func(*c.Char)) {
|
||||||
|
f(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func print(msg *c.Char) {
|
||||||
|
c.Printf(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
callback(c.Str("Hello\n"), print)
|
||||||
|
callback(c.Str("callback\n"), print)
|
||||||
|
}
|
||||||
64
cl/_testrt/callback/out.ll
Normal file
64
cl/_testrt/callback/out.ll
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [10 x i8] c"callback\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.callback(ptr %0, { ptr, ptr } %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = extractvalue { ptr, ptr } %1, 1
|
||||||
|
%3 = extractvalue { ptr, ptr } %1, 0
|
||||||
|
call void %3(ptr %2, ptr %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.main.print, ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
call void @main.callback(ptr @0, { ptr, ptr } %3)
|
||||||
|
%4 = alloca { ptr, ptr }, align 8
|
||||||
|
%5 = getelementptr inbounds { ptr, ptr }, ptr %4, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.main.print, ptr %5, align 8
|
||||||
|
%6 = getelementptr inbounds { ptr, ptr }, ptr %4, i32 0, i32 1
|
||||||
|
store ptr null, ptr %6, align 8
|
||||||
|
%7 = load { ptr, ptr }, ptr %4, align 8
|
||||||
|
call void @main.callback(ptr @1, { ptr, ptr } %7)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.print(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i32 (ptr, ...) @printf(ptr %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
define linkonce void @__llgo_stub.main.print(ptr %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
tail call void @main.print(ptr %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
18
cl/_testrt/closure/in.go
Normal file
18
cl/_testrt/closure/in.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
func(n1, n2 int) {
|
||||||
|
c.Printf(c.Str("%d %d\n"), n1, n2)
|
||||||
|
}(100, 200)
|
||||||
|
fn1 := func(n1, n2 int) {
|
||||||
|
c.Printf(c.Str("%d %d\n"), n1, n2)
|
||||||
|
}
|
||||||
|
fn2 := func() {
|
||||||
|
fn1(100, 200)
|
||||||
|
}
|
||||||
|
fn2()
|
||||||
|
}
|
||||||
84
cl/_testrt/closure/out.ll
Normal file
84
cl/_testrt/closure/out.ll
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @"main.main$1"(i64 100, i64 200)
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%1 = alloca { ptr, ptr }, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.main$2", ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 1
|
||||||
|
store ptr null, ptr %3, align 8
|
||||||
|
%4 = load { ptr, ptr }, ptr %1, align 8
|
||||||
|
store { ptr, ptr } %4, ptr %0, align 8
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%6 = getelementptr inbounds { ptr }, ptr %5, i32 0, i32 0
|
||||||
|
store ptr %0, ptr %6, align 8
|
||||||
|
%7 = alloca { ptr, ptr }, align 8
|
||||||
|
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0
|
||||||
|
store ptr @"main.main$3", ptr %8, align 8
|
||||||
|
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
|
||||||
|
store ptr %5, ptr %9, align 8
|
||||||
|
%10 = load { ptr, ptr }, ptr %7, align 8
|
||||||
|
%11 = extractvalue { ptr, ptr } %10, 1
|
||||||
|
%12 = extractvalue { ptr, ptr } %10, 0
|
||||||
|
call void %12(ptr %11)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
define void @"main.main$1"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = call i32 (ptr, ...) @printf(ptr @0, i64 %0, i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
define void @"main.main$2"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = call i32 (ptr, ...) @printf(ptr @1, i64 %0, i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define linkonce void @"__llgo_stub.main.main$2"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
tail call void @"main.main$2"(i64 %1, i64 %2)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"main.main$3"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { ptr }, ptr %0, align 8
|
||||||
|
%2 = extractvalue { ptr } %1, 0
|
||||||
|
%3 = load { ptr, ptr }, ptr %2, align 8
|
||||||
|
%4 = extractvalue { ptr, ptr } %3, 1
|
||||||
|
%5 = extractvalue { ptr, ptr } %3, 0
|
||||||
|
call void %5(ptr %4, i64 100, i64 200)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
17
cl/_testrt/concat/in.go
Normal file
17
cl/_testrt/concat/in.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func concat(args ...string) (ret string) {
|
||||||
|
for _, v := range args {
|
||||||
|
ret += v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := concat("Hello", " ", "World")
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))
|
||||||
|
}
|
||||||
106
cl/_testrt/concat/out.ll
Normal file
106
cl/_testrt/concat/out.ll
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||||
|
@1 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [2 x i8] c" \00", align 1
|
||||||
|
@3 = private unnamed_addr constant [6 x i8] c"World\00", align 1
|
||||||
|
@__stderrp = external global ptr
|
||||||
|
@4 = private unnamed_addr constant [8 x i8] c"Hi, %s\0A\00", align 1
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 0)
|
||||||
|
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 0
|
||||||
|
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
%5 = phi ptr [ %3, %_llgo_0 ], [ %18, %_llgo_2 ]
|
||||||
|
%6 = phi i64 [ %4, %_llgo_0 ], [ %19, %_llgo_2 ]
|
||||||
|
%7 = phi i64 [ -1, %_llgo_0 ], [ %12, %_llgo_2 ]
|
||||||
|
%8 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 0
|
||||||
|
store ptr %5, ptr %9, align 8
|
||||||
|
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 1
|
||||||
|
store i64 %6, ptr %10, align 4
|
||||||
|
%11 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %8, align 8
|
||||||
|
%12 = add i64 %7, 1
|
||||||
|
%13 = icmp slt i64 %12, %1
|
||||||
|
br i1 %13, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i64 %12
|
||||||
|
%16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8
|
||||||
|
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %16)
|
||||||
|
%18 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 0
|
||||||
|
%19 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 1
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %11
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 0
|
||||||
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %2, ptr %1, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 1
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %4, ptr %3, align 8
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 2
|
||||||
|
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %5, align 8
|
||||||
|
%7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 16, i64 3, i64 0, i64 3, i64 3)
|
||||||
|
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
|
%9 = load ptr, ptr @__stderrp, align 8
|
||||||
|
%10 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %8)
|
||||||
|
%11 = add i64 %10, 1
|
||||||
|
%12 = alloca i8, i64 %11, align 1
|
||||||
|
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %12, %"github.com/goplus/llgo/internal/runtime.String" %8)
|
||||||
|
%14 = call i32 (ptr, ptr, ...) @fprintf(ptr %9, ptr @4, ptr %13)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare i32 @fprintf(ptr, ptr, ...)
|
||||||
13
cl/_testrt/cstr/in.go
Normal file
13
cl/_testrt/cstr/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname cstr llgo.cstr
|
||||||
|
func cstr(string) *int8
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
printf(cstr("Hello, world\n"))
|
||||||
|
}
|
||||||
30
cl/_testrt/cstr/out.ll
Normal file
30
cl/_testrt/cstr/out.ll
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [14 x i8] c"Hello, world\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void (ptr, ...) @printf(ptr @0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
19
cl/_testrt/cvar/in.go
Normal file
19
cl/_testrt/cvar/in.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname barX _bar_x
|
||||||
|
var barX struct {
|
||||||
|
Arr [16]int8
|
||||||
|
Callbacks [2]func()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname barY _bar_y
|
||||||
|
var barY struct {
|
||||||
|
Arr [16]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_ = barX
|
||||||
|
_ = barY
|
||||||
|
}
|
||||||
30
cl/_testrt/cvar/out.ll
Normal file
30
cl/_testrt/cvar/out.ll
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@_bar_x = external global ptr
|
||||||
|
@_bar_y = external global ptr
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = load { [16 x i8], [2 x ptr] }, ptr @_bar_x, align 8
|
||||||
|
%1 = load { [16 x i8] }, ptr @_bar_y, align 1
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
16
cl/_testrt/fprintf/in.go
Normal file
16
cl/_testrt/fprintf/in.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
//go:linkname cstr llgo.cstr
|
||||||
|
func cstr(string) *int8
|
||||||
|
|
||||||
|
//go:linkname stderr __stderrp
|
||||||
|
var stderr unsafe.Pointer
|
||||||
|
|
||||||
|
//go:linkname fprintf C.fprintf
|
||||||
|
func fprintf(fp unsafe.Pointer, format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fprintf(stderr, cstr("Hello %d\n"), 100)
|
||||||
|
}
|
||||||
32
cl/_testrt/fprintf/out.ll
Normal file
32
cl/_testrt/fprintf/out.ll
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__stderrp = external global ptr
|
||||||
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = load ptr, ptr @__stderrp, align 8
|
||||||
|
call void (ptr, ptr, ...) @fprintf(ptr %0, ptr @0, i64 100)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @fprintf(ptr, ptr, ...)
|
||||||
32
cl/_testrt/gblarray/in.go
Normal file
32
cl/_testrt/gblarray/in.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/abi"
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Basic(kind abi.Kind) *abi.Type {
|
||||||
|
return basicTypes[kind]
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
basicTypes = [...]*abi.Type{
|
||||||
|
abi.String: basicType(abi.String),
|
||||||
|
}
|
||||||
|
sizeBasicTypes = [...]uintptr{
|
||||||
|
abi.String: 16,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func basicType(kind abi.Kind) *abi.Type {
|
||||||
|
return &abi.Type{
|
||||||
|
Size_: sizeBasicTypes[kind],
|
||||||
|
Hash: uint32(kind),
|
||||||
|
Kind_: uint8(kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := Basic(abi.String)
|
||||||
|
c.Printf(c.Str("Kind: %d, Size: %d\n"), int(t.Kind_), t.Size_)
|
||||||
|
}
|
||||||
71
cl/_testrt/gblarray/out.ll
Normal file
71
cl/_testrt/gblarray/out.ll
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
|
||||||
|
|
||||||
|
@main.basicTypes = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@main.sizeBasicTypes = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1
|
||||||
|
|
||||||
|
define ptr @main.Basic(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds ptr, ptr @main.basicTypes, i64 %0
|
||||||
|
%2 = load ptr, ptr %1, align 8
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @main.basicType(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 56)
|
||||||
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0
|
||||||
|
%3 = getelementptr inbounds i64, ptr @main.sizeBasicTypes, i64 %0
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2
|
||||||
|
%6 = trunc i64 %0 to i32
|
||||||
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6
|
||||||
|
%8 = trunc i64 %0 to i8
|
||||||
|
store i64 %4, ptr %2, align 4
|
||||||
|
store i32 %6, ptr %5, align 4
|
||||||
|
store i8 %8, ptr %7, align 1
|
||||||
|
ret ptr %1
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
call void @"github.com/goplus/llgo/internal/abi.init"()
|
||||||
|
store i64 16, ptr getelementptr inbounds (i64, ptr @main.sizeBasicTypes, i64 24), align 4
|
||||||
|
%1 = call ptr @main.basicType(i64 24)
|
||||||
|
store ptr %1, ptr getelementptr inbounds (ptr, ptr @main.basicTypes, i64 24), align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @main.Basic(i64 24)
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
|
||||||
|
%2 = load i8, ptr %1, align 1
|
||||||
|
%3 = sext i8 %2 to i64
|
||||||
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 0
|
||||||
|
%5 = load i64, ptr %4, align 4
|
||||||
|
%6 = call i32 (ptr, ...) @printf(ptr @0, i64 %3, i64 %5)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/abi.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
17
cl/_testrt/gotypes/in.go
Normal file
17
cl/_testrt/gotypes/in.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type base interface {
|
||||||
|
f(m map[string]func())
|
||||||
|
}
|
||||||
|
|
||||||
|
type bar interface {
|
||||||
|
base
|
||||||
|
g(c chan func())
|
||||||
|
}
|
||||||
|
|
||||||
|
func foo(bar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
foo(nil)
|
||||||
|
}
|
||||||
34
cl/_testrt/gotypes/out.ll
Normal file
34
cl/_testrt/gotypes/out.ll
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.foo(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @main.foo(%"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
10
cl/_testrt/hello/in.go
Normal file
10
cl/_testrt/hello/in.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/cl/internal/libc"
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sfmt := &format[0]
|
||||||
|
libc.Printf(sfmt, libc.Strlen(sfmt))
|
||||||
|
}
|
||||||
43
cl/_testrt/hello/out.ll
Normal file
43
cl/_testrt/hello/out.ll
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call i32 @strlen(ptr @main.format)
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @strlen(ptr)
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
25
cl/_testrt/index/in.go
Normal file
25
cl/_testrt/index/in.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
|
||||||
|
type point struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := [...]point{{1, 2}, {3, 4}, {5, 6}}[2]
|
||||||
|
c.Printf(c.Str("%d %d\n"), a.x, a.y)
|
||||||
|
|
||||||
|
b := [...][2]int{[2]int{1, 2}, [2]int{3, 4}}[1]
|
||||||
|
c.Printf(c.Str("%d %d\n"), b[0], b[1])
|
||||||
|
|
||||||
|
var i int = 2
|
||||||
|
n := [...]int{1, 2, 3, 4, 5}[i]
|
||||||
|
c.Printf(c.Str("%d\n"), n)
|
||||||
|
c.Printf(c.Str("%d\n"), [...]int{1, 2, 3, 4, 5}[i])
|
||||||
|
|
||||||
|
s := "123456"
|
||||||
|
c.Printf(c.Str("%c\n"), s[i])
|
||||||
|
c.Printf(c.Str("%c\n"), "123456"[1])
|
||||||
|
}
|
||||||
138
cl/_testrt/index/out.ll
Normal file
138
cl/_testrt/index/out.ll
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%main.point = type { i64, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [4 x i8] c"%c\0A\00", align 1
|
||||||
|
@5 = private unnamed_addr constant [7 x i8] c"123456\00", align 1
|
||||||
|
@6 = private unnamed_addr constant [4 x i8] c"%c\0A\00", align 1
|
||||||
|
@7 = private unnamed_addr constant [7 x i8] c"123456\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca %main.point, align 8
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 16)
|
||||||
|
%2 = alloca [3 x %main.point], align 8
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 48)
|
||||||
|
%4 = getelementptr inbounds %main.point, ptr %3, i64 0
|
||||||
|
%5 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 0
|
||||||
|
%6 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 1
|
||||||
|
%7 = getelementptr inbounds %main.point, ptr %3, i64 1
|
||||||
|
%8 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 0
|
||||||
|
%9 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 1
|
||||||
|
%10 = getelementptr inbounds %main.point, ptr %3, i64 2
|
||||||
|
%11 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 0
|
||||||
|
%12 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 1
|
||||||
|
store i64 1, ptr %5, align 4
|
||||||
|
store i64 2, ptr %6, align 4
|
||||||
|
store i64 3, ptr %8, align 4
|
||||||
|
store i64 4, ptr %9, align 4
|
||||||
|
store i64 5, ptr %11, align 4
|
||||||
|
store i64 6, ptr %12, align 4
|
||||||
|
%13 = load [3 x %main.point], ptr %3, align 4
|
||||||
|
%14 = getelementptr inbounds %main.point, ptr %3, i64 2
|
||||||
|
%15 = load %main.point, ptr %14, align 4
|
||||||
|
store %main.point %15, ptr %1, align 4
|
||||||
|
%16 = getelementptr inbounds %main.point, ptr %1, i32 0, i32 0
|
||||||
|
%17 = load i64, ptr %16, align 4
|
||||||
|
%18 = getelementptr inbounds %main.point, ptr %1, i32 0, i32 1
|
||||||
|
%19 = load i64, ptr %18, align 4
|
||||||
|
%20 = call i32 (ptr, ...) @printf(ptr @0, i64 %17, i64 %19)
|
||||||
|
%21 = alloca [2 x i64], align 8
|
||||||
|
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %21, i64 16)
|
||||||
|
%23 = alloca [2 x [2 x i64]], align 8
|
||||||
|
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %23, i64 32)
|
||||||
|
%25 = getelementptr inbounds [2 x i64], ptr %24, i64 0
|
||||||
|
%26 = getelementptr inbounds i64, ptr %25, i64 0
|
||||||
|
%27 = getelementptr inbounds i64, ptr %25, i64 1
|
||||||
|
%28 = getelementptr inbounds [2 x i64], ptr %24, i64 1
|
||||||
|
%29 = getelementptr inbounds i64, ptr %28, i64 0
|
||||||
|
%30 = getelementptr inbounds i64, ptr %28, i64 1
|
||||||
|
store i64 1, ptr %26, align 4
|
||||||
|
store i64 2, ptr %27, align 4
|
||||||
|
store i64 3, ptr %29, align 4
|
||||||
|
store i64 4, ptr %30, align 4
|
||||||
|
%31 = load [2 x [2 x i64]], ptr %24, align 4
|
||||||
|
%32 = getelementptr inbounds [2 x i64], ptr %24, i64 1
|
||||||
|
%33 = load [2 x i64], ptr %32, align 4
|
||||||
|
store [2 x i64] %33, ptr %22, align 4
|
||||||
|
%34 = getelementptr inbounds i64, ptr %22, i64 0
|
||||||
|
%35 = load i64, ptr %34, align 4
|
||||||
|
%36 = getelementptr inbounds i64, ptr %22, i64 1
|
||||||
|
%37 = load i64, ptr %36, align 4
|
||||||
|
%38 = call i32 (ptr, ...) @printf(ptr @1, i64 %35, i64 %37)
|
||||||
|
%39 = alloca [5 x i64], align 8
|
||||||
|
%40 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %39, i64 40)
|
||||||
|
%41 = getelementptr inbounds i64, ptr %40, i64 0
|
||||||
|
%42 = getelementptr inbounds i64, ptr %40, i64 1
|
||||||
|
%43 = getelementptr inbounds i64, ptr %40, i64 2
|
||||||
|
%44 = getelementptr inbounds i64, ptr %40, i64 3
|
||||||
|
%45 = getelementptr inbounds i64, ptr %40, i64 4
|
||||||
|
store i64 1, ptr %41, align 4
|
||||||
|
store i64 2, ptr %42, align 4
|
||||||
|
store i64 3, ptr %43, align 4
|
||||||
|
store i64 4, ptr %44, align 4
|
||||||
|
store i64 5, ptr %45, align 4
|
||||||
|
%46 = load [5 x i64], ptr %40, align 4
|
||||||
|
%47 = getelementptr inbounds i64, ptr %40, i64 2
|
||||||
|
%48 = load i64, ptr %47, align 4
|
||||||
|
%49 = call i32 (ptr, ...) @printf(ptr @2, i64 %48)
|
||||||
|
%50 = alloca [5 x i64], align 8
|
||||||
|
%51 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %50, i64 40)
|
||||||
|
%52 = getelementptr inbounds i64, ptr %51, i64 0
|
||||||
|
%53 = getelementptr inbounds i64, ptr %51, i64 1
|
||||||
|
%54 = getelementptr inbounds i64, ptr %51, i64 2
|
||||||
|
%55 = getelementptr inbounds i64, ptr %51, i64 3
|
||||||
|
%56 = getelementptr inbounds i64, ptr %51, i64 4
|
||||||
|
store i64 1, ptr %52, align 4
|
||||||
|
store i64 2, ptr %53, align 4
|
||||||
|
store i64 3, ptr %54, align 4
|
||||||
|
store i64 4, ptr %55, align 4
|
||||||
|
store i64 5, ptr %56, align 4
|
||||||
|
%57 = load [5 x i64], ptr %51, align 4
|
||||||
|
%58 = getelementptr inbounds i64, ptr %51, i64 2
|
||||||
|
%59 = load i64, ptr %58, align 4
|
||||||
|
%60 = call i32 (ptr, ...) @printf(ptr @3, i64 %59)
|
||||||
|
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
|
||||||
|
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
||||||
|
%63 = getelementptr inbounds i8, ptr %62, i64 2
|
||||||
|
%64 = load i8, ptr %63, align 1
|
||||||
|
%65 = call i32 (ptr, ...) @printf(ptr @4, i8 %64)
|
||||||
|
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
|
||||||
|
%67 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
||||||
|
%68 = getelementptr inbounds i8, ptr %67, i64 1
|
||||||
|
%69 = load i8, ptr %68, align 1
|
||||||
|
%70 = call i32 (ptr, ...) @printf(ptr @6, i8 %69)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
42
cl/_testrt/intgen/in.go
Normal file
42
cl/_testrt/intgen/in.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
type generator struct {
|
||||||
|
val c.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *generator) next() c.Int {
|
||||||
|
g.val++
|
||||||
|
return g.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func genInts(n int, gen func() c.Int) []c.Int {
|
||||||
|
a := make([]c.Int, n)
|
||||||
|
for i := range a {
|
||||||
|
a[i] = gen()
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, v := range genInts(5, c.Rand) {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
initVal := c.Int(1)
|
||||||
|
ints := genInts(5, func() c.Int {
|
||||||
|
initVal *= 2
|
||||||
|
return initVal
|
||||||
|
})
|
||||||
|
for _, v := range ints {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
g := &generator{val: 1}
|
||||||
|
for _, v := range genInts(5, g.next) {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
195
cl/_testrt/intgen/out.ll
Normal file
195
cl/_testrt/intgen/out.ll
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%main.generator = type { i32 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 %0, { ptr, ptr } %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = mul i64 %0, 4
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2)
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %3, i64 %0, i64 %0)
|
||||||
|
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
%6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ]
|
||||||
|
%7 = add i64 %6, 1
|
||||||
|
%8 = icmp slt i64 %7, %5
|
||||||
|
br i1 %8, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%9 = extractvalue { ptr, ptr } %1, 1
|
||||||
|
%10 = extractvalue { ptr, ptr } %1, 0
|
||||||
|
%11 = call i32 %10(ptr %9)
|
||||||
|
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
|
%13 = getelementptr inbounds i32, ptr %12, i64 %7
|
||||||
|
store i32 %11, ptr %13, align 4
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.Slice" %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @"(*main.generator).next"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0
|
||||||
|
%2 = load i32, ptr %1, align 4
|
||||||
|
%3 = add i32 %2, 1
|
||||||
|
%4 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0
|
||||||
|
store i32 %3, ptr %4, align 4
|
||||||
|
%5 = getelementptr inbounds %main.generator, ptr %0, i32 0, i32 0
|
||||||
|
%6 = load i32, ptr %5, align 4
|
||||||
|
ret i32 %6
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.rand, ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %3)
|
||||||
|
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
%6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ]
|
||||||
|
%7 = add i64 %6, 1
|
||||||
|
%8 = icmp slt i64 %7, %5
|
||||||
|
br i1 %8, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
|
%10 = getelementptr inbounds i32, ptr %9, i64 %7
|
||||||
|
%11 = load i32, ptr %10, align 4
|
||||||
|
%12 = call i32 (ptr, ...) @printf(ptr @0, i32 %11)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4)
|
||||||
|
store i32 1, ptr %13, align 4
|
||||||
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%15 = getelementptr inbounds { ptr }, ptr %14, i32 0, i32 0
|
||||||
|
store ptr %13, ptr %15, align 8
|
||||||
|
%16 = alloca { ptr, ptr }, align 8
|
||||||
|
%17 = getelementptr inbounds { ptr, ptr }, ptr %16, i32 0, i32 0
|
||||||
|
store ptr @"main.main$1", ptr %17, align 8
|
||||||
|
%18 = getelementptr inbounds { ptr, ptr }, ptr %16, i32 0, i32 1
|
||||||
|
store ptr %14, ptr %18, align 8
|
||||||
|
%19 = load { ptr, ptr }, ptr %16, align 8
|
||||||
|
%20 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %19)
|
||||||
|
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %20)
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_5, %_llgo_3
|
||||||
|
%22 = phi i64 [ -1, %_llgo_3 ], [ %23, %_llgo_5 ]
|
||||||
|
%23 = add i64 %22, 1
|
||||||
|
%24 = icmp slt i64 %23, %21
|
||||||
|
br i1 %24, label %_llgo_5, label %_llgo_6
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_4
|
||||||
|
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %20)
|
||||||
|
%26 = getelementptr inbounds i32, ptr %25, i64 %23
|
||||||
|
%27 = load i32, ptr %26, align 4
|
||||||
|
%28 = call i32 (ptr, ...) @printf(ptr @1, i32 %27)
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_4
|
||||||
|
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4)
|
||||||
|
%30 = getelementptr inbounds %main.generator, ptr %29, i32 0, i32 0
|
||||||
|
store i32 1, ptr %30, align 4
|
||||||
|
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%32 = getelementptr inbounds { ptr }, ptr %31, i32 0, i32 0
|
||||||
|
store ptr %29, ptr %32, align 8
|
||||||
|
%33 = alloca { ptr, ptr }, align 8
|
||||||
|
%34 = getelementptr inbounds { ptr, ptr }, ptr %33, i32 0, i32 0
|
||||||
|
store ptr @"main.next$bound", ptr %34, align 8
|
||||||
|
%35 = getelementptr inbounds { ptr, ptr }, ptr %33, i32 0, i32 1
|
||||||
|
store ptr %31, ptr %35, align 8
|
||||||
|
%36 = load { ptr, ptr }, ptr %33, align 8
|
||||||
|
%37 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %36)
|
||||||
|
%38 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %37)
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_8, %_llgo_6
|
||||||
|
%39 = phi i64 [ -1, %_llgo_6 ], [ %40, %_llgo_8 ]
|
||||||
|
%40 = add i64 %39, 1
|
||||||
|
%41 = icmp slt i64 %40, %38
|
||||||
|
br i1 %41, label %_llgo_8, label %_llgo_9
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_7
|
||||||
|
%42 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %37)
|
||||||
|
%43 = getelementptr inbounds i32, ptr %42, i64 %40
|
||||||
|
%44 = load i32, ptr %43, align 4
|
||||||
|
%45 = call i32 (ptr, ...) @printf(ptr @2, i32 %44)
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_7
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @rand()
|
||||||
|
|
||||||
|
define linkonce i32 @__llgo_stub.rand(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = tail call i32 @rand()
|
||||||
|
ret i32 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
define i32 @"main.main$1"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { ptr }, ptr %0, align 8
|
||||||
|
%2 = extractvalue { ptr } %1, 0
|
||||||
|
%3 = load i32, ptr %2, align 4
|
||||||
|
%4 = mul i32 %3, 2
|
||||||
|
%5 = extractvalue { ptr } %1, 0
|
||||||
|
store i32 %4, ptr %5, align 4
|
||||||
|
%6 = extractvalue { ptr } %1, 0
|
||||||
|
%7 = load i32, ptr %6, align 4
|
||||||
|
ret i32 %7
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
define i32 @"main.next$bound"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { ptr }, ptr %0, align 8
|
||||||
|
%2 = extractvalue { ptr } %1, 0
|
||||||
|
%3 = call i32 @"(*main.generator).next"(ptr %2)
|
||||||
|
ret i32 %3
|
||||||
|
}
|
||||||
15
cl/_testrt/linkname/in.go
Normal file
15
cl/_testrt/linkname/in.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname print github.com/goplus/llgo/cl/internal/linktarget.F
|
||||||
|
func print(a, b, c, d *c.Char)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print(c.Str("a"), c.Str("b"), c.Str("c"), c.Str("d"))
|
||||||
|
print(c.Str("1"), c.Str("2"), c.Str("3"), c.Str("4"))
|
||||||
|
}
|
||||||
38
cl/_testrt/linkname/out.ll
Normal file
38
cl/_testrt/linkname/out.ll
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [2 x i8] c"a\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [2 x i8] c"b\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [2 x i8] c"c\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [2 x i8] c"d\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [2 x i8] c"1\00", align 1
|
||||||
|
@5 = private unnamed_addr constant [2 x i8] c"2\00", align 1
|
||||||
|
@6 = private unnamed_addr constant [2 x i8] c"3\00", align 1
|
||||||
|
@7 = private unnamed_addr constant [2 x i8] c"4\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr @0, ptr @1, ptr @2, ptr @3)
|
||||||
|
call void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr @4, ptr @5, ptr @6, ptr @7)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr, ptr, ptr, ptr)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
10
cl/_testrt/map/in.go
Normal file
10
cl/_testrt/map/in.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := map[int]int{23: 100, 7: 29}
|
||||||
|
c.Printf(c.Str("Hello %d\n"), a[23])
|
||||||
|
}
|
||||||
33
cl/_testrt/map/out.ll
Normal file
33
cl/_testrt/map/out.ll
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
|
||||||
|
%1 = call i32 (ptr, ...) @printf(ptr @0, <null operand!>)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
5
cl/_testrt/panic/in.go
Normal file
5
cl/_testrt/panic/in.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
panic("panic message")
|
||||||
|
}
|
||||||
39
cl/_testrt/panic/out.ll
Normal file
39
cl/_testrt/panic/out.ll
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [14 x i8] c"panic message\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 13)
|
||||||
|
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %1)
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface")
|
||||||
20
cl/_testrt/qsort/in.go
Normal file
20
cl/_testrt/qsort/in.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname qsort C.qsort
|
||||||
|
func qsort(base c.Pointer, count, elem uintptr, compar func(a, b c.Pointer) c.Int)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := [...]int{100, 8, 23, 2, 7}
|
||||||
|
qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), func(a, b c.Pointer) c.Int {
|
||||||
|
return c.Int(*(*int)(a) - *(*int)(b))
|
||||||
|
})
|
||||||
|
for _, v := range a {
|
||||||
|
c.Printf(c.Str("%d\n"), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
71
cl/_testrt/qsort/out.ll
Normal file
71
cl/_testrt/qsort/out.ll
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
|
||||||
|
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
||||||
|
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
||||||
|
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
||||||
|
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
||||||
|
%5 = getelementptr inbounds i64, ptr %0, i64 4
|
||||||
|
store i64 100, ptr %1, align 4
|
||||||
|
store i64 8, ptr %2, align 4
|
||||||
|
store i64 23, ptr %3, align 4
|
||||||
|
store i64 2, ptr %4, align 4
|
||||||
|
store i64 7, ptr %5, align 4
|
||||||
|
%6 = getelementptr inbounds i64, ptr %0, i64 0
|
||||||
|
call void @qsort(ptr %6, i64 5, i64 8, ptr @"main.main$1")
|
||||||
|
%7 = load [5 x i64], ptr %0, align 4
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
%8 = phi i64 [ -1, %_llgo_0 ], [ %9, %_llgo_2 ]
|
||||||
|
%9 = add i64 %8, 1
|
||||||
|
%10 = icmp slt i64 %9, 5
|
||||||
|
br i1 %10, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%11 = getelementptr inbounds i64, ptr %0, i64 %9
|
||||||
|
%12 = load i64, ptr %11, align 4
|
||||||
|
%13 = call i32 (ptr, ...) @printf(ptr @0, i64 %12)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare void @qsort(ptr, i64, i64, ptr)
|
||||||
|
|
||||||
|
define i32 @"main.main$1"(ptr %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = load i64, ptr %0, align 4
|
||||||
|
%3 = load i64, ptr %1, align 4
|
||||||
|
%4 = sub i64 %2, %3
|
||||||
|
%5 = trunc i64 %4 to i32
|
||||||
|
ret i32 %5
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
29
cl/_testrt/result/in.go
Normal file
29
cl/_testrt/result/in.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fn := func() func(int, int) int {
|
||||||
|
return func(x, y int) int {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
c.Printf(c.Str("%d\n"), fn(100, 200))
|
||||||
|
c.Printf(c.Str("%d\n"), add()(100, 200))
|
||||||
|
fn, n := add2()
|
||||||
|
c.Printf(c.Str("%d %d\n"), add()(100, 200), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func add() func(int, int) int {
|
||||||
|
return func(x, y int) int {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func add2() (func(int, int) int, int) {
|
||||||
|
return func(x, y int) int {
|
||||||
|
return x + y
|
||||||
|
}, 1
|
||||||
|
}
|
||||||
120
cl/_testrt/result/out.ll
Normal file
120
cl/_testrt/result/out.ll
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
||||||
|
|
||||||
|
define { ptr, ptr } @main.add() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.add$1", ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
ret { ptr, ptr } %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define { { ptr, ptr }, i64 } @main.add2() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.add2$1", ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
%mrv = insertvalue { { ptr, ptr }, i64 } poison, { ptr, ptr } %3, 0
|
||||||
|
%mrv1 = insertvalue { { ptr, ptr }, i64 } %mrv, i64 1, 1
|
||||||
|
ret { { ptr, ptr }, i64 } %mrv1
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call { ptr, ptr } @"main.main$1"()
|
||||||
|
%1 = extractvalue { ptr, ptr } %0, 1
|
||||||
|
%2 = extractvalue { ptr, ptr } %0, 0
|
||||||
|
%3 = call i64 %2(ptr %1, i64 100, i64 200)
|
||||||
|
%4 = call i32 (ptr, ...) @printf(ptr @0, i64 %3)
|
||||||
|
%5 = call { ptr, ptr } @main.add()
|
||||||
|
%6 = extractvalue { ptr, ptr } %5, 1
|
||||||
|
%7 = extractvalue { ptr, ptr } %5, 0
|
||||||
|
%8 = call i64 %7(ptr %6, i64 100, i64 200)
|
||||||
|
%9 = call i32 (ptr, ...) @printf(ptr @1, i64 %8)
|
||||||
|
%10 = call { { ptr, ptr }, i64 } @main.add2()
|
||||||
|
%11 = extractvalue { { ptr, ptr }, i64 } %10, 0
|
||||||
|
%12 = extractvalue { { ptr, ptr }, i64 } %10, 1
|
||||||
|
%13 = call { ptr, ptr } @main.add()
|
||||||
|
%14 = extractvalue { ptr, ptr } %13, 1
|
||||||
|
%15 = extractvalue { ptr, ptr } %13, 0
|
||||||
|
%16 = call i64 %15(ptr %14, i64 100, i64 200)
|
||||||
|
%17 = call i32 (ptr, ...) @printf(ptr @2, i64 %16, i64 %12)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"main.add$1"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define linkonce i64 @"__llgo_stub.main.add$1"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = tail call i64 @"main.add$1"(i64 %1, i64 %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"main.add2$1"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define linkonce i64 @"__llgo_stub.main.add2$1"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = tail call i64 @"main.add2$1"(i64 %1, i64 %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
define { ptr, ptr } @"main.main$1"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.main$1$1", ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
ret { ptr, ptr } %3
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
define i64 @"main.main$1$1"(i64 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = add i64 %0, %1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define linkonce i64 @"__llgo_stub.main.main$1$1"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = tail call i64 @"main.main$1$1"(i64 %1, i64 %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
17
cl/_testrt/strlen/in.go
Normal file
17
cl/_testrt/strlen/in.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
//go:linkname strlen C.strlen
|
||||||
|
func strlen(str *int8) C.int
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sfmt := &format[0]
|
||||||
|
printf(sfmt, strlen(sfmt))
|
||||||
|
}
|
||||||
43
cl/_testrt/strlen/out.ll
Normal file
43
cl/_testrt/strlen/out.ll
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call i32 @strlen(ptr @main.format)
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @strlen(ptr)
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
25
cl/_testrt/struct/in.go
Normal file
25
cl/_testrt/struct/in.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
type Foo struct {
|
||||||
|
A C.int
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func (p Foo) Print() {
|
||||||
|
if p.ok {
|
||||||
|
printf(&format[0], p.A)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
foo := Foo{100, true}
|
||||||
|
foo.Print()
|
||||||
|
}
|
||||||
77
cl/_testrt/struct/out.ll
Normal file
77
cl/_testrt/struct/out.ll
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%main.Foo = type { i32, i1 }
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @"(main.Foo).Print"(%main.Foo %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %main.Foo, align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 8)
|
||||||
|
store %main.Foo %0, ptr %2, align 4
|
||||||
|
%3 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 1
|
||||||
|
%4 = load i1, ptr %3, align 1
|
||||||
|
br i1 %4, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%5 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 0
|
||||||
|
%6 = load i32, ptr %5, align 4
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i32 %6)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"(*main.Foo).Print"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load %main.Foo, ptr %0, align 4
|
||||||
|
call void @"(main.Foo).Print"(%main.Foo %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca %main.Foo, align 8
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 8)
|
||||||
|
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 0
|
||||||
|
%3 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
|
||||||
|
store i32 100, ptr %2, align 4
|
||||||
|
store i1 true, ptr %3, align 1
|
||||||
|
%4 = load %main.Foo, ptr %1, align 4
|
||||||
|
call void @"(main.Foo).Print"(%main.Foo %4)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
16
cl/_testrt/sum/in.go
Normal file
16
cl/_testrt/sum/in.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sum(args ...int) (ret int) {
|
||||||
|
for _, v := range args {
|
||||||
|
ret += v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello %d\n"), sum(1, 2, 3, 4))
|
||||||
|
}
|
||||||
74
cl/_testrt/sum/out.ll
Normal file
74
cl/_testrt/sum/out.ll
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
|
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
||||||
|
store i64 1, ptr %1, align 4
|
||||||
|
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
||||||
|
store i64 2, ptr %2, align 4
|
||||||
|
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
||||||
|
store i64 3, ptr %3, align 4
|
||||||
|
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
||||||
|
store i64 4, ptr %4, align 4
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4)
|
||||||
|
%6 = call i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
||||||
|
%7 = call i32 (ptr, ...) @printf(ptr @0, i64 %6)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
%2 = phi i64 [ 0, %_llgo_0 ], [ %9, %_llgo_2 ]
|
||||||
|
%3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ]
|
||||||
|
%4 = add i64 %3, 1
|
||||||
|
%5 = icmp slt i64 %4, %1
|
||||||
|
br i1 %5, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%7 = getelementptr inbounds i64, ptr %6, i64 %4
|
||||||
|
%8 = load i64, ptr %7, align 4
|
||||||
|
%9 = add i64 %2, %8
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
25
cl/_testrt/typalias/in.go
Normal file
25
cl/_testrt/typalias/in.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname printf C.printf
|
||||||
|
func printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
type Foo = struct {
|
||||||
|
A C.int
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
|
||||||
|
|
||||||
|
func Print(p *Foo) {
|
||||||
|
if p.ok {
|
||||||
|
printf(&format[0], p.A)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
foo := &Foo{100, true}
|
||||||
|
Print(foo)
|
||||||
|
}
|
||||||
63
cl/_testrt/typalias/out.ll
Normal file
63
cl/_testrt/typalias/out.ll
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@main.format = global ptr null
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define void @main.Print(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
||||||
|
%2 = load i1, ptr %1, align 1
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%3 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
||||||
|
%4 = load i32, ptr %3, align 4
|
||||||
|
call void (ptr, ...) @printf(ptr @main.format, i32 %4)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i8 72, ptr @main.format, align 1
|
||||||
|
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
|
||||||
|
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
|
||||||
|
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
|
||||||
|
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
|
||||||
|
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
|
||||||
|
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
|
||||||
|
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
|
||||||
|
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
|
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
||||||
|
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
||||||
|
store i32 100, ptr %1, align 4
|
||||||
|
store i1 true, ptr %2, align 1
|
||||||
|
call void @main.Print(ptr %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
||||||
14
cl/_testrt/unreachable/in.go
Normal file
14
cl/_testrt/unreachable/in.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
c.Unreachable()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
foo()
|
||||||
|
c.Printf(c.Str("Hello\n"))
|
||||||
|
}
|
||||||
37
cl/_testrt/unreachable/out.ll
Normal file
37
cl/_testrt/unreachable/out.ll
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.foo() {
|
||||||
|
_llgo_0:
|
||||||
|
unreachable
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @main.foo()
|
||||||
|
%0 = call i32 (ptr, ...) @printf(ptr @0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
187
cl/builtin_test.go
Normal file
187
cl/builtin_test.go
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/constant"
|
||||||
|
"go/types"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
|
"golang.org/x/tools/go/ssa"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
func TestErrCompileValue(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != "can't use llgo instruction as a value" {
|
||||||
|
t.Fatal("TestErrCompileValue:", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
pkg := types.NewPackage("foo", "foo")
|
||||||
|
ctx := &context{
|
||||||
|
goTyps: pkg,
|
||||||
|
link: map[string]string{
|
||||||
|
"foo.": "llgo.unreachable",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx.compileValue(nil, &ssa.Function{
|
||||||
|
Pkg: &ssa.Package{Pkg: pkg},
|
||||||
|
Signature: types.NewSignatureType(nil, nil, nil, nil, nil, false),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func TestErrCompileInstrOrValue(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("compileInstrOrValue: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ctx := &context{
|
||||||
|
bvals: make(map[ssa.Value]llssa.Expr),
|
||||||
|
}
|
||||||
|
ctx.compileInstrOrValue(nil, &ssa.Call{}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrAdvance(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("advance: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var ctx context
|
||||||
|
ctx.advance(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrAlloca(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("alloca: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var ctx context
|
||||||
|
ctx.alloca(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCStrNoArgs(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("cstr: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cstr(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCStrNonconst(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("cstr: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cstr(nil, []ssa.Value{&ssa.Parameter{}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPkgNoInit(t *testing.T) {
|
||||||
|
pkg := types.NewPackage("foo", "foo")
|
||||||
|
ctx := &context{
|
||||||
|
goTyps: pkg,
|
||||||
|
loaded: make(map[*types.Package]*pkgInfo),
|
||||||
|
}
|
||||||
|
if ctx.pkgNoInit(pkg) {
|
||||||
|
t.Fatal("pkgNoInit?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPkgKind(t *testing.T) {
|
||||||
|
if v := pkgKind("noinit"); v != PkgNoInit {
|
||||||
|
t.Fatal("pkgKind:", v)
|
||||||
|
}
|
||||||
|
if v := pkgKind(""); v != PkgLLGo {
|
||||||
|
t.Fatal("pkgKind:", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPkgKindOf(t *testing.T) {
|
||||||
|
if v := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
|
||||||
|
t.Fatal("PkgKindOf unsafe:", v)
|
||||||
|
}
|
||||||
|
pkg := types.NewPackage("foo", "foo")
|
||||||
|
pkg.Scope().Insert(
|
||||||
|
types.NewConst(
|
||||||
|
0, pkg, "LLGoPackage", types.Typ[types.String],
|
||||||
|
constant.MakeString("noinit")),
|
||||||
|
)
|
||||||
|
if v := PkgKindOf(pkg); v != PkgNoInit {
|
||||||
|
t.Fatal("PkgKindOf foo:", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsAny(t *testing.T) {
|
||||||
|
if isAny(types.Typ[types.UntypedInt]) {
|
||||||
|
t.Fatal("isAny?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntVal(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("intVal: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
intVal(&ssa.Parameter{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIgnoreName(t *testing.T) {
|
||||||
|
if !ignoreName("runtime.foo") || !ignoreName("runtime/foo") || !ignoreName("internal/abi") {
|
||||||
|
t.Fatal("ignoreName failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrImport(t *testing.T) {
|
||||||
|
var ctx context
|
||||||
|
pkg := types.NewPackage("foo", "foo")
|
||||||
|
ctx.importPkg(pkg, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrInitLinkname(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("initLinkname: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var ctx context
|
||||||
|
ctx.initLinkname("foo", "//go:linkname Printf printf", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrVarOf(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("varOf: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
prog := llssa.NewProgram(nil)
|
||||||
|
pkg := prog.NewPackage("foo", "foo")
|
||||||
|
pkgTypes := types.NewPackage("foo", "foo")
|
||||||
|
ctx := &context{
|
||||||
|
pkg: pkg,
|
||||||
|
goTyps: pkgTypes,
|
||||||
|
}
|
||||||
|
ssaPkg := &ssa.Package{Pkg: pkgTypes}
|
||||||
|
g := &ssa.Global{Pkg: ssaPkg}
|
||||||
|
ctx.varOf(g)
|
||||||
|
}
|
||||||
131
cl/cltest/cltest.go
Normal file
131
cl/cltest/cltest.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cltest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/goplus/gogen/packages"
|
||||||
|
"github.com/goplus/llgo/cl"
|
||||||
|
"github.com/goplus/llgo/internal/llgen"
|
||||||
|
"golang.org/x/tools/go/ssa"
|
||||||
|
"golang.org/x/tools/go/ssa/ssautil"
|
||||||
|
|
||||||
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cl.SetDebug(cl.DbgFlagAll)
|
||||||
|
llssa.Initialize(llssa.InitAll | llssa.InitNative)
|
||||||
|
llssa.SetDebug(llssa.DbgFlagAll)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromDir(t *testing.T, sel, relDir string, byLLGen bool) {
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Getwd failed:", err)
|
||||||
|
}
|
||||||
|
dir = path.Join(dir, relDir)
|
||||||
|
fis, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("ReadDir failed:", err)
|
||||||
|
}
|
||||||
|
for _, fi := range fis {
|
||||||
|
name := fi.Name()
|
||||||
|
if !fi.IsDir() || strings.HasPrefix(name, "_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
testFrom(t, dir+"/"+name, sel, byLLGen)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pkg(t *testing.T, pkgPath, outFile string) {
|
||||||
|
b, err := os.ReadFile(outFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("ReadFile failed:", err)
|
||||||
|
}
|
||||||
|
expected := string(b)
|
||||||
|
if v := llgen.GenFrom(pkgPath); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
|
||||||
|
if sel != "" && !strings.Contains(pkgDir, sel) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("Parsing", pkgDir)
|
||||||
|
in := pkgDir + "/in.go"
|
||||||
|
out := pkgDir + "/out.ll"
|
||||||
|
b, err := os.ReadFile(out)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("ReadFile failed:", err)
|
||||||
|
}
|
||||||
|
expected := string(b)
|
||||||
|
if byLLGen {
|
||||||
|
if v := llgen.GenFrom(in); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TestCompileEx(t, nil, in, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompileEx(t *testing.T, src any, fname, expected string) {
|
||||||
|
t.Helper()
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("ParseFile failed:", err)
|
||||||
|
}
|
||||||
|
files := []*ast.File{f}
|
||||||
|
name := f.Name.Name
|
||||||
|
pkg := types.NewPackage(name, name)
|
||||||
|
imp := packages.NewImporter(fset)
|
||||||
|
foo, _, err := ssautil.BuildPackage(
|
||||||
|
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("BuildPackage failed:", err)
|
||||||
|
}
|
||||||
|
foo.WriteTo(os.Stderr)
|
||||||
|
prog := llssa.NewProgram(nil)
|
||||||
|
prog.SetRuntime(func() *types.Package {
|
||||||
|
rt, err := imp.Import(llssa.PkgRuntime)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("load runtime failed:", err)
|
||||||
|
}
|
||||||
|
return rt
|
||||||
|
})
|
||||||
|
|
||||||
|
ret, err := cl.NewPackage(prog, foo, files)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("cl.NewPackage failed:", err)
|
||||||
|
}
|
||||||
|
if v := ret.String(); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
613
cl/compile.go
613
cl/compile.go
@@ -19,11 +19,13 @@ package cl
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
@@ -56,16 +58,16 @@ func SetDebug(dbgFlags dbgFlags) {
|
|||||||
const (
|
const (
|
||||||
fnNormal = iota
|
fnNormal = iota
|
||||||
fnHasVArg
|
fnHasVArg
|
||||||
fnUnsafeInit
|
fnIgnore
|
||||||
)
|
)
|
||||||
|
|
||||||
func funcKind(vfn ssa.Value) int {
|
func (p *context) funcKind(vfn ssa.Value) int {
|
||||||
if fn, ok := vfn.(*ssa.Function); ok && fn.Signature.Recv() == nil {
|
if fn, ok := vfn.(*ssa.Function); ok && fn.Signature.Recv() == nil {
|
||||||
params := fn.Signature.Params()
|
params := fn.Signature.Params()
|
||||||
n := params.Len()
|
n := params.Len()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
if fn.Name() == "init" && fn.Pkg.Pkg.Path() == "unsafe" {
|
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
||||||
return fnUnsafeInit
|
return fnIgnore
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
last := params.At(n - 1)
|
last := params.At(n - 1)
|
||||||
@@ -77,106 +79,410 @@ func funcKind(vfn ssa.Value) int {
|
|||||||
return fnNormal
|
return fnNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *context) pkgNoInit(pkg *types.Package) bool {
|
||||||
|
p.ensureLoaded(pkg)
|
||||||
|
if i, ok := p.loaded[pkg]; ok {
|
||||||
|
return i.kind >= PkgNoInit
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ignoreName(name string) bool {
|
||||||
|
/* TODO(xsw): confirm this is not needed more
|
||||||
|
if name == "unsafe.init" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") ||
|
||||||
|
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
|
||||||
|
strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
|
||||||
|
strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") ||
|
||||||
|
strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "errors.") {
|
||||||
|
return true // TODO(xsw)
|
||||||
|
}
|
||||||
|
return inPkg(name, "runtime") || inPkg(name, "sync")
|
||||||
|
}
|
||||||
|
|
||||||
|
func inPkg(name, pkg string) bool {
|
||||||
|
if len(name) > len(pkg) && strings.HasPrefix(name, pkg) {
|
||||||
|
c := name[len(pkg)]
|
||||||
|
return c == '.' || c == '/'
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type none = struct{}
|
type instrOrValue interface {
|
||||||
|
|
||||||
type instrAndValue interface {
|
|
||||||
ssa.Instruction
|
ssa.Instruction
|
||||||
ssa.Value
|
ssa.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PkgNormal = iota
|
||||||
|
PkgLLGo
|
||||||
|
PkgNoInit // noinit: a package that don't need to be initialized
|
||||||
|
PkgDeclOnly // decl: a package that only have declarations
|
||||||
|
)
|
||||||
|
|
||||||
|
type pkgInfo struct {
|
||||||
|
kind int
|
||||||
|
}
|
||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
prog llssa.Program
|
prog llssa.Program
|
||||||
pkg llssa.Package
|
pkg llssa.Package
|
||||||
fn llssa.Function
|
fn llssa.Function
|
||||||
fset *token.FileSet
|
fset *token.FileSet
|
||||||
|
goProg *ssa.Program
|
||||||
goTyps *types.Package
|
goTyps *types.Package
|
||||||
goPkg *ssa.Package
|
goPkg *ssa.Package
|
||||||
link map[string]string // pkgPath.nameInPkg => linkname
|
link map[string]string // pkgPath.nameInPkg => linkname
|
||||||
loaded map[*types.Package]none // loaded packages
|
loaded map[*types.Package]*pkgInfo // loaded packages
|
||||||
bvals map[ssa.Value]llssa.Expr // block values
|
bvals map[ssa.Value]llssa.Expr // block values
|
||||||
|
vargs map[*ssa.Alloc][]llssa.Expr // varargs
|
||||||
inits []func()
|
inits []func()
|
||||||
|
phis []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileType(pkg llssa.Package, member *ssa.Type) {
|
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
||||||
panic("todo")
|
tn := t.Object().(*types.TypeName)
|
||||||
|
if tn.IsAlias() { // don't need to compile alias type
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tnName := tn.Name()
|
||||||
|
typ := tn.Type()
|
||||||
|
name := llssa.FullName(tn.Pkg(), tnName)
|
||||||
|
if ignoreName(name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("==> NewType", name, typ)
|
||||||
|
}
|
||||||
|
p.compileMethods(pkg, typ)
|
||||||
|
p.compileMethods(pkg, types.NewPointer(typ))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
||||||
|
prog := p.goProg
|
||||||
|
mthds := prog.MethodSets.MethodSet(typ)
|
||||||
|
for i, n := 0, mthds.Len(); i < n; i++ {
|
||||||
|
mthd := mthds.At(i)
|
||||||
|
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
||||||
|
p.compileFuncDecl(pkg, mthd.Obj().Pkg(), ssaMthd)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global variable.
|
// Global variable.
|
||||||
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
||||||
typ := gbl.Type()
|
typ := gbl.Type()
|
||||||
name := fullName(gbl.Pkg.Pkg, gbl.Name())
|
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
|
||||||
if debugInstr {
|
if ignoreName(name) || checkCgo(gbl.Name()) {
|
||||||
log.Println("==> NewVar", name, typ)
|
|
||||||
}
|
|
||||||
g := pkg.NewVar(name, typ)
|
|
||||||
g.Init(p.prog.Null(g.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
|
|
||||||
name := p.funcName(f.Pkg.Pkg, f)
|
|
||||||
if name == "unsafe.init" {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewFunc", name)
|
log.Println("==> NewVar", name, typ)
|
||||||
|
}
|
||||||
|
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
||||||
|
if vtype == goVar {
|
||||||
|
g.Init(p.prog.Null(g.Type))
|
||||||
}
|
}
|
||||||
fn := pkg.NewFunc(name, f.Signature)
|
|
||||||
p.inits = append(p.inits, func() {
|
|
||||||
p.fn = fn
|
|
||||||
defer func() {
|
|
||||||
p.fn = nil
|
|
||||||
}()
|
|
||||||
nblk := len(f.Blocks)
|
|
||||||
if nblk == 0 { // external function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if debugGoSSA {
|
|
||||||
f.WriteTo(os.Stderr)
|
|
||||||
}
|
|
||||||
if debugInstr {
|
|
||||||
log.Println("==> FuncBody", name)
|
|
||||||
}
|
|
||||||
fn.MakeBlocks(nblk)
|
|
||||||
b := fn.NewBuilder()
|
|
||||||
for i, block := range f.Blocks {
|
|
||||||
p.compileBlock(b, block, i == 0 && name == "main")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bool) llssa.BasicBlock {
|
func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var {
|
||||||
|
n := len(vars)
|
||||||
|
flds := make([]*types.Var, n)
|
||||||
|
for i, v := range vars {
|
||||||
|
flds[i] = types.NewField(token.NoPos, pkg, v.Name(), v.Type(), false)
|
||||||
|
}
|
||||||
|
t := types.NewPointer(types.NewStruct(flds, nil))
|
||||||
|
return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compileFuncDecl(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function) llssa.Function {
|
||||||
|
name, ftype := p.funcName(pkgTypes, f, true)
|
||||||
|
if ftype != goFunc {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fn := pkg.FuncOf(name)
|
||||||
|
if fn != nil && fn.HasBody() {
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
var sig = f.Signature
|
||||||
|
var hasCtx = len(f.FreeVars) > 0
|
||||||
|
if hasCtx {
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("==> NewClosure", name, "type:", sig)
|
||||||
|
}
|
||||||
|
ctx := makeClosureCtx(pkgTypes, f.FreeVars)
|
||||||
|
sig = llssa.FuncAddCtx(ctx, sig)
|
||||||
|
} else {
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fn == nil {
|
||||||
|
fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx)
|
||||||
|
}
|
||||||
|
if nblk := len(f.Blocks); nblk > 0 {
|
||||||
|
fn.MakeBlocks(nblk) // to set fn.HasBody() = true
|
||||||
|
p.inits = append(p.inits, func() {
|
||||||
|
p.fn = fn
|
||||||
|
defer func() {
|
||||||
|
p.fn = nil
|
||||||
|
}()
|
||||||
|
p.phis = nil
|
||||||
|
if debugGoSSA {
|
||||||
|
f.WriteTo(os.Stderr)
|
||||||
|
}
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("==> FuncBody", name)
|
||||||
|
}
|
||||||
|
b := fn.NewBuilder()
|
||||||
|
p.bvals = make(map[ssa.Value]llssa.Expr)
|
||||||
|
off := make([]int, len(f.Blocks))
|
||||||
|
for i, block := range f.Blocks {
|
||||||
|
off[i] = p.compilePhis(b, block)
|
||||||
|
}
|
||||||
|
for i, block := range f.Blocks {
|
||||||
|
p.compileBlock(b, block, off[i], i == 0 && name == "main")
|
||||||
|
}
|
||||||
|
for _, phi := range p.phis {
|
||||||
|
phi()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
|
||||||
|
// or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
|
||||||
|
func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
|
||||||
|
pkgTypes := p.ensureLoaded(fn.Pkg.Pkg)
|
||||||
|
pkg := p.pkg
|
||||||
|
name, ftype := p.funcName(pkgTypes, fn, false)
|
||||||
|
if ftype == llgoInstr {
|
||||||
|
switch name {
|
||||||
|
case "cstr":
|
||||||
|
ftype = llgoCstr
|
||||||
|
case "advance":
|
||||||
|
ftype = llgoAdvance
|
||||||
|
case "alloca":
|
||||||
|
ftype = llgoAlloca
|
||||||
|
case "allocaCStr":
|
||||||
|
ftype = llgoAllocaCStr
|
||||||
|
case "unreachable":
|
||||||
|
ftype = llgoUnreachable
|
||||||
|
default:
|
||||||
|
panic("unknown llgo instruction: " + name)
|
||||||
|
}
|
||||||
|
} else if ret = pkg.FuncOf(name); ret == nil && len(fn.FreeVars) == 0 {
|
||||||
|
sig := fn.Signature
|
||||||
|
ret = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doInit bool) llssa.BasicBlock {
|
||||||
ret := p.fn.Block(block.Index)
|
ret := p.fn.Block(block.Index)
|
||||||
b.SetBlock(ret)
|
b.SetBlock(ret)
|
||||||
p.bvals = make(map[ssa.Value]llssa.Expr)
|
|
||||||
if doInit {
|
if doInit {
|
||||||
fn := p.pkg.FuncOf("main.init")
|
pkg := p.pkg
|
||||||
b.Call(fn.Expr)
|
callRuntimeInit(b, pkg)
|
||||||
|
b.Call(pkg.FuncOf("main.init").Expr)
|
||||||
}
|
}
|
||||||
for _, instr := range block.Instrs {
|
for _, instr := range block.Instrs[n:] {
|
||||||
p.compileInstr(b, instr)
|
p.compileInstr(b, instr)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret llssa.Expr) {
|
const (
|
||||||
if v, ok := p.bvals[iv]; ok {
|
RuntimeInit = llssa.PkgRuntime + ".init"
|
||||||
return v
|
)
|
||||||
|
|
||||||
|
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
||||||
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
|
fn := pkg.NewFunc(RuntimeInit, sig, llssa.InC) // don't need to convert runtime.init
|
||||||
|
b.Call(fn.Expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAny(t types.Type) bool {
|
||||||
|
if t, ok := t.(*types.Interface); ok {
|
||||||
|
return t.Empty()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func intVal(v ssa.Value) int64 {
|
||||||
|
if c, ok := v.(*ssa.Const); ok {
|
||||||
|
if iv, exact := constant.Int64Val(c.Value); exact {
|
||||||
|
return iv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("intVal: ssa.Value is not a const int")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
||||||
|
if va, vok := vx.(*ssa.Alloc); vok {
|
||||||
|
ret, ok = p.vargs[va] // varargs: this is a varargs index
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
||||||
|
if v.Comment == "varargs" { // this is a varargs allocation
|
||||||
|
if arr, ok := t.Elem().(*types.Array); ok {
|
||||||
|
if isAny(arr.Elem()) {
|
||||||
|
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// func cstr(string) *int8
|
||||||
|
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 1 {
|
||||||
|
if c, ok := args[0].(*ssa.Const); ok {
|
||||||
|
if v := c.Value; v.Kind() == constant.String {
|
||||||
|
sv := constant.StringVal(v)
|
||||||
|
return b.CStr(sv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("cstr(<string-literal>): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 2 {
|
||||||
|
ptr := p.compileValue(b, args[0])
|
||||||
|
offset := p.compileValue(b, args[1])
|
||||||
|
return b.Advance(ptr, offset)
|
||||||
|
}
|
||||||
|
panic("advance(p ptr, offset int): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
// func alloca(size uintptr) unsafe.Pointer
|
||||||
|
func (p *context) alloca(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 1 {
|
||||||
|
n := p.compileValue(b, args[0])
|
||||||
|
return b.Alloca(n)
|
||||||
|
}
|
||||||
|
panic("alloca(size uintptr): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
// func allocaCStr(s string) *int8
|
||||||
|
func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 1 {
|
||||||
|
s := p.compileValue(b, args[0])
|
||||||
|
return b.AllocaCStr(s)
|
||||||
|
}
|
||||||
|
panic("allocaCStr(s string): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPhi(i ssa.Instruction) bool {
|
||||||
|
_, ok := i.(*ssa.Phi)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
|
||||||
|
ret := p.fn.Block(block.Index)
|
||||||
|
b.SetBlock(ret)
|
||||||
|
if ninstr := len(block.Instrs); ninstr > 0 {
|
||||||
|
if isPhi(block.Instrs[0]) {
|
||||||
|
n := 1
|
||||||
|
for n < ninstr && isPhi(block.Instrs[n]) {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
rets := make([]llssa.Expr, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
iv := block.Instrs[i].(*ssa.Phi)
|
||||||
|
rets[i] = p.compilePhi(b, iv)
|
||||||
|
}
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
iv := block.Instrs[i].(*ssa.Phi)
|
||||||
|
p.bvals[iv] = rets[i].Do(b)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
|
||||||
|
phi := b.Phi(p.prog.Type(v.Type(), llssa.InGo))
|
||||||
|
ret = phi.Expr
|
||||||
|
p.phis = append(p.phis, func() {
|
||||||
|
preds := v.Block().Preds
|
||||||
|
bblks := make([]llssa.BasicBlock, len(preds))
|
||||||
|
for i, pred := range preds {
|
||||||
|
bblks[i] = p.fn.Block(pred.Index)
|
||||||
|
}
|
||||||
|
edges := v.Edges
|
||||||
|
phi.AddIncoming(b, bblks, func(i int) llssa.Expr {
|
||||||
|
return p.compileValue(b, edges[i])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue bool) (ret llssa.Expr) {
|
||||||
|
if asValue {
|
||||||
|
if v, ok := p.bvals[iv]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
log.Panicln("unreachable:", iv)
|
||||||
}
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
case *ssa.Call:
|
case *ssa.Call:
|
||||||
call := v.Call
|
call := v.Call
|
||||||
kind := funcKind(call.Value)
|
cv := call.Value
|
||||||
if kind == fnUnsafeInit {
|
kind := p.funcKind(cv)
|
||||||
|
if kind == fnIgnore {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugGoSSA {
|
if debugGoSSA {
|
||||||
log.Println(">>> Call", call.Value, call.Args)
|
log.Println(">>> Call", cv, call.Args)
|
||||||
|
}
|
||||||
|
switch cv := cv.(type) {
|
||||||
|
case *ssa.Builtin:
|
||||||
|
fn := cv.Name()
|
||||||
|
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
|
||||||
|
arg := call.Args[0]
|
||||||
|
ret = p.compileValue(b, arg)
|
||||||
|
// log.Println("wrapnilchk:", ret.TypeOf())
|
||||||
|
} else {
|
||||||
|
args := p.compileValues(b, call.Args, kind)
|
||||||
|
ret = b.BuiltinCall(fn, args...)
|
||||||
|
}
|
||||||
|
case *ssa.Function:
|
||||||
|
fn, ftype := p.compileFunction(cv)
|
||||||
|
switch ftype {
|
||||||
|
case goFunc, cFunc:
|
||||||
|
args := p.compileValues(b, call.Args, kind)
|
||||||
|
ret = b.Call(fn.Expr, args...)
|
||||||
|
case llgoCstr:
|
||||||
|
ret = cstr(b, call.Args)
|
||||||
|
case llgoAdvance:
|
||||||
|
ret = p.advance(b, call.Args)
|
||||||
|
case llgoAlloca:
|
||||||
|
ret = p.alloca(b, call.Args)
|
||||||
|
case llgoAllocaCStr:
|
||||||
|
ret = p.allocaCStr(b, call.Args)
|
||||||
|
case llgoUnreachable: // func unreachable()
|
||||||
|
b.Unreachable()
|
||||||
|
default:
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fn := p.compileValue(b, cv)
|
||||||
|
args := p.compileValues(b, call.Args, kind)
|
||||||
|
ret = b.Call(fn, args...)
|
||||||
}
|
}
|
||||||
fn := p.compileValue(b, call.Value)
|
|
||||||
args := p.compileValues(b, call.Args, kind)
|
|
||||||
ret = b.Call(fn, args...)
|
|
||||||
case *ssa.BinOp:
|
case *ssa.BinOp:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
y := p.compileValue(b, v.Y)
|
y := p.compileValue(b, v.Y)
|
||||||
@@ -184,13 +490,97 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
|
|||||||
case *ssa.UnOp:
|
case *ssa.UnOp:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.UnOp(v.Op, x)
|
ret = b.UnOp(v.Op, x)
|
||||||
case *ssa.IndexAddr:
|
case *ssa.ChangeType:
|
||||||
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
|
ret = b.ChangeType(p.prog.Type(t, llssa.InGo), x)
|
||||||
|
case *ssa.Convert:
|
||||||
|
t := v.Type()
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
ret = b.Convert(p.prog.Type(t, llssa.InGo), x)
|
||||||
|
case *ssa.FieldAddr:
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
ret = b.FieldAddr(x, v.Field)
|
||||||
|
case *ssa.Alloc:
|
||||||
|
t := v.Type().(*types.Pointer)
|
||||||
|
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
||||||
|
return
|
||||||
|
}
|
||||||
|
elem := p.prog.Type(t.Elem(), llssa.InGo)
|
||||||
|
ret = b.Alloc(elem, v.Heap)
|
||||||
|
case *ssa.IndexAddr:
|
||||||
|
vx := v.X
|
||||||
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
||||||
|
return
|
||||||
|
}
|
||||||
|
x := p.compileValue(b, vx)
|
||||||
idx := p.compileValue(b, v.Index)
|
idx := p.compileValue(b, v.Index)
|
||||||
ret = b.IndexAddr(x, idx)
|
ret = b.IndexAddr(x, idx)
|
||||||
case *ssa.Alloc:
|
case *ssa.Index:
|
||||||
t := v.Type()
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.Alloc(p.prog.Type(t), v.Heap)
|
idx := p.compileValue(b, v.Index)
|
||||||
|
ret = b.Index(x, idx, func(e llssa.Expr) (ret llssa.Expr) {
|
||||||
|
if e == x {
|
||||||
|
if n, ok := v.X.(*ssa.UnOp); ok {
|
||||||
|
return p.compileValue(b, n.X)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("todo: addr of %v", e))
|
||||||
|
})
|
||||||
|
case *ssa.Lookup:
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
idx := p.compileValue(b, v.Index)
|
||||||
|
ret = b.Lookup(x, idx, v.CommaOk)
|
||||||
|
case *ssa.Slice:
|
||||||
|
vx := v.X
|
||||||
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var low, high, max llssa.Expr
|
||||||
|
x := p.compileValue(b, vx)
|
||||||
|
if v.Low != nil {
|
||||||
|
low = p.compileValue(b, v.Low)
|
||||||
|
}
|
||||||
|
if v.High != nil {
|
||||||
|
high = p.compileValue(b, v.High)
|
||||||
|
}
|
||||||
|
if v.Max != nil {
|
||||||
|
max = p.compileValue(b, v.Max)
|
||||||
|
}
|
||||||
|
ret = b.Slice(x, low, high, max)
|
||||||
|
case *ssa.MakeInterface:
|
||||||
|
const (
|
||||||
|
delayExpr = true // varargs: don't need to convert an expr to any
|
||||||
|
)
|
||||||
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
ret = b.MakeInterface(t, x, delayExpr)
|
||||||
|
case *ssa.MakeSlice:
|
||||||
|
var nCap llssa.Expr
|
||||||
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
|
nLen := p.compileValue(b, v.Len)
|
||||||
|
if v.Cap != nil {
|
||||||
|
nCap = p.compileValue(b, v.Cap)
|
||||||
|
}
|
||||||
|
ret = b.MakeSlice(t, nLen, nCap)
|
||||||
|
case *ssa.MakeMap:
|
||||||
|
var nReserve llssa.Expr
|
||||||
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
|
if v.Reserve != nil {
|
||||||
|
nReserve = p.compileValue(b, v.Reserve)
|
||||||
|
}
|
||||||
|
ret = b.MakeMap(t, nReserve)
|
||||||
|
case *ssa.MakeClosure:
|
||||||
|
fn := p.compileValue(b, v.Fn)
|
||||||
|
bindings := p.compileValues(b, v.Bindings, 0)
|
||||||
|
ret = b.MakeClosure(fn, bindings)
|
||||||
|
case *ssa.TypeAssert:
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
t := p.prog.Type(v.AssertedType, llssa.InGo)
|
||||||
|
ret = b.TypeAssert(x, t, v.CommaOk)
|
||||||
|
case *ssa.Extract:
|
||||||
|
x := p.compileValue(b, v.Tuple)
|
||||||
|
ret = b.Extract(x, v.Index)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
|
panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
|
||||||
}
|
}
|
||||||
@@ -199,13 +589,25 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
||||||
if iv, ok := instr.(instrAndValue); ok {
|
if iv, ok := instr.(instrOrValue); ok {
|
||||||
p.compileInstrAndValue(b, iv)
|
p.compileInstrOrValue(b, iv, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch v := instr.(type) {
|
switch v := instr.(type) {
|
||||||
case *ssa.Store:
|
case *ssa.Store:
|
||||||
ptr := p.compileValue(b, v.Addr)
|
va := v.Addr
|
||||||
|
if va, ok := va.(*ssa.IndexAddr); ok {
|
||||||
|
if args, ok := p.isVArgs(va.X); ok { // varargs: this is a varargs store
|
||||||
|
idx := intVal(va.Index)
|
||||||
|
val := v.Val
|
||||||
|
if vi, ok := val.(*ssa.MakeInterface); ok {
|
||||||
|
val = vi.X
|
||||||
|
}
|
||||||
|
args[idx] = p.compileValue(b, val)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr := p.compileValue(b, va)
|
||||||
val := p.compileValue(b, v.Val)
|
val := p.compileValue(b, v.Val)
|
||||||
b.Store(ptr, val)
|
b.Store(ptr, val)
|
||||||
case *ssa.Jump:
|
case *ssa.Jump:
|
||||||
@@ -229,14 +631,33 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
thenb := fn.Block(succs[0].Index)
|
thenb := fn.Block(succs[0].Index)
|
||||||
elseb := fn.Block(succs[1].Index)
|
elseb := fn.Block(succs[1].Index)
|
||||||
b.If(cond, thenb, elseb)
|
b.If(cond, thenb, elseb)
|
||||||
|
case *ssa.MapUpdate:
|
||||||
|
m := p.compileValue(b, v.Map)
|
||||||
|
key := p.compileValue(b, v.Key)
|
||||||
|
val := p.compileValue(b, v.Value)
|
||||||
|
b.MapUpdate(m, key, val)
|
||||||
|
case *ssa.Panic:
|
||||||
|
arg := p.compileValue(b, v.X).Do(b)
|
||||||
|
b.Panic(arg)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
|
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *context) compileFunction(v *ssa.Function) (llssa.Function, int) {
|
||||||
|
// v.Pkg == nil: means auto generated function?
|
||||||
|
if v.Pkg == p.goPkg || v.Pkg == nil {
|
||||||
|
// function in this package
|
||||||
|
if fn := p.compileFuncDecl(p.pkg, p.goTyps, v); fn != nil {
|
||||||
|
return fn, goFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.funcOf(v)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
||||||
if iv, ok := v.(instrAndValue); ok {
|
if iv, ok := v.(instrOrValue); ok {
|
||||||
return p.compileInstrAndValue(b, iv)
|
return p.compileInstrOrValue(b, iv, true)
|
||||||
}
|
}
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case *ssa.Parameter:
|
case *ssa.Parameter:
|
||||||
@@ -247,14 +668,21 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
fn := p.funcOf(v)
|
fn, _ := p.compileFunction(v)
|
||||||
return fn.Expr
|
return fn.Expr
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
g := p.varOf(v)
|
g := p.varOf(v)
|
||||||
return g.Expr
|
return g.Expr
|
||||||
case *ssa.Const:
|
case *ssa.Const:
|
||||||
t := v.Type()
|
t := types.Default(v.Type())
|
||||||
return b.Const(v.Value, p.prog.Type(t))
|
return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
|
||||||
|
case *ssa.FreeVar:
|
||||||
|
fn := v.Parent()
|
||||||
|
for idx, freeVar := range fn.FreeVars {
|
||||||
|
if freeVar == v {
|
||||||
|
return p.fn.FreeVar(b, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
|
panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
|
||||||
}
|
}
|
||||||
@@ -262,19 +690,23 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []llssa.Expr {
|
func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []llssa.Expr {
|
||||||
_ = b
|
_ = b
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
|
case *ssa.Slice: // varargs: this is a varargs slice
|
||||||
|
if args, ok := p.isVArgs(v.X); ok {
|
||||||
|
return append(ret, args...)
|
||||||
|
}
|
||||||
case *ssa.Const:
|
case *ssa.Const:
|
||||||
if v.Value == nil {
|
if v.Value == nil {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) []llssa.Expr {
|
func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) []llssa.Expr {
|
||||||
n := len(vals) - hasVArg
|
n := len(vals) - hasVArg
|
||||||
ret := make([]llssa.Expr, n)
|
ret := make([]llssa.Expr, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ret[i] = p.compileValue(b, vals[i])
|
ret[i] = p.compileValue(b, vals[i]).Do(b)
|
||||||
}
|
}
|
||||||
if hasVArg > 0 {
|
if hasVArg > 0 {
|
||||||
ret = p.compileVArg(ret, b, vals[n])
|
ret = p.compileVArg(ret, b, vals[n])
|
||||||
@@ -291,31 +723,34 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
val ssa.Member
|
val ssa.Member
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by position, so that the order of the functions in the IR matches
|
members := make([]*namedMember, 0, len(pkg.Members))
|
||||||
// the order of functions in the source file. This is useful for testing,
|
|
||||||
// for example.
|
|
||||||
var members []*namedMember
|
|
||||||
for name, v := range pkg.Members {
|
for name, v := range pkg.Members {
|
||||||
members = append(members, &namedMember{name, v})
|
members = append(members, &namedMember{name, v})
|
||||||
}
|
}
|
||||||
sort.Slice(members, func(i, j int) bool {
|
sort.Slice(members, func(i, j int) bool {
|
||||||
iPos := members[i].val.Pos()
|
return members[i].name < members[j].name
|
||||||
jPos := members[j].val.Pos()
|
|
||||||
return iPos < jPos
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
pkgProg := pkg.Prog
|
||||||
pkgTypes := pkg.Pkg
|
pkgTypes := pkg.Pkg
|
||||||
pkgName, pkgPath := pkgTypes.Name(), pkgTypes.Path()
|
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
|
||||||
|
if pkgPath == llssa.PkgRuntime {
|
||||||
|
prog.SetRuntime(pkgTypes)
|
||||||
|
}
|
||||||
ret = prog.NewPackage(pkgName, pkgPath)
|
ret = prog.NewPackage(pkgName, pkgPath)
|
||||||
|
|
||||||
ctx := &context{
|
ctx := &context{
|
||||||
prog: prog,
|
prog: prog,
|
||||||
pkg: ret,
|
pkg: ret,
|
||||||
fset: pkg.Prog.Fset,
|
fset: pkgProg.Fset,
|
||||||
|
goProg: pkgProg,
|
||||||
goTyps: pkgTypes,
|
goTyps: pkgTypes,
|
||||||
goPkg: pkg,
|
goPkg: pkg,
|
||||||
link: make(map[string]string),
|
link: make(map[string]string),
|
||||||
loaded: make(map[*types.Package]none),
|
vargs: make(map[*ssa.Alloc][]llssa.Expr),
|
||||||
|
loaded: map[*types.Package]*pkgInfo{
|
||||||
|
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
|
||||||
|
},
|
||||||
}
|
}
|
||||||
ctx.initFiles(pkgPath, files)
|
ctx.initFiles(pkgPath, files)
|
||||||
for _, m := range members {
|
for _, m := range members {
|
||||||
@@ -326,15 +761,19 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
// Do not try to build generic (non-instantiated) functions.
|
// Do not try to build generic (non-instantiated) functions.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctx.compileFunc(ret, member)
|
ctx.compileFuncDecl(ret, member.Pkg.Pkg, member)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
ctx.compileType(ret, member)
|
ctx.compileType(ret, member)
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
ctx.compileGlobal(ret, member)
|
ctx.compileGlobal(ret, member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, ini := range ctx.inits {
|
for len(ctx.inits) > 0 {
|
||||||
ini()
|
inits := ctx.inits
|
||||||
|
ctx.inits = nil
|
||||||
|
for _, ini := range inits {
|
||||||
|
ini()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,101 +14,30 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cl
|
package cl_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/gogen/packages"
|
"github.com/goplus/llgo/cl/cltest"
|
||||||
"golang.org/x/tools/go/ssa"
|
"github.com/goplus/llgo/ssa"
|
||||||
"golang.org/x/tools/go/ssa/ssautil"
|
|
||||||
|
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
|
||||||
testFromDir(t, "", "./_testdata")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
SetDebug(DbgFlagAll)
|
|
||||||
llssa.Initialize(llssa.InitAll)
|
|
||||||
llssa.SetDebug(llssa.DbgFlagAll)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testFromDir(t *testing.T, sel, relDir string) {
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Getwd failed:", err)
|
|
||||||
}
|
|
||||||
dir = path.Join(dir, relDir)
|
|
||||||
fis, err := os.ReadDir(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("ReadDir failed:", err)
|
|
||||||
}
|
|
||||||
for _, fi := range fis {
|
|
||||||
name := fi.Name()
|
|
||||||
if !fi.IsDir() || strings.HasPrefix(name, "_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
testFrom(t, dir+"/"+name, sel)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testFrom(t *testing.T, pkgDir, sel string) {
|
|
||||||
if sel != "" && !strings.Contains(pkgDir, sel) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Println("Parsing", pkgDir)
|
|
||||||
in := pkgDir + "/in.go"
|
|
||||||
out := pkgDir + "/out.ll"
|
|
||||||
expected, err := os.ReadFile(out)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("ReadFile failed:", err)
|
|
||||||
}
|
|
||||||
testCompileEx(t, nil, in, string(expected))
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCompileEx(t *testing.T, src any, fname, expected string) {
|
|
||||||
t.Helper()
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("ParseFile failed:", err)
|
|
||||||
}
|
|
||||||
files := []*ast.File{f}
|
|
||||||
name := f.Name.Name
|
|
||||||
pkg := types.NewPackage(name, name)
|
|
||||||
imp := packages.NewImporter(fset)
|
|
||||||
foo, _, err := ssautil.BuildPackage(
|
|
||||||
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("BuildPackage failed:", err)
|
|
||||||
}
|
|
||||||
foo.WriteTo(os.Stderr)
|
|
||||||
prog := llssa.NewProgram(nil)
|
|
||||||
ret, err := NewPackage(prog, foo, files)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cl.NewPackage failed:", err)
|
|
||||||
}
|
|
||||||
if v := ret.String(); v != expected {
|
|
||||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCompile(t *testing.T, src, expected string) {
|
func testCompile(t *testing.T, src, expected string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testCompileEx(t, src, "foo.go", expected)
|
cltest.TestCompileEx(t, src, "foo.go", expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromTestrt(t *testing.T) {
|
||||||
|
cltest.FromDir(t, "", "./_testrt", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
cltest.FromDir(t, "", "./_testdata", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuntime(t *testing.T) {
|
||||||
|
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
@@ -118,8 +47,8 @@ var a int
|
|||||||
`, `; ModuleID = 'foo'
|
`, `; ModuleID = 'foo'
|
||||||
source_filename = "foo"
|
source_filename = "foo"
|
||||||
|
|
||||||
@"foo.init$guard" = global ptr null
|
|
||||||
@foo.a = global ptr null
|
@foo.a = global ptr null
|
||||||
|
@"foo.init$guard" = global ptr null
|
||||||
|
|
||||||
define void @foo.init() {
|
define void @foo.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -147,6 +76,11 @@ source_filename = "foo"
|
|||||||
|
|
||||||
@"foo.init$guard" = global ptr null
|
@"foo.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define i64 @foo.fn(i64 %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
ret i64 1
|
||||||
|
}
|
||||||
|
|
||||||
define void @foo.init() {
|
define void @foo.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"foo.init$guard", align 1
|
%0 = load i1, ptr @"foo.init$guard", align 1
|
||||||
@@ -159,10 +93,5 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define i64 @foo.fn(i64 %0, double %1) {
|
|
||||||
_llgo_0:
|
|
||||||
ret i64 1
|
|
||||||
}
|
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|||||||
208
cl/import.go
208
cl/import.go
@@ -19,6 +19,7 @@ package cl
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
@@ -43,31 +44,60 @@ func contentOf(m contentMap, file string) (lines contentLines, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) importPkg(pkg *types.Package) {
|
// PkgKindOf returns the kind of a package.
|
||||||
|
func PkgKindOf(pkg *types.Package) int {
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
if scope.Lookup("LLGoPackage") == nil {
|
kind := pkgKindByScope(scope)
|
||||||
|
if kind == PkgNormal {
|
||||||
|
kind = pkgKindByPath(pkg.Path())
|
||||||
|
}
|
||||||
|
return kind
|
||||||
|
}
|
||||||
|
|
||||||
|
// decl: a package that only contains declarations
|
||||||
|
// noinit: a package that does not need to be initialized
|
||||||
|
func pkgKind(v string) int {
|
||||||
|
switch v {
|
||||||
|
case "decl":
|
||||||
|
return PkgDeclOnly
|
||||||
|
case "noinit":
|
||||||
|
return PkgNoInit
|
||||||
|
}
|
||||||
|
return PkgLLGo
|
||||||
|
}
|
||||||
|
|
||||||
|
func pkgKindByScope(scope *types.Scope) int {
|
||||||
|
if v, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
|
||||||
|
if v := v.Val(); v.Kind() == constant.String {
|
||||||
|
return pkgKind(constant.StringVal(v))
|
||||||
|
}
|
||||||
|
return PkgLLGo
|
||||||
|
}
|
||||||
|
return PkgNormal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
||||||
|
scope := pkg.Scope()
|
||||||
|
kind := pkgKindByScope(scope)
|
||||||
|
if kind == PkgNormal {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
i.kind = kind
|
||||||
fset := p.fset
|
fset := p.fset
|
||||||
names := scope.Names()
|
names := scope.Names()
|
||||||
contents := make(contentMap)
|
contents := make(contentMap)
|
||||||
pkgPath := pkg.Path()
|
pkgPath := llssa.PathOf(pkg)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if token.IsExported(name) {
|
if token.IsExported(name) {
|
||||||
obj := scope.Lookup(name)
|
obj := scope.Lookup(name)
|
||||||
if obj, ok := obj.(*types.Func); ok {
|
switch obj := obj.(type) {
|
||||||
|
case *types.Func:
|
||||||
if pos := obj.Pos(); pos != token.NoPos {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
f := fset.File(pos)
|
p.initLinknameByPos(fset, pos, pkgPath, contents, false)
|
||||||
if fp := f.Position(pos); fp.Line > 2 {
|
}
|
||||||
lines, err := contentOf(contents, fp.Filename)
|
case *types.Var:
|
||||||
if err != nil {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
panic(err)
|
p.initLinknameByPos(fset, pos, pkgPath, contents, true)
|
||||||
}
|
|
||||||
if i := fp.Line - 2; i < len(lines) {
|
|
||||||
line := string(lines[i])
|
|
||||||
p.initLinkname(pkgPath, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,84 +107,160 @@ func (p *context) importPkg(pkg *types.Package) {
|
|||||||
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
for _, decl := range file.Decls {
|
for _, decl := range file.Decls {
|
||||||
if decl, ok := decl.(*ast.FuncDecl); ok {
|
switch decl := decl.(type) {
|
||||||
|
case *ast.FuncDecl:
|
||||||
if decl.Recv == nil {
|
if decl.Recv == nil {
|
||||||
if doc := decl.Doc; doc != nil {
|
p.initLinknameByDoc(decl.Doc, pkgPath, false)
|
||||||
if n := len(doc.List); n > 0 {
|
}
|
||||||
line := doc.List[n-1].Text
|
case *ast.GenDecl:
|
||||||
p.initLinkname(pkgPath, line)
|
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
|
||||||
}
|
p.initLinknameByDoc(decl.Doc, pkgPath, true)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinkname(pkgPath, line string) {
|
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, pkgPath string, isVar bool) {
|
||||||
|
if doc != nil {
|
||||||
|
if n := len(doc.List); n > 0 {
|
||||||
|
line := doc.List[n-1].Text
|
||||||
|
p.initLinkname(pkgPath, line, isVar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) initLinknameByPos(fset *token.FileSet, pos token.Pos, pkgPath string, contents contentMap, isVar bool) {
|
||||||
|
f := fset.File(pos)
|
||||||
|
if fp := f.Position(pos); fp.Line > 2 {
|
||||||
|
lines, err := contentOf(contents, fp.Filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if i := fp.Line - 2; i < len(lines) {
|
||||||
|
line := string(lines[i])
|
||||||
|
p.initLinkname(pkgPath, line, isVar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) initLinkname(pkgPath, line string, isVar bool) {
|
||||||
const (
|
const (
|
||||||
linkname = "//go:linkname "
|
linkname = "//go:linkname "
|
||||||
)
|
)
|
||||||
if strings.HasPrefix(line, linkname) {
|
if strings.HasPrefix(line, linkname) {
|
||||||
text := strings.TrimSpace(line[len(linkname):])
|
text := strings.TrimSpace(line[len(linkname):])
|
||||||
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
||||||
name := pkgPath + "." + text[:idx]
|
|
||||||
link := strings.TrimLeft(text[idx+1:], " ")
|
link := strings.TrimLeft(text[idx+1:], " ")
|
||||||
p.link[name] = link
|
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
||||||
|
name := pkgPath + "." + text[:idx]
|
||||||
|
p.link[name] = link
|
||||||
|
} else {
|
||||||
|
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullName(pkg *types.Package, name string) string {
|
// func: pkg.name
|
||||||
pkgPath := pkg.Name()
|
// method: (pkg.T).name, (*pkg.T).name
|
||||||
if pkgPath != "main" {
|
|
||||||
pkgPath = pkg.Path()
|
|
||||||
}
|
|
||||||
return pkgPath + "." + name
|
|
||||||
}
|
|
||||||
|
|
||||||
func funcName(pkg *types.Package, fn *ssa.Function) string {
|
func funcName(pkg *types.Package, fn *ssa.Function) string {
|
||||||
ret := fullName(pkg, fn.Name())
|
sig := fn.Signature
|
||||||
|
name := fn.Name()
|
||||||
|
if recv := sig.Recv(); recv != nil {
|
||||||
|
var tName string
|
||||||
|
t := recv.Type()
|
||||||
|
if tp, ok := t.(*types.Pointer); ok {
|
||||||
|
t, tName = tp.Elem(), "*"
|
||||||
|
}
|
||||||
|
tName += llssa.NameOf(t.(*types.Named))
|
||||||
|
return "(" + tName + ")." + name
|
||||||
|
}
|
||||||
|
ret := llssa.FullName(pkg, name)
|
||||||
if ret == "main.main" {
|
if ret == "main.main" {
|
||||||
ret = "main"
|
ret = "main"
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) funcName(pkg *types.Package, fn *ssa.Function) string {
|
func checkCgo(fnName string) bool {
|
||||||
|
return len(fnName) > 4 && fnName[0] == '_' && fnName[2] == 'g' && fnName[3] == 'o' &&
|
||||||
|
(fnName[1] == 'C' || fnName[1] == 'c') &&
|
||||||
|
(fnName[4] == '_' || strings.HasPrefix(fnName[4:], "Check"))
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ignoredFunc = iota
|
||||||
|
goFunc = int(llssa.InGo)
|
||||||
|
cFunc = int(llssa.InC)
|
||||||
|
llgoInstr = -1
|
||||||
|
|
||||||
|
llgoInstrBase = 0x80
|
||||||
|
llgoUnreachable = llgoInstrBase + 0
|
||||||
|
llgoCstr = llgoInstrBase + 1
|
||||||
|
llgoAlloca = llgoInstrBase + 2
|
||||||
|
llgoAllocaCStr = llgoInstrBase + 3
|
||||||
|
llgoAdvance = llgoInstrBase + 4
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, int) {
|
||||||
name := funcName(pkg, fn)
|
name := funcName(pkg, fn)
|
||||||
|
if ignore && ignoreName(name) || checkCgo(fn.Name()) {
|
||||||
|
return name, ignoredFunc
|
||||||
|
}
|
||||||
if v, ok := p.link[name]; ok {
|
if v, ok := p.link[name]; ok {
|
||||||
return v
|
if strings.HasPrefix(v, "C.") {
|
||||||
|
return v[2:], cFunc
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(v, "llgo.") {
|
||||||
|
return v[5:], llgoInstr
|
||||||
|
}
|
||||||
|
return v, goFunc
|
||||||
}
|
}
|
||||||
return name
|
return name, goFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) funcOf(fn *ssa.Function) llssa.Function {
|
const (
|
||||||
pkgTypes := p.ensureLoaded(fn.Pkg.Pkg)
|
ignoredVar = iota
|
||||||
pkg := p.pkg
|
goVar = int(llssa.InGo)
|
||||||
name := p.funcName(pkgTypes, fn)
|
cVar = int(llssa.InC)
|
||||||
if ret := pkg.FuncOf(name); ret != nil {
|
)
|
||||||
return ret
|
|
||||||
|
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
||||||
|
name := llssa.FullName(pkg, v.Name())
|
||||||
|
if v, ok := p.link[name]; ok {
|
||||||
|
return v, cVar
|
||||||
}
|
}
|
||||||
return pkg.NewFunc(name, fn.Signature)
|
return name, goVar
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) varOf(v *ssa.Global) llssa.Global {
|
func (p *context) varOf(v *ssa.Global) (ret llssa.Global) {
|
||||||
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
|
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
|
||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
name := fullName(pkgTypes, v.Name())
|
name, vtype := p.varName(pkgTypes, v)
|
||||||
if ret := pkg.VarOf(name); ret != nil {
|
if ret = pkg.VarOf(name); ret == nil {
|
||||||
return ret
|
ret = pkg.NewVar(name, v.Type(), llssa.Background(vtype))
|
||||||
}
|
}
|
||||||
return pkg.NewVar(name, v.Type())
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
||||||
if p.goTyps != pkgTypes {
|
if p.goTyps != pkgTypes {
|
||||||
if _, ok := p.loaded[pkgTypes]; !ok {
|
if _, ok := p.loaded[pkgTypes]; !ok {
|
||||||
p.loaded[pkgTypes] = none{}
|
i := &pkgInfo{
|
||||||
p.importPkg(pkgTypes)
|
kind: pkgKindByPath(pkgTypes.Path()),
|
||||||
|
}
|
||||||
|
p.loaded[pkgTypes] = i
|
||||||
|
p.importPkg(pkgTypes, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pkgTypes
|
return pkgTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pkgKindByPath(pkgPath string) int {
|
||||||
|
switch pkgPath {
|
||||||
|
case "syscall", "runtime/cgo", "unsafe":
|
||||||
|
return PkgDeclOnly
|
||||||
|
}
|
||||||
|
return PkgNormal
|
||||||
|
}
|
||||||
|
|||||||
14
cl/internal/libc/libc.go
Normal file
14
cl/internal/libc/libc.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package libc
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Printf C.printf
|
||||||
|
func Printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
|
//go:linkname Strlen C.strlen
|
||||||
|
func Strlen(str *int8) C.int
|
||||||
9
cl/internal/linktarget/foo.go
Normal file
9
cl/internal/linktarget/foo.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package linktarget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func F(a, b *c.Char) {
|
||||||
|
c.Printf(c.Str("a: %s, b: %s\n"), a, b)
|
||||||
|
}
|
||||||
26
cl/internal/linktarget/out.ll
Normal file
26
cl/internal/linktarget/out.ll
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/cl/internal/linktarget'
|
||||||
|
source_filename = "github.com/goplus/llgo/cl/internal/linktarget"
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/cl/internal/linktarget.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [14 x i8] c"a: %s, b: %s\0A\00", align 1
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = call i32 (ptr, ...) @printf(ptr @0, ptr %0, ptr %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/internal/linktarget.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
@@ -6,7 +6,7 @@ const (
|
|||||||
LLGoPackage = true
|
LLGoPackage = true
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname Printf printf
|
//go:linkname Printf C.printf
|
||||||
func Printf(format *int8, __llgo_va_list ...any)
|
func Printf(format *int8, __llgo_va_list ...any)
|
||||||
|
|
||||||
func Max(a, b int) int {
|
func Max(a, b int) int {
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cl
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Define unimplemented intrinsic functions.
|
|
||||||
//
|
|
||||||
// Some functions are either normally implemented in Go assembly (like
|
|
||||||
// sync/atomic functions) or intentionally left undefined to be implemented
|
|
||||||
// directly in the compiler (like runtime/volatile functions). Either way, look
|
|
||||||
// for these and implement them if this is the case.
|
|
||||||
func (b *builder) defineIntrinsicFunction() {
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
|
||||||
"math.Ceil": "llvm.ceil.f64",
|
|
||||||
"math.Exp": "llvm.exp.f64",
|
|
||||||
"math.Exp2": "llvm.exp2.f64",
|
|
||||||
"math.Floor": "llvm.floor.f64",
|
|
||||||
"math.Log": "llvm.log.f64",
|
|
||||||
"math.Sqrt": "llvm.sqrt.f64",
|
|
||||||
"math.Trunc": "llvm.trunc.f64",
|
|
||||||
}
|
|
||||||
|
|
||||||
// defineMathOp defines a math function body as a call to a LLVM intrinsic,
|
|
||||||
// instead of the regular Go implementation. This allows LLVM to reason about
|
|
||||||
// the math operation and (depending on the architecture) allows it to lower the
|
|
||||||
// operation to very fast floating point instructions. If this is not possible,
|
|
||||||
// LLVM will emit a call to a libm function that implements the same operation.
|
|
||||||
//
|
|
||||||
// One example of an optimization that LLVM can do is to convert
|
|
||||||
// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
|
|
||||||
// beneficial on architectures where 64-bit floating point operations are (much)
|
|
||||||
// more expensive than 32-bit ones.
|
|
||||||
func (b *builder) defineMathOp() {
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement most math/bits functions.
|
|
||||||
//
|
|
||||||
// This implements all the functions that operate on bits. It does not yet
|
|
||||||
// implement the arithmetic functions (like bits.Add), which also have LLVM
|
|
||||||
// intrinsics.
|
|
||||||
func (b *builder) defineMathBitsIntrinsic() bool {
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -33,8 +33,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
build.Do(args, &build.Config{
|
conf := &build.Config{
|
||||||
Mode: build.ModeBuild,
|
Mode: build.ModeBuild,
|
||||||
AppExt: build.DefaultAppExt(),
|
AppExt: build.DefaultAppExt(),
|
||||||
})
|
}
|
||||||
|
if len(args) >= 2 && args[0] == "-o" {
|
||||||
|
conf.OutFile = args[1]
|
||||||
|
args = args[2:]
|
||||||
|
}
|
||||||
|
build.Do(args, conf)
|
||||||
}
|
}
|
||||||
|
|||||||
38
cmd/internal/clean/clean.go
Normal file
38
cmd/internal/clean/clean.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package clean implements the "llgo clean" command.
|
||||||
|
package clean
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/internal/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
// llgo build
|
||||||
|
var Cmd = &base.Command{
|
||||||
|
UsageLine: "llgo clean [clean flags] [build flags] [packages]",
|
||||||
|
Short: "Remove object files and cached files",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Cmd.Run = runCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
|
conf := build.NewDefaultConf(0)
|
||||||
|
build.Clean(args, conf)
|
||||||
|
}
|
||||||
@@ -20,7 +20,6 @@ package run
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
@@ -49,7 +48,7 @@ func runCmd(cmd *base.Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseRunArgs(args []string) ([]string, []string, error) {
|
func parseRunArgs(args []string) ([]string, []string, error) {
|
||||||
n := parseArgs(args)
|
n := build.SkipFlagArgs(args)
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
return nil, nil, errNoProj
|
return nil, nil, errNoProj
|
||||||
}
|
}
|
||||||
@@ -65,15 +64,6 @@ func parseRunArgs(args []string) ([]string, []string, error) {
|
|||||||
return args[:n+1], args[n+1:], nil
|
return args[:n+1], args[n+1:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArgs(args []string) int {
|
|
||||||
for i, arg := range args {
|
|
||||||
if !strings.HasPrefix(arg, "-") {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGoFile(fname string) bool {
|
func isGoFile(fname string) bool {
|
||||||
return filepath.Ext(fname) == ".go"
|
return filepath.Ext(fname) == ".go"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
"github.com/goplus/llgo/cmd/internal/build"
|
"github.com/goplus/llgo/cmd/internal/build"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/clean"
|
||||||
"github.com/goplus/llgo/cmd/internal/help"
|
"github.com/goplus/llgo/cmd/internal/help"
|
||||||
"github.com/goplus/llgo/cmd/internal/install"
|
"github.com/goplus/llgo/cmd/internal/install"
|
||||||
"github.com/goplus/llgo/cmd/internal/run"
|
"github.com/goplus/llgo/cmd/internal/run"
|
||||||
@@ -42,6 +43,7 @@ func init() {
|
|||||||
build.Cmd,
|
build.Cmd,
|
||||||
install.Cmd,
|
install.Cmd,
|
||||||
run.Cmd,
|
run.Cmd,
|
||||||
|
clean.Cmd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -5,13 +5,16 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
github.com/aykevl/go-wasm v0.0.1
|
github.com/aykevl/go-wasm v0.0.1
|
||||||
github.com/goplus/gogen v1.15.2
|
github.com/goplus/gogen v1.15.2
|
||||||
github.com/goplus/llvm v0.7.1
|
github.com/goplus/llvm v0.7.5
|
||||||
github.com/goplus/mod v0.13.10
|
github.com/goplus/mod v0.13.10
|
||||||
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/qiniu/x v1.13.10
|
github.com/qiniu/x v1.13.10
|
||||||
golang.org/x/tools v0.20.0
|
golang.org/x/tools v0.20.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
16
go.sum
16
go.sum
@@ -1,13 +1,25 @@
|
|||||||
github.com/aykevl/go-wasm v0.0.1 h1:lPxy8l48P39W7I0tLrtCrLfZBOUq9IWZ7odGdyJP2AM=
|
github.com/aykevl/go-wasm v0.0.1 h1:lPxy8l48P39W7I0tLrtCrLfZBOUq9IWZ7odGdyJP2AM=
|
||||||
github.com/aykevl/go-wasm v0.0.1/go.mod h1:b4nggwg3lEkNKOU4wzhtLKz2q2sLxSHFnc98aGt6z/Y=
|
github.com/aykevl/go-wasm v0.0.1/go.mod h1:b4nggwg3lEkNKOU4wzhtLKz2q2sLxSHFnc98aGt6z/Y=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/goplus/gogen v1.15.2 h1:Q6XaSx/Zi5tWnjfAziYsQI6Jv6MgODRpFtOYqNkiiqM=
|
github.com/goplus/gogen v1.15.2 h1:Q6XaSx/Zi5tWnjfAziYsQI6Jv6MgODRpFtOYqNkiiqM=
|
||||||
github.com/goplus/gogen v1.15.2/go.mod h1:92qEzVgv7y8JEFICWG9GvYI5IzfEkxYdsA1DbmnTkqk=
|
github.com/goplus/gogen v1.15.2/go.mod h1:92qEzVgv7y8JEFICWG9GvYI5IzfEkxYdsA1DbmnTkqk=
|
||||||
github.com/goplus/llvm v0.7.1 h1:B12Fr/wc3pAsq5PLuac9u9IuKpLRuCufdVAeGDP/MRw=
|
github.com/goplus/llvm v0.7.5 h1:ges8WcUdu4FBi0mkZUs27p/4qDQlj28N1UpMg3VQUoE=
|
||||||
github.com/goplus/llvm v0.7.1/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
github.com/goplus/llvm v0.7.5/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
||||||
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
|
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
|
||||||
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
|
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE=
|
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE=
|
||||||
github.com/qiniu/x v1.13.10/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
|
github.com/qiniu/x v1.13.10/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
|||||||
636
internal/abi/llgo_autogen.ll
Normal file
636
internal/abi/llgo_autogen.ll
Normal file
@@ -0,0 +1,636 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/internal/abi'
|
||||||
|
source_filename = "github.com/goplus/llgo/internal/abi"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/abi.ArrayType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.ChanType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.FuncType" = type { %"github.com/goplus/llgo/internal/abi.Type", i16, i16 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.InterfaceType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.Name" = type { ptr }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.MapType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, ptr, { ptr, ptr }, i8, i8, i16, i32 }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.PtrType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.SliceType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
|
||||||
|
%"github.com/goplus/llgo/internal/abi.StructType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/internal/abi.init$guard" = global ptr null
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.ArrayType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Elem"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Elem"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Elem"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
||||||
|
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp ne i64 %1, 17
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret ptr null
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp eq i64 %1, 17
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 1
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
ret ptr %4
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 1
|
||||||
|
%6 = load ptr, ptr %5, align 8
|
||||||
|
ret ptr %6
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%7 = icmp eq i64 %1, 18
|
||||||
|
br i1 %7, label %_llgo_2, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_5
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 2
|
||||||
|
%9 = load ptr, ptr %8, align 8
|
||||||
|
ret ptr %9
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_3
|
||||||
|
%10 = icmp eq i64 %1, 21
|
||||||
|
br i1 %10, label %_llgo_4, label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_7
|
||||||
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 1
|
||||||
|
%12 = load ptr, ptr %11, align 8
|
||||||
|
ret ptr %12
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_5
|
||||||
|
%13 = icmp eq i64 %1, 22
|
||||||
|
br i1 %13, label %_llgo_6, label %_llgo_9
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_9
|
||||||
|
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 1
|
||||||
|
%15 = load ptr, ptr %14, align 8
|
||||||
|
ret ptr %15
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_7
|
||||||
|
%16 = icmp eq i64 %1, 23
|
||||||
|
br i1 %16, label %_llgo_8, label %_llgo_10
|
||||||
|
|
||||||
|
_llgo_10: ; preds = %_llgo_9
|
||||||
|
ret ptr null
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp ne i64 %1, 19
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret ptr null
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp ne i64 %1, 20
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret ptr null
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
|
||||||
|
%2 = load i8, ptr %1, align 1
|
||||||
|
%3 = and i8 %2, 31
|
||||||
|
%4 = sext i8 %3 to i64
|
||||||
|
ret i64 %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp eq i64 %1, 17
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 3
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
ret i64 %4
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret i64 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp ne i64 %1, 21
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret ptr null
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
||||||
|
%2 = icmp ne i64 %1, 25
|
||||||
|
br i1 %2, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
ret ptr null
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/internal/abi.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
14
internal/abi/map.go
Normal file
14
internal/abi/map.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package abi
|
||||||
|
|
||||||
|
// Map constants common to several packages
|
||||||
|
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
|
||||||
|
const (
|
||||||
|
MapBucketCountBits = 3 // log2 of number of elements in a bucket.
|
||||||
|
MapBucketCount = 1 << MapBucketCountBits
|
||||||
|
MapMaxKeyBytes = 128 // Must fit in a uint8.
|
||||||
|
MapMaxElemBytes = 128 // Must fit in a uint8.
|
||||||
|
)
|
||||||
332
internal/abi/type.go
Normal file
332
internal/abi/type.go
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package abi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Type is the runtime representation of a Go type.
|
||||||
|
//
|
||||||
|
// Type is also referenced implicitly
|
||||||
|
// (in the form of expressions involving constants and arch.PtrSize)
|
||||||
|
// in cmd/compile/internal/reflectdata/reflect.go
|
||||||
|
// and cmd/link/internal/ld/decodesym.go
|
||||||
|
// (e.g. data[2*arch.PtrSize+4] references the TFlag field)
|
||||||
|
// unsafe.OffsetOf(Type{}.TFlag) cannot be used directly in those
|
||||||
|
// places because it varies with cross compilation and experiments.
|
||||||
|
type Type struct {
|
||||||
|
Size_ uintptr
|
||||||
|
PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers
|
||||||
|
Hash uint32 // hash of type; avoids computation in hash tables
|
||||||
|
TFlag TFlag // extra type information flags
|
||||||
|
Align_ uint8 // alignment of variable with this type
|
||||||
|
FieldAlign_ uint8 // alignment of struct field with this type
|
||||||
|
Kind_ uint8 // enumeration for C
|
||||||
|
// function for comparing objects of this type
|
||||||
|
// (ptr to object A, ptr to object B) -> ==?
|
||||||
|
Equal func(unsafe.Pointer, unsafe.Pointer) bool
|
||||||
|
// GCData stores the GC type data for the garbage collector.
|
||||||
|
// If the KindGCProg bit is set in kind, GCData is a GC program.
|
||||||
|
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
|
||||||
|
GCData *byte
|
||||||
|
Str NameOff // string form
|
||||||
|
PtrToThis TypeOff // type for pointer to this type, may be zero
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
|
||||||
|
|
||||||
|
// A Kind represents the specific kind of type that a Type represents.
|
||||||
|
// The zero Kind is not a valid kind.
|
||||||
|
type Kind uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
Invalid Kind = iota
|
||||||
|
Bool
|
||||||
|
Int
|
||||||
|
Int8
|
||||||
|
Int16
|
||||||
|
Int32
|
||||||
|
Int64
|
||||||
|
Uint
|
||||||
|
Uint8
|
||||||
|
Uint16
|
||||||
|
Uint32
|
||||||
|
Uint64
|
||||||
|
Uintptr
|
||||||
|
Float32
|
||||||
|
Float64
|
||||||
|
Complex64
|
||||||
|
Complex128
|
||||||
|
Array
|
||||||
|
Chan
|
||||||
|
Func
|
||||||
|
Interface
|
||||||
|
Map
|
||||||
|
Pointer
|
||||||
|
Slice
|
||||||
|
String
|
||||||
|
Struct
|
||||||
|
UnsafePointer
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible.
|
||||||
|
KindDirectIface = 1 << 5
|
||||||
|
KindGCProg = 1 << 6 // Type.gc points to GC program
|
||||||
|
KindMask = (1 << 5) - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// TFlag is used by a Type to signal what extra type information is
|
||||||
|
// available in the memory directly following the Type value.
|
||||||
|
type TFlag uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TFlagUncommon means that there is a data with a type, UncommonType,
|
||||||
|
// just beyond the shared-per-type common data. That is, the data
|
||||||
|
// for struct types will store their UncommonType at one offset, the
|
||||||
|
// data for interface types will store their UncommonType at a different
|
||||||
|
// offset. UncommonType is always accessed via a pointer that is computed
|
||||||
|
// using trust-us-we-are-the-implementors pointer arithmetic.
|
||||||
|
//
|
||||||
|
// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
|
||||||
|
// then t has UncommonType data and it can be accessed as:
|
||||||
|
//
|
||||||
|
// type structTypeUncommon struct {
|
||||||
|
// structType
|
||||||
|
// u UncommonType
|
||||||
|
// }
|
||||||
|
// u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
|
||||||
|
TFlagUncommon TFlag = 1 << 0
|
||||||
|
|
||||||
|
// TFlagExtraStar means the name in the str field has an
|
||||||
|
// extraneous '*' prefix. This is because for most types T in
|
||||||
|
// a program, the type *T also exists and reusing the str data
|
||||||
|
// saves binary size.
|
||||||
|
TFlagExtraStar TFlag = 1 << 1
|
||||||
|
|
||||||
|
// TFlagNamed means the type has a name.
|
||||||
|
TFlagNamed TFlag = 1 << 2
|
||||||
|
|
||||||
|
// TFlagRegularMemory means that equal and hash functions can treat
|
||||||
|
// this type as a single region of t.size bytes.
|
||||||
|
TFlagRegularMemory TFlag = 1 << 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime.
|
||||||
|
type NameOff int32
|
||||||
|
|
||||||
|
// TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime.
|
||||||
|
type TypeOff int32
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ArrayType represents a fixed array type.
|
||||||
|
type ArrayType struct {
|
||||||
|
Type
|
||||||
|
Elem *Type // array element type
|
||||||
|
Slice *Type // slice type
|
||||||
|
Len uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type SliceType struct {
|
||||||
|
Type
|
||||||
|
Elem *Type // slice element type
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapType struct {
|
||||||
|
Type
|
||||||
|
Key *Type
|
||||||
|
Elem *Type
|
||||||
|
Bucket *Type // internal type representing a hash bucket
|
||||||
|
// function for hashing keys (ptr to key, seed) -> hash
|
||||||
|
Hasher func(unsafe.Pointer, uintptr) uintptr
|
||||||
|
KeySize uint8 // size of key slot
|
||||||
|
ValueSize uint8 // size of elem slot
|
||||||
|
BucketSize uint16 // size of bucket
|
||||||
|
Flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type PtrType struct {
|
||||||
|
Type
|
||||||
|
Elem *Type // pointer element (pointed at) type
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChanDir int
|
||||||
|
|
||||||
|
const (
|
||||||
|
RecvDir ChanDir = 1 << iota // <-chan
|
||||||
|
SendDir // chan<-
|
||||||
|
BothDir = RecvDir | SendDir // chan
|
||||||
|
InvalidDir ChanDir = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChanType represents a channel type
|
||||||
|
type ChanType struct {
|
||||||
|
Type
|
||||||
|
Elem *Type
|
||||||
|
Dir ChanDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// funcType represents a function type.
|
||||||
|
//
|
||||||
|
// A *Type for each in and out parameter is stored in an array that
|
||||||
|
// directly follows the funcType (and possibly its uncommonType). So
|
||||||
|
// a function type with one method, one input, and one output is:
|
||||||
|
//
|
||||||
|
// struct {
|
||||||
|
// funcType
|
||||||
|
// uncommonType
|
||||||
|
// [2]*rtype // [0] is in, [1] is out
|
||||||
|
// }
|
||||||
|
type FuncType struct {
|
||||||
|
Type
|
||||||
|
InCount uint16
|
||||||
|
OutCount uint16 // top bit is set if last input parameter is ...
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructField struct {
|
||||||
|
Name Name // name is always non-empty
|
||||||
|
Typ *Type // type of field
|
||||||
|
Offset uintptr // byte offset of field
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructType struct {
|
||||||
|
Type
|
||||||
|
PkgPath Name
|
||||||
|
Fields []StructField
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name is an encoded type Name with optional extra data.
|
||||||
|
//
|
||||||
|
// The first byte is a bit field containing:
|
||||||
|
//
|
||||||
|
// 1<<0 the name is exported
|
||||||
|
// 1<<1 tag data follows the name
|
||||||
|
// 1<<2 pkgPath nameOff follows the name and tag
|
||||||
|
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
|
||||||
|
//
|
||||||
|
// Following that, there is a varint-encoded length of the name,
|
||||||
|
// followed by the name itself.
|
||||||
|
//
|
||||||
|
// If tag data is present, it also has a varint-encoded length
|
||||||
|
// followed by the tag itself.
|
||||||
|
//
|
||||||
|
// If the import path follows, then 4 bytes at the end of
|
||||||
|
// the data form a nameOff. The import path is only set for concrete
|
||||||
|
// methods that are defined in a different package than their type.
|
||||||
|
//
|
||||||
|
// If a name starts with "*", then the exported bit represents
|
||||||
|
// whether the pointed to type is exported.
|
||||||
|
//
|
||||||
|
// Note: this encoding must match here and in:
|
||||||
|
// cmd/compile/internal/reflectdata/reflect.go
|
||||||
|
// cmd/link/internal/ld/decodesym.go
|
||||||
|
|
||||||
|
type Name struct {
|
||||||
|
Bytes *byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type InterfaceType struct {
|
||||||
|
Type
|
||||||
|
PkgPath Name // import path
|
||||||
|
Methods []Imethod // sorted by hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imethod represents a method on an interface type
|
||||||
|
type Imethod struct {
|
||||||
|
Name NameOff // name of method
|
||||||
|
Typ TypeOff // .(*FuncType) underneath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) Common() *Type {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of t if t is an array type, otherwise 0
|
||||||
|
func (t *Type) Len() int {
|
||||||
|
if t.Kind() == Array {
|
||||||
|
return int((*ArrayType)(unsafe.Pointer(t)).Len)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
|
||||||
|
func (t *Type) Elem() *Type {
|
||||||
|
switch t.Kind() {
|
||||||
|
case Array:
|
||||||
|
tt := (*ArrayType)(unsafe.Pointer(t))
|
||||||
|
return tt.Elem
|
||||||
|
case Chan:
|
||||||
|
tt := (*ChanType)(unsafe.Pointer(t))
|
||||||
|
return tt.Elem
|
||||||
|
case Map:
|
||||||
|
tt := (*MapType)(unsafe.Pointer(t))
|
||||||
|
return tt.Elem
|
||||||
|
case Pointer:
|
||||||
|
tt := (*PtrType)(unsafe.Pointer(t))
|
||||||
|
return tt.Elem
|
||||||
|
case Slice:
|
||||||
|
tt := (*SliceType)(unsafe.Pointer(t))
|
||||||
|
return tt.Elem
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructType returns t cast to a *StructType, or nil if its tag does not match.
|
||||||
|
func (t *Type) StructType() *StructType {
|
||||||
|
if t.Kind() != Struct {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*StructType)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapType returns t cast to a *MapType, or nil if its tag does not match.
|
||||||
|
func (t *Type) MapType() *MapType {
|
||||||
|
if t.Kind() != Map {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*MapType)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
|
||||||
|
func (t *Type) ArrayType() *ArrayType {
|
||||||
|
if t.Kind() != Array {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*ArrayType)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncType returns t cast to a *FuncType, or nil if its tag does not match.
|
||||||
|
func (t *Type) FuncType() *FuncType {
|
||||||
|
if t.Kind() != Func {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*FuncType)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
|
||||||
|
func (t *Type) InterfaceType() *InterfaceType {
|
||||||
|
if t.Kind() != Interface {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*InterfaceType)(unsafe.Pointer(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
32
internal/aliases/aliases.go
Normal file
32
internal/aliases/aliases.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package aliases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Package aliases defines backward compatible shims
|
||||||
|
// for the types.Alias type representation added in 1.22.
|
||||||
|
// This defines placeholders for x/tools until 1.26.
|
||||||
|
|
||||||
|
// NewAlias creates a new TypeName in Package pkg that
|
||||||
|
// is an alias for the type rhs.
|
||||||
|
//
|
||||||
|
// The enabled parameter determines whether the resulting [TypeName]'s
|
||||||
|
// type is an [types.Alias]. Its value must be the result of a call to
|
||||||
|
// [Enabled], which computes the effective value of
|
||||||
|
// GODEBUG=gotypesalias=... by invoking the type checker. The Enabled
|
||||||
|
// function is expensive and should be called once per task (e.g.
|
||||||
|
// package import), not once per call to NewAlias.
|
||||||
|
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
|
||||||
|
if enabled {
|
||||||
|
tname := types.NewTypeName(pos, pkg, name, nil)
|
||||||
|
newAlias(tname, rhs)
|
||||||
|
return tname
|
||||||
|
}
|
||||||
|
return types.NewTypeName(pos, pkg, name, rhs)
|
||||||
|
}
|
||||||
31
internal/aliases/aliases_go121.go
Normal file
31
internal/aliases/aliases_go121.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !go1.22
|
||||||
|
// +build !go1.22
|
||||||
|
|
||||||
|
package aliases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Alias is a placeholder for a go/types.Alias for <=1.21.
|
||||||
|
// It will never be created by go/types.
|
||||||
|
type Alias struct{}
|
||||||
|
|
||||||
|
func (*Alias) String() string { panic("unreachable") }
|
||||||
|
func (*Alias) Underlying() types.Type { panic("unreachable") }
|
||||||
|
func (*Alias) Obj() *types.TypeName { panic("unreachable") }
|
||||||
|
func Rhs(alias *Alias) types.Type { panic("unreachable") }
|
||||||
|
|
||||||
|
// Unalias returns the type t for go <=1.21.
|
||||||
|
func Unalias(t types.Type) types.Type { return t }
|
||||||
|
|
||||||
|
func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") }
|
||||||
|
|
||||||
|
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
||||||
|
//
|
||||||
|
// Before go1.22, this function always returns false.
|
||||||
|
func Enabled() bool { return false }
|
||||||
63
internal/aliases/aliases_go122.go
Normal file
63
internal/aliases/aliases_go122.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build go1.22
|
||||||
|
// +build go1.22
|
||||||
|
|
||||||
|
package aliases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Alias is an alias of types.Alias.
|
||||||
|
type Alias = types.Alias
|
||||||
|
|
||||||
|
// Rhs returns the type on the right-hand side of the alias declaration.
|
||||||
|
func Rhs(alias *Alias) types.Type {
|
||||||
|
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
|
||||||
|
return alias.Rhs() // go1.23+
|
||||||
|
}
|
||||||
|
|
||||||
|
// go1.22's Alias didn't have the Rhs method,
|
||||||
|
// so Unalias is the best we can do.
|
||||||
|
return Unalias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unalias is a wrapper of types.Unalias.
|
||||||
|
func Unalias(t types.Type) types.Type { return types.Unalias(t) }
|
||||||
|
|
||||||
|
// newAlias is an internal alias around types.NewAlias.
|
||||||
|
// Direct usage is discouraged as the moment.
|
||||||
|
// Try to use NewAlias instead.
|
||||||
|
func newAlias(tname *types.TypeName, rhs types.Type) *Alias {
|
||||||
|
a := types.NewAlias(tname, rhs)
|
||||||
|
// TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect.
|
||||||
|
Unalias(a)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
||||||
|
//
|
||||||
|
// This function is expensive! Call it sparingly.
|
||||||
|
func Enabled() bool {
|
||||||
|
// The only reliable way to compute the answer is to invoke go/types.
|
||||||
|
// We don't parse the GODEBUG environment variable, because
|
||||||
|
// (a) it's tricky to do so in a manner that is consistent
|
||||||
|
// with the godebug package; in particular, a simple
|
||||||
|
// substring check is not good enough. The value is a
|
||||||
|
// rightmost-wins list of options. But more importantly:
|
||||||
|
// (b) it is impossible to detect changes to the effective
|
||||||
|
// setting caused by os.Setenv("GODEBUG"), as happens in
|
||||||
|
// many tests. Therefore any attempt to cache the result
|
||||||
|
// is just incorrect.
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
|
||||||
|
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
|
||||||
|
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
|
||||||
|
return enabled
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user