Compare commits
173 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 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,6 +8,7 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
err.log
|
err.log
|
||||||
|
|
||||||
_go/
|
_go/
|
||||||
|
|||||||
38
README.md
38
README.md
@@ -9,3 +9,41 @@ llgo - A Go compiler based on LLVM
|
|||||||
[](https://github.com/goplus/gop)
|
[](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).
|
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,8 +19,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/llgen"
|
"github.com/goplus/llgo/internal/llgen"
|
||||||
)
|
)
|
||||||
@@ -31,24 +29,6 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inFile := os.Args[1]
|
|
||||||
|
|
||||||
dir, _ := filepath.Split(inFile)
|
|
||||||
fname := "llgo_autogen.ll"
|
|
||||||
if inCompilerDir(dir) {
|
|
||||||
fname = "out.ll"
|
|
||||||
}
|
|
||||||
outFile := dir + fname
|
|
||||||
|
|
||||||
llgen.Init()
|
llgen.Init()
|
||||||
if len(os.Args) >= 3 {
|
llgen.SmartDoFile(os.Args[1], os.Args[2:]...)
|
||||||
llgen.Do(os.Args[2], inFile, outFile)
|
|
||||||
} else {
|
|
||||||
llgen.DoFile(inFile, outFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func inCompilerDir(dir string) bool {
|
|
||||||
dir, _ = filepath.Abs(dir)
|
|
||||||
return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import _ "unsafe"
|
|
||||||
|
|
||||||
func incVal(a any) int {
|
|
||||||
return a.(int) + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
//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], incVal(100))
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,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 @main.max(i64 1, i64 2)
|
%0 = call i64 @main.max(i64 1, i64 2)
|
||||||
ret void
|
ret void
|
||||||
@@ -34,3 +35,5 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_0
|
_llgo_2: ; preds = %_llgo_0
|
||||||
ret i64 %1
|
ret i64 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|||||||
@@ -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, ...)
|
||||||
|
|||||||
@@ -42,10 +42,13 @@ _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 @"(main.T).Add"(i64 1, i64 2)
|
%0 = call i64 @"(main.T).Add"(i64 1, i64 2)
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i64 %0)
|
call void (ptr, ...) @printf(ptr @main.format, i64 %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
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)
|
||||||
@@ -26,9 +26,12 @@ _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()
|
||||||
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, ...)
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -29,9 +29,12 @@ _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()
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i64 100)
|
call void (ptr, ...) @printf(ptr @main.format, i64 100)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -35,9 +35,12 @@ _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()
|
||||||
call void @"(*main.T).Print"(ptr @main.format, i64 100)
|
call void @"(*main.T).Print"(ptr @main.format, i64 100)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
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"()
|
||||||
@@ -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))
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
@main.format = global ptr null
|
|
||||||
@"main.init$guard" = global ptr null
|
@"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) {
|
define i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -21,16 +21,6 @@ _llgo_0:
|
|||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
store i1 true, ptr @"main.init$guard", align 1
|
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
|
br label %_llgo_2
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
@@ -39,17 +29,21 @@ _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 %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(i64 100)
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
%1 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %0)
|
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 100)
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i64 %1)
|
%2 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %1)
|
||||||
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i64 %2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
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 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 %"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"()
|
||||||
@@ -29,12 +29,15 @@ _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 i32 @strlen(ptr @main.format)
|
%0 = call i32 @strlen(ptr @main.format)
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare i32 @strlen(ptr)
|
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
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ _llgo_0:
|
|||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
store i1 true, ptr @"main.init$guard", align 1
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
call void @"github.com/goplus/llgo/cl/internal/libc.init"()
|
|
||||||
store i8 72, ptr @main.format, 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 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 2), align 1
|
||||||
@@ -30,14 +29,15 @@ _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 i32 @strlen(ptr @main.format)
|
%0 = call i32 @strlen(ptr @main.format)
|
||||||
call void (ptr, ...) @"github.com/goplus/llgo/cl/internal/libc.Printf"(ptr @main.format, i32 %0)
|
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/cl/internal/libc.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare i32 @strlen(ptr)
|
declare i32 @strlen(ptr)
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/cl/internal/libc.Printf"(ptr, ...)
|
declare void @printf(ptr, ...)
|
||||||
@@ -9,15 +9,16 @@ source_filename = "main"
|
|||||||
define void @"(main.Foo).Print"(%main.Foo %0) {
|
define void @"(main.Foo).Print"(%main.Foo %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = alloca %main.Foo, align 8
|
%1 = alloca %main.Foo, align 8
|
||||||
store %main.Foo %0, ptr %1, align 4
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 8)
|
||||||
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
|
store %main.Foo %0, ptr %2, align 4
|
||||||
%3 = load i1, ptr %2, align 1
|
%3 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 1
|
||||||
br i1 %3, label %_llgo_1, label %_llgo_2
|
%4 = load i1, ptr %3, align 1
|
||||||
|
br i1 %4, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%4 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 0
|
%5 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 0
|
||||||
%5 = load i32, ptr %4, align 4
|
%6 = load i32, ptr %5, align 4
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i32 %5)
|
call void (ptr, ...) @printf(ptr @main.format, i32 %6)
|
||||||
br label %_llgo_2
|
br label %_llgo_2
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
@@ -56,15 +57,21 @@ _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 = alloca %main.Foo, align 8
|
%0 = alloca %main.Foo, align 8
|
||||||
%1 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 0
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 8)
|
||||||
%2 = getelementptr inbounds %main.Foo, ptr %0, i32 0, i32 1
|
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 0
|
||||||
store i32 100, ptr %1, align 4
|
%3 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
|
||||||
store i1 true, ptr %2, align 1
|
store i32 100, ptr %2, align 4
|
||||||
%3 = load %main.Foo, ptr %0, align 4
|
store i1 true, ptr %3, align 1
|
||||||
call void @"(main.Foo).Print"(%main.Foo %3)
|
%4 = load %main.Foo, ptr %1, align 4
|
||||||
|
call void @"(main.Foo).Print"(%main.Foo %4)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
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")
|
||||||
@@ -45,8 +45,9 @@ _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 ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
||||||
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
||||||
store i32 100, ptr %1, align 4
|
store i32 100, ptr %1, align 4
|
||||||
@@ -57,4 +58,6 @@ _llgo_0:
|
|||||||
|
|
||||||
declare void @printf(ptr, ...)
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64)
|
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, ...)
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package cl
|
package cl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go/constant"
|
||||||
"go/types"
|
"go/types"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -24,6 +25,112 @@ import (
|
|||||||
"golang.org/x/tools/go/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) {
|
func TestIsAny(t *testing.T) {
|
||||||
if isAny(types.Typ[types.UntypedInt]) {
|
if isAny(types.Typ[types.UntypedInt]) {
|
||||||
t.Fatal("isAny?")
|
t.Fatal("isAny?")
|
||||||
@@ -48,7 +155,7 @@ func TestIgnoreName(t *testing.T) {
|
|||||||
func TestErrImport(t *testing.T) {
|
func TestErrImport(t *testing.T) {
|
||||||
var ctx context
|
var ctx context
|
||||||
pkg := types.NewPackage("foo", "foo")
|
pkg := types.NewPackage("foo", "foo")
|
||||||
ctx.importPkg(pkg)
|
ctx.importPkg(pkg, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrInitLinkname(t *testing.T) {
|
func TestErrInitLinkname(t *testing.T) {
|
||||||
@@ -58,7 +165,7 @@ func TestErrInitLinkname(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var ctx context
|
var ctx context
|
||||||
ctx.initLinkname("foo", "//go:linkname Printf printf")
|
ctx.initLinkname("foo", "//go:linkname Printf printf", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrVarOf(t *testing.T) {
|
func TestErrVarOf(t *testing.T) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cl.SetDebug(cl.DbgFlagAll)
|
cl.SetDebug(cl.DbgFlagAll)
|
||||||
llssa.Initialize(llssa.InitAll)
|
llssa.Initialize(llssa.InitAll | llssa.InitNative)
|
||||||
llssa.SetDebug(llssa.DbgFlagAll)
|
llssa.SetDebug(llssa.DbgFlagAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +113,14 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) {
|
|||||||
}
|
}
|
||||||
foo.WriteTo(os.Stderr)
|
foo.WriteTo(os.Stderr)
|
||||||
prog := llssa.NewProgram(nil)
|
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)
|
ret, err := cl.NewPackage(prog, foo, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("cl.NewPackage failed:", err)
|
t.Fatal("cl.NewPackage failed:", err)
|
||||||
|
|||||||
403
cl/compile.go
403
cl/compile.go
@@ -61,12 +61,12 @@ const (
|
|||||||
fnIgnore
|
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" && ignorePkgInit(fn.Pkg.Pkg.Path()) {
|
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
||||||
return fnIgnore
|
return fnIgnore
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -79,10 +79,10 @@ func funcKind(vfn ssa.Value) int {
|
|||||||
return fnNormal
|
return fnNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignorePkgInit(pkgPath string) bool {
|
func (p *context) pkgNoInit(pkg *types.Package) bool {
|
||||||
switch pkgPath {
|
p.ensureLoaded(pkg)
|
||||||
case "unsafe", "syscall", "runtime/cgo":
|
if i, ok := p.loaded[pkg]; ok {
|
||||||
return true
|
return i.kind >= PkgNoInit
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -113,13 +113,22 @@ func inPkg(name, pkg string) bool {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type none = struct{}
|
|
||||||
|
|
||||||
type instrOrValue interface {
|
type instrOrValue 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
|
||||||
@@ -129,10 +138,11 @@ type context struct {
|
|||||||
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
|
vargs map[*ssa.Alloc][]llssa.Expr // varargs
|
||||||
inits []func()
|
inits []func()
|
||||||
|
phis []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
|
||||||
@@ -159,7 +169,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
|||||||
for i, n := 0, mthds.Len(); i < n; i++ {
|
for i, n := 0, mthds.Len(); i < n; i++ {
|
||||||
mthd := mthds.At(i)
|
mthd := mthds.At(i)
|
||||||
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
|
||||||
p.compileFunc(pkg, mthd.Obj().Pkg(), ssaMthd)
|
p.compileFuncDecl(pkg, mthd.Obj().Pkg(), ssaMthd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,64 +177,138 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
|
|||||||
// 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 := llssa.FullName(gbl.Pkg.Pkg, gbl.Name())
|
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
|
||||||
if ignoreName(name) || checkCgo(gbl.Name()) {
|
if ignoreName(name) || checkCgo(gbl.Name()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewVar", name, typ)
|
log.Println("==> NewVar", name, typ)
|
||||||
}
|
}
|
||||||
g := pkg.NewVar(name, typ)
|
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
||||||
g.Init(p.prog.Null(g.Type))
|
if vtype == goVar {
|
||||||
|
g.Init(p.prog.Null(g.Type))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function) {
|
func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var {
|
||||||
sig := f.Signature
|
n := len(vars)
|
||||||
name, ok := p.funcName(pkgTypes, f, true)
|
flds := make([]*types.Var, n)
|
||||||
if !ok { // ignored
|
for i, v := range vars {
|
||||||
return
|
flds[i] = types.NewField(token.NoPos, pkg, v.Name(), v.Type(), false)
|
||||||
}
|
}
|
||||||
if debugInstr {
|
t := types.NewPointer(types.NewStruct(flds, nil))
|
||||||
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
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.NewFunc(name, sig)
|
fn := pkg.FuncOf(name)
|
||||||
p.inits = append(p.inits, func() {
|
if fn != nil && fn.HasBody() {
|
||||||
p.fn = fn
|
return fn
|
||||||
defer func() {
|
}
|
||||||
p.fn = nil
|
|
||||||
}()
|
var sig = f.Signature
|
||||||
nblk := len(f.Blocks)
|
var hasCtx = len(f.FreeVars) > 0
|
||||||
if nblk == 0 { // external function
|
if hasCtx {
|
||||||
return
|
|
||||||
}
|
|
||||||
if debugGoSSA {
|
|
||||||
f.WriteTo(os.Stderr)
|
|
||||||
}
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> FuncBody", name)
|
log.Println("==> NewClosure", name, "type:", sig)
|
||||||
}
|
}
|
||||||
fn.MakeBlocks(nblk)
|
ctx := makeClosureCtx(pkgTypes, f.FreeVars)
|
||||||
b := fn.NewBuilder()
|
sig = llssa.FuncAddCtx(ctx, sig)
|
||||||
p.bvals = make(map[ssa.Value]llssa.Expr)
|
} else {
|
||||||
for i, block := range f.Blocks {
|
if debugInstr {
|
||||||
p.compileBlock(b, block, i == 0 && name == "main")
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bool) llssa.BasicBlock {
|
// 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)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
RuntimeInit = llssa.PkgRuntime + ".init"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 {
|
func isAny(t types.Type) bool {
|
||||||
if t, ok := t.(*types.Interface); ok {
|
if t, ok := t.(*types.Interface); ok {
|
||||||
return t.Empty()
|
return t.Empty()
|
||||||
@@ -260,6 +344,92 @@ func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
|||||||
return false
|
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) {
|
func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue bool) (ret llssa.Expr) {
|
||||||
if asValue {
|
if asValue {
|
||||||
if v, ok := p.bvals[iv]; ok {
|
if v, ok := p.bvals[iv]; ok {
|
||||||
@@ -271,15 +441,16 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case *ssa.Call:
|
case *ssa.Call:
|
||||||
call := v.Call
|
call := v.Call
|
||||||
cv := call.Value
|
cv := call.Value
|
||||||
kind := funcKind(cv)
|
kind := p.funcKind(cv)
|
||||||
if kind == fnIgnore {
|
if kind == fnIgnore {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugGoSSA {
|
if debugGoSSA {
|
||||||
log.Println(">>> Call", cv, call.Args)
|
log.Println(">>> Call", cv, call.Args)
|
||||||
}
|
}
|
||||||
if builtin, ok := cv.(*ssa.Builtin); ok {
|
switch cv := cv.(type) {
|
||||||
fn := builtin.Name()
|
case *ssa.Builtin:
|
||||||
|
fn := cv.Name()
|
||||||
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
|
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
|
||||||
arg := call.Args[0]
|
arg := call.Args[0]
|
||||||
ret = p.compileValue(b, arg)
|
ret = p.compileValue(b, arg)
|
||||||
@@ -288,7 +459,26 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, call.Args, kind)
|
||||||
ret = b.BuiltinCall(fn, args...)
|
ret = b.BuiltinCall(fn, args...)
|
||||||
}
|
}
|
||||||
} else {
|
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)
|
fn := p.compileValue(b, cv)
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, call.Args, kind)
|
||||||
ret = b.Call(fn, args...)
|
ret = b.Call(fn, args...)
|
||||||
@@ -303,14 +493,21 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case *ssa.ChangeType:
|
case *ssa.ChangeType:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.ChangeType(p.prog.Type(t), x)
|
ret = b.ChangeType(p.prog.Type(t, llssa.InGo), x)
|
||||||
case *ssa.Convert:
|
case *ssa.Convert:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.Convert(p.prog.Type(t), x)
|
ret = b.Convert(p.prog.Type(t, llssa.InGo), x)
|
||||||
case *ssa.FieldAddr:
|
case *ssa.FieldAddr:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.FieldAddr(x, v.Field)
|
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:
|
case *ssa.IndexAddr:
|
||||||
vx := v.X
|
vx := v.X
|
||||||
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
||||||
@@ -319,28 +516,71 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
x := p.compileValue(b, vx)
|
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.Index:
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
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:
|
case *ssa.Slice:
|
||||||
vx := v.X
|
vx := v.X
|
||||||
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic("todo")
|
var low, high, max llssa.Expr
|
||||||
case *ssa.Alloc:
|
x := p.compileValue(b, vx)
|
||||||
t := v.Type().(*types.Pointer)
|
if v.Low != nil {
|
||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
low = p.compileValue(b, v.Low)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ret = b.Alloc(t, v.Heap)
|
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:
|
case *ssa.MakeInterface:
|
||||||
const (
|
const (
|
||||||
delayExpr = true // varargs: don't need to convert an expr to any
|
delayExpr = true // varargs: don't need to convert an expr to any
|
||||||
)
|
)
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.MakeInterface(t, x, delayExpr)
|
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:
|
case *ssa.TypeAssert:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.TypeAssert(x, p.prog.Type(v.AssertedType), v.CommaOk)
|
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))
|
||||||
}
|
}
|
||||||
@@ -391,14 +631,30 @@ 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:
|
case *ssa.Panic:
|
||||||
arg := p.compileValue(b, v.X).Do()
|
arg := p.compileValue(b, v.X).Do(b)
|
||||||
b.Panic(arg)
|
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.(instrOrValue); ok {
|
if iv, ok := v.(instrOrValue); ok {
|
||||||
return p.compileInstrOrValue(b, iv, true)
|
return p.compileInstrOrValue(b, iv, true)
|
||||||
@@ -412,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))
|
||||||
}
|
}
|
||||||
@@ -443,7 +706,7 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
|
|||||||
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]).Do()
|
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])
|
||||||
@@ -484,8 +747,10 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
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),
|
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 {
|
||||||
@@ -496,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.Pkg.Pkg, 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
cltest.TestCompileEx(t, src, "foo.go", expected)
|
cltest.TestCompileEx(t, src, "foo.go", expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestcgo(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testcgo", true)
|
cltest.FromDir(t, "", "./_testrt", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
|||||||
172
cl/import.go
172
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,11 +44,45 @@ 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)
|
||||||
@@ -55,19 +90,14 @@ func (p *context) importPkg(pkg *types.Package) {
|
|||||||
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,21 +107,44 @@ 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 "
|
||||||
)
|
)
|
||||||
@@ -99,9 +152,9 @@ func (p *context) initLinkname(pkgPath, line string) {
|
|||||||
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 {
|
||||||
link := strings.TrimLeft(text[idx+1:], " ")
|
link := strings.TrimLeft(text[idx+1:], " ")
|
||||||
if strings.Contains(link, ".") { // eg. C.printf, C.strlen
|
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
||||||
name := pkgPath + "." + text[:idx]
|
name := pkgPath + "." + text[:idx]
|
||||||
p.link[name] = link[2:]
|
p.link[name] = link
|
||||||
} else {
|
} else {
|
||||||
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
|
||||||
}
|
}
|
||||||
@@ -136,43 +189,78 @@ func checkCgo(fnName string) bool {
|
|||||||
(fnName[4] == '_' || strings.HasPrefix(fnName[4:], "Check"))
|
(fnName[4] == '_' || strings.HasPrefix(fnName[4:], "Check"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, bool) {
|
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()) {
|
if ignore && ignoreName(name) || checkCgo(fn.Name()) {
|
||||||
return name, false
|
return name, ignoredFunc
|
||||||
}
|
}
|
||||||
if v, ok := p.link[name]; ok {
|
if v, ok := p.link[name]; ok {
|
||||||
return v, true
|
if strings.HasPrefix(v, "C.") {
|
||||||
|
return v[2:], cFunc
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(v, "llgo.") {
|
||||||
|
return v[5:], llgoInstr
|
||||||
|
}
|
||||||
|
return v, goFunc
|
||||||
}
|
}
|
||||||
return name, true
|
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, false)
|
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 := llssa.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
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import "C"
|
|||||||
import _ "unsafe"
|
import _ "unsafe"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = true
|
LLGoPackage = "decl"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname Printf C.printf
|
//go:linkname Printf C.printf
|
||||||
|
|||||||
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, ...)
|
||||||
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.2
|
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
|
||||||
)
|
)
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -1,15 +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/llvm v0.7.2 h1:NL3LlwAmYVCGA6yV40AjOvMDKl2dbCqoYPtugmLQK+E=
|
|
||||||
github.com/goplus/llvm v0.7.2/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=
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
source_filename = "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.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, i32, i32 }
|
%"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.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.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.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/abi.Name" = type { ptr }
|
||||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
%"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, i8, i8, i16, i32 }
|
%"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.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.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.StructType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
||||||
|
|||||||
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.
|
||||||
|
)
|
||||||
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
|
||||||
|
}
|
||||||
@@ -126,7 +126,7 @@ func Do(args []string, conf *Config) {
|
|||||||
return rt[0].Types
|
return rt[0].Types
|
||||||
})
|
})
|
||||||
|
|
||||||
buildAllPkgs(prog, initial, mode, verbose)
|
pkgs := buildAllPkgs(prog, initial, mode, verbose)
|
||||||
|
|
||||||
var runtimeFiles []string
|
var runtimeFiles []string
|
||||||
if rt != nil {
|
if rt != nil {
|
||||||
@@ -136,12 +136,11 @@ func Do(args []string, conf *Config) {
|
|||||||
nErr := 0
|
nErr := 0
|
||||||
for _, pkg := range initial {
|
for _, pkg := range initial {
|
||||||
if pkg.Name == "main" {
|
if pkg.Name == "main" {
|
||||||
nErr += linkMainPkg(pkg, runtimeFiles, conf, mode, verbose)
|
nErr += linkMainPkg(pkg, pkgs, runtimeFiles, conf, mode, verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nErr > 0 {
|
if nErr > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "%d errors occurred\n", nErr)
|
os.Exit(nErr)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,11 +153,14 @@ func isNeedRuntime(pkg *packages.Package) bool {
|
|||||||
return pkg.ID == ""
|
return pkg.ID == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) {
|
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) (pkgs []*aPackage) {
|
||||||
// Create SSA-form program representation.
|
// Create SSA-form program representation.
|
||||||
ssaProg, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions)
|
ssaProg, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions)
|
||||||
ssaProg.Build()
|
ssaProg.Build()
|
||||||
for _, errPkg := range errPkgs {
|
for _, errPkg := range errPkgs {
|
||||||
|
for _, err := range errPkg.Errors {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
}
|
||||||
fmt.Fprintln(os.Stderr, "cannot build SSA for package", errPkg)
|
fmt.Fprintln(os.Stderr, "cannot build SSA for package", errPkg)
|
||||||
}
|
}
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
@@ -167,9 +169,10 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
setNeedRuntime(pkg.Package)
|
setNeedRuntime(pkg.Package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mode Mode, verbose bool) (nErr int) {
|
func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string, conf *Config, mode Mode, verbose bool) (nErr int) {
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
name := path.Base(pkgPath)
|
name := path.Base(pkgPath)
|
||||||
app := conf.OutFile
|
app := conf.OutFile
|
||||||
@@ -183,7 +186,7 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod
|
|||||||
args[2] = "-Wno-override-module"
|
args[2] = "-Wno-override-module"
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
||||||
if p.PkgPath != "unsafe" { // TODO(xsw): maybe can remove this special case
|
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
|
||||||
args = append(args, p.ExportFile+".ll")
|
args = append(args, p.ExportFile+".ll")
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = isNeedRuntime(p)
|
needRuntime = isNeedRuntime(p)
|
||||||
@@ -192,6 +195,17 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod
|
|||||||
})
|
})
|
||||||
if needRuntime && runtimeFiles != nil {
|
if needRuntime && runtimeFiles != nil {
|
||||||
args = append(args, runtimeFiles...)
|
args = append(args, runtimeFiles...)
|
||||||
|
} else {
|
||||||
|
for _, aPkg := range pkgs {
|
||||||
|
if aPkg.Package == pkg { // make empty runtime.init if no runtime needed
|
||||||
|
lpkg := aPkg.LPkg
|
||||||
|
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
|
||||||
|
if needLLFile(mode) {
|
||||||
|
file := pkg.ExportFile + ".ll"
|
||||||
|
os.WriteFile(file, []byte(lpkg.String()), 0644)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose || mode != ModeRun {
|
if verbose || mode != ModeRun {
|
||||||
@@ -204,7 +218,9 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// TODO(xsw): show work
|
// TODO(xsw): show work
|
||||||
// fmt.Fprintln(os.Stderr, "clang", args)
|
if verbose {
|
||||||
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
|
}
|
||||||
err := clang.New("").Exec(args...)
|
err := clang.New("").Exec(args...)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
@@ -218,8 +234,14 @@ func linkMainPkg(pkg *packages.Package, runtimeFiles []string, conf *Config, mod
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPkg(prog llssa.Program, aPkg aPackage, mode Mode, verbose bool) {
|
func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) {
|
||||||
pkg := aPkg.Package
|
pkg := aPkg.Package
|
||||||
|
if cl.PkgKindOf(pkg.Types) == cl.PkgDeclOnly {
|
||||||
|
// skip packages that only contain declarations
|
||||||
|
// and set no export file
|
||||||
|
pkg.ExportFile = ""
|
||||||
|
return
|
||||||
|
}
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Fprintln(os.Stderr, pkgPath)
|
fmt.Fprintln(os.Stderr, pkgPath)
|
||||||
@@ -233,14 +255,16 @@ func buildPkg(prog llssa.Program, aPkg aPackage, mode Mode, verbose bool) {
|
|||||||
file := pkg.ExportFile + ".ll"
|
file := pkg.ExportFile + ".ll"
|
||||||
os.WriteFile(file, []byte(ret.String()), 0644)
|
os.WriteFile(file, []byte(ret.String()), 0644)
|
||||||
}
|
}
|
||||||
|
aPkg.LPkg = ret
|
||||||
}
|
}
|
||||||
|
|
||||||
type aPackage struct {
|
type aPackage struct {
|
||||||
*packages.Package
|
*packages.Package
|
||||||
SSA *ssa.Package
|
SSA *ssa.Package
|
||||||
|
LPkg llssa.Package
|
||||||
}
|
}
|
||||||
|
|
||||||
func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Program, all []aPackage, errs []*packages.Package) {
|
func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Program, all []*aPackage, errs []*packages.Package) {
|
||||||
var fset *token.FileSet
|
var fset *token.FileSet
|
||||||
if len(initial) > 0 {
|
if len(initial) > 0 {
|
||||||
fset = initial[0].Fset
|
fset = initial[0].Fset
|
||||||
@@ -250,7 +274,7 @@ func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Progr
|
|||||||
packages.Visit(initial, nil, func(p *packages.Package) {
|
packages.Visit(initial, nil, func(p *packages.Package) {
|
||||||
if p.Types != nil && !p.IllTyped {
|
if p.Types != nil && !p.IllTyped {
|
||||||
ssaPkg := prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true)
|
ssaPkg := prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true)
|
||||||
all = append(all, aPackage{p, ssaPkg})
|
all = append(all, &aPackage{p, ssaPkg, nil})
|
||||||
} else {
|
} else {
|
||||||
errs = append(errs, p)
|
errs = append(errs, p)
|
||||||
}
|
}
|
||||||
@@ -320,14 +344,28 @@ func allLinkFiles(rt []*packages.Package) (outFiles []string) {
|
|||||||
outFiles = make([]string, 0, len(rt))
|
outFiles = make([]string, 0, len(rt))
|
||||||
root := rootLLGo(rt[0])
|
root := rootLLGo(rt[0])
|
||||||
packages.Visit(rt, nil, func(p *packages.Package) {
|
packages.Visit(rt, nil, func(p *packages.Package) {
|
||||||
if isPkgInLLGo(p.PkgPath) {
|
pkgPath := p.PkgPath
|
||||||
outFile := filepath.Join(root+p.PkgPath[len(llgoModPath):], "llgo_autogen.ll")
|
if isRuntimePkg(pkgPath) {
|
||||||
|
outFile := filepath.Join(root+pkgPath[len(llgoModPath):], "llgo_autogen.ll")
|
||||||
outFiles = append(outFiles, outFile)
|
outFiles = append(outFiles, outFile)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
pkgAbi = llgoModPath + "/internal/abi"
|
||||||
|
pkgRuntime = llgoModPath + "/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isRuntimePkg(pkgPath string) bool {
|
||||||
|
switch pkgPath {
|
||||||
|
case pkgRuntime, pkgAbi:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(xsw): llgo root dir
|
// TODO(xsw): llgo root dir
|
||||||
func rootLLGo(runtime *packages.Package) string {
|
func rootLLGo(runtime *packages.Package) string {
|
||||||
return runtime.Module.Dir
|
return runtime.Module.Dir
|
||||||
@@ -337,6 +375,7 @@ const (
|
|||||||
llgoModPath = "github.com/goplus/llgo"
|
llgoModPath = "github.com/goplus/llgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
func isPkgInLLGo(pkgPath string) bool {
|
func isPkgInLLGo(pkgPath string) bool {
|
||||||
return isPkgInMod(pkgPath, llgoModPath)
|
return isPkgInMod(pkgPath, llgoModPath)
|
||||||
}
|
}
|
||||||
@@ -348,6 +387,7 @@ func isPkgInMod(pkgPath, modPath string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -66,9 +66,16 @@ func Gen(pkgPath, inFile string, src any) string {
|
|||||||
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
|
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
ssaPkg.WriteTo(os.Stderr)
|
if Verbose {
|
||||||
|
ssaPkg.WriteTo(os.Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
prog := llssa.NewProgram(nil)
|
prog := llssa.NewProgram(nil)
|
||||||
|
prog.SetRuntime(func() *types.Package {
|
||||||
|
rt, err := imp.Import(llssa.PkgRuntime)
|
||||||
|
check(err)
|
||||||
|
return rt
|
||||||
|
})
|
||||||
ret, err := cl.NewPackage(prog, ssaPkg, files)
|
ret, err := cl.NewPackage(prog, ssaPkg, files)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
@@ -80,3 +87,7 @@ func check(err error) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Verbose = true
|
||||||
|
)
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package llgen
|
|||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
@@ -37,7 +39,7 @@ const (
|
|||||||
|
|
||||||
func GenFrom(fileOrPkg string) string {
|
func GenFrom(fileOrPkg string) string {
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax,
|
Mode: loadSyntax | packages.NeedDeps,
|
||||||
}
|
}
|
||||||
initial, err := packages.Load(cfg, fileOrPkg)
|
initial, err := packages.Load(cfg, fileOrPkg)
|
||||||
check(err)
|
check(err)
|
||||||
@@ -55,6 +57,10 @@ func GenFrom(fileOrPkg string) string {
|
|||||||
return rt[0].Types
|
return rt[0].Types
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if Verbose {
|
||||||
|
ssaPkg.WriteTo(os.Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
|
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
@@ -66,3 +72,23 @@ func DoFile(fileOrPkg, outFile string) {
|
|||||||
err := os.WriteFile(outFile, []byte(ret), 0644)
|
err := os.WriteFile(outFile, []byte(ret), 0644)
|
||||||
check(err)
|
check(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SmartDoFile(inFile string, pkgPath ...string) {
|
||||||
|
dir, _ := filepath.Split(inFile)
|
||||||
|
fname := "llgo_autogen.ll"
|
||||||
|
if inCompilerDir(dir) {
|
||||||
|
fname = "out.ll"
|
||||||
|
}
|
||||||
|
outFile := dir + fname
|
||||||
|
|
||||||
|
if len(pkgPath) > 0 {
|
||||||
|
Do(pkgPath[0], inFile, outFile)
|
||||||
|
} else {
|
||||||
|
DoFile(inFile, outFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func inCompilerDir(dir string) bool {
|
||||||
|
dir, _ = filepath.Abs(dir)
|
||||||
|
return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/")
|
||||||
|
}
|
||||||
|
|||||||
73
internal/runtime/c/c.go
Normal file
73
internal/runtime/c/c.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
@@ -1,23 +1,36 @@
|
|||||||
; ModuleID = 'github.com/goplus/llgo/internal/runtime'
|
; ModuleID = 'github.com/goplus/llgo/internal/runtime'
|
||||||
source_filename = "github.com/goplus/llgo/internal/runtime"
|
source_filename = "github.com/goplus/llgo/internal/runtime"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
%"github.com/goplus/llgo/internal/runtime.itab" = type { ptr, ptr, i32, [4 x i8], [1 x i64] }
|
%"github.com/goplus/llgo/internal/runtime.itab" = type { ptr, ptr, i32, [4 x i8], [1 x i64] }
|
||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, ptr, ptr, i32, i32 }
|
%"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/runtime.hmap" = type { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr }
|
||||||
|
|
||||||
@"github.com/goplus/llgo/internal/runtime.TyAny" = global ptr null
|
@"github.com/goplus/llgo/internal/runtime.TyAny" = global ptr null
|
||||||
@"github.com/goplus/llgo/internal/runtime.basicTypes" = global ptr null
|
@"github.com/goplus/llgo/internal/runtime.basicTypes" = global ptr null
|
||||||
@"github.com/goplus/llgo/internal/runtime.init$guard" = global ptr null
|
@"github.com/goplus/llgo/internal/runtime.init$guard" = global ptr null
|
||||||
@"github.com/goplus/llgo/internal/runtime.sizeBasicTypes" = global ptr null
|
@"github.com/goplus/llgo/internal/runtime.sizeBasicTypes" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [21 x i8] c"I2Int: type mismatch\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [26 x i8] c"slice index out of bounds\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [33 x i8] c"string slice index out of bounds\00", align 1
|
||||||
|
@__stderrp = external global ptr
|
||||||
|
@3 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1
|
||||||
|
|
||||||
define ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 %0) {
|
define ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = call ptr @malloc(i64 %0)
|
%1 = call ptr @malloc(i64 %0)
|
||||||
ret ptr %1
|
ret ptr %1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @malloc(i64 %0)
|
||||||
|
%2 = call ptr @memset(ptr %1, i32 0, i64 %0)
|
||||||
|
ret ptr %2
|
||||||
|
}
|
||||||
|
|
||||||
define ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 %0) {
|
define ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = getelementptr inbounds ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 %0
|
%1 = getelementptr inbounds ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 %0
|
||||||
@@ -25,22 +38,52 @@ _llgo_0:
|
|||||||
ret ptr %2
|
ret ptr %2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %3, align 8
|
||||||
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||||
|
%5 = load i64, ptr %4, align 4
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
|
||||||
|
%7 = load ptr, ptr %6, align 8
|
||||||
|
%8 = call ptr @memcpy(ptr %0, ptr %7, i64 %5)
|
||||||
|
%9 = getelementptr inbounds i8, ptr %0, i64 %5
|
||||||
|
store i8 0, ptr %9, align 1
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.CStrDup"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
%5 = add i64 %4, 1
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %5)
|
||||||
|
%7 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
|
||||||
|
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %6, %"github.com/goplus/llgo/internal/runtime.String" %7)
|
||||||
|
ret ptr %8
|
||||||
|
}
|
||||||
|
|
||||||
define { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
define { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
|
||||||
%4 = load ptr, ptr %3, align 8
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
%5 = load ptr, ptr %4, align 8
|
||||||
%6 = load ptr, ptr %5, align 8
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
||||||
%7 = icmp eq ptr %6, %1
|
%7 = load ptr, ptr %6, align 8
|
||||||
br i1 %7, label %_llgo_1, label %_llgo_2
|
%8 = icmp eq ptr %7, %1
|
||||||
|
br i1 %8, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
||||||
%9 = load ptr, ptr %8, align 8
|
%10 = load ptr, ptr %9, align 8
|
||||||
%10 = ptrtoint ptr %9 to i64
|
%11 = ptrtoint ptr %10 to i64
|
||||||
%mrv = insertvalue { i64, i1 } poison, i64 %10, 0
|
%mrv = insertvalue { i64, i1 } poison, i64 %11, 0
|
||||||
%mrv1 = insertvalue { i64, i1 } %mrv, i1 true, 1
|
%mrv1 = insertvalue { i64, i1 } %mrv, i1 true, 1
|
||||||
ret { i64, i1 } %mrv1
|
ret { i64, i1 } %mrv1
|
||||||
|
|
||||||
@@ -51,152 +94,422 @@ _llgo_2: ; preds = %_llgo_0
|
|||||||
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() {
|
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 16)
|
||||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 0
|
||||||
store ptr null, ptr %1, align 8
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 1
|
||||||
store i64 0, ptr %2, align 4
|
store ptr null, ptr %2, align 8
|
||||||
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
|
store i64 0, ptr %3, align 4
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.String" %3
|
%4 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %4
|
||||||
}
|
}
|
||||||
|
|
||||||
define i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
define i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
|
||||||
%4 = load ptr, ptr %3, align 8
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
%5 = load ptr, ptr %4, align 8
|
||||||
%6 = load ptr, ptr %5, align 8
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
||||||
%7 = icmp eq ptr %6, %1
|
%7 = load ptr, ptr %6, align 8
|
||||||
br i1 %7, label %_llgo_1, label %_llgo_2
|
%8 = icmp eq ptr %7, %1
|
||||||
|
br i1 %8, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
||||||
%9 = load ptr, ptr %8, align 8
|
%10 = load ptr, ptr %9, align 8
|
||||||
%10 = ptrtoint ptr %9 to i64
|
%11 = ptrtoint ptr %10 to i64
|
||||||
ret i64 %10
|
ret i64 %11
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
_llgo_2: ; preds = %_llgo_0
|
||||||
%11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"([21 x i8] c"I2Int: type mismatch\00")
|
%12 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 20)
|
||||||
|
%13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %12)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %13)
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %0, ptr %1) {
|
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
|
||||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2
|
||||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
|
||||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
|
||||||
store ptr %6, ptr %5, align 8
|
|
||||||
store ptr %0, ptr %7, align 8
|
|
||||||
store i32 0, ptr %8, align 4
|
|
||||||
store i64 0, ptr %10, align 4
|
|
||||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
|
||||||
store ptr %4, ptr %3, align 8
|
store ptr %4, ptr %3, align 8
|
||||||
store ptr %1, ptr %11, align 8
|
store ptr %0, ptr %5, align 8
|
||||||
%12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
store i32 0, ptr %6, align 4
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %12
|
store i64 0, ptr %8, align 4
|
||||||
|
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
|
||||||
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
|
||||||
|
store ptr %2, ptr %11, align 8
|
||||||
|
store ptr %1, ptr %12, align 8
|
||||||
|
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
|
||||||
}
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 %1) {
|
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
|
||||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2
|
||||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
|
||||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
|
||||||
store ptr %6, ptr %5, align 8
|
|
||||||
store ptr %0, ptr %7, align 8
|
|
||||||
store i32 0, ptr %8, align 4
|
|
||||||
store i64 0, ptr %10, align 4
|
|
||||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
|
||||||
%12 = inttoptr i64 %1 to ptr
|
|
||||||
store ptr %4, ptr %3, align 8
|
store ptr %4, ptr %3, align 8
|
||||||
store ptr %12, ptr %11, align 8
|
store ptr %0, ptr %5, align 8
|
||||||
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
store i32 0, ptr %6, align 4
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
|
store i64 0, ptr %8, align 4
|
||||||
|
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
|
||||||
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
|
||||||
|
%13 = inttoptr i64 %1 to ptr
|
||||||
|
store ptr %2, ptr %11, align 8
|
||||||
|
store ptr %13, ptr %12, align 8
|
||||||
|
%14 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.iface" %14
|
||||||
}
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%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
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %1, align 8
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%2 = load ptr, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 0
|
%5 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||||
%6 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1
|
||||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2
|
||||||
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 2
|
%9 = getelementptr inbounds i64, ptr %8, i64 0
|
||||||
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 4
|
store ptr %5, ptr %4, align 8
|
||||||
%11 = getelementptr inbounds i64, ptr %10, i64 0
|
store ptr %2, ptr %6, align 8
|
||||||
store ptr %6, ptr %5, align 8
|
store i32 0, ptr %7, align 4
|
||||||
store ptr %8, ptr %7, align 8
|
store i64 0, ptr %9, align 4
|
||||||
store i32 0, ptr %9, align 4
|
%10 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
store i64 0, ptr %11, align 4
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %10, i64 16)
|
||||||
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 0
|
||||||
store ptr %4, ptr %3, align 8
|
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 1
|
||||||
store ptr %1, ptr %12, align 8
|
store ptr %3, ptr %12, align 8
|
||||||
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, align 8
|
store ptr %1, ptr %13, align 8
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
|
%14 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.iface" %14
|
||||||
}
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeInterface"(ptr %0, ptr %1, ptr %2) {
|
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeInterface"(ptr %0, ptr %1, ptr %2) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%3 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1
|
||||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 0
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2
|
||||||
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 2
|
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 4
|
store ptr %0, ptr %4, align 8
|
||||||
%10 = getelementptr inbounds i64, ptr %9, i64 0
|
store ptr %1, ptr %5, align 8
|
||||||
store ptr %0, ptr %6, align 8
|
store i32 0, ptr %6, align 4
|
||||||
store ptr %1, ptr %7, align 8
|
store i64 0, ptr %8, align 4
|
||||||
store i32 0, ptr %8, align 4
|
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
store i64 0, ptr %10, align 4
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
|
||||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
|
||||||
store ptr %5, ptr %4, align 8
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
|
||||||
store ptr %2, ptr %11, align 8
|
store ptr %3, ptr %11, align 8
|
||||||
%12 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, align 8
|
store ptr %2, ptr %12, align 8
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.iface" %12
|
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
|
||||||
}
|
}
|
||||||
|
|
||||||
declare ptr @malloc(i64)
|
define ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.makemap_small"()
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 24)
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 0
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 1
|
||||||
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 2
|
||||||
|
store ptr %0, ptr %5, align 8
|
||||||
|
store i64 %1, ptr %6, align 4
|
||||||
|
store i64 %2, ptr %7, align 4
|
||||||
|
%8 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.Slice" %8
|
||||||
|
}
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
|
||||||
|
_llgo_0:
|
||||||
|
%6 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %6, i64 24)
|
||||||
|
%8 = icmp slt i64 %3, 0
|
||||||
|
br i1 %8, label %_llgo_1, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_5, %_llgo_4, %_llgo_3, %_llgo_0
|
||||||
|
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 25)
|
||||||
|
%10 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %9)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %10)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3
|
||||||
|
%11 = sub i64 %4, %3
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 1
|
||||||
|
store i64 %11, ptr %12, align 4
|
||||||
|
%13 = sub i64 %5, %3
|
||||||
|
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 2
|
||||||
|
store i64 %13, ptr %14, align 4
|
||||||
|
%15 = sub i64 %5, %3
|
||||||
|
%16 = icmp sgt i64 %15, 0
|
||||||
|
br i1 %16, label %_llgo_6, label %_llgo_8
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_4
|
||||||
|
%17 = icmp sgt i64 %5, %2
|
||||||
|
br i1 %17, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_5
|
||||||
|
%18 = icmp slt i64 %5, %4
|
||||||
|
br i1 %18, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_0
|
||||||
|
%19 = icmp slt i64 %4, %3
|
||||||
|
br i1 %19, label %_llgo_1, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_2
|
||||||
|
%20 = mul i64 %3, %1
|
||||||
|
%21 = getelementptr i8, ptr %0, i64 %20
|
||||||
|
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 0
|
||||||
|
store ptr %21, ptr %22, align 8
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_8, %_llgo_6
|
||||||
|
%23 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.Slice" %23
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_2
|
||||||
|
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 0
|
||||||
|
store ptr %0, ptr %24, align 8
|
||||||
|
br label %_llgo_7
|
||||||
|
}
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||||
|
store ptr %0, ptr %4, align 8
|
||||||
|
store i64 %1, ptr %5, align 4
|
||||||
|
%6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %6
|
||||||
|
}
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %0, i64 %1, i64 %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %4, align 8
|
||||||
|
%5 = icmp slt i64 %1, 0
|
||||||
|
br i1 %5, label %_llgo_1, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_4, %_llgo_3, %_llgo_0
|
||||||
|
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 32)
|
||||||
|
%7 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %6)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %7)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
|
||||||
|
%9 = load i64, ptr %8, align 4
|
||||||
|
%10 = icmp slt i64 %1, %9
|
||||||
|
br i1 %10, label %_llgo_5, label %_llgo_6
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_4
|
||||||
|
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
|
||||||
|
%12 = load i64, ptr %11, align 4
|
||||||
|
%13 = icmp sgt i64 %2, %12
|
||||||
|
br i1 %13, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_0
|
||||||
|
%14 = icmp slt i64 %2, %1
|
||||||
|
br i1 %14, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_2
|
||||||
|
%15 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %15, i64 16)
|
||||||
|
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0
|
||||||
|
%18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 0
|
||||||
|
%19 = load ptr, ptr %18, align 8
|
||||||
|
%20 = getelementptr i8, ptr %19, i64 %1
|
||||||
|
%21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1
|
||||||
|
%22 = sub i64 %2, %1
|
||||||
|
store ptr %20, ptr %17, align 8
|
||||||
|
store i64 %22, ptr %21, align 4
|
||||||
|
%23 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %23
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_2
|
||||||
|
%24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %24, i64 16)
|
||||||
|
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 0
|
||||||
|
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1
|
||||||
|
store ptr null, ptr %26, align 8
|
||||||
|
store i64 0, ptr %27, align 4
|
||||||
|
%28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %28
|
||||||
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NilSlice"() {
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NilSlice"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
%0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %0, i32 0, i32 0
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 24)
|
||||||
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %0, i32 0, i32 1
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 0
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %0, i32 0, i32 2
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 1
|
||||||
store ptr null, ptr %1, align 8
|
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 2
|
||||||
store i64 0, ptr %2, align 4
|
store ptr null, ptr %2, align 8
|
||||||
store i64 0, ptr %3, align 4
|
store i64 0, ptr %3, align 4
|
||||||
%4 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %0, align 8
|
store i64 0, ptr %4, align 4
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.Slice" %4
|
%5 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.Slice" %5
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 2
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
ret i64 %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 0
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
ret ptr %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 1
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
ret i64 %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %0, %"github.com/goplus/llgo/internal/runtime.String" %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %3, align 8
|
||||||
|
%4 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %4, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %5, align 8
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||||
|
%7 = load i64, ptr %6, align 4
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1
|
||||||
|
%9 = load i64, ptr %8, align 4
|
||||||
|
%10 = add i64 %7, %9
|
||||||
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %10)
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
|
||||||
|
%13 = load ptr, ptr %12, align 8
|
||||||
|
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||||
|
%15 = load i64, ptr %14, align 4
|
||||||
|
%16 = call ptr @memcpy(ptr %11, ptr %13, i64 %15)
|
||||||
|
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
|
||||||
|
%18 = load i64, ptr %17, align 4
|
||||||
|
%19 = getelementptr i8, ptr %11, i64 %18
|
||||||
|
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 0
|
||||||
|
%21 = load ptr, ptr %20, align 8
|
||||||
|
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1
|
||||||
|
%23 = load i64, ptr %22, align 4
|
||||||
|
%24 = call ptr @memcpy(ptr %19, ptr %21, i64 %23)
|
||||||
|
%25 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %25, i64 16)
|
||||||
|
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0
|
||||||
|
%28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1
|
||||||
|
store ptr %11, ptr %27, align 8
|
||||||
|
store i64 %10, ptr %28, align 4
|
||||||
|
%29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8
|
||||||
|
ret %"github.com/goplus/llgo/internal/runtime.String" %29
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
ret ptr %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
|
||||||
|
%4 = load i64, ptr %3, align 4
|
||||||
|
ret i64 %4
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
|
||||||
|
%6 = load ptr, ptr %5, align 8
|
||||||
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %6, i32 0, i32 6
|
||||||
|
%8 = load i8, ptr %7, align 1
|
||||||
|
%9 = sext i8 %8 to i64
|
||||||
|
%10 = icmp eq i64 %9, 24
|
||||||
|
br i1 %10, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
%11 = load ptr, ptr @__stderrp, align 8
|
||||||
|
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
|
||||||
|
%13 = load ptr, ptr %12, align 8
|
||||||
|
%14 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %11, ptr @3, %"github.com/goplus/llgo/internal/runtime.String" %14)
|
||||||
|
br label %_llgo_1
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = call ptr @memset(ptr %0, i32 0, i64 %1)
|
||||||
|
ret ptr %2
|
||||||
}
|
}
|
||||||
|
|
||||||
define ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 %0) {
|
define ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%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
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0
|
||||||
%3 = getelementptr inbounds i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 %0
|
%3 = getelementptr inbounds i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 %0
|
||||||
%4 = load i64, ptr %3, align 4
|
%4 = load i64, ptr %3, align 4
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2
|
||||||
%6 = trunc i64 %0 to i8
|
%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 i64 %4, ptr %2, align 4
|
||||||
store i8 %6, ptr %5, align 1
|
store i32 %6, ptr %5, align 4
|
||||||
|
store i8 %8, ptr %7, align 1
|
||||||
ret ptr %1
|
ret ptr %1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +521,7 @@ _llgo_0:
|
|||||||
_llgo_1: ; preds = %_llgo_0
|
_llgo_1: ; preds = %_llgo_0
|
||||||
store i1 true, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
store i1 true, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
||||||
call void @"github.com/goplus/llgo/internal/abi.init"()
|
call void @"github.com/goplus/llgo/internal/abi.init"()
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 16)
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 88)
|
||||||
store ptr %1, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
store ptr %1, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
||||||
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 1), align 4
|
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 1), align 4
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 2), align 4
|
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 2), align 4
|
||||||
@@ -267,4 +580,44 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i1 @"github.com/goplus/llgo/internal/runtime.isEmpty"(i8 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = icmp ule i8 %0, 1
|
||||||
|
ret i1 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptr @"github.com/goplus/llgo/internal/runtime.makemap_small"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
|
||||||
|
%1 = call i32 @rand()
|
||||||
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.hmap", ptr %0, i32 0, i32 4
|
||||||
|
store i32 %1, ptr %2, align 4
|
||||||
|
ret ptr %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %0, ptr %1, %"github.com/goplus/llgo/internal/runtime.String" %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 16)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.String" %2, ptr %4, align 8
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
|
||||||
|
%6 = load i64, ptr %5, align 4
|
||||||
|
%7 = add i64 %6, 1
|
||||||
|
%8 = alloca i8, i64 %7, align 1
|
||||||
|
%9 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %4, align 8
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %8, %"github.com/goplus/llgo/internal/runtime.String" %9)
|
||||||
|
%11 = call i32 (ptr, ptr, ...) @fprintf(ptr %0, ptr %1, ptr %10)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @malloc(i64)
|
||||||
|
|
||||||
|
declare ptr @memset(ptr, i32, i64)
|
||||||
|
|
||||||
|
declare ptr @memcpy(ptr, ptr, i64)
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/abi.init"()
|
declare void @"github.com/goplus/llgo/internal/abi.init"()
|
||||||
|
|
||||||
|
declare i32 @rand()
|
||||||
|
|
||||||
|
declare i32 @fprintf(ptr, ptr, ...)
|
||||||
|
|||||||
1726
internal/runtime/map.go
Normal file
1726
internal/runtime/map.go
Normal file
File diff suppressed because it is too large
Load Diff
38
internal/runtime/stubs.go
Normal file
38
internal/runtime/stubs.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2014 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 runtime
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname fastrand C.rand
|
||||||
|
func fastrand() uint32
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
func fastrand() uint32 {
|
||||||
|
mp := getg().m
|
||||||
|
// Implement wyrand: https://github.com/wangyi-fudan/wyhash
|
||||||
|
// Only the platform that math.Mul64 can be lowered
|
||||||
|
// by the compiler should be in this list.
|
||||||
|
if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
|
||||||
|
goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
|
||||||
|
goarch.IsS390x|goarch.IsRiscv64|goarch.IsLoong64 == 1 {
|
||||||
|
mp.fastrand += 0xa0761d6478bd642f
|
||||||
|
hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
|
||||||
|
return uint32(hi ^ lo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement xorshift64+: 2 32-bit xorshift sequences added together.
|
||||||
|
// Shift triplet [17,7,16] was calculated as indicated in Marsaglia's
|
||||||
|
// Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
|
||||||
|
// This generator passes the SmallCrush suite, part of TestU01 framework:
|
||||||
|
// http://simul.iro.umontreal.ca/testu01/tu01.html
|
||||||
|
t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
|
||||||
|
s1, s0 := t[0], t[1]
|
||||||
|
s1 ^= s1 << 17
|
||||||
|
s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
|
||||||
|
t[0], t[1] = s0, s1
|
||||||
|
return s0 + s1
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -16,3 +16,21 @@ import (
|
|||||||
type _type = abi.Type
|
type _type = abi.Type
|
||||||
|
|
||||||
type interfacetype = abi.InterfaceType
|
type interfacetype = abi.InterfaceType
|
||||||
|
|
||||||
|
type maptype = abi.MapType
|
||||||
|
|
||||||
|
/*
|
||||||
|
type arraytype = abi.ArrayType
|
||||||
|
|
||||||
|
type chantype = abi.ChanType
|
||||||
|
|
||||||
|
type slicetype = abi.SliceType
|
||||||
|
|
||||||
|
type functype = abi.FuncType
|
||||||
|
|
||||||
|
type ptrtype = abi.PtrType
|
||||||
|
|
||||||
|
type name = abi.Name
|
||||||
|
|
||||||
|
type structtype = abi.StructType
|
||||||
|
*/
|
||||||
|
|||||||
55
internal/runtime/z_c.go
Normal file
55
internal/runtime/z_c.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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 runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/abi"
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllocU allocates uninitialized memory.
|
||||||
|
func AllocU(size uintptr) unsafe.Pointer {
|
||||||
|
return c.Malloc(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllocZ allocates zero-initialized memory.
|
||||||
|
func AllocZ(size uintptr) unsafe.Pointer {
|
||||||
|
ret := c.Malloc(size)
|
||||||
|
return c.Memset(ret, 0, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeroinit initializes memory to zero.
|
||||||
|
func Zeroinit(p c.Pointer, size uintptr) c.Pointer {
|
||||||
|
return c.Memset(p, 0, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TracePanic prints panic message.
|
||||||
|
func TracePanic(v Interface) {
|
||||||
|
kind := abi.Kind(v.tab._type.Kind_)
|
||||||
|
switch {
|
||||||
|
case kind == abi.String:
|
||||||
|
stringTracef(c.Stderr, c.Str("panic: %s\n"), *(*String)(v.data))
|
||||||
|
}
|
||||||
|
// TODO(xsw): other message type
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringTracef(fp c.FilePtr, format *c.Char, s String) {
|
||||||
|
cs := c.Alloca(uintptr(s.len) + 1)
|
||||||
|
c.Fprintf(fp, format, CStrCopy(cs, s))
|
||||||
|
}
|
||||||
44
internal/runtime/z_closure.go
Normal file
44
internal/runtime/z_closure.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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 runtime
|
||||||
|
|
||||||
|
/*
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Closure represents a closure.
|
||||||
|
type Closure struct {
|
||||||
|
f unsafe.Pointer
|
||||||
|
data unsafe.Pointer // means no context if data is nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClosure creates a closure.
|
||||||
|
func NewClosure(f, data unsafe.Pointer) Closure {
|
||||||
|
return Closure{f, data}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosureF returns the function of a closure.
|
||||||
|
func ClosureF(c Closure) unsafe.Pointer {
|
||||||
|
return c.f
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosureData returns the data of a closure.
|
||||||
|
func ClosureData(c Closure) unsafe.Pointer {
|
||||||
|
return c.data
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/abi"
|
"github.com/goplus/llgo/internal/abi"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface = iface
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type InterfaceType = abi.InterfaceType
|
type InterfaceType = abi.InterfaceType
|
||||||
|
|
||||||
@@ -30,31 +30,36 @@ var (
|
|||||||
TyAny = &InterfaceType{}
|
TyAny = &InterfaceType{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Interface = iface
|
||||||
|
|
||||||
func MakeAnyInt(typ *Type, data uintptr) Interface {
|
func MakeAnyInt(typ *Type, data uintptr) Interface {
|
||||||
|
tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}
|
||||||
return Interface{
|
return Interface{
|
||||||
tab: &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}},
|
tab: tab, data: unsafe.Pointer(data),
|
||||||
data: unsafe.Pointer(data),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeAnyString(data string) Interface {
|
func MakeAnyString(data string) Interface {
|
||||||
|
typ := basicTypes[abi.String]
|
||||||
|
tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}
|
||||||
return Interface{
|
return Interface{
|
||||||
tab: &itab{inter: TyAny, _type: Basic(abi.String), hash: 0, fun: [1]uintptr{0}},
|
tab: tab, data: unsafe.Pointer(&data),
|
||||||
data: unsafe.Pointer(&data),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeAny(typ *Type, data unsafe.Pointer) Interface {
|
func MakeAny(typ *Type, data unsafe.Pointer) Interface {
|
||||||
|
tab := &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}}
|
||||||
return Interface{
|
return Interface{
|
||||||
tab: &itab{inter: TyAny, _type: typ, hash: 0, fun: [1]uintptr{0}},
|
tab: tab, data: data,
|
||||||
data: data,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeInterface(inter *InterfaceType, typ *Type, data unsafe.Pointer) Interface {
|
func MakeInterface(inter *InterfaceType, typ *Type, data unsafe.Pointer) Interface {
|
||||||
|
tab := &itab{inter: inter, _type: typ, hash: 0, fun: [1]uintptr{0}}
|
||||||
return Interface{
|
return Interface{
|
||||||
tab: &itab{inter: inter, _type: typ, hash: 0, fun: [1]uintptr{0}},
|
tab: tab, data: data,
|
||||||
data: data,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,3 +76,5 @@ func CheckI2Int(v Interface, t *Type) (uintptr, bool) {
|
|||||||
}
|
}
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -16,16 +16,10 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "unsafe"
|
// Map represents a Go map.
|
||||||
|
type Map = hmap
|
||||||
|
|
||||||
const (
|
// MakeSmallMap creates a new small map.
|
||||||
LLGoPackage = true
|
func MakeSmallMap() *Map {
|
||||||
)
|
return makemap_small()
|
||||||
|
|
||||||
//go:linkname Malloc C.malloc
|
|
||||||
func Malloc(size uintptr) unsafe.Pointer
|
|
||||||
|
|
||||||
// Alloc allocates memory.
|
|
||||||
func Alloc(size uintptr) unsafe.Pointer {
|
|
||||||
return Malloc(size)
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user