Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9cc7ad9f7 | ||
|
|
65f88cc64e | ||
|
|
374ff92444 | ||
|
|
6d56a60d2b | ||
|
|
75aea37ced | ||
|
|
b133f70b6b | ||
|
|
093af00bbe | ||
|
|
f1da2613be | ||
|
|
1800c52c04 | ||
|
|
329f65a1ad | ||
|
|
d4dd0c00ff | ||
|
|
d9a24f5ac2 | ||
|
|
a13d9a92bd | ||
|
|
2b70bb60a9 | ||
|
|
48737e361a | ||
|
|
8e9f019f82 | ||
|
|
f6a7815837 | ||
|
|
5016de56fe | ||
|
|
879e4a0061 | ||
|
|
6eaf21e5a6 | ||
|
|
b0b38c02b2 | ||
|
|
cd8e1f2080 | ||
|
|
6cc58c194f | ||
|
|
14cf646c47 | ||
|
|
d49197cbe9 | ||
|
|
1687faa438 | ||
|
|
f0e3e556cf | ||
|
|
c9e8709490 | ||
|
|
52dcfaa452 | ||
|
|
9b5a30896d | ||
|
|
4e1450bbb5 | ||
|
|
d478efe444 | ||
|
|
dacb662d99 | ||
|
|
f8cd76bd92 | ||
|
|
6392fd41c6 | ||
|
|
9d91152f01 | ||
|
|
13972c932b | ||
|
|
81ec9017fc | ||
|
|
79b11b9f51 | ||
|
|
d474a051fd | ||
|
|
073cac8530 | ||
|
|
bc3dca45e7 | ||
|
|
ff36c3dfae | ||
|
|
5a5d86ccc3 | ||
|
|
942b1f5159 | ||
|
|
c93fce87da | ||
|
|
1038b06510 | ||
|
|
f8de6022dc | ||
|
|
a8ead2543d | ||
|
|
db856c4391 | ||
|
|
68949c28c8 | ||
|
|
cf67795ff4 | ||
|
|
1136526e4c | ||
|
|
0edeb5cfd0 | ||
|
|
bc7412f6c9 | ||
|
|
025cff9494 | ||
|
|
445e7154e8 | ||
|
|
4eb7e4000b | ||
|
|
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 | ||
|
|
5d1d51dd58 | ||
|
|
52018cd424 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -8,12 +8,16 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
|
test.db
|
||||||
|
llgo_autogen.ll
|
||||||
|
stories*.bin
|
||||||
.DS_Store
|
.DS_Store
|
||||||
err.log
|
err.log
|
||||||
|
|
||||||
_go/
|
_go/
|
||||||
_runtime/
|
_runtime/
|
||||||
_tinygo/
|
_tinygo/
|
||||||
|
build.dir/
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "x/llama2/llama2.c"]
|
||||||
|
path = x/llama2/llama2.c
|
||||||
|
url = https://github.com/karpathy/llama2.c.git
|
||||||
|
[submodule "x/sqlite/sqlite"]
|
||||||
|
path = x/sqlite/sqlite
|
||||||
|
url = https://github.com/sqlite/sqlite.git
|
||||||
45
README.md
45
README.md
@@ -9,3 +9,48 @@ 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 ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### on Windows
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
* [llama2-c](_demo/llama2-c): inference Llama 2 (It's the first llgo AI example)
|
||||||
|
* [hellopy](https://github.com/goplus/cpython/blob/main/_demo/hellopy/hello.go): link Python to Go and say `Hello world`
|
||||||
|
|
||||||
|
### 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
|
||||||
|
*/
|
||||||
137
_demo/llama2-c/README.md
Normal file
137
_demo/llama2-c/README.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
llama2 - Inference Llama 2 in LLGo
|
||||||
|
=====
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="assets/llama_cute.jpg" width="300" height="300" alt="Cute Llama">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Have you ever wanted to inference a baby [Llama 2](https://ai.meta.com/llama/) model in Go? No? Well, now you can!
|
||||||
|
|
||||||
|
This is based on [llama2.c](https://github.com/karpathy/llama2.c), we didn't port anything! So it's very different from these Go implementations:
|
||||||
|
* https://github.com/nikolaydubina/llama2.go
|
||||||
|
* https://github.com/tmc/go-llama2
|
||||||
|
|
||||||
|
llgo plays a great role as a bridge, allowing the C ecosystem to be seamlessly connected to Go.
|
||||||
|
|
||||||
|
You might think that you need many billion parameter LLMs to do anything useful, but in fact very small LLMs can have surprisingly strong performance if you make the domain narrow enough (ref: [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories) paper). This repo is a "fullstack" train + inference solution for Llama 2 LLM, with focus on minimalism and simplicity.
|
||||||
|
|
||||||
|
As the architecture is identical, you can also load and inference Meta's Llama 2 models. However, the current code only inferences models in fp32, so you will most likely not be able to productively load models larger than 7B.
|
||||||
|
|
||||||
|
## feel the magic
|
||||||
|
|
||||||
|
How to run this example? The simplest way is to run it without any arguments:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
llgo run .
|
||||||
|
```
|
||||||
|
|
||||||
|
This means it uses the default model checkpoint file (`stories15M.bin`), and the default prompt (`Once upon a time`).
|
||||||
|
|
||||||
|
You need download the model checkpoint file first. Download this 15M parameter model trained on the [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories) dataset (~60MB download):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to specify a prompt (eg. `Long long ago`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
llgo run . 'Long long ago'
|
||||||
|
```
|
||||||
|
|
||||||
|
We can also try a bit bigger 42M parameter model (ie. `stories42M.bin`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories42M.bin
|
||||||
|
llgo run . -m stories42M.bin 'Long long ago'
|
||||||
|
```
|
||||||
|
|
||||||
|
There is also an even better 110M param model available, see [models](#models).
|
||||||
|
|
||||||
|
Quick note on sampling, the recommendation for ~best results is to sample with `-t 1.0 -p 0.9`, i.e. temperature 1.0 (default) but also top-p sampling at 0.9 (default). Intuitively, top-p ensures that tokens with tiny probabilities do not get sampled, so we can't get "unlucky" during sampling, and we are less likely to go "off the rails" afterwards. More generally, to control the diversity of samples use either the temperature (i.e. vary `-t` between 0 and 1 and keep top-p off with `-p 0`) or the top-p value (i.e. vary `-p` between 0 and 1 and keep `-t 1`), but not both. Nice explainers on LLM sampling strategies include [this](https://peterchng.com/blog/2023/05/02/token-selection-strategies-top-k-top-p-and-temperature/), [this](https://docs.cohere.com/docs/controlling-generation-with-top-k-top-p) or [this](https://huggingface.co/blog/how-to-generate).
|
||||||
|
|
||||||
|
|
||||||
|
## Meta's Llama 2 models
|
||||||
|
|
||||||
|
As the neural net architecture is identical, we can also inference the Llama 2 models released by Meta. Sadly there is a bit of friction here due to licensing (I can't directly upload the checkpoints, I think). So Step 1, get the Llama 2 checkpoints by following the [Meta instructions](https://github.com/facebookresearch/llama). Once we have those checkpoints, we have to convert them into the llama2.c format.
|
||||||
|
For this we need to install the python dependencies (`pip install -r requirements.txt`) and then use the `export.py` file, e.g. for 7B model:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python export.py llama2_7b.bin --meta-llama path/to/llama/model/7B
|
||||||
|
```
|
||||||
|
|
||||||
|
The export will take ~10 minutes or so and generate a 26GB file (the weights of the 7B model in float32) called `llama2_7b.bin` in the current directory. It has been [reported](https://github.com/karpathy/llama2.c/pull/85) that despite efforts. I would not attempt to run anything above 7B right now for two reasons: first, 13B+ currently doesn't work because of integer flow in pointer arithmetic, which is yet to be fixed, and second, even if it were fixed, this repo is doing float32 inference right now, so it would be fairly unusably slow. Once the export is done, we can run it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run llama2_7b.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
This ran at about 4 tokens/s compiled with [OpenMP](#OpenMP) on 96 threads on my CPU Linux box in the cloud. (On my MacBook Air M1, currently it's closer to 30 seconds per token if you just build with `make runfast`.) Example output:
|
||||||
|
|
||||||
|
> The purpose of this document is to highlight the state-of-the-art of CoO generation technologies, both recent developments and those in commercial use. The focus is on the technologies with the highest merit to become the dominating processes of the future and therefore to be technologies of interest to S&T ... R&D. As such, CoO generation technologies developed in Russia, Japan and Europe are described in some depth. The document starts with an introduction to cobalt oxides as complex products and a short view on cobalt as an essential material. The document continues with the discussion of the available CoO generation processes with respect to energy and capital consumption as well as to environmental damage.
|
||||||
|
|
||||||
|
base models... ¯\\_(ツ)_/¯. Since we can inference the base model, it should be possible to also inference the chat model quite easily, and have a conversation with it. And if we can find a way to run 7B more efficiently, we can start adding LoRA to our training script, and going wild with finetunes all within the repo!
|
||||||
|
|
||||||
|
You can also try Meta's Code Llama models even if support for them is incomplete. In particular, some hyperparameters changed (e.g. the constant in RoPE layer), so the inference is not exactly correct and a bit buggy right now. Looking into fixes. Make sure to build the tokenizer for the plain and instruct variants and pass it when doing inference.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python export.py codellama2_7b.bin --meta-llama /path/to/CodeLlama-7b
|
||||||
|
python tokenizer.py --tokenizer-model=/path/to/CodeLlama-7b/tokenizer.model
|
||||||
|
./run codellama2_7b.bin -z /path/to/CodeLlama-7b/tokenizer.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Chat with Code Llama Instruct:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python export.py codellama2_7b_instruct.bin --meta-llama /path/to/CodeLlama-7b-Instruct
|
||||||
|
python tokenizer.py --tokenizer-model=/path/to/CodeLlama-7b-Instruct/tokenizer.model
|
||||||
|
./run codellama2_7b_instruct.bin -m chat -z /path/to/CodeLlama-7b-Instruct/tokenizer.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## huggingface models
|
||||||
|
|
||||||
|
We can load any huggingface models that use the Llama 2 architecture. See the script [export.py](export.py) and the `--hf` flag to export the model .bin file.
|
||||||
|
|
||||||
|
## models
|
||||||
|
|
||||||
|
For the sake of examples of smaller, from-scratch models, I trained a small model series on TinyStories. All of these trained in a few hours on my training setup (4X A100 40GB GPUs). The 110M took around 24 hours. I am hosting them on huggingface hub [tinyllamas](https://huggingface.co/karpathy/tinyllamas), both in the original PyTorch .pt, and also in the llama2.c format .bin:
|
||||||
|
|
||||||
|
| model | dim | n_layers | n_heads | n_kv_heads | max context length | parameters | val loss | download
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| 260K | 64 | 5 | 8 | 4 | 512 | 260K | 1.297 | [stories260K](https://huggingface.co/karpathy/tinyllamas/tree/main/stories260K)
|
||||||
|
| OG | 288 | 6 | 6 | 6 | 256 | 15M | 1.072 | [stories15M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin) |
|
||||||
|
| 42M| 512 | 8 | 8 | 8 | 1024 | 42M | 0.847 | [stories42M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories42M.bin) |
|
||||||
|
| 110M| 768 | 12 | 12 | 12 | 1024 | 110M | 0.760 | [stories110M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories110M.bin) |
|
||||||
|
|
||||||
|
You'll notice that the 110M model is equivalent to GPT-1 in size. Alternatively, this is also the smallest model in the GPT-2 series (`GPT-2 small`), except the max context length is only 1024 instead of 2048. The only notable changes from GPT-1/2 architecture is that Llama uses RoPE relatively positional embeddings instead of absolute/learned positional embeddings, a bit more fancy SwiGLU non-linearity in the MLP, RMSNorm instead of LayerNorm, bias=False on all Linear layers, and is optionally multiquery.
|
||||||
|
|
||||||
|
|
||||||
|
## training
|
||||||
|
|
||||||
|
Let's see how we can train a baby Llama 2 from scratch using the code in this repo. First let's download and pretokenize some source dataset, e.g. I like [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories) so this is the only example currently available in this repo. But it should be very easy to add datasets, see the code.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python tinystories.py download
|
||||||
|
python tinystories.py pretokenize
|
||||||
|
```
|
||||||
|
|
||||||
|
Then train our model:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python train.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**brief training guide**. See the train.py script for more exotic launches and hyperparameter overrides. Here is a brief guide to how to set the parameters. Look at the table at the very end of the [Chinchilla paper](https://arxiv.org/abs/2203.15556) to get a sense of how the Transformer parameters (dim, n_layers, n_heads) grow or shrink together. Extrapolate/interpolate this pattern to get bigger or smaller transformers. Set the max context length however you wish, depending on the problem: this should be the max number of tokens that matter to predict the next token. E.g. Llama 2 uses 2048. Next, you want the _total_ batch size per update (printed by the script as "tokens per iteration will be:") to be somewhere around 100K tokens for medium-sized applications. For tiny applications it could be lower, for large training (e.g. GPTs/LLamas) it is usually ~0.5M, or even more. You get there by first maxing out the batch_size to whatever your system allows (e.g. mine was 16 in a recent run because after that my GPU runs out of memory), and then you want to increase gradient_accumulation_steps to be as high as necessary to reach the total batch size of ~100K. Finally, you want to tune your learning_rate (LR). You want this to be as high as your training allows. Very small networks can get away with a large LR (e.g. 1e-3 or even higher). Large networks need lower LRs. 3e-4 is a safe choice in most medium-sized applications, but can be too low for small networks, so try to increase it! Finally, max_iters is the length of training. Play with different settings. I mostly only ever tune these parameters and leave most of the others unchanged. Here is an example of how I trained the 110M model, which I don't think is anywhere near optimal, but looked sensible to me: dim 768, n_layers 12, n_heads 12 (so size of each head is 768 / 12 = 64 channels), seq len of 1024, batch size 16 (this is the most that fit my A100 40GB GPU), gradient_accumulation_steps = 8 was needed to get total tokens batch size to be 16 batch size * 1024 tokens in sequence * 8 grad_accum = 131,072 tokens per update. Good. Learning rate 4e-4 (probably a little too low). max_iters 200K (probably a bit too high). Dropout 0.1, as that usually helps a bit at medium size. That was it. I ran using Distributed Data Parallel (DDP) on 4 GPUs on my cloud machine, training took ~day or so.
|
||||||
|
|
||||||
|
Totally understand if you want to skip model training, for simple demo just download one of the pretrained models (see [models](#models) section), e.g.:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Once we have the model.bin file, we can inference in C. Compile the C code first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
llgo run . -m stories15M.bin
|
||||||
|
```
|
||||||
BIN
_demo/llama2-c/assets/llama_cute.jpg
Normal file
BIN
_demo/llama2-c/assets/llama_cute.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
50
_demo/llama2-c/run.go
Normal file
50
_demo/llama2-c/run.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/x/llama2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var prompt *c.Char = c.Str("Once upon a time")
|
||||||
|
var checkpointPath *c.Char = c.Str("stories15M.bin")
|
||||||
|
var tokenizerPath *c.Char = c.Str("tokenizer.bin")
|
||||||
|
var temperature, topp c.Float = 1.0, 0.9
|
||||||
|
var steps c.Int = 256
|
||||||
|
var rngSeed uint64 = uint64(c.Time(nil))
|
||||||
|
|
||||||
|
loop: // parse command line arguments
|
||||||
|
for {
|
||||||
|
switch c.Getopt(c.Argc, c.Argv, c.Str("m:")) {
|
||||||
|
case 'm':
|
||||||
|
checkpointPath = c.Optarg
|
||||||
|
c.Fprintf(c.Stderr, c.Str("==> use model: %s\n"), checkpointPath)
|
||||||
|
case -1:
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.Optind < c.Argc {
|
||||||
|
prompt = c.Index(c.Argv, c.Optind)
|
||||||
|
c.Fprintf(c.Stderr, c.Str("==> prompt: %s\n"), prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the Transformer via the model .bin file
|
||||||
|
var transformer llama2.Transformer
|
||||||
|
llama2.BuildTransformer(&transformer, checkpointPath)
|
||||||
|
|
||||||
|
// build the Tokenizer via the tokenizer .bin file
|
||||||
|
var tokenizer llama2.Tokenizer
|
||||||
|
llama2.BuildTokenizer(&tokenizer, tokenizerPath, transformer.Config.VocabSize)
|
||||||
|
|
||||||
|
// build the Sampler
|
||||||
|
var sampler llama2.Sampler
|
||||||
|
llama2.BuildSampler(&sampler, transformer.Config.VocabSize, temperature, topp, rngSeed)
|
||||||
|
|
||||||
|
// run!
|
||||||
|
llama2.Generate(&transformer, &tokenizer, &sampler, prompt, steps)
|
||||||
|
|
||||||
|
// memory and file handles cleanup
|
||||||
|
llama2.FreeSampler(&sampler)
|
||||||
|
llama2.FreeTokenizer(&tokenizer)
|
||||||
|
llama2.FreeTransformer(&transformer)
|
||||||
|
}
|
||||||
BIN
_demo/llama2-c/tokenizer.bin
Normal file
BIN
_demo/llama2-c/tokenizer.bin
Normal file
Binary file not shown.
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
|
||||||
|
*/
|
||||||
61
_demo/sqlite/sqlite.go
Normal file
61
_demo/sqlite/sqlite.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/x/sqlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Remove(c.Str("test.db"))
|
||||||
|
|
||||||
|
db, err := sqlite.Open(c.Str("test.db"))
|
||||||
|
check(err, db, "sqlite: Open")
|
||||||
|
|
||||||
|
err = db.Exec(c.Str("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"), nil, nil, nil)
|
||||||
|
check(err, db, "sqlite: Exec CREATE TABLE")
|
||||||
|
|
||||||
|
stmt, err := db.PrepareV3("INSERT INTO users (id, name) VALUES (?, ?)", 0, nil)
|
||||||
|
check(err, db, "sqlite: PrepareV3 INSERT")
|
||||||
|
|
||||||
|
stmt.BindInt(1, 100)
|
||||||
|
stmt.BindText(2, c.Str("Hello World"), -1, nil)
|
||||||
|
|
||||||
|
err = stmt.Step()
|
||||||
|
checkDone(err, db, "sqlite: Step INSERT 1")
|
||||||
|
|
||||||
|
stmt.Reset()
|
||||||
|
stmt.BindInt(1, 200)
|
||||||
|
stmt.BindText(2, c.Str("This is llgo"), -1, nil)
|
||||||
|
|
||||||
|
err = stmt.Step()
|
||||||
|
checkDone(err, db, "sqlite: Step INSERT 2")
|
||||||
|
|
||||||
|
stmt.Close()
|
||||||
|
|
||||||
|
stmt, err = db.PrepareV3("SELECT * FROM users", 0, nil)
|
||||||
|
check(err, db, "sqlite: PrepareV3 SELECT")
|
||||||
|
|
||||||
|
for {
|
||||||
|
if err = stmt.Step(); err != sqlite.HasRow {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("==> id=%d, name=%s\n"), stmt.ColumnInt(0), stmt.ColumnText(1))
|
||||||
|
}
|
||||||
|
checkDone(err, db, "sqlite: Step done")
|
||||||
|
|
||||||
|
stmt.Close()
|
||||||
|
db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err sqlite.Errno, db *sqlite.Sqlite3, at string) {
|
||||||
|
if err != sqlite.OK {
|
||||||
|
c.Printf(c.Str("==> %s Error: (%d) %s\n"), c.AllocaCStr(at), err, db.Errmsg())
|
||||||
|
c.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkDone(err sqlite.Errno, db *sqlite.Sqlite3, at string) {
|
||||||
|
if err != sqlite.Done {
|
||||||
|
check(err, db, at)
|
||||||
|
}
|
||||||
|
}
|
||||||
148
c/c.go
Normal file
148
c/c.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// typedef unsigned int uint;
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Char = int8
|
||||||
|
Int = C.int
|
||||||
|
Uint = C.uint
|
||||||
|
Float = float32
|
||||||
|
Pointer = unsafe.Pointer
|
||||||
|
FilePtr = unsafe.Pointer
|
||||||
|
)
|
||||||
|
|
||||||
|
type integer interface {
|
||||||
|
~int | ~uint | ~uintptr | ~int32 | ~uint32 | ~int64 | ~uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Str llgo.cstr
|
||||||
|
func Str(string) *Char
|
||||||
|
|
||||||
|
// llgo:link Advance llgo.advance
|
||||||
|
func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr }
|
||||||
|
|
||||||
|
// llgo:link Index llgo.index
|
||||||
|
func Index[T any, I integer](ptr *T, offset I) T { return *ptr }
|
||||||
|
|
||||||
|
//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 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 GoStringData github.com/goplus/llgo/internal/runtime.StringData
|
||||||
|
func GoStringData(string) *Char
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Remove C.remove
|
||||||
|
func Remove(path *Char) Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Exit C.exit
|
||||||
|
func Exit(Int)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Rand C.rand
|
||||||
|
func Rand() Int
|
||||||
|
|
||||||
|
//go:linkname Qsort C.qsort
|
||||||
|
func Qsort(base Pointer, count, elem uintptr, compar func(a, b Pointer) Int)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Stdin __stdinp
|
||||||
|
var Stdin FilePtr
|
||||||
|
|
||||||
|
//go:linkname Stdout __stdoutp
|
||||||
|
var Stdout FilePtr
|
||||||
|
|
||||||
|
//go:linkname Stderr __stderrp
|
||||||
|
var Stderr FilePtr
|
||||||
|
|
||||||
|
//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 Time C.time
|
||||||
|
func Time(*int32) int32
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Option struct {
|
||||||
|
Name *Char
|
||||||
|
HasArg Int
|
||||||
|
Flag *Int
|
||||||
|
Val Int
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname Argc __llgo_argc
|
||||||
|
var Argc Int
|
||||||
|
|
||||||
|
//go:linkname Argv __llgo_argv
|
||||||
|
var Argv **Char
|
||||||
|
|
||||||
|
//go:linkname Optarg optarg
|
||||||
|
var Optarg *Char
|
||||||
|
|
||||||
|
//go:linkname Optind optind
|
||||||
|
var Optind Int
|
||||||
|
|
||||||
|
//go:linkname Opterr opterr
|
||||||
|
var Opterr Int
|
||||||
|
|
||||||
|
//go:linkname Optopt optopt
|
||||||
|
var Optopt Int
|
||||||
|
|
||||||
|
//go:linkname Getopt C.getopt
|
||||||
|
func Getopt(argc Int, argv **Char, optstring *Char) Int
|
||||||
|
|
||||||
|
//go:linkname GetoptLong C.getopt_long
|
||||||
|
func GetoptLong(argc Int, argv **Char, optstring *Char, longopts *Option, longindex *Int) Int
|
||||||
|
|
||||||
|
//go:linkname GetoptLongOnly C.getopt_long_only
|
||||||
|
func GetoptLongOnly(argc Int, argv **Char, optstring *Char, longopts *Option, longindex *Int) 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ func main() {
|
|||||||
|
|
||||||
llgen.Verbose = false
|
llgen.Verbose = false
|
||||||
|
|
||||||
|
llgenDir(dir + "/cl/_testlibc")
|
||||||
llgenDir(dir + "/cl/_testrt")
|
llgenDir(dir + "/cl/_testrt")
|
||||||
llgenDir(dir+"/cl/_testdata", "")
|
llgenDir(dir+"/cl/_testdata", "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/x/nm"
|
"github.com/goplus/llgo/x/env/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -29,9 +30,8 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := nm.New("nm")
|
nm := llvm.New().Nm()
|
||||||
items, err := nm.List(os.Args[1])
|
items, err := nm.List(os.Args[1])
|
||||||
check(err)
|
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
if item.File != "" {
|
if item.File != "" {
|
||||||
fmt.Printf("\n%s:\n", item.File)
|
fmt.Printf("\n%s:\n", item.File)
|
||||||
@@ -44,10 +44,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func check(err error) {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func makeIndex() {
|
|||||||
usrLib(true),
|
usrLib(true),
|
||||||
stdLib("LLGO_STDROOT"),
|
stdLib("LLGO_STDROOT"),
|
||||||
stdLib("LLGO_USRROOT"),
|
stdLib("LLGO_USRROOT"),
|
||||||
|
pythonLib(),
|
||||||
}
|
}
|
||||||
err := b.Index(libDirs, idxDir, func(path string) {
|
err := b.Index(libDirs, idxDir, func(path string) {
|
||||||
fmt.Println("==>", path)
|
fmt.Println("==>", path)
|
||||||
@@ -103,6 +104,10 @@ func usrLib(local bool) string {
|
|||||||
return "/usr/lib"
|
return "/usr/lib"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pythonLib() string {
|
||||||
|
return os.Getenv("LLGO_PYTHON_ROOT")
|
||||||
|
}
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -16,11 +18,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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)
|
%2 = call i64 @main.max(i64 1, i64 2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.hello = global ptr null
|
@main.hello = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -25,11 +27,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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)
|
%2 = 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)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define i64 @"(main.T).Add"(i64 %0, i64 %1) {
|
define i64 @"(main.T).Add"(i64 %0, i64 %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -40,15 +42,17 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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)
|
%2 = 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 %2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
231
cl/_testdata/print/in.go
Normal file
231
cl/_testdata/print/in.go
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func gwrite(b []byte) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Printf(c.Str("%s"), b)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
prinxor(1)
|
||||||
|
printnl()
|
||||||
|
prinsub(100)
|
||||||
|
printnl()
|
||||||
|
prinusub(1<<64 - 1)
|
||||||
|
printnl()
|
||||||
|
prinfsub(100.1)
|
||||||
|
printnl()
|
||||||
|
printnum(float32(1e9))
|
||||||
|
printnl()
|
||||||
|
printnum(float64(2e9))
|
||||||
|
printnl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printnum(v any) {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case int:
|
||||||
|
printint(int64(v))
|
||||||
|
case int8:
|
||||||
|
printint(int64(v))
|
||||||
|
case int16:
|
||||||
|
printint(int64(v))
|
||||||
|
case int32:
|
||||||
|
printint(int64(v))
|
||||||
|
case int64:
|
||||||
|
printint(int64(v))
|
||||||
|
case uint:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case uint8:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case uint16:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case uint32:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case uint64:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case uintptr:
|
||||||
|
printuint(uint64(v))
|
||||||
|
case float32:
|
||||||
|
printfloat(float64(v))
|
||||||
|
case float64:
|
||||||
|
printfloat(float64(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prinxor(n int64) {
|
||||||
|
printint(^n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prinsub(n int64) {
|
||||||
|
printint(-n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prinusub(n uint64) {
|
||||||
|
printuint(-n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prinfsub(n float64) {
|
||||||
|
printfloat(-n)
|
||||||
|
}
|
||||||
610
cl/_testdata/print/out.ll
Normal file
610
cl/_testdata/print/out.ll
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
; 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 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@main.minhexdigits = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@1 = private unnamed_addr constant [5 x i8] c"llgo\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [4 x i8] c"NaN\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [5 x i8] c"+Inf\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [5 x i8] c"-Inf\00", align 1
|
||||||
|
@5 = private unnamed_addr constant [17 x i8] c"0123456789abcdef\00", align 1
|
||||||
|
@6 = private unnamed_addr constant [2 x i8] c"-\00", align 1
|
||||||
|
@7 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
|
||||||
|
@8 = 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 i32 (ptr, ...) @printf(ptr @0, %"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
store i64 0, ptr @main.minhexdigits, align 4
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = 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" %2)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.printuint(i64 1024)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.printhex(i64 305441743)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.prinxor(i64 1)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.prinsub(i64 100)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.prinusub(i64 -1)
|
||||||
|
call void @main.printnl()
|
||||||
|
call void @main.prinfsub(double 1.001000e+02)
|
||||||
|
call void @main.printnl()
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %3, i64 1315859240)
|
||||||
|
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %4)
|
||||||
|
call void @main.printnl()
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
||||||
|
%6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %5, i64 4746175415993761792)
|
||||||
|
call void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %6)
|
||||||
|
call void @main.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.prinfsub(double %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = fneg double %0
|
||||||
|
call void @main.printfloat(double %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.prinsub(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = sub i64 0, %0
|
||||||
|
call void @main.printint(i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printfloat(double %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = fcmp one double %0, %0
|
||||||
|
br i1 %1, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 3)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_7
|
||||||
|
%3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 4)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%4 = fadd double %0, %0
|
||||||
|
%5 = fcmp oeq double %4, %0
|
||||||
|
br i1 %5, label %_llgo_6, label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_10
|
||||||
|
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %6)
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_7
|
||||||
|
%7 = fadd double %0, %0
|
||||||
|
%8 = fcmp oeq double %7, %0
|
||||||
|
br i1 %8, label %_llgo_9, label %_llgo_10
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_3
|
||||||
|
%9 = fcmp ogt double %0, 0.000000e+00
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_6, %_llgo_3
|
||||||
|
%10 = phi i1 [ false, %_llgo_3 ], [ %9, %_llgo_6 ]
|
||||||
|
br i1 %10, label %_llgo_2, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_10
|
||||||
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 14)
|
||||||
|
%12 = getelementptr inbounds i8, ptr %11, i64 0
|
||||||
|
store i8 43, ptr %12, align 1
|
||||||
|
%13 = fcmp oeq double %0, 0.000000e+00
|
||||||
|
br i1 %13, label %_llgo_11, label %_llgo_13
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_5
|
||||||
|
%14 = fcmp olt double %0, 0.000000e+00
|
||||||
|
br label %_llgo_10
|
||||||
|
|
||||||
|
_llgo_10: ; preds = %_llgo_9, %_llgo_5
|
||||||
|
%15 = phi i1 [ false, %_llgo_5 ], [ %14, %_llgo_9 ]
|
||||||
|
br i1 %15, label %_llgo_4, label %_llgo_8
|
||||||
|
|
||||||
|
_llgo_11: ; preds = %_llgo_8
|
||||||
|
%16 = fdiv double 1.000000e+00, %0
|
||||||
|
%17 = fcmp olt double %16, 0.000000e+00
|
||||||
|
br i1 %17, label %_llgo_14, label %_llgo_12
|
||||||
|
|
||||||
|
_llgo_12: ; preds = %_llgo_24, %_llgo_22, %_llgo_14, %_llgo_11
|
||||||
|
%18 = phi double [ %0, %_llgo_11 ], [ %36, %_llgo_22 ], [ %0, %_llgo_14 ], [ %42, %_llgo_24 ]
|
||||||
|
%19 = phi i64 [ 0, %_llgo_11 ], [ %32, %_llgo_22 ], [ 0, %_llgo_14 ], [ %41, %_llgo_24 ]
|
||||||
|
br label %_llgo_27
|
||||||
|
|
||||||
|
_llgo_13: ; preds = %_llgo_8
|
||||||
|
%20 = fcmp olt double %0, 0.000000e+00
|
||||||
|
br i1 %20, label %_llgo_15, label %_llgo_17
|
||||||
|
|
||||||
|
_llgo_14: ; preds = %_llgo_11
|
||||||
|
%21 = getelementptr inbounds i8, ptr %11, i64 0
|
||||||
|
store i8 45, ptr %21, align 1
|
||||||
|
br label %_llgo_12
|
||||||
|
|
||||||
|
_llgo_15: ; preds = %_llgo_13
|
||||||
|
%22 = fneg double %0
|
||||||
|
%23 = getelementptr inbounds i8, ptr %11, i64 0
|
||||||
|
store i8 45, ptr %23, align 1
|
||||||
|
br label %_llgo_17
|
||||||
|
|
||||||
|
_llgo_16: ; preds = %_llgo_17
|
||||||
|
%24 = add i64 %27, 1
|
||||||
|
%25 = fdiv double %26, 1.000000e+01
|
||||||
|
br label %_llgo_17
|
||||||
|
|
||||||
|
_llgo_17: ; preds = %_llgo_16, %_llgo_15, %_llgo_13
|
||||||
|
%26 = phi double [ %0, %_llgo_13 ], [ %25, %_llgo_16 ], [ %22, %_llgo_15 ]
|
||||||
|
%27 = phi i64 [ 0, %_llgo_13 ], [ %24, %_llgo_16 ], [ 0, %_llgo_15 ]
|
||||||
|
%28 = fcmp oge double %26, 1.000000e+01
|
||||||
|
br i1 %28, label %_llgo_16, label %_llgo_20
|
||||||
|
|
||||||
|
_llgo_18: ; preds = %_llgo_20
|
||||||
|
%29 = sub i64 %32, 1
|
||||||
|
%30 = fmul double %31, 1.000000e+01
|
||||||
|
br label %_llgo_20
|
||||||
|
|
||||||
|
_llgo_19: ; preds = %_llgo_20
|
||||||
|
br label %_llgo_23
|
||||||
|
|
||||||
|
_llgo_20: ; preds = %_llgo_18, %_llgo_17
|
||||||
|
%31 = phi double [ %26, %_llgo_17 ], [ %30, %_llgo_18 ]
|
||||||
|
%32 = phi i64 [ %27, %_llgo_17 ], [ %29, %_llgo_18 ]
|
||||||
|
%33 = fcmp olt double %31, 1.000000e+00
|
||||||
|
br i1 %33, label %_llgo_18, label %_llgo_19
|
||||||
|
|
||||||
|
_llgo_21: ; preds = %_llgo_23
|
||||||
|
%34 = fdiv double %38, 1.000000e+01
|
||||||
|
%35 = add i64 %39, 1
|
||||||
|
br label %_llgo_23
|
||||||
|
|
||||||
|
_llgo_22: ; preds = %_llgo_23
|
||||||
|
%36 = fadd double %31, %38
|
||||||
|
%37 = fcmp oge double %36, 1.000000e+01
|
||||||
|
br i1 %37, label %_llgo_24, label %_llgo_12
|
||||||
|
|
||||||
|
_llgo_23: ; preds = %_llgo_21, %_llgo_19
|
||||||
|
%38 = phi double [ 5.000000e+00, %_llgo_19 ], [ %34, %_llgo_21 ]
|
||||||
|
%39 = phi i64 [ 0, %_llgo_19 ], [ %35, %_llgo_21 ]
|
||||||
|
%40 = icmp slt i64 %39, 7
|
||||||
|
br i1 %40, label %_llgo_21, label %_llgo_22
|
||||||
|
|
||||||
|
_llgo_24: ; preds = %_llgo_22
|
||||||
|
%41 = add i64 %32, 1
|
||||||
|
%42 = fdiv double %36, 1.000000e+01
|
||||||
|
br label %_llgo_12
|
||||||
|
|
||||||
|
_llgo_25: ; preds = %_llgo_27
|
||||||
|
%43 = fptosi double %59 to i64
|
||||||
|
%44 = add i64 %60, 2
|
||||||
|
%45 = add i64 %43, 48
|
||||||
|
%46 = trunc i64 %45 to i8
|
||||||
|
%47 = getelementptr inbounds i8, ptr %11, i64 %44
|
||||||
|
store i8 %46, ptr %47, align 1
|
||||||
|
%48 = sitofp i64 %43 to double
|
||||||
|
%49 = fsub double %59, %48
|
||||||
|
%50 = fmul double %49, 1.000000e+01
|
||||||
|
%51 = add i64 %60, 1
|
||||||
|
br label %_llgo_27
|
||||||
|
|
||||||
|
_llgo_26: ; preds = %_llgo_27
|
||||||
|
%52 = getelementptr inbounds i8, ptr %11, i64 2
|
||||||
|
%53 = load i8, ptr %52, align 1
|
||||||
|
%54 = getelementptr inbounds i8, ptr %11, i64 1
|
||||||
|
store i8 %53, ptr %54, align 1
|
||||||
|
%55 = getelementptr inbounds i8, ptr %11, i64 2
|
||||||
|
store i8 46, ptr %55, align 1
|
||||||
|
%56 = getelementptr inbounds i8, ptr %11, i64 9
|
||||||
|
store i8 101, ptr %56, align 1
|
||||||
|
%57 = getelementptr inbounds i8, ptr %11, i64 10
|
||||||
|
store i8 43, ptr %57, align 1
|
||||||
|
%58 = icmp slt i64 %19, 0
|
||||||
|
br i1 %58, label %_llgo_28, label %_llgo_29
|
||||||
|
|
||||||
|
_llgo_27: ; preds = %_llgo_25, %_llgo_12
|
||||||
|
%59 = phi double [ %18, %_llgo_12 ], [ %50, %_llgo_25 ]
|
||||||
|
%60 = phi i64 [ 0, %_llgo_12 ], [ %51, %_llgo_25 ]
|
||||||
|
%61 = icmp slt i64 %60, 7
|
||||||
|
br i1 %61, label %_llgo_25, label %_llgo_26
|
||||||
|
|
||||||
|
_llgo_28: ; preds = %_llgo_26
|
||||||
|
%62 = sub i64 0, %19
|
||||||
|
%63 = getelementptr inbounds i8, ptr %11, i64 10
|
||||||
|
store i8 45, ptr %63, align 1
|
||||||
|
br label %_llgo_29
|
||||||
|
|
||||||
|
_llgo_29: ; preds = %_llgo_28, %_llgo_26
|
||||||
|
%64 = phi i64 [ %19, %_llgo_26 ], [ %62, %_llgo_28 ]
|
||||||
|
%65 = sdiv i64 %64, 100
|
||||||
|
%66 = trunc i64 %65 to i8
|
||||||
|
%67 = add i8 %66, 48
|
||||||
|
%68 = getelementptr inbounds i8, ptr %11, i64 11
|
||||||
|
store i8 %67, ptr %68, align 1
|
||||||
|
%69 = sdiv i64 %64, 10
|
||||||
|
%70 = trunc i64 %69 to i8
|
||||||
|
%71 = urem i8 %70, 10
|
||||||
|
%72 = add i8 %71, 48
|
||||||
|
%73 = getelementptr inbounds i8, ptr %11, i64 12
|
||||||
|
store i8 %72, ptr %73, align 1
|
||||||
|
%74 = srem i64 %64, 10
|
||||||
|
%75 = trunc i64 %74 to i8
|
||||||
|
%76 = add i8 %75, 48
|
||||||
|
%77 = getelementptr inbounds i8, ptr %11, i64 13
|
||||||
|
store i8 %76, ptr %77, align 1
|
||||||
|
%78 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %11, i64 1, i64 14, i64 0, i64 14, i64 14)
|
||||||
|
call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %78)
|
||||||
|
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 @5, 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.printint(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = icmp slt i64 %0, 0
|
||||||
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 1)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
|
%3 = sub i64 0, %0
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
%4 = phi i64 [ %0, %_llgo_0 ], [ %3, %_llgo_1 ]
|
||||||
|
call void @main.printuint(i64 %4)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printnl() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 1)
|
||||||
|
call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printnum(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%2 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
|
||||||
|
%3 = extractvalue { i64, i1 } %2, 0
|
||||||
|
%4 = extractvalue { i64, i1 } %2, 1
|
||||||
|
br i1 %4, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_26, %_llgo_25, %_llgo_24, %_llgo_22, %_llgo_20, %_llgo_18, %_llgo_16, %_llgo_14, %_llgo_12, %_llgo_10, %_llgo_8, %_llgo_6, %_llgo_4, %_llgo_2
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
call void @main.printint(i64 %3)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
|
||||||
|
%6 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %5)
|
||||||
|
%7 = extractvalue { i64, i1 } %6, 0
|
||||||
|
%8 = extractvalue { i64, i1 } %6, 1
|
||||||
|
br i1 %8, label %_llgo_4, label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_3
|
||||||
|
call void @main.printint(i64 %7)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_3
|
||||||
|
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4)
|
||||||
|
%10 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %9)
|
||||||
|
%11 = extractvalue { i64, i1 } %10, 0
|
||||||
|
%12 = extractvalue { i64, i1 } %10, 1
|
||||||
|
br i1 %12, label %_llgo_6, label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_5
|
||||||
|
call void @main.printint(i64 %11)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_5
|
||||||
|
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5)
|
||||||
|
%14 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %13)
|
||||||
|
%15 = extractvalue { i64, i1 } %14, 0
|
||||||
|
%16 = extractvalue { i64, i1 } %14, 1
|
||||||
|
br i1 %16, label %_llgo_8, label %_llgo_9
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_7
|
||||||
|
call void @main.printint(i64 %15)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_7
|
||||||
|
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6)
|
||||||
|
%18 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %17)
|
||||||
|
%19 = extractvalue { i64, i1 } %18, 0
|
||||||
|
%20 = extractvalue { i64, i1 } %18, 1
|
||||||
|
br i1 %20, label %_llgo_10, label %_llgo_11
|
||||||
|
|
||||||
|
_llgo_10: ; preds = %_llgo_9
|
||||||
|
call void @main.printint(i64 %19)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_11: ; preds = %_llgo_9
|
||||||
|
%21 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 7)
|
||||||
|
%22 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %21)
|
||||||
|
%23 = extractvalue { i64, i1 } %22, 0
|
||||||
|
%24 = extractvalue { i64, i1 } %22, 1
|
||||||
|
br i1 %24, label %_llgo_12, label %_llgo_13
|
||||||
|
|
||||||
|
_llgo_12: ; preds = %_llgo_11
|
||||||
|
call void @main.printuint(i64 %23)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_13: ; preds = %_llgo_11
|
||||||
|
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8)
|
||||||
|
%26 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %25)
|
||||||
|
%27 = extractvalue { i64, i1 } %26, 0
|
||||||
|
%28 = extractvalue { i64, i1 } %26, 1
|
||||||
|
br i1 %28, label %_llgo_14, label %_llgo_15
|
||||||
|
|
||||||
|
_llgo_14: ; preds = %_llgo_13
|
||||||
|
call void @main.printuint(i64 %27)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_15: ; preds = %_llgo_13
|
||||||
|
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9)
|
||||||
|
%30 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %29)
|
||||||
|
%31 = extractvalue { i64, i1 } %30, 0
|
||||||
|
%32 = extractvalue { i64, i1 } %30, 1
|
||||||
|
br i1 %32, label %_llgo_16, label %_llgo_17
|
||||||
|
|
||||||
|
_llgo_16: ; preds = %_llgo_15
|
||||||
|
call void @main.printuint(i64 %31)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_17: ; preds = %_llgo_15
|
||||||
|
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10)
|
||||||
|
%34 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %33)
|
||||||
|
%35 = extractvalue { i64, i1 } %34, 0
|
||||||
|
%36 = extractvalue { i64, i1 } %34, 1
|
||||||
|
br i1 %36, label %_llgo_18, label %_llgo_19
|
||||||
|
|
||||||
|
_llgo_18: ; preds = %_llgo_17
|
||||||
|
call void @main.printuint(i64 %35)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_19: ; preds = %_llgo_17
|
||||||
|
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11)
|
||||||
|
%38 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %37)
|
||||||
|
%39 = extractvalue { i64, i1 } %38, 0
|
||||||
|
%40 = extractvalue { i64, i1 } %38, 1
|
||||||
|
br i1 %40, label %_llgo_20, label %_llgo_21
|
||||||
|
|
||||||
|
_llgo_20: ; preds = %_llgo_19
|
||||||
|
call void @main.printuint(i64 %39)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_21: ; preds = %_llgo_19
|
||||||
|
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12)
|
||||||
|
%42 = call { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %41)
|
||||||
|
%43 = extractvalue { i64, i1 } %42, 0
|
||||||
|
%44 = extractvalue { i64, i1 } %42, 1
|
||||||
|
br i1 %44, label %_llgo_22, label %_llgo_23
|
||||||
|
|
||||||
|
_llgo_22: ; preds = %_llgo_21
|
||||||
|
call void @main.printuint(i64 %43)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_23: ; preds = %_llgo_21
|
||||||
|
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13)
|
||||||
|
%46 = call { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %45)
|
||||||
|
%47 = extractvalue { float, i1 } %46, 0
|
||||||
|
%48 = extractvalue { float, i1 } %46, 1
|
||||||
|
br i1 %48, label %_llgo_24, label %_llgo_25
|
||||||
|
|
||||||
|
_llgo_24: ; preds = %_llgo_23
|
||||||
|
%49 = fpext float %47 to double
|
||||||
|
call void @main.printfloat(double %49)
|
||||||
|
br label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_25: ; preds = %_llgo_23
|
||||||
|
%50 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14)
|
||||||
|
%51 = call { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %50)
|
||||||
|
%52 = extractvalue { double, i1 } %51, 0
|
||||||
|
%53 = extractvalue { double, i1 } %51, 1
|
||||||
|
br i1 %53, label %_llgo_26, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_26: ; preds = %_llgo_25
|
||||||
|
call void @main.printfloat(double %52)
|
||||||
|
br label %_llgo_1
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.printsp() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, 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 void @main.prinusub(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = sub i64 0, %0
|
||||||
|
call void @main.printuint(i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.prinxor(i64 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = xor i64 %0, -1
|
||||||
|
call void @main.printint(i64 %1)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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.Basic"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
|
declare { float, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float32"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
|
declare { double, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Float64"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.hello = global ptr null
|
@main.hello = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -24,14 +26,16 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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 @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -27,14 +29,16 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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 @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @"(*main.T).Print"(ptr %0, i64 %1) {
|
define void @"(*main.T).Print"(ptr %0, i64 %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -33,8 +35,10 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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)
|
||||||
|
|||||||
13
cl/_testdata/uint/in.go
Normal file
13
cl/_testdata/uint/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/c"
|
||||||
|
|
||||||
|
func f(a c.Uint) c.Uint {
|
||||||
|
a++
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var a c.Uint = 100
|
||||||
|
c.Printf(c.Str("Hello, %u\n"), f(a))
|
||||||
|
}
|
||||||
41
cl/_testdata/uint/out.ll
Normal file
41
cl/_testdata/uint/out.ll
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [11 x i8] c"Hello, %u\0A\00", align 1
|
||||||
|
|
||||||
|
define i32 @main.f(i32 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = add i32 %0, 1
|
||||||
|
ret i32 %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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call i32 @main.f(i32 100)
|
||||||
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %2)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.a = global ptr null
|
@main.a = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -18,8 +20,10 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
br i1 false, label %_llgo_1, label %_llgo_2
|
br i1 false, label %_llgo_1, label %_llgo_2
|
||||||
|
|||||||
13
cl/_testdata/vargs/in.go
Normal file
13
cl/_testdata/vargs/in.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
|
||||||
|
func test(a ...any) {
|
||||||
|
for _, v := range a {
|
||||||
|
c.Printf(c.Str("%d\n"), v.(int))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
test(1, 2, 3)
|
||||||
|
}
|
||||||
89
cl/_testdata/vargs/out.ll
Normal file
89
cl/_testdata/vargs/out.ll
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = 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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 0
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %4, i64 1)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %5, ptr %3, align 8
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 1
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%8 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %7, i64 2)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %8, ptr %6, align 8
|
||||||
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 2
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %10, i64 3)
|
||||||
|
store %"github.com/goplus/llgo/internal/runtime.iface" %11, ptr %9, align 8
|
||||||
|
%12 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3)
|
||||||
|
call void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %12)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.test(%"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 [ -1, %_llgo_0 ], [ %3, %_llgo_2 ]
|
||||||
|
%3 = add i64 %2, 1
|
||||||
|
%4 = icmp slt i64 %3, %1
|
||||||
|
br i1 %4, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3
|
||||||
|
%7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
|
||||||
|
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
|
%9 = call i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %7, ptr %8)
|
||||||
|
%10 = call i32 (ptr, ...) @printf(ptr @0, i64 %9)
|
||||||
|
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 ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, 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 ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.a = global ptr null
|
@main.a = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -18,14 +20,16 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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
|
|
||||||
%1 = add i64 %0, 1
|
|
||||||
store i64 %1, ptr @main.a, align 4
|
|
||||||
%2 = load i64, ptr @main.a, align 4
|
%2 = load i64, ptr @main.a, align 4
|
||||||
|
%3 = add i64 %2, 1
|
||||||
|
store i64 %3, ptr @main.a, align 4
|
||||||
|
%4 = load i64, ptr @main.a, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
cl/_testlibc/argv/in.go
Normal file
11
cl/_testlibc/argv/in.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for i := c.Int(0); i < c.Argc; i++ {
|
||||||
|
c.Printf(c.Str("%s\n"), c.Index(c.Argv, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
50
cl/_testlibc/argv/out.ll
Normal file
50
cl/_testlibc/argv/out.ll
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"%s\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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_3
|
||||||
|
%2 = load ptr, ptr @__llgo_argv, align 8
|
||||||
|
%3 = getelementptr ptr, ptr %2, i32 %7
|
||||||
|
%4 = load ptr, ptr %3, align 8
|
||||||
|
%5 = call i32 (ptr, ...) @printf(ptr @0, ptr %4)
|
||||||
|
%6 = add i32 %7, 1
|
||||||
|
br label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3
|
||||||
|
ret void
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
%7 = phi i32 [ 0, %_llgo_0 ], [ %6, %_llgo_1 ]
|
||||||
|
%8 = load i32, ptr @__llgo_argc, align 4
|
||||||
|
%9 = icmp slt i32 %7, %8
|
||||||
|
br i1 %9, label %_llgo_1, label %_llgo_2
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
20
cl/_testlibc/sqlite/in.go
Normal file
20
cl/_testlibc/sqlite/in.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/x/sqlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
db, err := sqlite.OpenV2(c.Str(":memory:"), sqlite.OpenReadWrite|sqlite.OpenMemory, nil)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err sqlite.Errno) {
|
||||||
|
if err != sqlite.OK {
|
||||||
|
c.Printf(c.Str("==> Error: (%d) %s\n"), err, err.Errstr())
|
||||||
|
c.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
62
cl/_testlibc/sqlite/out.ll
Normal file
62
cl/_testlibc/sqlite/out.ll
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [20 x i8] c"==> Error: (%d) %s\0A\00", align 1
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@1 = private unnamed_addr constant [9 x i8] c":memory:\00", align 1
|
||||||
|
|
||||||
|
define void @main.check(i32 %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = icmp ne i32 %0, 0
|
||||||
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%2 = call ptr @sqlite3_errstr()
|
||||||
|
%3 = call i32 (ptr, ...) @printf(ptr @0, i32 %0, ptr %2)
|
||||||
|
call void @exit(i32 1)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.init() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"main.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr @1, i32 130, ptr null)
|
||||||
|
%3 = extractvalue { ptr, i32 } %2, 0
|
||||||
|
%4 = extractvalue { ptr, i32 } %2, 1
|
||||||
|
call void @main.check(i32 %4)
|
||||||
|
%5 = call i32 @sqlite3_close()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @sqlite3_errstr()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|
||||||
|
declare void @exit(i32)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare { ptr, i32 } @"github.com/goplus/llgo/x/sqlite.OpenV2"(ptr, i32, ptr)
|
||||||
|
|
||||||
|
declare i32 @sqlite3_close()
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [4 x i8] c"Hi\0A\00", align 1
|
@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
|
@1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
|
||||||
|
|
||||||
@@ -18,13 +20,15 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = alloca i8, i64 4, align 1
|
%2 = alloca i8, i64 4, align 1
|
||||||
%1 = call ptr @memcpy(ptr %0, ptr @0, i64 4)
|
%3 = call ptr @memcpy(ptr %2, ptr @0, i64 4)
|
||||||
%2 = call i32 (ptr, ...) @printf(ptr @1, ptr %0)
|
%4 = call i32 (ptr, ...) @printf(ptr @1, ptr %2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@0 = private unnamed_addr constant [13 x i8] c"Hello world\0A\00", align 1
|
@0 = private unnamed_addr constant [13 x i8] c"Hello world\0A\00", align 1
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.String" @main.hello() {
|
define %"github.com/goplus/llgo/internal/runtime.String" @main.hello() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -25,16 +27,18 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.String" @main.hello()
|
%2 = 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)
|
%3 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
%2 = add i64 %1, 1
|
%4 = add i64 %3, 1
|
||||||
%3 = alloca i8, i64 %2, align 1
|
%5 = alloca i8, i64 %4, align 1
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %3, %"github.com/goplus/llgo/internal/runtime.String" %0)
|
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %5, %"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
%5 = call i32 (ptr, ...) @printf(ptr %4)
|
%7 = call i32 (ptr, ...) @printf(ptr %6)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,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.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
@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) {
|
||||||
@@ -27,14 +29,16 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.Basic"(i64 2)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
|
||||||
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 100)
|
%3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %2, i64 100)
|
||||||
%2 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %1)
|
%4 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %3)
|
||||||
%3 = call i32 (ptr, ...) @printf(ptr @0, i64 %2)
|
%5 = call i32 (ptr, ...) @printf(ptr @0, i64 %4)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ source_filename = "main"
|
|||||||
@main.b = global ptr null
|
@main.b = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@main.n = global ptr null
|
@main.n = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
@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
|
@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
|
@2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
|
||||||
@@ -30,113 +32,115 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.AllocZ"(i64 32)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
%3 = getelementptr inbounds i64, ptr %2, i64 0
|
||||||
store i64 1, ptr %1, align 4
|
store i64 1, ptr %3, align 4
|
||||||
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
%4 = getelementptr inbounds i64, ptr %2, i64 1
|
||||||
store i64 2, ptr %2, align 4
|
store i64 2, ptr %4, align 4
|
||||||
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
%5 = getelementptr inbounds i64, ptr %2, i64 2
|
||||||
store i64 3, ptr %3, align 4
|
store i64 3, ptr %5, align 4
|
||||||
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
%6 = getelementptr inbounds i64, ptr %2, i64 3
|
||||||
store i64 4, ptr %4, align 4
|
store i64 4, ptr %6, 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)
|
%7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 8, i64 4, i64 0, i64 4, i64 4)
|
||||||
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%7 = getelementptr inbounds i64, ptr %6, i64 0
|
%9 = getelementptr inbounds i64, ptr %8, i64 0
|
||||||
%8 = getelementptr inbounds i64, ptr %6, i64 1
|
%10 = getelementptr inbounds i64, ptr %8, i64 1
|
||||||
%9 = getelementptr inbounds i64, ptr %6, i64 2
|
%11 = getelementptr inbounds i64, ptr %8, i64 2
|
||||||
%10 = getelementptr inbounds i64, ptr %6, i64 3
|
%12 = getelementptr inbounds i64, ptr %8, i64 3
|
||||||
store i64 1, ptr %7, align 4
|
store i64 1, ptr %9, align 4
|
||||||
store i64 2, ptr %8, align 4
|
store i64 2, ptr %10, align 4
|
||||||
store i64 3, ptr %9, align 4
|
store i64 3, ptr %11, align 4
|
||||||
store i64 4, ptr %10, align 4
|
store i64 4, ptr %12, align 4
|
||||||
%11 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%13 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
call void @main.out(i64 %11)
|
call void @main.out(i64 %13)
|
||||||
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%13 = getelementptr inbounds i64, ptr %12, i64 0
|
%15 = getelementptr inbounds i64, ptr %14, i64 0
|
||||||
store i64 1, ptr %13, align 4
|
store i64 1, ptr %15, align 4
|
||||||
%14 = getelementptr inbounds i64, ptr %12, i64 1
|
%16 = getelementptr inbounds i64, ptr %14, i64 1
|
||||||
store i64 2, ptr %14, align 4
|
store i64 2, ptr %16, align 4
|
||||||
%15 = getelementptr inbounds i64, ptr %12, i64 2
|
%17 = getelementptr inbounds i64, ptr %14, i64 2
|
||||||
store i64 3, ptr %15, align 4
|
store i64 3, ptr %17, align 4
|
||||||
%16 = getelementptr inbounds i64, ptr %12, i64 3
|
%18 = getelementptr inbounds i64, ptr %14, i64 3
|
||||||
store i64 4, ptr %16, align 4
|
store i64 4, ptr %18, 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)
|
%19 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %14, 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)
|
%20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %19)
|
||||||
call void @main.out(i64 %18)
|
call void @main.out(i64 %20)
|
||||||
call void @main.out(i64 4)
|
call void @main.out(i64 4)
|
||||||
call void @main.out(i64 4)
|
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)
|
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
call void @main.out(i64 %19)
|
call void @main.out(i64 %21)
|
||||||
call void @main.out(i64 4)
|
call void @main.out(i64 4)
|
||||||
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)
|
%22 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %24, i64 8, i64 %22, i64 1, i64 %23, i64 %22)
|
||||||
%24 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %23)
|
%26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %25)
|
||||||
call void @main.out(i64 %24)
|
call void @main.out(i64 %26)
|
||||||
%25 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%27 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%28 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%29 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%30 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %29, i64 8, i64 %27, i64 1, i64 %28, i64 %27)
|
||||||
%29 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %28)
|
%31 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %30)
|
||||||
call void @main.out(i64 %29)
|
call void @main.out(i64 %31)
|
||||||
%30 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%32 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%34 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %33, i64 8, i64 %32, i64 1, i64 2, i64 %32)
|
||||||
%33 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %32)
|
%35 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %34)
|
||||||
call void @main.out(i64 %33)
|
call void @main.out(i64 %35)
|
||||||
%34 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%36 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%37 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%38 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %37, i64 8, i64 %36, i64 1, i64 2, i64 %36)
|
||||||
%37 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %36)
|
%39 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %38)
|
||||||
call void @main.out(i64 %37)
|
call void @main.out(i64 %39)
|
||||||
%38 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%39 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%41 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%42 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %41, i64 8, i64 %40, i64 1, i64 2, i64 2)
|
||||||
%41 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %40)
|
%43 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %42)
|
||||||
call void @main.out(i64 %41)
|
call void @main.out(i64 %43)
|
||||||
%42 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%44 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%45 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%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)
|
%46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %45, i64 8, i64 %44, i64 1, i64 2, i64 2)
|
||||||
%45 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %44)
|
%47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %46)
|
||||||
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)
|
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)
|
%48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, 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)
|
%49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %48)
|
||||||
call void @main.out(i64 %49)
|
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)
|
%50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 4, i64 4)
|
||||||
%51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %50)
|
%51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %50)
|
||||||
call void @main.out(i64 %51)
|
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)
|
%52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, 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)
|
%53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %52)
|
||||||
call void @main.out(i64 %53)
|
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)
|
%54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 4)
|
||||||
%55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %54)
|
%55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %54)
|
||||||
call void @main.out(i64 %55)
|
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)
|
%56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, 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)
|
%57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %56)
|
||||||
call void @main.out(i64 %57)
|
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)
|
%58 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 2)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %58)
|
%59 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %58)
|
||||||
%59 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
call void @main.out(i64 %59)
|
||||||
%60 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %59)
|
%60 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
|
||||||
%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" %60)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
||||||
%62 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
%62 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
||||||
%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)
|
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %61, i64 1, i64 %62)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
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)
|
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
||||||
%65 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %64)
|
%65 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 1, i64 2)
|
||||||
%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" %65)
|
||||||
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
|
%67 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
||||||
|
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %66, i64 5, i64 %67)
|
||||||
|
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %68)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
}
|
||||||
68
cl/_testrt/callback/out.ll
Normal file
68
cl/_testrt/callback/out.ll
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = 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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = alloca { ptr, ptr }, align 8
|
||||||
|
%3 = getelementptr inbounds { ptr, ptr }, ptr %2, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.main.print, ptr %3, align 8
|
||||||
|
%4 = getelementptr inbounds { ptr, ptr }, ptr %2, i32 0, i32 1
|
||||||
|
store ptr null, ptr %4, align 8
|
||||||
|
%5 = load { ptr, ptr }, ptr %2, align 8
|
||||||
|
call void @main.callback(ptr @0, { ptr, ptr } %5)
|
||||||
|
%6 = alloca { ptr, ptr }, align 8
|
||||||
|
%7 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 0
|
||||||
|
store ptr @__llgo_stub.main.print, ptr %7, align 8
|
||||||
|
%8 = getelementptr inbounds { ptr, ptr }, ptr %6, i32 0, i32 1
|
||||||
|
store ptr null, ptr %8, align 8
|
||||||
|
%9 = load { ptr, ptr }, ptr %6, align 8
|
||||||
|
call void @main.callback(ptr @1, { ptr, ptr } %9)
|
||||||
|
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, ...)
|
||||||
158
cl/_testrt/cast/in.go
Normal file
158
cl/_testrt/cast/in.go
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
//"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cvt64to8(0, 0)
|
||||||
|
cvt64to8(127, 127)
|
||||||
|
cvt64to8(128, -128)
|
||||||
|
cvt64to8(-128, -128)
|
||||||
|
cvt64to8(-129, 127)
|
||||||
|
cvt64to8(256, 0)
|
||||||
|
|
||||||
|
cvt64to8U(0, 0)
|
||||||
|
cvt64to8U(255, 255)
|
||||||
|
cvt64to8U(256, 0)
|
||||||
|
cvt64to8U(257, 1)
|
||||||
|
cvt64to8U(-1, 255)
|
||||||
|
|
||||||
|
cvt32Fto8(0.1, 0)
|
||||||
|
cvt32Fto8(127.1, 127)
|
||||||
|
cvt32Fto8(128.1, -128)
|
||||||
|
cvt32Fto8(-128.1, -128)
|
||||||
|
cvt32Fto8(-129.1, 127)
|
||||||
|
cvt32Fto8(256.1, 0)
|
||||||
|
|
||||||
|
cvt32Fto8U(0, 0)
|
||||||
|
cvt32Fto8U(255, 255)
|
||||||
|
cvt32Fto8U(256, 0)
|
||||||
|
cvt32Fto8U(257, 1)
|
||||||
|
cvt32Fto8U(-1, 255)
|
||||||
|
|
||||||
|
// MaxInt32 = 1<<31 - 1 // 2147483647
|
||||||
|
// MinInt32 = -1 << 31 // -2147483648
|
||||||
|
cvt32Fto32(0, 0)
|
||||||
|
cvt32Fto32(1.5, 1)
|
||||||
|
cvt32Fto32(1147483647.1, 1147483648)
|
||||||
|
cvt32Fto32(2147483647.1, -2147483648)
|
||||||
|
cvt32Fto32(4147483647.1, -2147483648)
|
||||||
|
cvt32Fto32(-2147483648.1, -2147483648)
|
||||||
|
cvt32Fto32(-2147482648.1, -2147482624)
|
||||||
|
|
||||||
|
// MaxUint32 = 1<<32 - 1 // 4294967295
|
||||||
|
cvt32Fto32U(0, 0)
|
||||||
|
cvt32Fto32U(1.5, 1)
|
||||||
|
cvt32Fto32U(4294967295.1, 0)
|
||||||
|
cvt32Fto32U(5294967295.1, 1000000000)
|
||||||
|
cvt32Fto32U(-4294967295.1, 0)
|
||||||
|
cvt32Fto32U(-1294967295.1, 3000000000)
|
||||||
|
cvt32Fto32U(-1.1, 4294967295)
|
||||||
|
|
||||||
|
// MaxFloat32 = 0x1p127 * (1 + (1 - 0x1p-23)) // 3.40282346638528859811704183484516925440e+38
|
||||||
|
// SmallestNonzeroFloat32 = 0x1p-126 * 0x1p-23 // 1.401298464324817070923729583289916131280e-45
|
||||||
|
// MaxFloat64 = 0x1p1023 * (1 + (1 - 0x1p-52)) // 1.79769313486231570814527423731704356798070e+308
|
||||||
|
// SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52 // 4.9406564584124654417656879286822137236505980e-324
|
||||||
|
|
||||||
|
cvt32Fto64F(0, 0)
|
||||||
|
cvt32Fto64F(1.5, 1.5)
|
||||||
|
cvt32Fto64F(1e10, 1e10)
|
||||||
|
cvt32Fto64F(-1e10, -1e10)
|
||||||
|
|
||||||
|
cvt64Fto32F(0, 0)
|
||||||
|
cvt64Fto32F(1.5, 1.5)
|
||||||
|
cvt64Fto32F(1e10, 1e10)
|
||||||
|
cvt64Fto32F(-1e10, -1e10)
|
||||||
|
|
||||||
|
// MaxInt64 = 1<<63 - 1 // 9223372036854775807
|
||||||
|
// MinInt64 = -1 << 63 // -9223372036854775808
|
||||||
|
cvt64to64F(0, 0)
|
||||||
|
cvt64to64F(1e10, 1e10)
|
||||||
|
cvt64to64F(9223372036854775807, 9223372036854775807)
|
||||||
|
cvt64to64F(-9223372036854775807, -9223372036854775807)
|
||||||
|
|
||||||
|
// MaxUint64 = 1<<64 - 1 // 18446744073709551615
|
||||||
|
cvt64Uto64F(0, 0)
|
||||||
|
cvt64Uto64F(1e10, 1e10)
|
||||||
|
cvt64Uto64F(9223372036854775807, 9223372036854775807)
|
||||||
|
cvt64Uto64F(18446744073709551615, 18446744073709551615)
|
||||||
|
|
||||||
|
cvt32to64(0, 0)
|
||||||
|
cvt32to64(2147483647, 2147483647)
|
||||||
|
|
||||||
|
cvtUinptr(1024, 1024)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvtUinptr(a int32, b uintptr) {
|
||||||
|
if uintptr(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
if int32(b) != a {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32to64(a int32, b int64) {
|
||||||
|
if int64(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt64to64F(a int64, b float64) {
|
||||||
|
if float64(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt64Uto64F(a uint64, b float64) {
|
||||||
|
if float64(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt64Fto32F(a float64, b float32) {
|
||||||
|
if float32(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32Fto64F(a float32, b float64) {
|
||||||
|
if float64(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32Fto32(a float32, b int32) {
|
||||||
|
if int32(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32Fto32U(a float32, b uint32) {
|
||||||
|
if uint32(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32Fto8(a float32, b int8) {
|
||||||
|
if int8(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt32Fto8U(a float32, b uint8) {
|
||||||
|
if uint8(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt64to8(a int64, b int8) {
|
||||||
|
if int8(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvt64to8U(a int, b uint8) {
|
||||||
|
if uint8(a) != b {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
310
cl/_testrt/cast/out.ll
Normal file
310
cl/_testrt/cast/out.ll
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
; 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 [6 x i8] c"error\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@2 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@3 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@4 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@5 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@6 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@7 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@8 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@9 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@10 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@11 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@12 = private unnamed_addr constant [6 x i8] c"error\00", align 1
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
|
define void @main.cvt32Fto32(float %0, i32 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fptosi float %0 to i32
|
||||||
|
%3 = icmp ne i32 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt32Fto32U(float %0, i32 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fptoui float %0 to i32
|
||||||
|
%3 = icmp ne i32 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt32Fto64F(float %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fpext float %0 to double
|
||||||
|
%3 = fcmp one double %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt32Fto8(float %0, i8 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fptosi float %0 to i8
|
||||||
|
%3 = icmp ne i8 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt32Fto8U(float %0, i8 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fptoui float %0 to i8
|
||||||
|
%3 = icmp ne i8 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt32to64(i32 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = sext i32 %0 to i64
|
||||||
|
%3 = icmp ne i64 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt64Fto32F(double %0, float %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = fptrunc double %0 to float
|
||||||
|
%3 = fcmp one float %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @6, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt64Uto64F(i64 %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = uitofp i64 %0 to double
|
||||||
|
%3 = fcmp one double %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt64to64F(i64 %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = sitofp i64 %0 to double
|
||||||
|
%3 = fcmp one double %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @8, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt64to8(i64 %0, i8 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = trunc i64 %0 to i8
|
||||||
|
%3 = icmp ne i8 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @9, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvt64to8U(i64 %0, i8 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = trunc i64 %0 to i8
|
||||||
|
%3 = icmp ne i8 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @10, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main.cvtUinptr(i32 %0, i64 %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = sext i32 %0 to i64
|
||||||
|
%3 = icmp ne i64 %2, %1
|
||||||
|
br i1 %3, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @11, i64 5)
|
||||||
|
%5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %4)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %5)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
%6 = trunc i64 %1 to i32
|
||||||
|
%7 = icmp ne i32 %6, %0
|
||||||
|
br i1 %7, label %_llgo_3, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_2
|
||||||
|
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 5)
|
||||||
|
%9 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %8)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %9)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_2
|
||||||
|
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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @main.cvt64to8(i64 0, i8 0)
|
||||||
|
call void @main.cvt64to8(i64 127, i8 127)
|
||||||
|
call void @main.cvt64to8(i64 128, i8 -128)
|
||||||
|
call void @main.cvt64to8(i64 -128, i8 -128)
|
||||||
|
call void @main.cvt64to8(i64 -129, i8 127)
|
||||||
|
call void @main.cvt64to8(i64 256, i8 0)
|
||||||
|
call void @main.cvt64to8U(i64 0, i8 0)
|
||||||
|
call void @main.cvt64to8U(i64 255, i8 -1)
|
||||||
|
call void @main.cvt64to8U(i64 256, i8 0)
|
||||||
|
call void @main.cvt64to8U(i64 257, i8 1)
|
||||||
|
call void @main.cvt64to8U(i64 -1, i8 -1)
|
||||||
|
call void @main.cvt32Fto8(float 0x3FB99999A0000000, i8 0)
|
||||||
|
call void @main.cvt32Fto8(float 0x405FC66660000000, i8 127)
|
||||||
|
call void @main.cvt32Fto8(float 0x4060033340000000, i8 -128)
|
||||||
|
call void @main.cvt32Fto8(float 0xC060033340000000, i8 -128)
|
||||||
|
call void @main.cvt32Fto8(float 0xC060233340000000, i8 127)
|
||||||
|
call void @main.cvt32Fto8(float 0x40700199A0000000, i8 0)
|
||||||
|
call void @main.cvt32Fto8U(float 0.000000e+00, i8 0)
|
||||||
|
call void @main.cvt32Fto8U(float 2.550000e+02, i8 -1)
|
||||||
|
call void @main.cvt32Fto8U(float 2.560000e+02, i8 0)
|
||||||
|
call void @main.cvt32Fto8U(float 2.570000e+02, i8 1)
|
||||||
|
call void @main.cvt32Fto8U(float -1.000000e+00, i8 -1)
|
||||||
|
call void @main.cvt32Fto32(float 0.000000e+00, i32 0)
|
||||||
|
call void @main.cvt32Fto32(float 1.500000e+00, i32 1)
|
||||||
|
call void @main.cvt32Fto32(float 0x41D1194D80000000, i32 1147483648)
|
||||||
|
call void @main.cvt32Fto32(float 0x41E0000000000000, i32 -2147483648)
|
||||||
|
call void @main.cvt32Fto32(float 0x41EEE6B280000000, i32 -2147483648)
|
||||||
|
call void @main.cvt32Fto32(float 0xC1E0000000000000, i32 -2147483648)
|
||||||
|
call void @main.cvt32Fto32(float 0xC1DFFFFF00000000, i32 -2147482624)
|
||||||
|
call void @main.cvt32Fto32U(float 0.000000e+00, i32 0)
|
||||||
|
call void @main.cvt32Fto32U(float 1.500000e+00, i32 1)
|
||||||
|
call void @main.cvt32Fto32U(float 0x41F0000000000000, i32 0)
|
||||||
|
call void @main.cvt32Fto32U(float 0x41F3B9ACA0000000, i32 1000000000)
|
||||||
|
call void @main.cvt32Fto32U(float 0xC1F0000000000000, i32 0)
|
||||||
|
call void @main.cvt32Fto32U(float 0xC1D34BE880000000, i32 -1294967296)
|
||||||
|
call void @main.cvt32Fto32U(float 0xBFF19999A0000000, i32 -1)
|
||||||
|
call void @main.cvt32Fto64F(float 0.000000e+00, double 0.000000e+00)
|
||||||
|
call void @main.cvt32Fto64F(float 1.500000e+00, double 1.500000e+00)
|
||||||
|
call void @main.cvt32Fto64F(float 1.000000e+10, double 1.000000e+10)
|
||||||
|
call void @main.cvt32Fto64F(float -1.000000e+10, double -1.000000e+10)
|
||||||
|
call void @main.cvt64Fto32F(double 0.000000e+00, float 0.000000e+00)
|
||||||
|
call void @main.cvt64Fto32F(double 1.500000e+00, float 1.500000e+00)
|
||||||
|
call void @main.cvt64Fto32F(double 1.000000e+10, float 1.000000e+10)
|
||||||
|
call void @main.cvt64Fto32F(double -1.000000e+10, float -1.000000e+10)
|
||||||
|
call void @main.cvt64to64F(i64 0, double 0.000000e+00)
|
||||||
|
call void @main.cvt64to64F(i64 10000000000, double 1.000000e+10)
|
||||||
|
call void @main.cvt64to64F(i64 9223372036854775807, double 0x43E0000000000000)
|
||||||
|
call void @main.cvt64to64F(i64 -9223372036854775807, double 0xC3E0000000000000)
|
||||||
|
call void @main.cvt64Uto64F(i64 0, double 0.000000e+00)
|
||||||
|
call void @main.cvt64Uto64F(i64 10000000000, double 1.000000e+10)
|
||||||
|
call void @main.cvt64Uto64F(i64 9223372036854775807, double 0x43E0000000000000)
|
||||||
|
call void @main.cvt64Uto64F(i64 -1, double 0x43F0000000000000)
|
||||||
|
call void @main.cvt32to64(i32 0, i64 0)
|
||||||
|
call void @main.cvt32to64(i32 2147483647, i64 2147483647)
|
||||||
|
call void @main.cvtUinptr(i32 1024, i64 1024)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
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()
|
||||||
|
}
|
||||||
88
cl/_testrt/closure/out.ll
Normal file
88
cl/_testrt/closure/out.ll
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = 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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
call void @"main.main$1"(i64 100, i64 200)
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%3 = alloca { ptr, ptr }, align 8
|
||||||
|
%4 = getelementptr inbounds { ptr, ptr }, ptr %3, i32 0, i32 0
|
||||||
|
store ptr @"__llgo_stub.main.main$2", ptr %4, align 8
|
||||||
|
%5 = getelementptr inbounds { ptr, ptr }, ptr %3, i32 0, i32 1
|
||||||
|
store ptr null, ptr %5, align 8
|
||||||
|
%6 = load { ptr, ptr }, ptr %3, align 8
|
||||||
|
store { ptr, ptr } %6, ptr %2, align 8
|
||||||
|
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%8 = getelementptr inbounds { ptr }, ptr %7, i32 0, i32 0
|
||||||
|
store ptr %2, ptr %8, align 8
|
||||||
|
%9 = alloca { ptr, ptr }, align 8
|
||||||
|
%10 = getelementptr inbounds { ptr, ptr }, ptr %9, i32 0, i32 0
|
||||||
|
store ptr @"main.main$3", ptr %10, align 8
|
||||||
|
%11 = getelementptr inbounds { ptr, ptr }, ptr %9, i32 0, i32 1
|
||||||
|
store ptr %7, ptr %11, align 8
|
||||||
|
%12 = load { ptr, ptr }, ptr %9, align 8
|
||||||
|
%13 = extractvalue { ptr, ptr } %12, 1
|
||||||
|
%14 = extractvalue { ptr, ptr } %12, 0
|
||||||
|
call void %14(ptr %13)
|
||||||
|
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, ...)
|
||||||
@@ -6,6 +6,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@1 = 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 [2 x i8] c" \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
|
@3 = private unnamed_addr constant [6 x i8] c"World\00", align 1
|
||||||
@@ -60,28 +62,30 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.AllocZ"(i64 48)
|
%2 = 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
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 0
|
||||||
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
|
%4 = 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
|
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
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 1
|
||||||
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
%6 = 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" %6, ptr %5, align 8
|
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)
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i64 2
|
||||||
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
|
||||||
%9 = load ptr, ptr @__stderrp, align 8
|
store %"github.com/goplus/llgo/internal/runtime.String" %8, ptr %7, align 8
|
||||||
%10 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %8)
|
%9 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3)
|
||||||
%11 = add i64 %10, 1
|
%10 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %9)
|
||||||
%12 = alloca i8, i64 %11, align 1
|
%11 = load ptr, ptr @__stderrp, align 8
|
||||||
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %12, %"github.com/goplus/llgo/internal/runtime.String" %8)
|
%12 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %10)
|
||||||
%14 = call i32 (ptr, ptr, ...) @fprintf(ptr %9, ptr @4, ptr %13)
|
%13 = add i64 %12, 1
|
||||||
|
%14 = alloca i8, i64 %13, align 1
|
||||||
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %14, %"github.com/goplus/llgo/internal/runtime.String" %10)
|
||||||
|
%16 = call i32 (ptr, ptr, ...) @fprintf(ptr %11, ptr @4, ptr %15)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [14 x i8] c"Hello, world\0A\00", align 1
|
@0 = private unnamed_addr constant [14 x i8] c"Hello, world\0A\00", align 1
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
@@ -17,14 +19,16 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
call void (ptr, ...) @printf(ptr @0)
|
call void (ptr, ...) @printf(ptr @0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ source_filename = "main"
|
|||||||
@_bar_x = external global ptr
|
@_bar_x = external global ptr
|
||||||
@_bar_y = external global ptr
|
@_bar_y = external global ptr
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -18,12 +20,14 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = load { [16 x i8], [2 x ptr] }, ptr @_bar_x, align 8
|
%2 = load { [16 x i8], [2 x ptr] }, ptr @_bar_x, align 8
|
||||||
%1 = load { [16 x i8] }, ptr @_bar_y, align 1
|
%3 = load { [16 x i8] }, ptr @_bar_y, align 1
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ source_filename = "main"
|
|||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@__stderrp = external global ptr
|
@__stderrp = external global ptr
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
declare void @fprintf(ptr, ptr, ...)
|
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
@@ -20,13 +20,17 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = load ptr, ptr @__stderrp, align 8
|
%2 = load ptr, ptr @__stderrp, align 8
|
||||||
call void (ptr, ptr, ...) @fprintf(ptr %0, ptr @0, i64 100)
|
call void (ptr, ptr, ...) @fprintf(ptr %2, ptr @0, i64 100)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare void @fprintf(ptr, ptr, ...)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ source_filename = "main"
|
|||||||
@main.basicTypes = global ptr null
|
@main.basicTypes = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
@main.sizeBasicTypes = global ptr null
|
@main.sizeBasicTypes = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1
|
@0 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1
|
||||||
|
|
||||||
define ptr @main.Basic(i64 %0) {
|
define ptr @main.Basic(i64 %0) {
|
||||||
@@ -48,17 +50,19 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = call ptr @main.Basic(i64 24)
|
%2 = call ptr @main.Basic(i64 24)
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 6
|
||||||
%2 = load i8, ptr %1, align 1
|
%4 = load i8, ptr %3, align 1
|
||||||
%3 = sext i8 %2 to i64
|
%5 = sext i8 %4 to i64
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 0
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %2, i32 0, i32 0
|
||||||
%5 = load i64, ptr %4, align 4
|
%7 = load i64, ptr %6, align 4
|
||||||
%6 = call i32 (ptr, ...) @printf(ptr @0, i64 %3, i64 %5)
|
%8 = call i32 (ptr, ...) @printf(ptr @0, i64 %5, i64 %7)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
}
|
||||||
38
cl/_testrt/gotypes/out.ll
Normal file
38
cl/_testrt/gotypes/out.ll
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = 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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
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"()
|
||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -27,12 +29,14 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = call i32 @strlen(ptr @main.format)
|
%2 = call i32 @strlen(ptr @main.format)
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
call void (ptr, ...) @printf(ptr @main.format, i32 %2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ source_filename = "main"
|
|||||||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
|
@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
|
@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
|
@2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
@@ -27,103 +29,105 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = alloca %main.point, align 8
|
%2 = alloca %main.point, align 8
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 16)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
||||||
%2 = alloca [3 x %main.point], align 8
|
%4 = alloca [3 x %main.point], align 8
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 48)
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %4, i64 48)
|
||||||
%4 = getelementptr inbounds %main.point, ptr %3, i64 0
|
%6 = getelementptr inbounds %main.point, ptr %5, i64 0
|
||||||
%5 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 0
|
%7 = getelementptr inbounds %main.point, ptr %6, i32 0, i32 0
|
||||||
%6 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 1
|
%8 = getelementptr inbounds %main.point, ptr %6, i32 0, i32 1
|
||||||
%7 = getelementptr inbounds %main.point, ptr %3, i64 1
|
%9 = getelementptr inbounds %main.point, ptr %5, i64 1
|
||||||
%8 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 0
|
%10 = getelementptr inbounds %main.point, ptr %9, i32 0, i32 0
|
||||||
%9 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 1
|
%11 = getelementptr inbounds %main.point, ptr %9, i32 0, i32 1
|
||||||
%10 = getelementptr inbounds %main.point, ptr %3, i64 2
|
%12 = getelementptr inbounds %main.point, ptr %5, i64 2
|
||||||
%11 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 0
|
%13 = getelementptr inbounds %main.point, ptr %12, i32 0, i32 0
|
||||||
%12 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 1
|
%14 = getelementptr inbounds %main.point, ptr %12, i32 0, i32 1
|
||||||
store i64 1, ptr %5, align 4
|
store i64 1, ptr %7, align 4
|
||||||
store i64 2, ptr %6, align 4
|
store i64 2, ptr %8, align 4
|
||||||
store i64 3, ptr %8, align 4
|
store i64 3, ptr %10, align 4
|
||||||
store i64 4, ptr %9, align 4
|
store i64 4, ptr %11, align 4
|
||||||
store i64 5, ptr %11, align 4
|
store i64 5, ptr %13, align 4
|
||||||
store i64 6, ptr %12, align 4
|
store i64 6, ptr %14, align 4
|
||||||
%13 = load [3 x %main.point], ptr %3, align 4
|
%15 = load [3 x %main.point], ptr %5, align 4
|
||||||
%14 = getelementptr inbounds %main.point, ptr %3, i64 2
|
%16 = getelementptr inbounds %main.point, ptr %5, i64 2
|
||||||
%15 = load %main.point, ptr %14, align 4
|
%17 = load %main.point, ptr %16, align 4
|
||||||
store %main.point %15, ptr %1, align 4
|
store %main.point %17, ptr %3, align 4
|
||||||
%16 = getelementptr inbounds %main.point, ptr %1, i32 0, i32 0
|
%18 = getelementptr inbounds %main.point, ptr %3, 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
|
%19 = load i64, ptr %18, align 4
|
||||||
%20 = call i32 (ptr, ...) @printf(ptr @0, i64 %17, i64 %19)
|
%20 = getelementptr inbounds %main.point, ptr %3, i32 0, i32 1
|
||||||
%21 = alloca [2 x i64], align 8
|
%21 = load i64, ptr %20, align 4
|
||||||
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %21, i64 16)
|
%22 = call i32 (ptr, ...) @printf(ptr @0, i64 %19, i64 %21)
|
||||||
%23 = alloca [2 x [2 x i64]], align 8
|
%23 = alloca [2 x i64], align 8
|
||||||
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %23, i64 32)
|
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %23, i64 16)
|
||||||
%25 = getelementptr inbounds [2 x i64], ptr %24, i64 0
|
%25 = alloca [2 x [2 x i64]], align 8
|
||||||
%26 = getelementptr inbounds i64, ptr %25, i64 0
|
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %25, i64 32)
|
||||||
%27 = getelementptr inbounds i64, ptr %25, i64 1
|
%27 = getelementptr inbounds [2 x i64], ptr %26, i64 0
|
||||||
%28 = getelementptr inbounds [2 x i64], ptr %24, i64 1
|
%28 = getelementptr inbounds i64, ptr %27, i64 0
|
||||||
%29 = getelementptr inbounds i64, ptr %28, i64 0
|
%29 = getelementptr inbounds i64, ptr %27, i64 1
|
||||||
%30 = getelementptr inbounds i64, ptr %28, i64 1
|
%30 = getelementptr inbounds [2 x i64], ptr %26, i64 1
|
||||||
store i64 1, ptr %26, align 4
|
%31 = getelementptr inbounds i64, ptr %30, i64 0
|
||||||
store i64 2, ptr %27, align 4
|
%32 = getelementptr inbounds i64, ptr %30, i64 1
|
||||||
store i64 3, ptr %29, align 4
|
store i64 1, ptr %28, align 4
|
||||||
store i64 4, ptr %30, align 4
|
store i64 2, ptr %29, align 4
|
||||||
%31 = load [2 x [2 x i64]], ptr %24, align 4
|
store i64 3, ptr %31, align 4
|
||||||
%32 = getelementptr inbounds [2 x i64], ptr %24, i64 1
|
store i64 4, ptr %32, align 4
|
||||||
%33 = load [2 x i64], ptr %32, align 4
|
%33 = load [2 x [2 x i64]], ptr %26, align 4
|
||||||
store [2 x i64] %33, ptr %22, align 4
|
%34 = getelementptr inbounds [2 x i64], ptr %26, i64 1
|
||||||
%34 = getelementptr inbounds i64, ptr %22, i64 0
|
%35 = load [2 x i64], ptr %34, align 4
|
||||||
%35 = load i64, ptr %34, align 4
|
store [2 x i64] %35, ptr %24, align 4
|
||||||
%36 = getelementptr inbounds i64, ptr %22, i64 1
|
%36 = getelementptr inbounds i64, ptr %24, i64 0
|
||||||
%37 = load i64, ptr %36, align 4
|
%37 = load i64, ptr %36, align 4
|
||||||
%38 = call i32 (ptr, ...) @printf(ptr @1, i64 %35, i64 %37)
|
%38 = getelementptr inbounds i64, ptr %24, i64 1
|
||||||
%39 = alloca [5 x i64], align 8
|
%39 = load i64, ptr %38, align 4
|
||||||
%40 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %39, i64 40)
|
%40 = call i32 (ptr, ...) @printf(ptr @1, i64 %37, i64 %39)
|
||||||
%41 = getelementptr inbounds i64, ptr %40, i64 0
|
%41 = alloca [5 x i64], align 8
|
||||||
%42 = getelementptr inbounds i64, ptr %40, i64 1
|
%42 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %41, i64 40)
|
||||||
%43 = getelementptr inbounds i64, ptr %40, i64 2
|
%43 = getelementptr inbounds i64, ptr %42, i64 0
|
||||||
%44 = getelementptr inbounds i64, ptr %40, i64 3
|
%44 = getelementptr inbounds i64, ptr %42, i64 1
|
||||||
%45 = getelementptr inbounds i64, ptr %40, i64 4
|
%45 = getelementptr inbounds i64, ptr %42, i64 2
|
||||||
store i64 1, ptr %41, align 4
|
%46 = getelementptr inbounds i64, ptr %42, i64 3
|
||||||
store i64 2, ptr %42, align 4
|
%47 = getelementptr inbounds i64, ptr %42, i64 4
|
||||||
store i64 3, ptr %43, align 4
|
store i64 1, ptr %43, align 4
|
||||||
store i64 4, ptr %44, align 4
|
store i64 2, ptr %44, align 4
|
||||||
store i64 5, ptr %45, align 4
|
store i64 3, ptr %45, align 4
|
||||||
%46 = load [5 x i64], ptr %40, align 4
|
store i64 4, ptr %46, align 4
|
||||||
%47 = getelementptr inbounds i64, ptr %40, i64 2
|
store i64 5, ptr %47, align 4
|
||||||
%48 = load i64, ptr %47, align 4
|
%48 = load [5 x i64], ptr %42, align 4
|
||||||
%49 = call i32 (ptr, ...) @printf(ptr @2, i64 %48)
|
%49 = getelementptr inbounds i64, ptr %42, i64 2
|
||||||
%50 = alloca [5 x i64], align 8
|
%50 = load i64, ptr %49, align 4
|
||||||
%51 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %50, i64 40)
|
%51 = call i32 (ptr, ...) @printf(ptr @2, i64 %50)
|
||||||
%52 = getelementptr inbounds i64, ptr %51, i64 0
|
%52 = alloca [5 x i64], align 8
|
||||||
%53 = getelementptr inbounds i64, ptr %51, i64 1
|
%53 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %52, i64 40)
|
||||||
%54 = getelementptr inbounds i64, ptr %51, i64 2
|
%54 = getelementptr inbounds i64, ptr %53, i64 0
|
||||||
%55 = getelementptr inbounds i64, ptr %51, i64 3
|
%55 = getelementptr inbounds i64, ptr %53, i64 1
|
||||||
%56 = getelementptr inbounds i64, ptr %51, i64 4
|
%56 = getelementptr inbounds i64, ptr %53, i64 2
|
||||||
store i64 1, ptr %52, align 4
|
%57 = getelementptr inbounds i64, ptr %53, i64 3
|
||||||
store i64 2, ptr %53, align 4
|
%58 = getelementptr inbounds i64, ptr %53, i64 4
|
||||||
store i64 3, ptr %54, align 4
|
store i64 1, ptr %54, align 4
|
||||||
store i64 4, ptr %55, align 4
|
store i64 2, ptr %55, align 4
|
||||||
store i64 5, ptr %56, align 4
|
store i64 3, ptr %56, align 4
|
||||||
%57 = load [5 x i64], ptr %51, align 4
|
store i64 4, ptr %57, align 4
|
||||||
%58 = getelementptr inbounds i64, ptr %51, i64 2
|
store i64 5, ptr %58, align 4
|
||||||
%59 = load i64, ptr %58, align 4
|
%59 = load [5 x i64], ptr %53, align 4
|
||||||
%60 = call i32 (ptr, ...) @printf(ptr @3, i64 %59)
|
%60 = getelementptr inbounds i64, ptr %53, i64 2
|
||||||
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
|
%61 = load i64, ptr %60, align 4
|
||||||
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %61)
|
%62 = call i32 (ptr, ...) @printf(ptr @3, i64 %61)
|
||||||
%63 = getelementptr inbounds i8, ptr %62, i64 2
|
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
|
||||||
%64 = load i8, ptr %63, align 1
|
%64 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %63)
|
||||||
%65 = call i32 (ptr, ...) @printf(ptr @4, i8 %64)
|
%65 = getelementptr inbounds i8, ptr %64, i64 2
|
||||||
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
|
%66 = load i8, ptr %65, align 1
|
||||||
%67 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %66)
|
%67 = call i32 (ptr, ...) @printf(ptr @4, i8 %66)
|
||||||
%68 = getelementptr inbounds i8, ptr %67, i64 1
|
%68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
|
||||||
%69 = load i8, ptr %68, align 1
|
%69 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %68)
|
||||||
%70 = call i32 (ptr, ...) @printf(ptr @6, i8 %69)
|
%70 = getelementptr inbounds i8, ptr %69, i64 1
|
||||||
|
%71 = load i8, ptr %70, align 1
|
||||||
|
%72 = call i32 (ptr, ...) @printf(ptr @6, i8 %71)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/runtime/c"
|
"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 {
|
func genInts(n int, gen func() c.Int) []c.Int {
|
||||||
a := make([]c.Int, n)
|
a := make([]c.Int, n)
|
||||||
for i := range a {
|
for i := range a {
|
||||||
@@ -13,8 +22,21 @@ func genInts(n int, gen func() c.Int) []c.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
a := genInts(5, c.Rand)
|
for _, v := range genInts(5, c.Rand) {
|
||||||
for _, v := range a {
|
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)
|
c.Printf(c.Str("%d\n"), v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%main.generator = type { i32 }
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
@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) {
|
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 %0, { ptr, ptr } %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -21,16 +26,30 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
|
|||||||
br i1 %8, label %_llgo_2, label %_llgo_3
|
br i1 %8, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_llgo_2: ; preds = %_llgo_1
|
||||||
%9 = extractvalue { ptr, ptr } %1, 0
|
%9 = extractvalue { ptr, ptr } %1, 1
|
||||||
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
%10 = extractvalue { ptr, ptr } %1, 0
|
||||||
%11 = getelementptr inbounds i32, ptr %10, i64 %7
|
%11 = call i32 %10(ptr %9)
|
||||||
store i32 0, ptr %11, align 4
|
%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
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1
|
_llgo_3: ; preds = %_llgo_1
|
||||||
ret %"github.com/goplus/llgo/internal/runtime.Slice" %4
|
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() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = load i1, ptr @"main.init$guard", align 1
|
%0 = load i1, ptr @"main.init$guard", align 1
|
||||||
@@ -44,34 +63,95 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = alloca { ptr, ptr }, align 8
|
%2 = alloca { ptr, ptr }, align 8
|
||||||
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
%3 = getelementptr inbounds { ptr, ptr }, ptr %2, i32 0, i32 0
|
||||||
store ptr @rand, ptr %1, align 8
|
store ptr @__llgo_stub.rand, ptr %3, align 8
|
||||||
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
%4 = getelementptr inbounds { ptr, ptr }, ptr %2, i32 0, i32 1
|
||||||
store ptr null, ptr %2, align 8
|
store ptr null, ptr %4, align 8
|
||||||
%3 = load { ptr, ptr }, ptr %0, align 8
|
%5 = load { ptr, ptr }, ptr %2, align 8
|
||||||
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %3)
|
%6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %5)
|
||||||
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
%7 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %6)
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
%6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ]
|
%8 = phi i64 [ -1, %_llgo_0 ], [ %9, %_llgo_2 ]
|
||||||
%7 = add i64 %6, 1
|
%9 = add i64 %8, 1
|
||||||
%8 = icmp slt i64 %7, %5
|
%10 = icmp slt i64 %9, %7
|
||||||
br i1 %8, label %_llgo_2, label %_llgo_3
|
br i1 %10, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_llgo_2: ; preds = %_llgo_1
|
||||||
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %6)
|
||||||
%10 = getelementptr inbounds i32, ptr %9, i64 %7
|
%12 = getelementptr inbounds i32, ptr %11, i64 %9
|
||||||
%11 = load i32, ptr %10, align 4
|
%13 = load i32, ptr %12, align 4
|
||||||
%12 = call i32 (ptr, ...) @printf(ptr @0, i32 %11)
|
%14 = call i32 (ptr, ...) @printf(ptr @0, i32 %13)
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4)
|
||||||
|
store i32 1, ptr %15, align 4
|
||||||
|
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%17 = getelementptr inbounds { ptr }, ptr %16, i32 0, i32 0
|
||||||
|
store ptr %15, ptr %17, align 8
|
||||||
|
%18 = alloca { ptr, ptr }, align 8
|
||||||
|
%19 = getelementptr inbounds { ptr, ptr }, ptr %18, i32 0, i32 0
|
||||||
|
store ptr @"main.main$1", ptr %19, align 8
|
||||||
|
%20 = getelementptr inbounds { ptr, ptr }, ptr %18, i32 0, i32 1
|
||||||
|
store ptr %16, ptr %20, align 8
|
||||||
|
%21 = load { ptr, ptr }, ptr %18, align 8
|
||||||
|
%22 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %21)
|
||||||
|
%23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %22)
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_5, %_llgo_3
|
||||||
|
%24 = phi i64 [ -1, %_llgo_3 ], [ %25, %_llgo_5 ]
|
||||||
|
%25 = add i64 %24, 1
|
||||||
|
%26 = icmp slt i64 %25, %23
|
||||||
|
br i1 %26, label %_llgo_5, label %_llgo_6
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_4
|
||||||
|
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %22)
|
||||||
|
%28 = getelementptr inbounds i32, ptr %27, i64 %25
|
||||||
|
%29 = load i32, ptr %28, align 4
|
||||||
|
%30 = call i32 (ptr, ...) @printf(ptr @1, i32 %29)
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_4
|
||||||
|
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4)
|
||||||
|
%32 = getelementptr inbounds %main.generator, ptr %31, i32 0, i32 0
|
||||||
|
store i32 1, ptr %32, align 4
|
||||||
|
%33 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8)
|
||||||
|
%34 = getelementptr inbounds { ptr }, ptr %33, i32 0, i32 0
|
||||||
|
store ptr %31, ptr %34, align 8
|
||||||
|
%35 = alloca { ptr, ptr }, align 8
|
||||||
|
%36 = getelementptr inbounds { ptr, ptr }, ptr %35, i32 0, i32 0
|
||||||
|
store ptr @"main.next$bound", ptr %36, align 8
|
||||||
|
%37 = getelementptr inbounds { ptr, ptr }, ptr %35, i32 0, i32 1
|
||||||
|
store ptr %33, ptr %37, align 8
|
||||||
|
%38 = load { ptr, ptr }, ptr %35, align 8
|
||||||
|
%39 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %38)
|
||||||
|
%40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %39)
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_7: ; preds = %_llgo_8, %_llgo_6
|
||||||
|
%41 = phi i64 [ -1, %_llgo_6 ], [ %42, %_llgo_8 ]
|
||||||
|
%42 = add i64 %41, 1
|
||||||
|
%43 = icmp slt i64 %42, %40
|
||||||
|
br i1 %43, label %_llgo_8, label %_llgo_9
|
||||||
|
|
||||||
|
_llgo_8: ; preds = %_llgo_7
|
||||||
|
%44 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %39)
|
||||||
|
%45 = getelementptr inbounds i32, ptr %44, i64 %42
|
||||||
|
%46 = load i32, ptr %45, align 4
|
||||||
|
%47 = call i32 (ptr, ...) @printf(ptr @2, i32 %46)
|
||||||
|
br label %_llgo_7
|
||||||
|
|
||||||
|
_llgo_9: ; preds = %_llgo_7
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,4 +167,33 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
|||||||
|
|
||||||
declare i32 @rand()
|
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, ...)
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [2 x i8] c"a\00", align 1
|
@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
|
@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
|
@2 = private unnamed_addr constant [2 x i8] c"c\00", align 1
|
||||||
@@ -24,8 +26,10 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.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 @0, ptr @1, ptr @2, ptr @3)
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
|
||||||
import (
|
import (
|
||||||
"github.com/goplus/llgo/internal/runtime/c"
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
)
|
)
|
||||||
*/
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
a := map[int]int{23: 100, 7: 29}
|
a := map[int]int{23: 100, 7: 29}
|
||||||
_ = a
|
c.Printf(c.Str("Hello %d\n"), a[23])
|
||||||
// c.Printf(c.Str("Hello %d\n"), a[23])
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -16,14 +19,19 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.MakeSmallMap"()
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
|
||||||
|
%3 = call i32 (ptr, ...) @printf(ptr @0, <null operand!>)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
|
declare ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
|
|||||||
@@ -5,6 +5,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.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [14 x i8] c"panic message\00", align 1
|
@0 = private unnamed_addr constant [14 x i8] c"panic message\00", align 1
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
@@ -20,13 +22,15 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 13)
|
%2 = 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)
|
%3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %2)
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %1)
|
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %3)
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
@@ -17,48 +19,50 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.AllocZ"(i64 40)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
|
||||||
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
%3 = getelementptr inbounds i64, ptr %2, i64 0
|
||||||
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
%4 = getelementptr inbounds i64, ptr %2, i64 1
|
||||||
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
%5 = getelementptr inbounds i64, ptr %2, i64 2
|
||||||
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
%6 = getelementptr inbounds i64, ptr %2, i64 3
|
||||||
%5 = getelementptr inbounds i64, ptr %0, i64 4
|
%7 = getelementptr inbounds i64, ptr %2, i64 4
|
||||||
store i64 100, ptr %1, align 4
|
store i64 100, ptr %3, align 4
|
||||||
store i64 8, ptr %2, align 4
|
store i64 8, ptr %4, align 4
|
||||||
store i64 23, ptr %3, align 4
|
store i64 23, ptr %5, align 4
|
||||||
store i64 2, ptr %4, align 4
|
store i64 2, ptr %6, align 4
|
||||||
store i64 7, ptr %5, align 4
|
store i64 7, ptr %7, align 4
|
||||||
%6 = getelementptr inbounds i64, ptr %0, i64 0
|
%8 = getelementptr inbounds i64, ptr %2, i64 0
|
||||||
call void @qsort(ptr %6, i64 5, i64 8, ptr @"main.main$1")
|
call void @qsort(ptr %8, i64 5, i64 8, ptr @"main.main$1")
|
||||||
%7 = load [5 x i64], ptr %0, align 4
|
%9 = load [5 x i64], ptr %2, align 4
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
_llgo_1: ; preds = %_llgo_2, %_llgo_0
|
||||||
%8 = phi i64 [ -1, %_llgo_0 ], [ %9, %_llgo_2 ]
|
%10 = phi i64 [ -1, %_llgo_0 ], [ %11, %_llgo_2 ]
|
||||||
%9 = add i64 %8, 1
|
%11 = add i64 %10, 1
|
||||||
%10 = icmp slt i64 %9, 5
|
%12 = icmp slt i64 %11, 5
|
||||||
br i1 %10, label %_llgo_2, label %_llgo_3
|
br i1 %12, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_llgo_2: ; preds = %_llgo_1
|
||||||
%11 = getelementptr inbounds i64, ptr %0, i64 %9
|
%13 = getelementptr inbounds i64, ptr %2, i64 %11
|
||||||
%12 = load i64, ptr %11, align 4
|
%14 = load i64, ptr %13, align 4
|
||||||
%13 = call i32 (ptr, ...) @printf(ptr @0, i64 %12)
|
%15 = call i32 (ptr, ...) @printf(ptr @0, i64 %14)
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1
|
_llgo_3: ; preds = %_llgo_1
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @qsort(ptr, i64, i64, ptr)
|
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
|
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) {
|
define i32 @"main.main$1"(ptr %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%2 = load i64, ptr %0, align 4
|
%2 = load i64, ptr %0, align 4
|
||||||
|
|||||||
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
|
||||||
|
}
|
||||||
124
cl/_testrt/result/out.ll
Normal file
124
cl/_testrt/result/out.ll
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = 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(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call { ptr, ptr } @"main.main$1"()
|
||||||
|
%3 = extractvalue { ptr, ptr } %2, 1
|
||||||
|
%4 = extractvalue { ptr, ptr } %2, 0
|
||||||
|
%5 = call i64 %4(ptr %3, i64 100, i64 200)
|
||||||
|
%6 = call i32 (ptr, ...) @printf(ptr @0, i64 %5)
|
||||||
|
%7 = call { ptr, ptr } @main.add()
|
||||||
|
%8 = extractvalue { ptr, ptr } %7, 1
|
||||||
|
%9 = extractvalue { ptr, ptr } %7, 0
|
||||||
|
%10 = call i64 %9(ptr %8, i64 100, i64 200)
|
||||||
|
%11 = call i32 (ptr, ...) @printf(ptr @1, i64 %10)
|
||||||
|
%12 = call { { ptr, ptr }, i64 } @main.add2()
|
||||||
|
%13 = extractvalue { { ptr, ptr }, i64 } %12, 0
|
||||||
|
%14 = extractvalue { { ptr, ptr }, i64 } %12, 1
|
||||||
|
%15 = call { ptr, ptr } @main.add()
|
||||||
|
%16 = extractvalue { ptr, ptr } %15, 1
|
||||||
|
%17 = extractvalue { ptr, ptr } %15, 0
|
||||||
|
%18 = call i64 %17(ptr %16, i64 100, i64 200)
|
||||||
|
%19 = call i32 (ptr, ...) @printf(ptr @2, i64 %18, i64 %14)
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -27,17 +29,19 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = call i32 @strlen(ptr @main.format)
|
%2 = call i32 @strlen(ptr @main.format)
|
||||||
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
|
call void (ptr, ...) @printf(ptr @main.format, i32 %2)
|
||||||
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 @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @printf(ptr, ...)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @"(main.Foo).Print"(%main.Foo %0) {
|
define void @"(main.Foo).Print"(%main.Foo %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -55,23 +57,25 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
%0 = alloca %main.Foo, align 8
|
%2 = alloca %main.Foo, align 8
|
||||||
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 8)
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 8)
|
||||||
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 0
|
%4 = getelementptr inbounds %main.Foo, ptr %3, i32 0, i32 0
|
||||||
%3 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
|
%5 = getelementptr inbounds %main.Foo, ptr %3, i32 0, i32 1
|
||||||
store i32 100, ptr %2, align 4
|
store i32 100, ptr %4, align 4
|
||||||
store i1 true, ptr %3, align 1
|
store i1 true, ptr %5, align 1
|
||||||
%4 = load %main.Foo, ptr %1, align 4
|
%6 = load %main.Foo, ptr %3, align 4
|
||||||
call void @"(main.Foo).Print"(%main.Foo %4)
|
call void @"(main.Foo).Print"(%main.Foo %6)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @printf(ptr, ...)
|
|
||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
||||||
|
|
||||||
|
declare void @printf(ptr, ...)
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ source_filename = "main"
|
|||||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
|
||||||
|
|
||||||
define void @main.init() {
|
define void @main.init() {
|
||||||
@@ -19,22 +21,24 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.AllocZ"(i64 32)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
||||||
%1 = getelementptr inbounds i64, ptr %0, i64 0
|
%3 = getelementptr inbounds i64, ptr %2, i64 0
|
||||||
store i64 1, ptr %1, align 4
|
store i64 1, ptr %3, align 4
|
||||||
%2 = getelementptr inbounds i64, ptr %0, i64 1
|
%4 = getelementptr inbounds i64, ptr %2, i64 1
|
||||||
store i64 2, ptr %2, align 4
|
store i64 2, ptr %4, align 4
|
||||||
%3 = getelementptr inbounds i64, ptr %0, i64 2
|
%5 = getelementptr inbounds i64, ptr %2, i64 2
|
||||||
store i64 3, ptr %3, align 4
|
store i64 3, ptr %5, align 4
|
||||||
%4 = getelementptr inbounds i64, ptr %0, i64 3
|
%6 = getelementptr inbounds i64, ptr %2, i64 3
|
||||||
store i64 4, ptr %4, align 4
|
store i64 4, ptr %6, 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)
|
%7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 8, i64 4, i64 0, i64 4, i64 4)
|
||||||
%6 = call i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
|
%8 = call i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
|
||||||
%7 = call i32 (ptr, ...) @printf(ptr @0, i64 %6)
|
%9 = call i32 (ptr, ...) @printf(ptr @0, i64 %8)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ source_filename = "main"
|
|||||||
|
|
||||||
@main.format = global ptr null
|
@main.format = global ptr null
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
|
||||||
define void @main.Print(ptr %0) {
|
define void @main.Print(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -43,16 +45,18 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
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.AllocZ"(i64 8)
|
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
|
||||||
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
|
%3 = getelementptr inbounds { i32, i1 }, ptr %2, i32 0, i32 0
|
||||||
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
|
%4 = getelementptr inbounds { i32, i1 }, ptr %2, i32 0, i32 1
|
||||||
store i32 100, ptr %1, align 4
|
store i32 100, ptr %3, align 4
|
||||||
store i1 true, ptr %2, align 1
|
store i1 true, ptr %4, align 1
|
||||||
call void @main.Print(ptr %0)
|
call void @main.Print(ptr %2)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"main.init$guard" = global ptr null
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
@0 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
@0 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
||||||
|
|
||||||
define void @main.foo() {
|
define void @main.foo() {
|
||||||
@@ -23,12 +25,14 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @main() {
|
define void @main(i32 %0, ptr %1) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
call void @main.foo()
|
call void @main.foo()
|
||||||
%0 = call i32 (ptr, ...) @printf(ptr @0)
|
%2 = call i32 (ptr, ...) @printf(ptr @0)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package cl
|
package cl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go/ast"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/types"
|
"go/types"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -25,6 +26,28 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestRecvTypeName(t *testing.T) {
|
||||||
|
if ret := recvTypeName(&ast.IndexExpr{
|
||||||
|
X: &ast.Ident{Name: "Pointer"},
|
||||||
|
Index: &ast.Ident{Name: "T"},
|
||||||
|
}); ret != "Pointer" {
|
||||||
|
t.Fatal("recvTypeName IndexExpr:", ret)
|
||||||
|
}
|
||||||
|
if ret := recvTypeName(&ast.IndexListExpr{
|
||||||
|
X: &ast.Ident{Name: "Pointer"},
|
||||||
|
Indices: []ast.Expr{&ast.Ident{Name: "T"}},
|
||||||
|
}); ret != "Pointer" {
|
||||||
|
t.Fatal("recvTypeName IndexListExpr:", ret)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("recvTypeName: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
recvTypeName(&ast.BadExpr{})
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestErrCompileValue(t *testing.T) {
|
func TestErrCompileValue(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != "can't use llgo instruction as a value" {
|
if r := recover(); r != "can't use llgo instruction as a value" {
|
||||||
@@ -43,6 +66,7 @@ func TestErrCompileValue(t *testing.T) {
|
|||||||
Signature: types.NewSignatureType(nil, nil, nil, nil, nil, false),
|
Signature: types.NewSignatureType(nil, nil, nil, nil, nil, false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func TestErrCompileInstrOrValue(t *testing.T) {
|
func TestErrCompileInstrOrValue(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -76,6 +100,16 @@ func TestErrAlloca(t *testing.T) {
|
|||||||
ctx.alloca(nil, nil)
|
ctx.alloca(nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestErrAllocaCStr(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Fatal("allocaCStr: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var ctx context
|
||||||
|
ctx.allocaCStr(nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCStrNoArgs(t *testing.T) {
|
func TestCStrNoArgs(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
if r := recover(); r == nil {
|
||||||
@@ -106,16 +140,19 @@ func TestPkgNoInit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPkgKind(t *testing.T) {
|
func TestPkgKind(t *testing.T) {
|
||||||
if v := pkgKind("noinit"); v != PkgNoInit {
|
if v, _ := pkgKind("link: hello.a"); v != PkgLinkExtern {
|
||||||
t.Fatal("pkgKind:", v)
|
t.Fatal("pkgKind:", v)
|
||||||
}
|
}
|
||||||
if v := pkgKind(""); v != PkgLLGo {
|
if v, _ := pkgKind("noinit"); v != PkgNoInit {
|
||||||
|
t.Fatal("pkgKind:", v)
|
||||||
|
}
|
||||||
|
if v, _ := pkgKind(""); v != PkgLLGo {
|
||||||
t.Fatal("pkgKind:", v)
|
t.Fatal("pkgKind:", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPkgKindOf(t *testing.T) {
|
func TestPkgKindOf(t *testing.T) {
|
||||||
if v := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
|
if v, _ := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
|
||||||
t.Fatal("PkgKindOf unsafe:", v)
|
t.Fatal("PkgKindOf unsafe:", v)
|
||||||
}
|
}
|
||||||
pkg := types.NewPackage("foo", "foo")
|
pkg := types.NewPackage("foo", "foo")
|
||||||
@@ -124,7 +161,7 @@ func TestPkgKindOf(t *testing.T) {
|
|||||||
0, pkg, "LLGoPackage", types.Typ[types.String],
|
0, pkg, "LLGoPackage", types.Typ[types.String],
|
||||||
constant.MakeString("noinit")),
|
constant.MakeString("noinit")),
|
||||||
)
|
)
|
||||||
if v := PkgKindOf(pkg); v != PkgNoInit {
|
if v, _ := PkgKindOf(pkg); v != PkgNoInit {
|
||||||
t.Fatal("PkgKindOf foo:", v)
|
t.Fatal("PkgKindOf foo:", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,13 +194,21 @@ func TestErrImport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestErrInitLinkname(t *testing.T) {
|
func TestErrInitLinkname(t *testing.T) {
|
||||||
|
var ctx context
|
||||||
|
ctx.initLinkname("//llgo:link abc", func(name string) (string, bool, bool) {
|
||||||
|
return "", false, false
|
||||||
|
})
|
||||||
|
ctx.initLinkname("//go:linkname Printf printf", func(name string) (string, bool, bool) {
|
||||||
|
return "", false, false
|
||||||
|
})
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
if r := recover(); r == nil {
|
||||||
t.Fatal("initLinkname: no error?")
|
t.Fatal("initLinkname: no error?")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var ctx context
|
ctx.initLinkname("//go:linkname Printf printf", func(name string) (string, bool, bool) {
|
||||||
ctx.initLinkname("foo", "//go:linkname Printf printf", false)
|
return "foo.Printf", false, name == "Printf"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrVarOf(t *testing.T) {
|
func TestErrVarOf(t *testing.T) {
|
||||||
|
|||||||
@@ -17,10 +17,12 @@
|
|||||||
package cltest
|
package cltest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -38,7 +40,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +65,36 @@ func FromDir(t *testing.T, sel, relDir string, byLLGen bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *.ll => *.lla
|
||||||
|
func decodeLinkFile(llFile string) (data []byte, err error) {
|
||||||
|
zipFile := llFile + "a"
|
||||||
|
zipf, err := zip.OpenReader(zipFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer zipf.Close()
|
||||||
|
f, err := zipf.Open("llgo_autogen.ll")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
data, err = io.ReadAll(f)
|
||||||
|
if err == nil {
|
||||||
|
os.WriteFile(llFile, data, 0644)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Pkg(t *testing.T, pkgPath, outFile string) {
|
func Pkg(t *testing.T, pkgPath, outFile string) {
|
||||||
b, err := os.ReadFile(outFile)
|
b, err := os.ReadFile(outFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
t.Fatal("ReadFile failed:", err)
|
t.Fatal("ReadFile failed:", err)
|
||||||
}
|
}
|
||||||
|
if b, err = decodeLinkFile(outFile); err != nil {
|
||||||
|
t.Fatal("decodeLinkFile failed:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
expected := string(b)
|
expected := string(b)
|
||||||
if v := llgen.GenFrom(pkgPath); v != expected {
|
if v := llgen.GenFrom(pkgPath); v != expected {
|
||||||
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
|||||||
285
cl/compile.go
285
cl/compile.go
@@ -62,13 +62,15 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) 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 {
|
||||||
params := fn.Signature.Params()
|
params := fn.Signature.Params()
|
||||||
n := params.Len()
|
n := params.Len()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
if fn.Signature.Recv() == nil {
|
||||||
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
||||||
return fnIgnore
|
return fnIgnore
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
last := params.At(n - 1)
|
last := params.At(n - 1)
|
||||||
if last.Name() == llssa.NameValist {
|
if last.Name() == llssa.NameValist {
|
||||||
@@ -123,6 +125,9 @@ const (
|
|||||||
PkgLLGo
|
PkgLLGo
|
||||||
PkgNoInit // noinit: a package that don't need to be initialized
|
PkgNoInit // noinit: a package that don't need to be initialized
|
||||||
PkgDeclOnly // decl: a package that only have declarations
|
PkgDeclOnly // decl: a package that only have declarations
|
||||||
|
PkgLinkIR // link llvm ir (.ll)
|
||||||
|
PkgLinkExtern // link external object (.a/.so/.dll/.dylib/etc.)
|
||||||
|
// PkgLinkBitCode // link bitcode (.bc)
|
||||||
)
|
)
|
||||||
|
|
||||||
type pkgInfo struct {
|
type pkgInfo struct {
|
||||||
@@ -169,7 +174,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, false)
|
p.compileFuncDecl(pkg, ssaMthd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,77 +189,141 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewVar", name, typ)
|
log.Println("==> NewVar", name, typ)
|
||||||
}
|
}
|
||||||
if vtype == cVar {
|
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
||||||
typ = llssa.CType(typ)
|
|
||||||
}
|
|
||||||
g := pkg.NewVar(name, typ)
|
|
||||||
if vtype == goVar {
|
if vtype == goVar {
|
||||||
g.Init(p.prog.Null(g.Type))
|
g.Init(p.prog.Null(g.Type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function, closure bool) llssa.Function {
|
func makeClosureCtx(pkg *types.Package, vars []*ssa.FreeVar) *types.Var {
|
||||||
|
n := len(vars)
|
||||||
|
flds := make([]*types.Var, n)
|
||||||
|
for i, v := range vars {
|
||||||
|
flds[i] = types.NewField(token.NoPos, pkg, v.Name(), v.Type(), false)
|
||||||
|
}
|
||||||
|
t := types.NewPointer(types.NewStruct(flds, nil))
|
||||||
|
return types.NewParam(token.NoPos, pkg, "__llgo_ctx", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
argvTy = types.NewPointer(types.NewPointer(types.Typ[types.Int8]))
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) llssa.Function {
|
||||||
|
pkgTypes, name, ftype := p.funcName(f, true)
|
||||||
|
if ftype != goFunc {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fn := pkg.FuncOf(name)
|
||||||
|
if fn != nil && fn.HasBody() {
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
var sig = f.Signature
|
var sig = f.Signature
|
||||||
var name string
|
var hasCtx = len(f.FreeVars) > 0
|
||||||
if closure {
|
if hasCtx {
|
||||||
name = funcName(pkgTypes, f)
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewClosure", name, "type:", sig)
|
log.Println("==> NewClosure", name, "type:", sig)
|
||||||
}
|
}
|
||||||
|
ctx := makeClosureCtx(pkgTypes, f.FreeVars)
|
||||||
|
sig = llssa.FuncAddCtx(ctx, sig)
|
||||||
} else {
|
} else {
|
||||||
var ftype int
|
|
||||||
name, ftype = p.funcName(pkgTypes, f, true)
|
|
||||||
switch ftype {
|
|
||||||
case ignoredFunc, llgoInstr: // llgo extended instructions
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
||||||
}
|
}
|
||||||
if ftype == cFunc {
|
|
||||||
sig = llssa.CFuncDecl(sig)
|
|
||||||
}
|
}
|
||||||
|
if fn == nil {
|
||||||
|
if name == "main" {
|
||||||
|
argc := types.NewParam(token.NoPos, pkgTypes, "", types.Typ[types.Int32])
|
||||||
|
argv := types.NewParam(token.NoPos, pkgTypes, "", argvTy)
|
||||||
|
params := types.NewTuple(argc, argv)
|
||||||
|
sig = types.NewSignatureType(nil, nil, nil, params, nil, false)
|
||||||
}
|
}
|
||||||
fn := pkg.NewFunc(name, sig)
|
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.inits = append(p.inits, func() {
|
||||||
p.fn = fn
|
p.fn = fn
|
||||||
defer func() {
|
defer func() {
|
||||||
p.fn = nil
|
p.fn = nil
|
||||||
}()
|
}()
|
||||||
p.phis = nil
|
p.phis = nil
|
||||||
nblk := len(f.Blocks)
|
|
||||||
if nblk == 0 { // external function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if debugGoSSA {
|
if debugGoSSA {
|
||||||
f.WriteTo(os.Stderr)
|
f.WriteTo(os.Stderr)
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> FuncBody", name)
|
log.Println("==> FuncBody", name)
|
||||||
}
|
}
|
||||||
fn.MakeBlocks(nblk)
|
|
||||||
b := fn.NewBuilder()
|
b := fn.NewBuilder()
|
||||||
p.bvals = make(map[ssa.Value]llssa.Expr)
|
p.bvals = make(map[ssa.Value]llssa.Expr)
|
||||||
|
off := make([]int, len(f.Blocks))
|
||||||
for i, block := range f.Blocks {
|
for i, block := range f.Blocks {
|
||||||
p.compileBlock(b, block, i == 0 && name == "main")
|
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 {
|
for _, phi := range p.phis {
|
||||||
phi()
|
phi()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
return fn
|
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) {
|
||||||
|
_, name, ftype := p.funcName(fn, false)
|
||||||
|
if ftype == llgoInstr {
|
||||||
|
switch name {
|
||||||
|
case "cstr":
|
||||||
|
ftype = llgoCstr
|
||||||
|
case "advance":
|
||||||
|
ftype = llgoAdvance
|
||||||
|
case "index":
|
||||||
|
ftype = llgoIndex
|
||||||
|
case "alloca":
|
||||||
|
ftype = llgoAlloca
|
||||||
|
case "allocaCStr":
|
||||||
|
ftype = llgoAllocaCStr
|
||||||
|
case "unreachable":
|
||||||
|
ftype = llgoUnreachable
|
||||||
|
case "bitCastTo64F":
|
||||||
|
ftype = llgoBitCastTo64F
|
||||||
|
case "bitCastTo32F":
|
||||||
|
ftype = llgoBitCastTo32F
|
||||||
|
default:
|
||||||
|
panic("unknown llgo instruction: " + name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pkg := p.pkg
|
||||||
|
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 {
|
||||||
|
prog := p.prog
|
||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
|
fn := p.fn
|
||||||
|
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
||||||
|
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
||||||
|
argc.Init(prog.Null(argc.Type))
|
||||||
|
argv.Init(prog.Null(argv.Type))
|
||||||
|
b.Store(argc.Expr, fn.Param(0))
|
||||||
|
b.Store(argv.Expr, fn.Param(1))
|
||||||
callRuntimeInit(b, pkg)
|
callRuntimeInit(b, pkg)
|
||||||
b.Call(pkg.FuncOf("main.init").Expr)
|
b.Call(pkg.FuncOf("main.init").Expr)
|
||||||
}
|
}
|
||||||
instrs := p.compilePhis(b, block.Instrs)
|
for _, instr := range block.Instrs[n:] {
|
||||||
for _, instr := range instrs {
|
|
||||||
p.compileInstr(b, instr)
|
p.compileInstr(b, instr)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
@@ -265,7 +334,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
||||||
fn := pkg.NewFunc(RuntimeInit, types.NewSignatureType(nil, nil, nil, nil, nil, false))
|
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)
|
b.Call(fn.Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,9 +363,9 @@ func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
||||||
if v.Comment == "varargs" { // this is a varargs allocation
|
if v.Comment == "varargs" { // this maybe a varargs allocation
|
||||||
if arr, ok := t.Elem().(*types.Array); ok {
|
if arr, ok := t.Elem().(*types.Array); ok {
|
||||||
if isAny(arr.Elem()) {
|
if isAny(arr.Elem()) && isVargs(p, v) {
|
||||||
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -304,6 +374,20 @@ func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isVargs(ctx *context, v *ssa.Alloc) bool {
|
||||||
|
refs := *v.Referrers()
|
||||||
|
n := len(refs)
|
||||||
|
lastref := refs[n-1]
|
||||||
|
if i, ok := lastref.(*ssa.Slice); ok {
|
||||||
|
if refs = *i.Referrers(); len(refs) == 1 {
|
||||||
|
if call, ok := refs[0].(*ssa.Call); ok {
|
||||||
|
return ctx.funcKind(call.Call.Value) == fnHasVArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// func cstr(string) *int8
|
// func cstr(string) *int8
|
||||||
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
@@ -317,6 +401,12 @@ func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
|||||||
panic("cstr(<string-literal>): invalid arguments")
|
panic("cstr(<string-literal>): invalid arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func index(arr *T, idx int) T
|
||||||
|
func (p *context) index(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
return b.Load(p.advance(b, args))
|
||||||
|
}
|
||||||
|
|
||||||
|
// func advance(ptr *T, offset int) *T
|
||||||
func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
if len(args) == 2 {
|
if len(args) == 2 {
|
||||||
ptr := p.compileValue(b, args[0])
|
ptr := p.compileValue(b, args[0])
|
||||||
@@ -349,30 +439,32 @@ func isPhi(i ssa.Instruction) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compilePhis(b llssa.Builder, instrs []ssa.Instruction) []ssa.Instruction {
|
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
|
||||||
if ninstr := len(instrs); ninstr > 0 {
|
ret := p.fn.Block(block.Index)
|
||||||
if isPhi(instrs[0]) {
|
b.SetBlock(ret)
|
||||||
|
if ninstr := len(block.Instrs); ninstr > 0 {
|
||||||
|
if isPhi(block.Instrs[0]) {
|
||||||
n := 1
|
n := 1
|
||||||
for n < ninstr && isPhi(instrs[n]) {
|
for n < ninstr && isPhi(block.Instrs[n]) {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
rets := make([]llssa.Expr, n)
|
rets := make([]llssa.Expr, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
iv := instrs[i].(*ssa.Phi)
|
iv := block.Instrs[i].(*ssa.Phi)
|
||||||
rets[i] = p.compilePhi(b, iv)
|
rets[i] = p.compilePhi(b, iv)
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
iv := instrs[i].(*ssa.Phi)
|
iv := block.Instrs[i].(*ssa.Phi)
|
||||||
p.bvals[iv] = rets[i].Do(b)
|
p.bvals[iv] = rets[i].Do(b)
|
||||||
}
|
}
|
||||||
return instrs[n:]
|
return n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instrs
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
|
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
|
||||||
phi := b.Phi(p.prog.Type(v.Type()))
|
phi := b.Phi(p.prog.Type(v.Type(), llssa.InGo))
|
||||||
ret = phi.Expr
|
ret = phi.Expr
|
||||||
p.phis = append(p.phis, func() {
|
p.phis = append(p.phis, func() {
|
||||||
preds := v.Block().Preds
|
preds := v.Block().Preds
|
||||||
@@ -397,48 +489,54 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
}
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
case *ssa.Call:
|
case *ssa.Call:
|
||||||
call := v.Call
|
cv := v.Call.Value
|
||||||
cv := call.Value
|
|
||||||
kind := p.funcKind(cv)
|
kind := p.funcKind(cv)
|
||||||
if kind == fnIgnore {
|
if kind == fnIgnore {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
args := v.Call.Args
|
||||||
if debugGoSSA {
|
if debugGoSSA {
|
||||||
log.Println(">>> Call", cv, call.Args)
|
log.Println(">>> Call", cv, args)
|
||||||
}
|
}
|
||||||
switch cv := cv.(type) {
|
switch cv := cv.(type) {
|
||||||
case *ssa.Builtin:
|
case *ssa.Builtin:
|
||||||
fn := cv.Name()
|
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 := args[0]
|
||||||
ret = p.compileValue(b, arg)
|
ret = p.compileValue(b, arg)
|
||||||
// log.Println("wrapnilchk:", ret.TypeOf())
|
// log.Println("wrapnilchk:", ret.TypeOf())
|
||||||
} else {
|
} else {
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.BuiltinCall(fn, args...)
|
ret = b.BuiltinCall(fn, args...)
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
fn, ftype := p.funcOf(cv)
|
fn, ftype := p.compileFunction(cv)
|
||||||
switch ftype {
|
switch ftype {
|
||||||
case goFunc, cFunc:
|
case goFunc, cFunc:
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(fn.Expr, args...)
|
ret = b.Call(fn.Expr, args...)
|
||||||
case llgoCstr:
|
case llgoCstr:
|
||||||
ret = cstr(b, call.Args)
|
ret = cstr(b, args)
|
||||||
case llgoAdvance:
|
case llgoAdvance:
|
||||||
ret = p.advance(b, call.Args)
|
ret = p.advance(b, args)
|
||||||
|
case llgoIndex:
|
||||||
|
ret = p.index(b, args)
|
||||||
case llgoAlloca:
|
case llgoAlloca:
|
||||||
ret = p.alloca(b, call.Args)
|
ret = p.alloca(b, args)
|
||||||
case llgoAllocaCStr:
|
case llgoAllocaCStr:
|
||||||
ret = p.allocaCStr(b, call.Args)
|
ret = p.allocaCStr(b, args)
|
||||||
case llgoUnreachable: // func unreachable()
|
case llgoUnreachable: // func unreachable()
|
||||||
b.Unreachable()
|
b.Unreachable()
|
||||||
|
case llgoBitCastTo32F:
|
||||||
|
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Type(types.Typ[types.Float32], llssa.InGo))
|
||||||
|
case llgoBitCastTo64F:
|
||||||
|
ret = b.BitCast(p.compileValue(b, args[0]), b.Prog.Float64())
|
||||||
default:
|
default:
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fn := p.compileValue(b, cv)
|
fn := p.compileValue(b, cv)
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(fn, args...)
|
ret = b.Call(fn, args...)
|
||||||
}
|
}
|
||||||
case *ssa.BinOp:
|
case *ssa.BinOp:
|
||||||
@@ -451,20 +549,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:
|
case *ssa.Alloc:
|
||||||
t := v.Type().(*types.Pointer)
|
t := v.Type().(*types.Pointer)
|
||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret = b.Alloc(t, v.Heap)
|
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
|
||||||
@@ -482,8 +581,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
return p.compileValue(b, n.X)
|
return p.compileValue(b, n.X)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Errorf("todo addr of %v", e))
|
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
|
||||||
@@ -502,30 +605,44 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
}
|
}
|
||||||
ret = b.Slice(x, low, high, max)
|
ret = b.Slice(x, low, high, max)
|
||||||
case *ssa.MakeInterface:
|
case *ssa.MakeInterface:
|
||||||
const (
|
if refs := *v.Referrers(); len(refs) == 1 {
|
||||||
delayExpr = true // varargs: don't need to convert an expr to any
|
if ref, ok := refs[0].(*ssa.Store); ok {
|
||||||
)
|
if va, ok := ref.Addr.(*ssa.IndexAddr); ok {
|
||||||
t := v.Type()
|
if _, ok = p.isVArgs(va.X); ok { // varargs: this is a varargs store
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
||||||
case *ssa.MakeSlice:
|
case *ssa.MakeSlice:
|
||||||
var nCap llssa.Expr
|
var nCap llssa.Expr
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
nLen := p.compileValue(b, v.Len)
|
nLen := p.compileValue(b, v.Len)
|
||||||
if v.Cap != nil {
|
if v.Cap != nil {
|
||||||
nCap = p.compileValue(b, v.Cap)
|
nCap = p.compileValue(b, v.Cap)
|
||||||
}
|
}
|
||||||
ret = b.MakeSlice(p.prog.Type(t), nLen, nCap)
|
ret = b.MakeSlice(t, nLen, nCap)
|
||||||
case *ssa.MakeMap:
|
case *ssa.MakeMap:
|
||||||
var nReserve llssa.Expr
|
var nReserve llssa.Expr
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
if v.Reserve != nil {
|
if v.Reserve != nil {
|
||||||
nReserve = p.compileValue(b, v.Reserve)
|
nReserve = p.compileValue(b, v.Reserve)
|
||||||
}
|
}
|
||||||
ret = b.MakeMap(p.prog.Type(t), nReserve)
|
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))
|
||||||
}
|
}
|
||||||
@@ -589,6 +706,17 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, 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)
|
||||||
@@ -602,21 +730,21 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
if v.Blocks != nil {
|
fn, _ := p.compileFunction(v)
|
||||||
fn := p.compileFunc(p.pkg, p.goTyps, v, true)
|
|
||||||
return fn.Expr
|
|
||||||
}
|
|
||||||
fn, ftype := p.funcOf(v)
|
|
||||||
if ftype >= llgoInstrBase {
|
|
||||||
panic("can't use llgo instruction as a value")
|
|
||||||
}
|
|
||||||
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 := types.Default(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))
|
||||||
}
|
}
|
||||||
@@ -691,11 +819,12 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
|||||||
member := m.val
|
member := m.val
|
||||||
switch member := member.(type) {
|
switch member := member.(type) {
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
if member.TypeParams() != nil {
|
if member.TypeParams() != nil || member.TypeArgs() != nil {
|
||||||
|
// TODO(xsw): don't compile generic functions
|
||||||
// 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, false)
|
ctx.compileFuncDecl(ret, member)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
ctx.compileType(ret, member)
|
ctx.compileType(ret, member)
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
cltest.TestCompileEx(t, src, "foo.go", expected)
|
cltest.TestCompileEx(t, src, "foo.go", expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFromTestlibc(t *testing.T) {
|
||||||
|
cltest.FromDir(t, "", "./_testlibc", false)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testrt", true)
|
cltest.FromDir(t, "", "./_testrt", true)
|
||||||
}
|
}
|
||||||
@@ -36,6 +40,10 @@ func TestFromTestdata(t *testing.T) {
|
|||||||
cltest.FromDir(t, "", "./_testdata", false)
|
cltest.FromDir(t, "", "./_testdata", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSqlite(t *testing.T) {
|
||||||
|
cltest.Pkg(t, "github.com/goplus/llgo/x/sqlite", "../x/sqlite/sqlite.ll")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRuntime(t *testing.T) {
|
func TestRuntime(t *testing.T) {
|
||||||
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
|
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|||||||
284
cl/import.go
284
cl/import.go
@@ -18,6 +18,7 @@ package cl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
@@ -29,79 +30,128 @@ import (
|
|||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
type contentLines = [][]byte
|
type symInfo struct {
|
||||||
type contentMap = map[string]contentLines
|
file string
|
||||||
|
fullName string
|
||||||
|
isVar bool
|
||||||
|
}
|
||||||
|
|
||||||
func contentOf(m contentMap, file string) (lines contentLines, err error) {
|
type pkgSymInfo struct {
|
||||||
if v, ok := m[file]; ok {
|
files map[string][]byte // file => content
|
||||||
return v, nil
|
syms map[string]symInfo // name => isVar
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPkgSymInfo() *pkgSymInfo {
|
||||||
|
return &pkgSymInfo{
|
||||||
|
files: make(map[string][]byte),
|
||||||
|
syms: make(map[string]symInfo),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pkgSymInfo) addSym(fset *token.FileSet, pos token.Pos, fullName, inPkgName string, isVar bool) {
|
||||||
|
f := fset.File(pos)
|
||||||
|
if fp := f.Position(pos); fp.Line > 2 {
|
||||||
|
file := fp.Filename
|
||||||
|
if _, ok := p.files[file]; !ok {
|
||||||
b, err := os.ReadFile(file)
|
b, err := os.ReadFile(file)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
lines = bytes.Split(b, []byte{'\n'})
|
p.files[file] = b
|
||||||
m[file] = lines
|
}
|
||||||
|
}
|
||||||
|
p.syms[inPkgName] = symInfo{file, fullName, isVar}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pkgSymInfo) initLinknames(ctx *context) {
|
||||||
|
for file, b := range p.files {
|
||||||
|
lines := bytes.Split(b, []byte{'\n'})
|
||||||
|
for _, line := range lines {
|
||||||
|
ctx.initLinkname(string(line), func(inPkgName string) (fullName string, isVar, ok bool) {
|
||||||
|
if sym, ok := p.syms[inPkgName]; ok && file == sym.file {
|
||||||
|
return sym.fullName, sym.isVar, true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PkgKindOf returns the kind of a package.
|
// PkgKindOf returns the kind of a package.
|
||||||
func PkgKindOf(pkg *types.Package) int {
|
func PkgKindOf(pkg *types.Package) (int, string) {
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
kind := pkgKindByScope(scope)
|
kind, param := pkgKindByScope(scope)
|
||||||
if kind == PkgNormal {
|
if kind == PkgNormal {
|
||||||
kind = pkgKindByPath(pkg.Path())
|
kind = pkgKindByPath(pkg.Path())
|
||||||
}
|
}
|
||||||
return kind
|
return kind, param
|
||||||
}
|
}
|
||||||
|
|
||||||
// decl: a package that only contains declarations
|
// decl: a package that only contains declarations
|
||||||
// noinit: a package that does not need to be initialized
|
// noinit: a package that does not need to be initialized
|
||||||
func pkgKind(v string) int {
|
func pkgKind(v string) (int, string) {
|
||||||
switch v {
|
switch v {
|
||||||
|
case "link":
|
||||||
|
return PkgLinkIR, ""
|
||||||
case "decl":
|
case "decl":
|
||||||
return PkgDeclOnly
|
return PkgDeclOnly, ""
|
||||||
case "noinit":
|
case "noinit":
|
||||||
return PkgNoInit
|
return PkgNoInit, ""
|
||||||
|
default:
|
||||||
|
// case "link:bc":
|
||||||
|
// return PkgLinkBitCode
|
||||||
|
if strings.HasPrefix(v, "link:") { // "link: <libpath>"
|
||||||
|
return PkgLinkExtern, v[5:]
|
||||||
}
|
}
|
||||||
return PkgLLGo
|
}
|
||||||
|
return PkgLLGo, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func pkgKindByScope(scope *types.Scope) int {
|
func pkgKindByScope(scope *types.Scope) (int, string) {
|
||||||
if v, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
|
if v, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
|
||||||
if v := v.Val(); v.Kind() == constant.String {
|
if v := v.Val(); v.Kind() == constant.String {
|
||||||
return pkgKind(constant.StringVal(v))
|
return pkgKind(constant.StringVal(v))
|
||||||
}
|
}
|
||||||
return PkgLLGo
|
return PkgLLGo, ""
|
||||||
}
|
}
|
||||||
return PkgNormal
|
return PkgNormal, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
kind := pkgKindByScope(scope)
|
kind, _ := pkgKindByScope(scope)
|
||||||
if kind == PkgNormal {
|
if kind == PkgNormal {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i.kind = kind
|
i.kind = kind
|
||||||
fset := p.fset
|
fset := p.fset
|
||||||
names := scope.Names()
|
|
||||||
contents := make(contentMap)
|
|
||||||
pkgPath := llssa.PathOf(pkg)
|
pkgPath := llssa.PathOf(pkg)
|
||||||
|
names := scope.Names()
|
||||||
|
syms := newPkgSymInfo()
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if token.IsExported(name) {
|
|
||||||
obj := scope.Lookup(name)
|
obj := scope.Lookup(name)
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.Func:
|
case *types.Func:
|
||||||
if pos := obj.Pos(); pos != token.NoPos {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
p.initLinknameByPos(fset, pos, pkgPath, contents, false)
|
fullName, inPkgName := typesFuncName(pkgPath, obj)
|
||||||
|
syms.addSym(fset, pos, fullName, inPkgName, false)
|
||||||
|
}
|
||||||
|
case *types.TypeName:
|
||||||
|
if !obj.IsAlias() {
|
||||||
|
if t, ok := obj.Type().(*types.Named); ok {
|
||||||
|
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||||
|
fn := t.Method(i)
|
||||||
|
fullName, inPkgName := typesFuncName(pkgPath, fn)
|
||||||
|
syms.addSym(fset, fn.Pos(), fullName, inPkgName, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *types.Var:
|
case *types.Var:
|
||||||
if pos := obj.Pos(); pos != token.NoPos {
|
if pos := obj.Pos(); pos != token.NoPos {
|
||||||
p.initLinknameByPos(fset, pos, pkgPath, contents, true)
|
syms.addSym(fset, pos, pkgPath+"."+name, name, true)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
syms.initLinknames(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
||||||
@@ -109,61 +159,121 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) {
|
|||||||
for _, decl := range file.Decls {
|
for _, decl := range file.Decls {
|
||||||
switch decl := decl.(type) {
|
switch decl := decl.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
if decl.Recv == nil {
|
fullName, inPkgName := astFuncName(pkgPath, decl)
|
||||||
p.initLinknameByDoc(decl.Doc, pkgPath, false)
|
p.initLinknameByDoc(decl.Doc, fullName, inPkgName, false)
|
||||||
}
|
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
|
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
|
||||||
p.initLinknameByDoc(decl.Doc, pkgPath, true)
|
if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 {
|
||||||
|
inPkgName := names[0].Name
|
||||||
|
p.initLinknameByDoc(decl.Doc, pkgPath+"."+inPkgName, inPkgName, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, pkgPath string, isVar bool) {
|
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar bool) {
|
||||||
if doc != nil {
|
if doc != nil {
|
||||||
if n := len(doc.List); n > 0 {
|
if n := len(doc.List); n > 0 {
|
||||||
line := doc.List[n-1].Text
|
line := doc.List[n-1].Text
|
||||||
p.initLinkname(pkgPath, line, isVar)
|
p.initLinkname(line, func(name string) (_ string, _, ok bool) {
|
||||||
|
return fullName, isVar, name == inPkgName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) initLinknameByPos(fset *token.FileSet, pos token.Pos, pkgPath string, contents contentMap, isVar bool) {
|
func (p *context) initLinkname(line string, f func(inPkgName string) (fullName string, isVar, ok 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 "
|
||||||
|
llgolink = "//llgo:link "
|
||||||
|
llgolink2 = "// llgo:link "
|
||||||
)
|
)
|
||||||
if strings.HasPrefix(line, linkname) {
|
if strings.HasPrefix(line, linkname) {
|
||||||
text := strings.TrimSpace(line[len(linkname):])
|
p.initLink(line, len(linkname), f)
|
||||||
|
} else if strings.HasPrefix(line, llgolink2) {
|
||||||
|
p.initLink(line, len(llgolink2), f)
|
||||||
|
} else if strings.HasPrefix(line, llgolink) {
|
||||||
|
p.initLink(line, len(llgolink), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) initLink(line string, prefix int, f func(inPkgName string) (fullName string, isVar, ok bool)) {
|
||||||
|
text := strings.TrimSpace(line[prefix:])
|
||||||
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
if idx := strings.IndexByte(text, ' '); idx > 0 {
|
||||||
|
inPkgName := text[:idx]
|
||||||
|
if fullName, isVar, ok := f(inPkgName); ok {
|
||||||
link := strings.TrimLeft(text[idx+1:], " ")
|
link := strings.TrimLeft(text[idx+1:], " ")
|
||||||
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
|
||||||
name := pkgPath + "." + text[:idx]
|
p.link[fullName] = link
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(os.Stderr, "==>", line)
|
||||||
|
fmt.Fprintf(os.Stderr, "llgo: linkname %s not found and ignored\n", inPkgName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func: pkg.name
|
func recvTypeName(t ast.Expr) string {
|
||||||
// method: (pkg.T).name, (*pkg.T).name
|
switch t := t.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
return t.Name
|
||||||
|
case *ast.IndexExpr:
|
||||||
|
return trecvTypeName(t.X, t.Index)
|
||||||
|
case *ast.IndexListExpr:
|
||||||
|
return trecvTypeName(t.X, t.Indices...)
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw): support generic type
|
||||||
|
func trecvTypeName(t ast.Expr, indices ...ast.Expr) string {
|
||||||
|
_ = indices
|
||||||
|
return t.(*ast.Ident).Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// inPkgName:
|
||||||
|
// - func: name
|
||||||
|
// - method: (T).name, (*T).name
|
||||||
|
// fullName:
|
||||||
|
// - func: pkg.name
|
||||||
|
// - method: (pkg.T).name, (*pkg.T).name
|
||||||
|
func astFuncName(pkgPath string, fn *ast.FuncDecl) (fullName, inPkgName string) {
|
||||||
|
name := fn.Name.Name
|
||||||
|
if recv := fn.Recv; recv != nil && len(recv.List) == 1 {
|
||||||
|
tPrefix := "("
|
||||||
|
t := recv.List[0].Type
|
||||||
|
if tp, ok := t.(*ast.StarExpr); ok {
|
||||||
|
t, tPrefix = tp.X, "(*"
|
||||||
|
}
|
||||||
|
tSuffix := recvTypeName(t) + ")." + name
|
||||||
|
return tPrefix + pkgPath + "." + tSuffix, tPrefix + tSuffix
|
||||||
|
}
|
||||||
|
return pkgPath + "." + name, name
|
||||||
|
}
|
||||||
|
|
||||||
|
func typesFuncName(pkgPath string, fn *types.Func) (fullName, inPkgName string) {
|
||||||
|
sig := fn.Type().(*types.Signature)
|
||||||
|
name := fn.Name()
|
||||||
|
if recv := sig.Recv(); recv != nil {
|
||||||
|
tPrefix := "("
|
||||||
|
t := recv.Type()
|
||||||
|
if tp, ok := t.(*types.Pointer); ok {
|
||||||
|
t, tPrefix = tp.Elem(), "(*"
|
||||||
|
}
|
||||||
|
tSuffix := t.(*types.Named).Obj().Name() + ")." + name
|
||||||
|
return tPrefix + pkgPath + "." + tSuffix, tPrefix + tSuffix
|
||||||
|
}
|
||||||
|
return pkgPath + "." + name, name
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw): may can use typesFuncName
|
||||||
|
// fullName:
|
||||||
|
// - func: pkg.name
|
||||||
|
// - method: (pkg.T).name, (*pkg.T).name
|
||||||
func funcName(pkg *types.Package, fn *ssa.Function) string {
|
func funcName(pkg *types.Package, fn *ssa.Function) string {
|
||||||
sig := fn.Signature
|
sig := fn.Signature
|
||||||
name := fn.Name()
|
name := fn.Name()
|
||||||
@@ -191,8 +301,8 @@ func checkCgo(fnName string) bool {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ignoredFunc = iota
|
ignoredFunc = iota
|
||||||
goFunc
|
goFunc = int(llssa.InGo)
|
||||||
cFunc
|
cFunc = int(llssa.InC)
|
||||||
llgoInstr = -1
|
llgoInstr = -1
|
||||||
|
|
||||||
llgoInstrBase = 0x80
|
llgoInstrBase = 0x80
|
||||||
@@ -201,29 +311,46 @@ const (
|
|||||||
llgoAlloca = llgoInstrBase + 2
|
llgoAlloca = llgoInstrBase + 2
|
||||||
llgoAllocaCStr = llgoInstrBase + 3
|
llgoAllocaCStr = llgoInstrBase + 3
|
||||||
llgoAdvance = llgoInstrBase + 4
|
llgoAdvance = llgoInstrBase + 4
|
||||||
|
llgoIndex = llgoInstrBase + 5
|
||||||
|
llgoBitCastTo32F = llgoInstrBase + 6
|
||||||
|
llgoBitCastTo64F = llgoInstrBase + 7
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, int) {
|
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
||||||
name := funcName(pkg, fn)
|
var pkg *types.Package
|
||||||
if ignore && ignoreName(name) || checkCgo(fn.Name()) {
|
var orgName string
|
||||||
return name, ignoredFunc
|
if origin := fn.Origin(); origin != nil {
|
||||||
|
pkg = origin.Pkg.Pkg
|
||||||
|
p.ensureLoaded(pkg)
|
||||||
|
orgName = funcName(pkg, origin)
|
||||||
|
} else {
|
||||||
|
if fnPkg := fn.Pkg; fnPkg != nil {
|
||||||
|
pkg = fnPkg.Pkg
|
||||||
|
} else {
|
||||||
|
pkg = p.goTyps
|
||||||
}
|
}
|
||||||
if v, ok := p.link[name]; ok {
|
p.ensureLoaded(pkg)
|
||||||
|
orgName = funcName(pkg, fn)
|
||||||
|
if ignore && ignoreName(orgName) || checkCgo(fn.Name()) {
|
||||||
|
return nil, orgName, ignoredFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := p.link[orgName]; ok {
|
||||||
if strings.HasPrefix(v, "C.") {
|
if strings.HasPrefix(v, "C.") {
|
||||||
return v[2:], cFunc
|
return nil, v[2:], cFunc
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(v, "llgo.") {
|
if strings.HasPrefix(v, "llgo.") {
|
||||||
return v[5:], llgoInstr
|
return nil, v[5:], llgoInstr
|
||||||
}
|
}
|
||||||
return v, goFunc
|
return pkg, v, goFunc
|
||||||
}
|
}
|
||||||
return name, goFunc
|
return pkg, funcName(pkg, fn), goFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ignoredVar = iota
|
ignoredVar = iota
|
||||||
goVar
|
goVar = int(llssa.InGo)
|
||||||
cVar
|
cVar = int(llssa.InC)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
||||||
@@ -234,39 +361,12 @@ func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtyp
|
|||||||
return name, goVar
|
return name, goVar
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
|
||||||
ret = pkg.NewFunc(name, fn.Signature)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *context) varOf(v *ssa.Global) (ret 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, _ := p.varName(pkgTypes, v)
|
name, vtype := p.varName(pkgTypes, v)
|
||||||
if ret = pkg.VarOf(name); ret == nil {
|
if ret = pkg.VarOf(name); ret == nil {
|
||||||
ret = pkg.NewVar(name, v.Type())
|
ret = pkg.NewVar(name, v.Type(), llssa.Background(vtype))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -7,11 +7,14 @@ require (
|
|||||||
github.com/goplus/gogen v1.15.2
|
github.com/goplus/gogen v1.15.2
|
||||||
github.com/goplus/llvm v0.7.5
|
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.21.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
|
||||||
)
|
)
|
||||||
|
|||||||
19
go.sum
19
go.sum
@@ -1,13 +1,28 @@
|
|||||||
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
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.5 h1:ges8WcUdu4FBi0mkZUs27p/4qDQlj28N1UpMg3VQUoE=
|
github.com/goplus/llvm v0.7.5 h1:ges8WcUdu4FBi0mkZUs27p/4qDQlj28N1UpMg3VQUoE=
|
||||||
github.com/goplus/llvm v0.7.5/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
github.com/goplus/llvm v0.7.5/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
||||||
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
|
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
|
||||||
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
|
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
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 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
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=
|
||||||
@@ -53,6 +68,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
|
||||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
@@ -1,636 +0,0 @@
|
|||||||
; ModuleID = 'github.com/goplus/llgo/internal/abi'
|
|
||||||
source_filename = "github.com/goplus/llgo/internal/abi"
|
|
||||||
|
|
||||||
%"github.com/goplus/llgo/internal/abi.ArrayType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, i64 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.ChanType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, i64 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.FuncType" = type { %"github.com/goplus/llgo/internal/abi.Type", i16, i16 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.InterfaceType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.Name" = type { ptr }
|
|
||||||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.MapType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, ptr, { ptr, ptr }, i8, i8, i16, i32 }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.PtrType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.SliceType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
|
|
||||||
%"github.com/goplus/llgo/internal/abi.StructType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
|
|
||||||
|
|
||||||
@"github.com/goplus/llgo/internal/abi.init$guard" = global ptr null
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.ArrayType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Elem"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Elem"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Elem"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
|
|
||||||
ret i64 %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
|
|
||||||
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
|
|
||||||
ret ptr %2
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp ne i64 %1, 17
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret ptr null
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp eq i64 %1, 17
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_3
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 1
|
|
||||||
%4 = load ptr, ptr %3, align 8
|
|
||||||
ret ptr %4
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_3
|
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 1
|
|
||||||
%6 = load ptr, ptr %5, align 8
|
|
||||||
ret ptr %6
|
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_0
|
|
||||||
%7 = icmp eq i64 %1, 18
|
|
||||||
br i1 %7, label %_llgo_2, label %_llgo_5
|
|
||||||
|
|
||||||
_llgo_4: ; preds = %_llgo_5
|
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 2
|
|
||||||
%9 = load ptr, ptr %8, align 8
|
|
||||||
ret ptr %9
|
|
||||||
|
|
||||||
_llgo_5: ; preds = %_llgo_3
|
|
||||||
%10 = icmp eq i64 %1, 21
|
|
||||||
br i1 %10, label %_llgo_4, label %_llgo_7
|
|
||||||
|
|
||||||
_llgo_6: ; preds = %_llgo_7
|
|
||||||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 1
|
|
||||||
%12 = load ptr, ptr %11, align 8
|
|
||||||
ret ptr %12
|
|
||||||
|
|
||||||
_llgo_7: ; preds = %_llgo_5
|
|
||||||
%13 = icmp eq i64 %1, 22
|
|
||||||
br i1 %13, label %_llgo_6, label %_llgo_9
|
|
||||||
|
|
||||||
_llgo_8: ; preds = %_llgo_9
|
|
||||||
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 1
|
|
||||||
%15 = load ptr, ptr %14, align 8
|
|
||||||
ret ptr %15
|
|
||||||
|
|
||||||
_llgo_9: ; preds = %_llgo_7
|
|
||||||
%16 = icmp eq i64 %1, 23
|
|
||||||
br i1 %16, label %_llgo_8, label %_llgo_10
|
|
||||||
|
|
||||||
_llgo_10: ; preds = %_llgo_9
|
|
||||||
ret ptr null
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp ne i64 %1, 19
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret ptr null
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp ne i64 %1, 20
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret ptr null
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
|
|
||||||
%2 = load i8, ptr %1, align 1
|
|
||||||
%3 = and i8 %2, 31
|
|
||||||
%4 = sext i8 %3 to i64
|
|
||||||
ret i64 %4
|
|
||||||
}
|
|
||||||
|
|
||||||
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp eq i64 %1, 17
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 3
|
|
||||||
%4 = load i64, ptr %3, align 4
|
|
||||||
ret i64 %4
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret i64 0
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp ne i64 %1, 21
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret ptr null
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
|
|
||||||
%2 = icmp ne i64 %1, 25
|
|
||||||
br i1 %2, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
ret ptr null
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret ptr %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @"github.com/goplus/llgo/internal/abi.init"() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = load i1, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
|
|
||||||
br i1 %0, label %_llgo_2, label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
store i1 true, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
|
|
||||||
br label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
BIN
internal/abi/llgo_autogen.lla
Normal file
BIN
internal/abi/llgo_autogen.lla
Normal file
Binary file not shown.
@@ -17,9 +17,11 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@@ -163,10 +165,35 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
}
|
}
|
||||||
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 _, aPkg := range pkgs {
|
||||||
buildPkg(prog, pkg, mode, verbose)
|
pkg := aPkg.Package
|
||||||
|
switch kind, param := cl.PkgKindOf(pkg.Types); kind {
|
||||||
|
case cl.PkgDeclOnly:
|
||||||
|
// skip packages that only contain declarations
|
||||||
|
// and set no export file
|
||||||
|
pkg.ExportFile = ""
|
||||||
|
case cl.PkgLinkIR:
|
||||||
|
// skip packages that don't need to be compiled but need to be linked
|
||||||
|
pkgPath := pkg.PkgPath
|
||||||
|
if isPkgInLLGo(pkgPath) {
|
||||||
|
pkg.ExportFile = concatPkgLinkFiles(pkgPath)
|
||||||
|
} else {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
case cl.PkgLinkExtern:
|
||||||
|
// skip packages that don't need to be compiled but need to be linked with external library
|
||||||
|
linkFile := os.ExpandEnv(strings.TrimSpace(param))
|
||||||
|
dir, lib := filepath.Split(linkFile)
|
||||||
|
command := " -l " + lib
|
||||||
|
if dir != "" {
|
||||||
|
command += " -L " + dir
|
||||||
|
}
|
||||||
|
pkg.ExportFile = command
|
||||||
|
default:
|
||||||
|
buildPkg(prog, aPkg, mode, verbose)
|
||||||
if prog.NeedRuntime() {
|
if prog.NeedRuntime() {
|
||||||
setNeedRuntime(pkg.Package)
|
setNeedRuntime(pkg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -187,7 +214,7 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string,
|
|||||||
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.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
|
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
|
||||||
args = append(args, p.ExportFile+".ll")
|
args = appendLinkFiles(args, p.ExportFile)
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = isNeedRuntime(p)
|
needRuntime = isNeedRuntime(p)
|
||||||
}
|
}
|
||||||
@@ -201,9 +228,9 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string,
|
|||||||
lpkg := aPkg.LPkg
|
lpkg := aPkg.LPkg
|
||||||
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
|
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
|
||||||
if needLLFile(mode) {
|
if needLLFile(mode) {
|
||||||
file := pkg.ExportFile + ".ll"
|
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
||||||
os.WriteFile(file, []byte(lpkg.String()), 0644)
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,28 +263,33 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string,
|
|||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
if pkgPath == "unsafe" { // TODO(xsw): maybe can remove this special case
|
if canSkipToBuild(pkgPath) {
|
||||||
|
pkg.ExportFile = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax)
|
ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax)
|
||||||
check(err)
|
check(err)
|
||||||
if needLLFile(mode) {
|
if needLLFile(mode) {
|
||||||
file := pkg.ExportFile + ".ll"
|
pkg.ExportFile += ".ll"
|
||||||
os.WriteFile(file, []byte(ret.String()), 0644)
|
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
|
||||||
}
|
}
|
||||||
aPkg.LPkg = ret
|
aPkg.LPkg = ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canSkipToBuild(pkgPath string) bool {
|
||||||
|
switch pkgPath {
|
||||||
|
case "unsafe", "runtime", "errors", "sync", "sync/atomic":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return strings.HasPrefix(pkgPath, "internal/") ||
|
||||||
|
strings.HasPrefix(pkgPath, "runtime/internal/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type aPackage struct {
|
type aPackage struct {
|
||||||
*packages.Package
|
*packages.Package
|
||||||
SSA *ssa.Package
|
SSA *ssa.Package
|
||||||
@@ -342,12 +374,12 @@ func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) {
|
|||||||
|
|
||||||
func allLinkFiles(rt []*packages.Package) (outFiles []string) {
|
func allLinkFiles(rt []*packages.Package) (outFiles []string) {
|
||||||
outFiles = make([]string, 0, len(rt))
|
outFiles = make([]string, 0, len(rt))
|
||||||
root := rootLLGo(rt[0])
|
|
||||||
packages.Visit(rt, nil, func(p *packages.Package) {
|
packages.Visit(rt, nil, func(p *packages.Package) {
|
||||||
pkgPath := p.PkgPath
|
pkgPath := p.PkgPath
|
||||||
if isRuntimePkg(pkgPath) {
|
if isRuntimePkg(pkgPath) {
|
||||||
outFile := filepath.Join(root+pkgPath[len(llgoModPath):], "llgo_autogen.ll")
|
llgoPkgLinkFiles(pkgPath, func(linkFile string) {
|
||||||
outFiles = append(outFiles, outFile)
|
outFiles = append(outFiles, linkFile)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -366,16 +398,78 @@ func isRuntimePkg(pkgPath string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(xsw): llgo root dir
|
var (
|
||||||
func rootLLGo(runtime *packages.Package) string {
|
rootDir string
|
||||||
return runtime.Module.Dir
|
)
|
||||||
|
|
||||||
|
func llgoRoot() string {
|
||||||
|
if rootDir == "" {
|
||||||
|
root := os.Getenv("LLGOROOT")
|
||||||
|
if root == "" {
|
||||||
|
panic("todo: LLGOROOT not set")
|
||||||
|
}
|
||||||
|
rootDir, _ = filepath.Abs(root)
|
||||||
|
}
|
||||||
|
return rootDir
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendLinkFiles(args []string, file string) []string {
|
||||||
|
if isMultiLinkFiles(file) {
|
||||||
|
return append(args, strings.Split(file[1:], " ")...)
|
||||||
|
}
|
||||||
|
return append(args, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMultiLinkFiles(ret string) bool {
|
||||||
|
return len(ret) > 0 && ret[0] == ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
func concatPkgLinkFiles(pkgPath string) string {
|
||||||
|
var b strings.Builder
|
||||||
|
var ret string
|
||||||
|
var n int
|
||||||
|
llgoPkgLinkFiles(pkgPath, func(linkFile string) {
|
||||||
|
if n == 0 {
|
||||||
|
ret = linkFile
|
||||||
|
} else {
|
||||||
|
b.WriteByte(' ')
|
||||||
|
b.WriteString(linkFile)
|
||||||
|
}
|
||||||
|
n++
|
||||||
|
})
|
||||||
|
if n > 1 {
|
||||||
|
b.WriteByte(' ')
|
||||||
|
b.WriteString(ret)
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func llgoPkgLinkFiles(pkgPath string, procFile func(linkFile string)) {
|
||||||
|
dir := llgoRoot() + pkgPath[len(llgoModPath):] + "/"
|
||||||
|
llFile := dir + "llgo_autogen.ll"
|
||||||
|
llaFile := llFile + "a"
|
||||||
|
zipf, err := zip.OpenReader(llaFile)
|
||||||
|
if err != nil {
|
||||||
|
procFile(llFile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer zipf.Close()
|
||||||
|
|
||||||
|
for _, f := range zipf.File {
|
||||||
|
procFile(dir + f.Name)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(llFile); os.IsNotExist(err) {
|
||||||
|
for _, f := range zipf.File {
|
||||||
|
decodeFile(dir+f.Name, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
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)
|
||||||
}
|
}
|
||||||
@@ -387,8 +481,52 @@ func isPkgInMod(pkgPath, modPath string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func llgoPkgLinkFile(pkgPath string) string {
|
||||||
|
// if kind == cl.PkgLinkBitCode {
|
||||||
|
// return filepath.Join(llgoRoot()+pkgPath[len(llgoModPath):], "llgo_autogen.bc")
|
||||||
|
// }
|
||||||
|
llFile := filepath.Join(llgoRoot()+pkgPath[len(llgoModPath):], "llgo_autogen.ll")
|
||||||
|
if _, err := os.Stat(llFile); os.IsNotExist(err) {
|
||||||
|
decodeLinkFile(llFile)
|
||||||
|
}
|
||||||
|
return llFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// *.ll => *.lla
|
||||||
|
func decodeLinkFile(llFile string) {
|
||||||
|
zipFile := llFile + "a"
|
||||||
|
zipf, err := zip.OpenReader(zipFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer zipf.Close()
|
||||||
|
f, err := zipf.Open("llgo_autogen.ll")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
data, err := io.ReadAll(f)
|
||||||
|
if err == nil {
|
||||||
|
os.WriteFile(llFile, data, 0644)
|
||||||
|
}
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
func decodeFile(outFile string, zipf *zip.File) (err error) {
|
||||||
|
f, err := zipf.Open()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
data, err := io.ReadAll(f)
|
||||||
|
if err == nil {
|
||||||
|
err = os.WriteFile(outFile, data, 0644)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ func Gen(pkgPath, inFile string, src any) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package llgen
|
|||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -74,10 +75,15 @@ func DoFile(fileOrPkg, outFile string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SmartDoFile(inFile string, pkgPath ...string) {
|
func SmartDoFile(inFile string, pkgPath ...string) {
|
||||||
|
const autgenFile = "llgo_autogen.ll"
|
||||||
dir, _ := filepath.Split(inFile)
|
dir, _ := filepath.Split(inFile)
|
||||||
fname := "llgo_autogen.ll"
|
absDir, _ := filepath.Abs(dir)
|
||||||
if inCompilerDir(dir) {
|
absDir = filepath.ToSlash(absDir)
|
||||||
|
fname := autgenFile
|
||||||
|
if inCompilerDir(absDir) {
|
||||||
fname = "out.ll"
|
fname = "out.ll"
|
||||||
|
} else if inSqlite(absDir) {
|
||||||
|
fname = "sqlite.ll"
|
||||||
}
|
}
|
||||||
outFile := dir + fname
|
outFile := dir + fname
|
||||||
|
|
||||||
@@ -86,9 +92,23 @@ func SmartDoFile(inFile string, pkgPath ...string) {
|
|||||||
} else {
|
} else {
|
||||||
DoFile(inFile, outFile)
|
DoFile(inFile, outFile)
|
||||||
}
|
}
|
||||||
|
if false && fname == autgenFile {
|
||||||
|
genZip(absDir, "llgo_autogen.lla", autgenFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func genZip(dir string, outFile, inFile string) {
|
||||||
|
cmd := exec.Command("zip", outFile, inFile)
|
||||||
|
cmd.Dir = dir
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func inCompilerDir(dir string) bool {
|
func inCompilerDir(dir string) bool {
|
||||||
dir, _ = filepath.Abs(dir)
|
return strings.Contains(dir, "/llgo/cl/")
|
||||||
return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/")
|
}
|
||||||
|
|
||||||
|
func inSqlite(dir string) bool {
|
||||||
|
return strings.HasSuffix(dir, "/llgo/x/sqlite")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,623 +0,0 @@
|
|||||||
; ModuleID = '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.itab" = type { ptr, ptr, i32, [4 x i8], [1 x 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 }, 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.basicTypes" = global ptr null
|
|
||||||
@"github.com/goplus/llgo/internal/runtime.init$guard" = 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.AllocU"(i64 %0) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = call ptr @malloc(i64 %0)
|
|
||||||
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) {
|
|
||||||
_llgo_0:
|
|
||||||
%1 = getelementptr inbounds ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 %0
|
|
||||||
%2 = load ptr, ptr %1, align 8
|
|
||||||
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) {
|
|
||||||
_llgo_0:
|
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
|
||||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
|
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
|
||||||
%5 = load ptr, ptr %4, align 8
|
|
||||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
|
||||||
%7 = load ptr, ptr %6, align 8
|
|
||||||
%8 = icmp eq ptr %7, %1
|
|
||||||
br i1 %8, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
|
||||||
%10 = load ptr, ptr %9, align 8
|
|
||||||
%11 = ptrtoint ptr %10 to i64
|
|
||||||
%mrv = insertvalue { i64, i1 } poison, i64 %11, 0
|
|
||||||
%mrv1 = insertvalue { i64, i1 } %mrv, i1 true, 1
|
|
||||||
ret { i64, i1 } %mrv1
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
ret { i64, i1 } zeroinitializer
|
|
||||||
}
|
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
|
||||||
%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 %1, i32 0, i32 0
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 1
|
|
||||||
store ptr null, ptr %2, align 8
|
|
||||||
store i64 0, ptr %3, align 4
|
|
||||||
%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) {
|
|
||||||
_llgo_0:
|
|
||||||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
|
|
||||||
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
|
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
|
|
||||||
%5 = load ptr, ptr %4, align 8
|
|
||||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
|
|
||||||
%7 = load ptr, ptr %6, align 8
|
|
||||||
%8 = icmp eq ptr %7, %1
|
|
||||||
br i1 %8, label %_llgo_1, label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
|
|
||||||
%10 = load ptr, ptr %9, align 8
|
|
||||||
%11 = ptrtoint ptr %10 to i64
|
|
||||||
ret i64 %11
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_0
|
|
||||||
%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
|
|
||||||
}
|
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %0, ptr %1) {
|
|
||||||
_llgo_0:
|
|
||||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
|
|
||||||
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
|
|
||||||
%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 %2, i32 0, i32 4
|
|
||||||
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
|
||||||
store ptr %4, ptr %3, align 8
|
|
||||||
store ptr %0, ptr %5, align 8
|
|
||||||
store i32 0, ptr %6, align 4
|
|
||||||
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) {
|
|
||||||
_llgo_0:
|
|
||||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
|
|
||||||
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
|
|
||||||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
|
|
||||||
%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 %2, i32 0, i32 4
|
|
||||||
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
|
||||||
store ptr %4, ptr %3, align 8
|
|
||||||
store ptr %0, ptr %5, align 8
|
|
||||||
store i32 0, ptr %6, align 4
|
|
||||||
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) {
|
|
||||||
_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 = load ptr, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0
|
|
||||||
%5 = 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 %3, i32 0, i32 2
|
|
||||||
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4
|
|
||||||
%9 = getelementptr inbounds i64, ptr %8, i64 0
|
|
||||||
store ptr %5, ptr %4, align 8
|
|
||||||
store ptr %2, ptr %6, align 8
|
|
||||||
store i32 0, ptr %7, align 4
|
|
||||||
store i64 0, ptr %9, align 4
|
|
||||||
%10 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
|
||||||
%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 %11, i32 0, i32 0
|
|
||||||
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 1
|
|
||||||
store ptr %3, ptr %12, align 8
|
|
||||||
store ptr %1, ptr %13, align 8
|
|
||||||
%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) {
|
|
||||||
_llgo_0:
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
|
|
||||||
%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 %3, i32 0, i32 1
|
|
||||||
%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 %3, i32 0, i32 4
|
|
||||||
%8 = getelementptr inbounds i64, ptr %7, i64 0
|
|
||||||
store ptr %0, ptr %4, align 8
|
|
||||||
store ptr %1, ptr %5, align 8
|
|
||||||
store i32 0, ptr %6, align 4
|
|
||||||
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 %3, ptr %11, align 8
|
|
||||||
store ptr %2, 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 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"() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
|
|
||||||
%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 %1, i32 0, i32 0
|
|
||||||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 1
|
|
||||||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 2
|
|
||||||
store ptr null, ptr %2, align 8
|
|
||||||
store i64 0, ptr %3, align 4
|
|
||||||
store i64 0, ptr %4, align 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) {
|
|
||||||
_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 @"github.com/goplus/llgo/internal/runtime.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
|
|
||||||
}
|
|
||||||
|
|
||||||
declare i32 @rand()
|
|
||||||
|
|
||||||
define void @"github.com/goplus/llgo/internal/runtime.init"() {
|
|
||||||
_llgo_0:
|
|
||||||
%0 = load i1, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
|
||||||
br i1 %0, label %_llgo_2, label %_llgo_1
|
|
||||||
|
|
||||||
_llgo_1: ; preds = %_llgo_0
|
|
||||||
store i1 true, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
|
|
||||||
call void @"github.com/goplus/llgo/internal/abi.init"()
|
|
||||||
%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 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 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 3), align 4
|
|
||||||
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 4), align 4
|
|
||||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 5), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 6), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 7), align 4
|
|
||||||
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 8), align 4
|
|
||||||
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 9), align 4
|
|
||||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 10), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 11), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 12), align 4
|
|
||||||
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 13), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 14), align 4
|
|
||||||
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 15), align 4
|
|
||||||
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 16), align 4
|
|
||||||
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 24), align 4
|
|
||||||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 1)
|
|
||||||
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 2)
|
|
||||||
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 3)
|
|
||||||
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 4)
|
|
||||||
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 5)
|
|
||||||
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 6)
|
|
||||||
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 7)
|
|
||||||
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 8)
|
|
||||||
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 9)
|
|
||||||
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 10)
|
|
||||||
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 11)
|
|
||||||
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 12)
|
|
||||||
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 13)
|
|
||||||
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 14)
|
|
||||||
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 15)
|
|
||||||
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 16)
|
|
||||||
%18 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 24)
|
|
||||||
store ptr %2, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 1), align 8
|
|
||||||
store ptr %3, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 2), align 8
|
|
||||||
store ptr %4, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 3), align 8
|
|
||||||
store ptr %5, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 4), align 8
|
|
||||||
store ptr %6, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 5), align 8
|
|
||||||
store ptr %7, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 6), align 8
|
|
||||||
store ptr %8, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 7), align 8
|
|
||||||
store ptr %9, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 8), align 8
|
|
||||||
store ptr %10, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 9), align 8
|
|
||||||
store ptr %11, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 10), align 8
|
|
||||||
store ptr %12, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 11), align 8
|
|
||||||
store ptr %13, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 12), align 8
|
|
||||||
store ptr %14, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 13), align 8
|
|
||||||
store ptr %15, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 14), align 8
|
|
||||||
store ptr %16, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 15), align 8
|
|
||||||
store ptr %17, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 16), align 8
|
|
||||||
store ptr %18, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
|
|
||||||
br label %_llgo_2
|
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|
||||||
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 i32 @fprintf(ptr, ptr, ...)
|
|
||||||
BIN
internal/runtime/llgo_autogen.lla
Normal file
BIN
internal/runtime/llgo_autogen.lla
Normal file
Binary file not shown.
@@ -77,4 +77,38 @@ func CheckI2Int(v Interface, t *Type) (uintptr, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func I2Float64(v Interface, t *Type) float64 {
|
||||||
|
if v.tab._type == t {
|
||||||
|
return bitCastTo64F(uint64(uintptr(v.data)))
|
||||||
|
}
|
||||||
|
panic("I2Float64: type mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckI2Float64(v Interface, t *Type) (float64, bool) {
|
||||||
|
if v.tab._type == t {
|
||||||
|
return bitCastTo64F(uint64(uintptr(v.data))), true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func I2Float32(v Interface, t *Type) float32 {
|
||||||
|
if v.tab._type == t {
|
||||||
|
return bitCastTo32F(uint32(uintptr(v.data)))
|
||||||
|
}
|
||||||
|
panic("I2Float32: type mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckI2Float32(v Interface, t *Type) (float32, bool) {
|
||||||
|
if v.tab._type == t {
|
||||||
|
return bitCastTo32F(uint32(uintptr(v.data))), true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname bitCastTo64F llgo.bitCastTo64F
|
||||||
|
func bitCastTo64F(uint64) float64
|
||||||
|
|
||||||
|
//go:linkname bitCastTo32F llgo.bitCastTo32F
|
||||||
|
func bitCastTo32F(uint32) float32
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -17,12 +17,9 @@
|
|||||||
package ssa_test
|
package ssa_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl/cltest"
|
"github.com/goplus/llgo/cl/cltest"
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
|
||||||
"github.com/goplus/llgo/ssa"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
@@ -38,6 +35,34 @@ func TestRuntime(t *testing.T) {
|
|||||||
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func TestCallback(t *testing.T) {
|
||||||
|
ctx := llvm.NewContext()
|
||||||
|
mod := ctx.NewModule("foo/bar")
|
||||||
|
|
||||||
|
tc := llvm.FunctionType(ctx.VoidType(), nil, false)
|
||||||
|
callback := llvm.PointerType(tc, 0)
|
||||||
|
params := []llvm.Type{callback}
|
||||||
|
|
||||||
|
tfn := llvm.FunctionType(ctx.VoidType(), params, false)
|
||||||
|
f := llvm.AddFunction(mod, "fn", tfn)
|
||||||
|
b := ctx.NewBuilder()
|
||||||
|
blk := llvm.AddBasicBlock(f, "")
|
||||||
|
b.SetInsertPointAtEnd(blk)
|
||||||
|
|
||||||
|
arg := f.Param(0)
|
||||||
|
// arg = b.CreateLoad(tc, arg, "")
|
||||||
|
b.CreateCall(tc, arg, nil, "")
|
||||||
|
b.CreateRetVoid()
|
||||||
|
|
||||||
|
expected := `; ModuleID = 'foo/bar'
|
||||||
|
`
|
||||||
|
if v := mod.String(); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
var m typeutil.Map
|
var m typeutil.Map
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
@@ -51,3 +76,4 @@ func TestMap(t *testing.T) {
|
|||||||
t.Fatal("At(csig):", v)
|
t.Fatal("At(csig):", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
64
ssa/decl.go
64
ssa/decl.go
@@ -25,6 +25,26 @@ import (
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
ClosureCtx = "__llgo_ctx"
|
||||||
|
ClosureStub = "__llgo_stub."
|
||||||
|
NameValist = "__llgo_va_list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VArg() *types.Var {
|
||||||
|
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVArg(arg *types.Var) bool {
|
||||||
|
return arg.Name() == NameValist
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasVArg(t *types.Tuple, n int) bool {
|
||||||
|
return n > 0 && IsVArg(t.At(n-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type aNamedConst struct {
|
type aNamedConst struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,24 +126,31 @@ func (g Global) Init(v Expr) {
|
|||||||
// respectively, and is nil in the generic method.
|
// respectively, and is nil in the generic method.
|
||||||
type aFunction struct {
|
type aFunction struct {
|
||||||
Expr
|
Expr
|
||||||
pkg Package
|
Pkg Package
|
||||||
prog Program
|
Prog Program
|
||||||
|
|
||||||
blks []BasicBlock
|
blks []BasicBlock
|
||||||
|
|
||||||
params []Type
|
params []Type
|
||||||
|
freeVars Expr
|
||||||
|
base int // base = 1 if hasFreeVars; base = 0 otherwise
|
||||||
hasVArg bool
|
hasVArg bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function represents a function or method.
|
// Function represents a function or method.
|
||||||
type Function = *aFunction
|
type Function = *aFunction
|
||||||
|
|
||||||
func newFunction(fn llvm.Value, t Type, pkg Package, prog Program) Function {
|
func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars bool) Function {
|
||||||
params, hasVArg := newParams(t, prog)
|
params, hasVArg := newParams(t, prog)
|
||||||
return &aFunction{Expr{fn, t}, pkg, prog, nil, params, hasVArg}
|
base := 0
|
||||||
|
if hasFreeVars {
|
||||||
|
base = 1
|
||||||
|
}
|
||||||
|
return &aFunction{Expr{fn, t}, pkg, prog, nil, params, Expr{}, base, hasVArg}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
||||||
sig := fn.t.(*types.Signature)
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
in := sig.Params()
|
in := sig.Params()
|
||||||
if n := in.Len(); n > 0 {
|
if n := in.Len(); n > 0 {
|
||||||
if hasVArg = HasVArg(in, n); hasVArg {
|
if hasVArg = HasVArg(in, n); hasVArg {
|
||||||
@@ -131,7 +158,7 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
|||||||
}
|
}
|
||||||
params = make([]Type, n)
|
params = make([]Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
params[i] = prog.Type(in.At(i).Type())
|
params[i] = prog.rawType(in.At(i).Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -139,18 +166,41 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
|||||||
|
|
||||||
// Params returns the function's ith parameter.
|
// Params returns the function's ith parameter.
|
||||||
func (p Function) Param(i int) Expr {
|
func (p Function) Param(i int) Expr {
|
||||||
|
i += p.base // skip if hasFreeVars
|
||||||
return Expr{p.impl.Param(i), p.params[i]}
|
return Expr{p.impl.Param(i), p.params[i]}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Function) closureCtx(b Builder) Expr {
|
||||||
|
if p.freeVars.IsNil() {
|
||||||
|
if p.base == 0 {
|
||||||
|
panic("ssa: function has no free variables")
|
||||||
|
}
|
||||||
|
ptr := Expr{p.impl.Param(0), p.params[0]}
|
||||||
|
p.freeVars = b.Load(ptr)
|
||||||
|
}
|
||||||
|
return p.freeVars
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreeVar returns the function's ith free variable.
|
||||||
|
func (p Function) FreeVar(b Builder, i int) Expr {
|
||||||
|
ctx := p.closureCtx(b)
|
||||||
|
return b.getField(ctx, i)
|
||||||
|
}
|
||||||
|
|
||||||
// NewBuilder creates a new Builder for the function.
|
// NewBuilder creates a new Builder for the function.
|
||||||
func (p Function) NewBuilder() Builder {
|
func (p Function) NewBuilder() Builder {
|
||||||
prog := p.prog
|
prog := p.Prog
|
||||||
b := prog.ctx.NewBuilder()
|
b := prog.ctx.NewBuilder()
|
||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
// b.Finalize()
|
// b.Finalize()
|
||||||
return &aBuilder{b, p, prog}
|
return &aBuilder{b, p, prog}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasBody reports whether the function has a body.
|
||||||
|
func (p Function) HasBody() bool {
|
||||||
|
return len(p.blks) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// MakeBody creates nblk basic blocks for the function, and creates
|
// MakeBody creates nblk basic blocks for the function, and creates
|
||||||
// a new Builder associated to #0 block.
|
// a new Builder associated to #0 block.
|
||||||
func (p Function) MakeBody(nblk int) Builder {
|
func (p Function) MakeBody(nblk int) Builder {
|
||||||
|
|||||||
422
ssa/expr.go
422
ssa/expr.go
@@ -41,20 +41,11 @@ func (v Expr) IsNil() bool {
|
|||||||
return v.Type == nil
|
return v.Type == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// TypeOf returns the type of the expression.
|
|
||||||
func (v Expr) TypeOf() types.Type {
|
|
||||||
return v.t
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Do evaluates the delay expression and returns the result.
|
// Do evaluates the delay expression and returns the result.
|
||||||
func (v Expr) Do(b Builder) Expr {
|
func (v Expr) Do(b Builder) Expr {
|
||||||
switch vt := v.Type; vt.kind {
|
switch vt := v.Type; vt.kind {
|
||||||
case vkDelayExpr:
|
|
||||||
return vt.t.(delayExprTy)()
|
|
||||||
case vkPhisExpr:
|
case vkPhisExpr:
|
||||||
e := vt.t.(*phisExprTy)
|
e := vt.raw.Type.(*phisExprTy)
|
||||||
return b.aggregateValue(e.Type, e.phis...)
|
return b.aggregateValue(e.Type, e.phis...)
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
@@ -62,23 +53,6 @@ func (v Expr) Do(b Builder) Expr {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// DelayExpr returns a delay expression.
|
|
||||||
func DelayExpr(f func() Expr) Expr {
|
|
||||||
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
|
|
||||||
}
|
|
||||||
|
|
||||||
type delayExprTy func() Expr
|
|
||||||
|
|
||||||
func (p delayExprTy) Underlying() types.Type {
|
|
||||||
panic("don't call")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p delayExprTy) String() string {
|
|
||||||
return "delayExpr"
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
type phisExprTy struct {
|
type phisExprTy struct {
|
||||||
phis []llvm.Value
|
phis []llvm.Value
|
||||||
Type
|
Type
|
||||||
@@ -93,7 +67,7 @@ func (p phisExprTy) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func phisExpr(t Type, phis []llvm.Value) Expr {
|
func phisExpr(t Type, phis []llvm.Value) Expr {
|
||||||
return Expr{Type: &aType{t: &phisExprTy{phis, t}, kind: vkPhisExpr}}
|
return Expr{Type: &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -148,7 +122,8 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
|
|||||||
if v == nil {
|
if v == nil {
|
||||||
return prog.Null(typ)
|
return prog.Null(typ)
|
||||||
}
|
}
|
||||||
switch t := typ.t.(type) {
|
raw := typ.raw.Type
|
||||||
|
switch t := raw.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := t.Kind()
|
kind := t.Kind()
|
||||||
switch {
|
switch {
|
||||||
@@ -170,7 +145,7 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
|
|||||||
return b.Str(constant.StringVal(v))
|
return b.Str(constant.StringVal(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("unsupported Const: %v, %v", v, typ.t))
|
panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SizeOf returns the size of a type.
|
// SizeOf returns the size of a type.
|
||||||
@@ -189,7 +164,7 @@ func (b Builder) CStr(v string) Expr {
|
|||||||
func (b Builder) Str(v string) (ret Expr) {
|
func (b Builder) Str(v string) (ret Expr) {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
cstr := b.CStr(v)
|
cstr := b.CStr(v)
|
||||||
ret = b.InlineCall(b.fn.pkg.rtFunc("NewString"), cstr, prog.Val(len(v)))
|
ret = b.InlineCall(b.Func.Pkg.rtFunc("NewString"), cstr, prog.Val(len(v)))
|
||||||
ret.Type = prog.String()
|
ret.Type = prog.String()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -302,7 +277,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
switch kind {
|
switch kind {
|
||||||
case vkString:
|
case vkString:
|
||||||
if op == token.ADD {
|
if op == token.ADD {
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
return b.InlineCall(pkg.rtFunc("StringCat"), x, y)
|
return b.InlineCall(pkg.rtFunc("StringCat"), x, y)
|
||||||
}
|
}
|
||||||
case vkComplex:
|
case vkComplex:
|
||||||
@@ -348,40 +323,86 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
// XOR is bitwise complement.
|
// XOR is bitwise complement.
|
||||||
// SUB is negation.
|
// SUB is negation.
|
||||||
// NOT is logical negation.
|
// NOT is logical negation.
|
||||||
func (b Builder) UnOp(op token.Token, x Expr) Expr {
|
func (b Builder) UnOp(op token.Token, x Expr) (ret Expr) {
|
||||||
switch op {
|
|
||||||
case token.MUL:
|
|
||||||
return b.Load(x)
|
|
||||||
}
|
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("UnOp %v, %v\n", op, x.impl)
|
log.Printf("UnOp %v, %v\n", op, x.impl)
|
||||||
}
|
}
|
||||||
|
switch op {
|
||||||
|
case token.MUL:
|
||||||
|
return b.Load(x)
|
||||||
|
case token.SUB:
|
||||||
|
switch t := x.Type.raw.Underlying().(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
ret.Type = x.Type
|
||||||
|
if t.Info()&types.IsInteger != 0 {
|
||||||
|
ret.impl = b.impl.CreateNeg(x.impl, "")
|
||||||
|
} else if t.Info()&types.IsFloat != 0 {
|
||||||
|
ret.impl = b.impl.CreateFNeg(x.impl, "")
|
||||||
|
} else {
|
||||||
panic("todo")
|
panic("todo")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
case token.NOT:
|
||||||
|
ret.Type = x.Type
|
||||||
|
ret.impl = b.impl.CreateNot(x.impl, "")
|
||||||
|
case token.XOR:
|
||||||
|
ret.Type = x.Type
|
||||||
|
ret.impl = b.impl.CreateXor(x.impl, llvm.ConstInt(x.Type.ll, ^uint64(0), false), "")
|
||||||
|
case token.ARROW:
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
||||||
if _, ok := t.(*types.Signature); ok {
|
if t, ok := t.(*types.Struct); ok && isClosure(t) {
|
||||||
if v.kind != vkClosure {
|
if v.kind != vkClosure {
|
||||||
prog := b.Prog
|
return b.Func.Pkg.closureStub(b, t, v)
|
||||||
nilVal := prog.Null(prog.VoidPtr()).impl
|
|
||||||
return b.aggregateValue(prog.Type(t), v.impl, nilVal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func llvmValues(vals []Expr, params *types.Tuple, b Builder) []llvm.Value {
|
func llvmParamsEx(data Expr, vals []Expr, params *types.Tuple, b Builder) (ret []llvm.Value) {
|
||||||
|
if data.IsNil() {
|
||||||
|
return llvmParams(0, vals, params, b)
|
||||||
|
}
|
||||||
|
ret = llvmParams(1, vals, params, b)
|
||||||
|
ret[0] = data.impl
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func llvmParams(base int, vals []Expr, params *types.Tuple, b Builder) (ret []llvm.Value) {
|
||||||
n := params.Len()
|
n := params.Len()
|
||||||
ret := make([]llvm.Value, len(vals))
|
if n > 0 {
|
||||||
for i, v := range vals {
|
ret = make([]llvm.Value, len(vals)+base)
|
||||||
|
for idx, v := range vals {
|
||||||
|
i := base + idx
|
||||||
if i < n {
|
if i < n {
|
||||||
v = checkExpr(v, params.At(i).Type(), b)
|
v = checkExpr(v, params.At(i).Type(), b)
|
||||||
}
|
}
|
||||||
ret[i] = v.impl
|
ret[i] = v.impl
|
||||||
}
|
}
|
||||||
return ret
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func llvmFields(vals []Expr, t *types.Struct, b Builder) (ret []llvm.Value) {
|
||||||
|
n := t.NumFields()
|
||||||
|
if n > 0 {
|
||||||
|
ret = make([]llvm.Value, len(vals))
|
||||||
|
for i, v := range vals {
|
||||||
|
if i < n {
|
||||||
|
v = checkExpr(v, t.Field(i).Type(), b)
|
||||||
|
}
|
||||||
|
ret[i] = v.impl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value {
|
func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value {
|
||||||
@@ -413,7 +434,7 @@ func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) {
|
|||||||
p.impl.AddIncoming(vs, bs)
|
p.impl.AddIncoming(vs, bs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := p.t.(*phisExprTy)
|
e := p.raw.Type.(*phisExprTy)
|
||||||
phis := e.phis
|
phis := e.phis
|
||||||
vals := make([][]llvm.Value, len(phis))
|
vals := make([][]llvm.Value, len(phis))
|
||||||
for iblk, blk := range bblks {
|
for iblk, blk := range bblks {
|
||||||
@@ -436,7 +457,7 @@ func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) {
|
|||||||
// Phi returns a phi node.
|
// Phi returns a phi node.
|
||||||
func (b Builder) Phi(t Type) Phi {
|
func (b Builder) Phi(t Type) Phi {
|
||||||
impl := b.impl
|
impl := b.impl
|
||||||
switch tund := t.t.Underlying().(type) {
|
switch tund := t.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tund.Kind()
|
kind := tund.Kind()
|
||||||
switch kind {
|
switch kind {
|
||||||
@@ -447,6 +468,8 @@ func (b Builder) Phi(t Type) Phi {
|
|||||||
phis[1] = llvm.CreatePHI(impl, prog.tyInt())
|
phis[1] = llvm.CreatePHI(impl, prog.tyInt())
|
||||||
return Phi{phisExpr(t, phis)}
|
return Phi{phisExpr(t, phis)}
|
||||||
}
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
panic("todo")
|
||||||
}
|
}
|
||||||
phi := llvm.CreatePHI(impl, t.ll)
|
phi := llvm.CreatePHI(impl, t.ll)
|
||||||
return Phi{Expr{phi, t}}
|
return Phi{Expr{phi, t}}
|
||||||
@@ -454,12 +477,20 @@ func (b Builder) Phi(t Type) Phi {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Advance returns the pointer ptr advanced by offset bytes.
|
// Advance returns the pointer ptr advanced by offset.
|
||||||
func (b Builder) Advance(ptr Expr, offset Expr) Expr {
|
func (b Builder) Advance(ptr Expr, offset Expr) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Advance %v, %v\n", ptr.impl, offset.impl)
|
log.Printf("Advance %v, %v\n", ptr.impl, offset.impl)
|
||||||
}
|
}
|
||||||
ret := llvm.CreateGEP(b.impl, b.Prog.tyInt8(), ptr.impl, []llvm.Value{offset.impl})
|
var elem llvm.Type
|
||||||
|
var prog = b.Prog
|
||||||
|
switch t := ptr.raw.Type.(type) {
|
||||||
|
case *types.Basic: // void
|
||||||
|
elem = prog.tyInt8()
|
||||||
|
default:
|
||||||
|
elem = prog.rawType(t.(*types.Pointer).Elem()).ll
|
||||||
|
}
|
||||||
|
ret := llvm.CreateGEP(b.impl, elem, ptr.impl, []llvm.Value{offset.impl})
|
||||||
return Expr{ret, ptr.Type}
|
return Expr{ret, ptr.Type}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,20 +505,32 @@ func (b Builder) Load(ptr Expr) Expr {
|
|||||||
|
|
||||||
// Store stores val at the pointer ptr.
|
// Store stores val at the pointer ptr.
|
||||||
func (b Builder) Store(ptr, val Expr) Builder {
|
func (b Builder) Store(ptr, val Expr) Builder {
|
||||||
|
raw := ptr.raw.Type
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Store %v, %v\n", ptr.impl, val.impl)
|
log.Printf("Store %v, %v, %v\n", raw, ptr.impl, val.impl)
|
||||||
}
|
}
|
||||||
|
val = checkExpr(val, raw.(*types.Pointer).Elem(), b)
|
||||||
b.impl.CreateStore(val.impl, ptr.impl)
|
b.impl.CreateStore(val.impl, ptr.impl)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Builder) aggregateAlloc(t Type, flds ...llvm.Value) llvm.Value {
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
size := prog.SizeOf(t)
|
||||||
|
ptr := b.InlineCall(pkg.rtFunc("AllocU"), prog.IntVal(size, prog.Uintptr())).impl
|
||||||
|
tll := t.ll
|
||||||
|
impl := b.impl
|
||||||
|
for i, fld := range flds {
|
||||||
|
impl.CreateStore(fld, llvm.CreateStructGEP(impl, tll, ptr, i))
|
||||||
|
}
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
// aggregateValue yields the value of the aggregate X with the fields
|
// aggregateValue yields the value of the aggregate X with the fields
|
||||||
func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr {
|
func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr {
|
||||||
if debugInstr {
|
|
||||||
log.Printf("AggregateValue %v, %v\n", t, flds)
|
|
||||||
}
|
|
||||||
impl := b.impl
|
|
||||||
tll := t.ll
|
tll := t.ll
|
||||||
|
impl := b.impl
|
||||||
ptr := llvm.CreateAlloca(impl, tll)
|
ptr := llvm.CreateAlloca(impl, tll)
|
||||||
for i, fld := range flds {
|
for i, fld := range flds {
|
||||||
impl.CreateStore(fld, llvm.CreateStructGEP(impl, tll, ptr, i))
|
impl.CreateStore(fld, llvm.CreateStructGEP(impl, tll, ptr, i))
|
||||||
@@ -495,6 +538,28 @@ func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr {
|
|||||||
return Expr{llvm.CreateLoad(b.impl, tll, ptr), t}
|
return Expr{llvm.CreateLoad(b.impl, tll, ptr), t}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The MakeClosure instruction yields a closure value whose code is
|
||||||
|
// Fn and whose free variables' values are supplied by Bindings.
|
||||||
|
//
|
||||||
|
// Type() returns a (possibly named) *types.Signature.
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t0 = make closure anon@1.2 [x y z]
|
||||||
|
// t1 = make closure bound$(main.I).add [i]
|
||||||
|
func (b Builder) MakeClosure(fn Expr, bindings []Expr) Expr {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("MakeClosure %v, %v\n", fn, bindings)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
tfn := fn.Type
|
||||||
|
sig := tfn.raw.Type.(*types.Signature)
|
||||||
|
tctx := sig.Params().At(0).Type().Underlying().(*types.Pointer).Elem().(*types.Struct)
|
||||||
|
flds := llvmFields(bindings, tctx, b)
|
||||||
|
data := b.aggregateAlloc(prog.rawType(tctx), flds...)
|
||||||
|
return b.aggregateValue(prog.Closure(tfn), fn.impl, data)
|
||||||
|
}
|
||||||
|
|
||||||
// The FieldAddr instruction yields the address of Field of *struct X.
|
// The FieldAddr instruction yields the address of Field of *struct X.
|
||||||
//
|
//
|
||||||
// The field is identified by its index within the field list of the
|
// The field is identified by its index within the field list of the
|
||||||
@@ -524,8 +589,13 @@ func (b Builder) Field(x Expr, idx int) Expr {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Field %v, %d\n", x.impl, idx)
|
log.Printf("Field %v, %d\n", x.impl, idx)
|
||||||
}
|
}
|
||||||
telem := b.Prog.Field(x.Type, idx)
|
return b.getField(x, idx)
|
||||||
return Expr{llvm.CreateExtractValue(b.impl, x.impl, idx), telem}
|
}
|
||||||
|
|
||||||
|
func (b Builder) getField(x Expr, idx int) Expr {
|
||||||
|
tfld := b.Prog.Field(x.Type, idx)
|
||||||
|
fld := llvm.CreateExtractValue(b.impl, x.impl, idx)
|
||||||
|
return Expr{fld, tfld}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IndexAddr instruction yields the address of the element at
|
// The IndexAddr instruction yields the address of the element at
|
||||||
@@ -547,9 +617,9 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
telem := prog.Index(x.Type)
|
telem := prog.Index(x.Type)
|
||||||
pt := prog.Pointer(telem)
|
pt := prog.Pointer(telem)
|
||||||
switch x.t.Underlying().(type) {
|
switch x.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
||||||
indices := []llvm.Value{idx.impl}
|
indices := []llvm.Value{idx.impl}
|
||||||
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
||||||
@@ -573,13 +643,13 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
var telem Type
|
var telem Type
|
||||||
var ptr Expr
|
var ptr Expr
|
||||||
switch t := x.t.Underlying().(type) {
|
switch t := x.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Info()&types.IsString == 0 {
|
if t.Kind() != types.String {
|
||||||
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
||||||
}
|
}
|
||||||
telem = prog.Type(types.Typ[types.Byte])
|
telem = prog.rawType(types.Typ[types.Byte])
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
telem = prog.Index(x.Type)
|
telem = prog.Index(x.Type)
|
||||||
@@ -597,6 +667,26 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr {
|
|||||||
return b.Load(buf)
|
return b.Load(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Lookup instruction yields element Index of collection map X.
|
||||||
|
// Index is the appropriate key type.
|
||||||
|
//
|
||||||
|
// If CommaOk, the result is a 2-tuple of the value above and a
|
||||||
|
// boolean indicating the result of a map membership test for the key.
|
||||||
|
// The components of the tuple are accessed using Extract.
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t2 = t0[t1]
|
||||||
|
// t5 = t3[t4],ok
|
||||||
|
func (b Builder) Lookup(x, key Expr, commaOk bool) (ret Expr) {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("Lookup %v, %v, %v\n", x.impl, key.impl, commaOk)
|
||||||
|
}
|
||||||
|
// TODO(xsw)
|
||||||
|
// panic("todo")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// The Slice instruction yields a slice of an existing string, slice
|
// The Slice instruction yields a slice of an existing string, slice
|
||||||
// or *array X between optional integer bounds Low and High.
|
// or *array X between optional integer bounds Low and High.
|
||||||
//
|
//
|
||||||
@@ -614,14 +704,14 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl)
|
log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
var nCap Expr
|
var nCap Expr
|
||||||
var nEltSize Expr
|
var nEltSize Expr
|
||||||
var base Expr
|
var base Expr
|
||||||
if low.IsNil() {
|
if low.IsNil() {
|
||||||
low = prog.IntVal(0, prog.Int())
|
low = prog.IntVal(0, prog.Int())
|
||||||
}
|
}
|
||||||
switch t := x.t.Underlying().(type) {
|
switch t := x.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Kind() != types.String {
|
if t.Kind() != types.String {
|
||||||
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
||||||
@@ -644,7 +734,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
telem := t.Elem()
|
telem := t.Elem()
|
||||||
switch te := telem.Underlying().(type) {
|
switch te := telem.Underlying().(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := prog.Type(te.Elem())
|
elem := prog.rawType(te.Elem())
|
||||||
ret.Type = prog.Slice(elem)
|
ret.Type = prog.Slice(elem)
|
||||||
nEltSize = b.SizeOf(elem)
|
nEltSize = b.SizeOf(elem)
|
||||||
nCap = prog.IntVal(uint64(te.Len()), prog.Int())
|
nCap = prog.IntVal(uint64(te.Len()), prog.Int())
|
||||||
@@ -674,9 +764,9 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
// t1 = make StringIntMap t0
|
// t1 = make StringIntMap t0
|
||||||
func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeMap %v, %v\n", t, nReserve.impl)
|
log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ret.Type = t
|
ret.Type = t
|
||||||
ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl
|
ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl
|
||||||
// TODO(xsw): nReserve
|
// TODO(xsw): nReserve
|
||||||
@@ -699,9 +789,9 @@ func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
|||||||
// t1 = make StringSlice 1:int t0
|
// t1 = make StringSlice 1:int t0
|
||||||
func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeSlice %v, %v, %v\n", t, len.impl, cap.impl)
|
log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
if cap.IsNil() {
|
if cap.IsNil() {
|
||||||
cap = len
|
cap = len
|
||||||
}
|
}
|
||||||
@@ -734,13 +824,12 @@ func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
|||||||
//
|
//
|
||||||
// t0 = local int
|
// t0 = local int
|
||||||
// t1 = new int
|
// t1 = new int
|
||||||
func (b Builder) Alloc(t *types.Pointer, heap bool) (ret Expr) {
|
func (b Builder) Alloc(elem Type, heap bool) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Alloc %v, %v\n", t, heap)
|
log.Printf("Alloc %v, %v\n", elem.RawType(), heap)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
elem := prog.Type(t.Elem())
|
|
||||||
size := b.SizeOf(elem)
|
size := b.SizeOf(elem)
|
||||||
if heap {
|
if heap {
|
||||||
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
||||||
@@ -748,7 +837,7 @@ func (b Builder) Alloc(t *types.Pointer, heap bool) (ret Expr) {
|
|||||||
ret = Expr{llvm.CreateAlloca(b.impl, elem.ll), prog.VoidPtr()}
|
ret = Expr{llvm.CreateAlloca(b.impl, elem.ll), prog.VoidPtr()}
|
||||||
ret.impl = b.InlineCall(pkg.rtFunc("Zeroinit"), ret, size).impl
|
ret.impl = b.InlineCall(pkg.rtFunc("Zeroinit"), ret, size).impl
|
||||||
}
|
}
|
||||||
ret.Type = prog.Type(t)
|
ret.Type = prog.Pointer(elem)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,7 +849,7 @@ func (b Builder) Alloca(n Expr) (ret Expr) {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
telem := prog.tyInt8()
|
telem := prog.tyInt8()
|
||||||
ret.impl = llvm.CreateArrayAlloca(b.impl, telem, n.impl)
|
ret.impl = llvm.CreateArrayAlloca(b.impl, telem, n.impl)
|
||||||
ret.Type = &aType{prog.tyVoidPtr(), types.Typ[types.UnsafePointer], vkPtr}
|
ret.Type = prog.VoidPtr()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,7 +870,7 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("AllocaCStr %v\n", gostr.impl)
|
log.Printf("AllocaCStr %v\n", gostr.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
n := b.InlineCall(pkg.rtFunc("StringLen"), gostr)
|
n := b.InlineCall(pkg.rtFunc("StringLen"), gostr)
|
||||||
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
||||||
cstr := b.Alloca(n1)
|
cstr := b.Alloca(n1)
|
||||||
@@ -815,13 +904,14 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) {
|
|||||||
// t1 = changetype *int <- IntPtr (t0)
|
// t1 = changetype *int <- IntPtr (t0)
|
||||||
func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("ChangeType %v, %v\n", t.t, x.impl)
|
log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl)
|
||||||
}
|
}
|
||||||
typ := t.t
|
typ := t.raw.Type
|
||||||
switch typ.(type) {
|
switch typ.(type) {
|
||||||
default:
|
default:
|
||||||
|
// TODO(xsw): remove instr name
|
||||||
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
||||||
ret.Type = b.Prog.Type(typ)
|
ret.Type = b.Prog.rawType(typ)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -853,19 +943,64 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
|||||||
//
|
//
|
||||||
// t1 = convert []byte <- string (t0)
|
// t1 = convert []byte <- string (t0)
|
||||||
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
||||||
typ := t.t
|
if debugInstr {
|
||||||
ret.Type = b.Prog.Type(typ)
|
log.Printf("Convert %v <- %v\n", t.RawType(), x.RawType())
|
||||||
switch und := typ.Underlying().(type) {
|
}
|
||||||
|
typ := t.raw.Type
|
||||||
|
ret.Type = b.Prog.rawType(typ)
|
||||||
|
switch typ := typ.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := und.Kind()
|
switch typ.Kind() {
|
||||||
switch {
|
case types.Uintptr:
|
||||||
case kind >= types.Int && kind <= types.Uintptr:
|
|
||||||
ret.impl = castInt(b.impl, x.impl, t.ll)
|
ret.impl = castInt(b.impl, x.impl, t.ll)
|
||||||
return
|
return
|
||||||
case kind == types.UnsafePointer:
|
case types.UnsafePointer:
|
||||||
ret.impl = castPtr(b.impl, x.impl, t.ll)
|
ret.impl = castPtr(b.impl, x.impl, t.ll)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
switch xtyp := x.RawType().Underlying().(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
size := b.Prog.SizeOf(t)
|
||||||
|
xsize := b.Prog.SizeOf(x.Type)
|
||||||
|
if typ.Info()&types.IsInteger != 0 {
|
||||||
|
// int <- int/float
|
||||||
|
if xtyp.Info()&types.IsInteger != 0 {
|
||||||
|
// if xsize > size {
|
||||||
|
// ret.impl = b.impl.CreateTrunc(x.impl, t.ll, "")
|
||||||
|
// } else if typ.Info()&types.IsUnsigned != 0 {
|
||||||
|
// ret.impl = b.impl.CreateZExt(x.impl, t.ll, "")
|
||||||
|
// } else {
|
||||||
|
// ret.impl = b.impl.CreateSExt(x.impl, t.ll, "")
|
||||||
|
// }
|
||||||
|
ret.impl = castInt(b.impl, x.impl, t.ll)
|
||||||
|
return
|
||||||
|
} else if xtyp.Info()&types.IsFloat != 0 {
|
||||||
|
if typ.Info()&types.IsUnsigned != 0 {
|
||||||
|
ret.impl = b.impl.CreateFPToUI(x.impl, t.ll, "")
|
||||||
|
} else {
|
||||||
|
ret.impl = b.impl.CreateFPToSI(x.impl, t.ll, "")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if typ.Info()&types.IsFloat != 0 {
|
||||||
|
// float <- int/float
|
||||||
|
if xtyp.Info()&types.IsInteger != 0 {
|
||||||
|
if xtyp.Info()&types.IsUnsigned != 0 {
|
||||||
|
ret.impl = b.impl.CreateUIToFP(x.impl, t.ll, "")
|
||||||
|
} else {
|
||||||
|
ret.impl = b.impl.CreateSIToFP(x.impl, t.ll, "")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if xtyp.Info()&types.IsFloat != 0 {
|
||||||
|
if xsize > size {
|
||||||
|
ret.impl = b.impl.CreateFPTrunc(x.impl, t.ll, "")
|
||||||
|
} else {
|
||||||
|
ret.impl = b.impl.CreateFPExt(x.impl, t.ll, "")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
ret.impl = castPtr(b.impl, x.impl, t.ll)
|
ret.impl = castPtr(b.impl, x.impl, t.ll)
|
||||||
return
|
return
|
||||||
@@ -905,17 +1040,14 @@ func castPtr(b llvm.Builder, x llvm.Value, t llvm.Type) llvm.Value {
|
|||||||
//
|
//
|
||||||
// t1 = make interface{} <- int (42:int)
|
// t1 = make interface{} <- int (42:int)
|
||||||
// t2 = make Stringer <- t0
|
// t2 = make Stringer <- t0
|
||||||
func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Expr) {
|
func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
|
||||||
|
raw := tinter.raw.Type
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeInterface %v, %v\n", inter, x.impl)
|
log.Printf("MakeInterface %v, %v\n", raw, x.impl)
|
||||||
}
|
}
|
||||||
tiund := inter.Underlying().(*types.Interface)
|
|
||||||
isAny := tiund.Empty()
|
|
||||||
fnDo := func() Expr {
|
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
tinter := prog.Type(inter)
|
switch tx := x.raw.Type.Underlying().(type) {
|
||||||
switch tx := x.t.Underlying().(type) {
|
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tx.Kind()
|
kind := tx.Kind()
|
||||||
switch {
|
switch {
|
||||||
@@ -924,16 +1056,22 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
|||||||
tptr := prog.Uintptr()
|
tptr := prog.Uintptr()
|
||||||
vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr}
|
vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr}
|
||||||
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
|
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
|
||||||
|
case kind == types.Float32:
|
||||||
|
t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind)))
|
||||||
|
tptr := prog.Uintptr()
|
||||||
|
i32 := b.impl.CreateBitCast(x.impl, prog.tyInt32(), "")
|
||||||
|
vptr := Expr{llvm.CreateIntCast(b.impl, i32, tptr.ll), tptr}
|
||||||
|
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
|
||||||
|
case kind == types.Float64:
|
||||||
|
t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind)))
|
||||||
|
tptr := prog.Uintptr()
|
||||||
|
vptr := Expr{b.impl.CreateBitCast(x.impl, tptr.ll, ""), tptr}
|
||||||
|
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter}
|
||||||
case kind == types.String:
|
case kind == types.String:
|
||||||
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyString"), x).impl, tinter}
|
return Expr{b.InlineCall(pkg.rtFunc("MakeAnyString"), x).impl, tinter}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
|
||||||
if mayDelay && isAny {
|
|
||||||
return DelayExpr(fnDo)
|
|
||||||
}
|
|
||||||
return fnDo()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The TypeAssert instruction tests whether interface value X has type
|
// The TypeAssert instruction tests whether interface value X has type
|
||||||
@@ -977,18 +1115,18 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
|||||||
// t3 = typeassert,ok t2.(T)
|
// t3 = typeassert,ok t2.(T)
|
||||||
func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.t, commaOk)
|
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.raw.Type, commaOk)
|
||||||
}
|
}
|
||||||
switch assertedTyp.kind {
|
switch assertedTyp.kind {
|
||||||
case vkSigned, vkUnsigned, vkFloat:
|
case vkSigned, vkUnsigned:
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
fnName := "I2Int"
|
fnName := "I2Int"
|
||||||
if commaOk {
|
if commaOk {
|
||||||
fnName = "CheckI2Int"
|
fnName = "CheckI2Int"
|
||||||
}
|
}
|
||||||
fn := pkg.rtFunc(fnName)
|
fn := pkg.rtFunc(fnName)
|
||||||
var kind types.BasicKind
|
var kind types.BasicKind
|
||||||
switch t := assertedTyp.t.(type) {
|
switch t := assertedTyp.raw.Type.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind = t.Kind()
|
kind = t.Kind()
|
||||||
default:
|
default:
|
||||||
@@ -996,6 +1134,25 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
}
|
}
|
||||||
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
||||||
return b.InlineCall(fn, x, typ)
|
return b.InlineCall(fn, x, typ)
|
||||||
|
case vkFloat:
|
||||||
|
var fnName string
|
||||||
|
kind := assertedTyp.raw.Underlying().(*types.Basic).Kind()
|
||||||
|
switch kind {
|
||||||
|
case types.Float32:
|
||||||
|
fnName = "I2Float32"
|
||||||
|
if commaOk {
|
||||||
|
fnName = "CheckI2Float32"
|
||||||
|
}
|
||||||
|
case types.Float64:
|
||||||
|
fnName = "I2Float64"
|
||||||
|
if commaOk {
|
||||||
|
fnName = "CheckI2Float64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg := b.Func.Pkg
|
||||||
|
fn := pkg.rtFunc(fnName)
|
||||||
|
typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind)))
|
||||||
|
return b.InlineCall(fn, x, typ)
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
@@ -1026,7 +1183,7 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
name = "closure"
|
name = "closure"
|
||||||
}
|
}
|
||||||
fmt.Fprint(&b, "Call ", fn.t, " ", name)
|
fmt.Fprint(&b, "Call ", fn.kind, " ", fn.raw.Type, " ", name)
|
||||||
sep := ": "
|
sep := ": "
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
fmt.Fprint(&b, sep, arg.impl)
|
fmt.Fprint(&b, sep, arg.impl)
|
||||||
@@ -1034,26 +1191,42 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
log.Println(b.String())
|
log.Println(b.String())
|
||||||
}
|
}
|
||||||
|
var ll llvm.Type
|
||||||
|
var data Expr
|
||||||
var sig *types.Signature
|
var sig *types.Signature
|
||||||
var t = fn.t
|
var raw = fn.raw.Type
|
||||||
normal := true
|
|
||||||
switch fn.kind {
|
switch fn.kind {
|
||||||
case vkClosure:
|
case vkClosure:
|
||||||
|
data = b.Field(fn, 1)
|
||||||
fn = b.Field(fn, 0)
|
fn = b.Field(fn, 0)
|
||||||
t = fn.t
|
raw = fn.raw.Type
|
||||||
normal = false
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case vkFuncDecl, vkFuncPtr:
|
case vkFuncPtr:
|
||||||
sig = t.(*types.Signature)
|
sig = raw.(*types.Signature)
|
||||||
ret.Type = prog.retType(sig)
|
ll = prog.FuncDecl(sig, InC).ll
|
||||||
|
case vkFuncDecl:
|
||||||
|
sig = raw.(*types.Signature)
|
||||||
|
ll = fn.ll
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
if normal {
|
ret.Type = prog.retType(sig)
|
||||||
ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args, sig.Params(), b))
|
ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sig.Params(), b))
|
||||||
} else {
|
return
|
||||||
ret = prog.IntVal(0, prog.Type(types.Typ[types.Int32]))
|
}
|
||||||
}
|
|
||||||
|
// The Extract instruction yields component Index of Tuple.
|
||||||
|
//
|
||||||
|
// This is used to access the results of instructions with multiple
|
||||||
|
// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and
|
||||||
|
// IndexExpr(Map).
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t1 = extract t0 #1
|
||||||
|
func (b Builder) Extract(x Expr, index int) (ret Expr) {
|
||||||
|
ret.Type = b.Prog.toType(x.Type.raw.Type.(*types.Tuple).At(index).Type())
|
||||||
|
ret.impl = b.impl.CreateExtractValue(x.impl, index, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1068,25 +1241,32 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
case "len":
|
case "len":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch t := arg.t.Underlying().(type) {
|
switch t := arg.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg)
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Kind() == types.String {
|
if t.Kind() == types.String {
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("StringLen"), arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "cap":
|
case "cap":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch arg.t.Underlying().(type) {
|
switch arg.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceCap"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("SliceCap"), arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitCast bit cast expr to type
|
||||||
|
func (b Builder) BitCast(val Expr, typ Type) (ret Expr) {
|
||||||
|
ret.Type = typ
|
||||||
|
ret.impl = b.impl.CreateBitCast(val.impl, typ.ll, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
108
ssa/package.go
108
ssa/package.go
@@ -17,10 +17,12 @@
|
|||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -95,8 +97,8 @@ func Initialize(flags InitFlags) {
|
|||||||
|
|
||||||
type aProgram struct {
|
type aProgram struct {
|
||||||
ctx llvm.Context
|
ctx llvm.Context
|
||||||
typs typeutil.Map
|
typs typeutil.Map // rawType -> Type
|
||||||
// sizs types.Sizes
|
gocvt goTypes
|
||||||
|
|
||||||
rt *types.Package
|
rt *types.Package
|
||||||
rtget func() *types.Package
|
rtget func() *types.Package
|
||||||
@@ -152,7 +154,7 @@ func NewProgram(target *Target) Program {
|
|||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
ctx.Finalize()
|
ctx.Finalize()
|
||||||
*/
|
*/
|
||||||
return &aProgram{ctx: ctx, target: target, td: td}
|
return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRuntime sets the runtime.
|
// SetRuntime sets the runtime.
|
||||||
@@ -180,11 +182,13 @@ func (p Program) runtime() *types.Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtNamed(name string) *types.Named {
|
func (p Program) rtNamed(name string) *types.Named {
|
||||||
return p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
t := p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
||||||
|
t, _ = p.gocvt.cvtNamed(t)
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtType(name string) Type {
|
func (p Program) rtType(name string) Type {
|
||||||
return p.Type(p.rtNamed(name))
|
return p.rawType(p.rtNamed(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtIface() llvm.Type {
|
func (p Program) rtIface() llvm.Type {
|
||||||
@@ -220,23 +224,24 @@ func (p Program) NewPackage(name, pkgPath string) Package {
|
|||||||
mod := p.ctx.NewModule(pkgPath)
|
mod := p.ctx.NewModule(pkgPath)
|
||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
// mod.Finalize()
|
// mod.Finalize()
|
||||||
fns := make(map[string]Function)
|
|
||||||
gbls := make(map[string]Global)
|
gbls := make(map[string]Global)
|
||||||
|
fns := make(map[string]Function)
|
||||||
|
stubs := make(map[string]Function)
|
||||||
p.needRuntime = false
|
p.needRuntime = false
|
||||||
return &aPackage{mod, fns, gbls, p}
|
return &aPackage{mod, gbls, fns, stubs, p}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Void returns void type.
|
// Void returns void type.
|
||||||
func (p Program) Void() Type {
|
func (p Program) Void() Type {
|
||||||
if p.voidTy == nil {
|
if p.voidTy == nil {
|
||||||
p.voidTy = &aType{p.tyVoid(), types.Typ[types.Invalid], vkInvalid}
|
p.voidTy = &aType{p.tyVoid(), rawType{types.Typ[types.Invalid]}, vkInvalid}
|
||||||
}
|
}
|
||||||
return p.voidTy
|
return p.voidTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) VoidPtr() Type {
|
func (p Program) VoidPtr() Type {
|
||||||
if p.voidPtr == nil {
|
if p.voidPtr == nil {
|
||||||
p.voidPtr = p.Type(types.Typ[types.UnsafePointer])
|
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
|
||||||
}
|
}
|
||||||
return p.voidPtr
|
return p.voidPtr
|
||||||
}
|
}
|
||||||
@@ -244,21 +249,21 @@ func (p Program) VoidPtr() Type {
|
|||||||
// Bool returns bool type.
|
// Bool returns bool type.
|
||||||
func (p Program) Bool() Type {
|
func (p Program) Bool() Type {
|
||||||
if p.boolTy == nil {
|
if p.boolTy == nil {
|
||||||
p.boolTy = p.Type(types.Typ[types.Bool])
|
p.boolTy = p.rawType(types.Typ[types.Bool])
|
||||||
}
|
}
|
||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) CStr() Type {
|
func (p Program) CStr() Type {
|
||||||
if p.cstrTy == nil { // *int8
|
if p.cstrTy == nil { // *int8
|
||||||
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
|
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
|
||||||
}
|
}
|
||||||
return p.cstrTy
|
return p.cstrTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) String() Type {
|
func (p Program) String() Type {
|
||||||
if p.stringTy == nil {
|
if p.stringTy == nil {
|
||||||
p.stringTy = p.Type(types.Typ[types.String])
|
p.stringTy = p.rawType(types.Typ[types.String])
|
||||||
}
|
}
|
||||||
return p.stringTy
|
return p.stringTy
|
||||||
}
|
}
|
||||||
@@ -266,7 +271,7 @@ func (p Program) String() Type {
|
|||||||
// Any returns any type.
|
// Any returns any type.
|
||||||
func (p Program) Any() Type {
|
func (p Program) Any() Type {
|
||||||
if p.anyTy == nil {
|
if p.anyTy == nil {
|
||||||
p.anyTy = p.Type(tyAny)
|
p.anyTy = p.rawType(tyAny)
|
||||||
}
|
}
|
||||||
return p.anyTy
|
return p.anyTy
|
||||||
}
|
}
|
||||||
@@ -274,7 +279,7 @@ func (p Program) Any() Type {
|
|||||||
// Int returns int type.
|
// Int returns int type.
|
||||||
func (p Program) Int() Type {
|
func (p Program) Int() Type {
|
||||||
if p.intTy == nil {
|
if p.intTy == nil {
|
||||||
p.intTy = p.Type(types.Typ[types.Int])
|
p.intTy = p.rawType(types.Typ[types.Int])
|
||||||
}
|
}
|
||||||
return p.intTy
|
return p.intTy
|
||||||
}
|
}
|
||||||
@@ -282,7 +287,7 @@ func (p Program) Int() Type {
|
|||||||
// Uintptr returns uintptr type.
|
// Uintptr returns uintptr type.
|
||||||
func (p Program) Uintptr() Type {
|
func (p Program) Uintptr() Type {
|
||||||
if p.uintptrTy == nil {
|
if p.uintptrTy == nil {
|
||||||
p.uintptrTy = p.Type(types.Typ[types.Uintptr])
|
p.uintptrTy = p.rawType(types.Typ[types.Uintptr])
|
||||||
}
|
}
|
||||||
return p.uintptrTy
|
return p.uintptrTy
|
||||||
}
|
}
|
||||||
@@ -290,7 +295,7 @@ func (p Program) Uintptr() Type {
|
|||||||
// Float64 returns float64 type.
|
// Float64 returns float64 type.
|
||||||
func (p Program) Float64() Type {
|
func (p Program) Float64() Type {
|
||||||
if p.f64Ty == nil {
|
if p.f64Ty == nil {
|
||||||
p.f64Ty = p.Type(types.Typ[types.Float64])
|
p.f64Ty = p.rawType(types.Typ[types.Float64])
|
||||||
}
|
}
|
||||||
return p.f64Ty
|
return p.f64Ty
|
||||||
}
|
}
|
||||||
@@ -307,9 +312,10 @@ func (p Program) Float64() Type {
|
|||||||
// and unspecified other things too.
|
// and unspecified other things too.
|
||||||
type aPackage struct {
|
type aPackage struct {
|
||||||
mod llvm.Module
|
mod llvm.Module
|
||||||
fns map[string]Function
|
|
||||||
vars map[string]Global
|
vars map[string]Global
|
||||||
prog Program
|
fns map[string]Function
|
||||||
|
stubs map[string]Function
|
||||||
|
Prog Program
|
||||||
}
|
}
|
||||||
|
|
||||||
type Package = *aPackage
|
type Package = *aPackage
|
||||||
@@ -322,8 +328,8 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// NewVar creates a new global variable.
|
// NewVar creates a new global variable.
|
||||||
func (p Package) NewVar(name string, typ types.Type) Global {
|
func (p Package) NewVar(name string, typ types.Type, bg Background) Global {
|
||||||
t := p.prog.Type(typ)
|
t := p.Prog.Type(typ, bg)
|
||||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||||
ret := &aGlobal{Expr{gbl, t}}
|
ret := &aGlobal{Expr{gbl, t}}
|
||||||
p.vars[name] = ret
|
p.vars[name] = ret
|
||||||
@@ -336,28 +342,70 @@ func (p Package) VarOf(name string) Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewFunc creates a new function.
|
// NewFunc creates a new function.
|
||||||
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function {
|
||||||
|
return p.NewFuncEx(name, sig, bg, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFuncEx creates a new function.
|
||||||
|
func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool) Function {
|
||||||
if v, ok := p.fns[name]; ok {
|
if v, ok := p.fns[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
t := p.prog.llvmFuncDecl(sig)
|
t := p.Prog.FuncDecl(sig, bg)
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars)
|
||||||
|
}
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
ret := newFunction(fn, t, p, p.prog)
|
ret := newFunction(fn, t, p, p.Prog, hasFreeVars)
|
||||||
p.fns[name] = ret
|
p.fns[name] = ret
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Package) rtFunc(fnName string) Expr {
|
||||||
|
fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
||||||
|
name := FullName(fn.Pkg(), fnName)
|
||||||
|
sig := fn.Type().(*types.Signature)
|
||||||
|
return p.NewFunc(name, sig, InGo).Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
||||||
|
name := v.impl.Name()
|
||||||
|
prog := b.Prog
|
||||||
|
nilVal := prog.Null(prog.VoidPtr()).impl
|
||||||
|
if fn, ok := p.stubs[name]; ok {
|
||||||
|
v = fn.Expr
|
||||||
|
} else {
|
||||||
|
sig := v.raw.Type.(*types.Signature)
|
||||||
|
n := sig.Params().Len()
|
||||||
|
nret := sig.Results().Len()
|
||||||
|
ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer])
|
||||||
|
sig = FuncAddCtx(ctx, sig)
|
||||||
|
fn := p.NewFunc(ClosureStub+name, sig, InC)
|
||||||
|
fn.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
|
args := make([]Expr, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
args[i] = fn.Param(i + 1)
|
||||||
|
}
|
||||||
|
b := fn.MakeBody(1)
|
||||||
|
call := b.Call(v, args...)
|
||||||
|
call.impl.SetTailCall(true)
|
||||||
|
switch nret {
|
||||||
|
case 0:
|
||||||
|
b.impl.CreateRetVoid()
|
||||||
|
default: // TODO(xsw): support multiple return values
|
||||||
|
b.impl.CreateRet(call.impl)
|
||||||
|
}
|
||||||
|
p.stubs[name] = fn
|
||||||
|
v = fn.Expr
|
||||||
|
}
|
||||||
|
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
|
||||||
|
}
|
||||||
|
|
||||||
// FuncOf returns a function by name.
|
// FuncOf returns a function by name.
|
||||||
func (p Package) FuncOf(name string) Function {
|
func (p Package) FuncOf(name string) Function {
|
||||||
return p.fns[name]
|
return p.fns[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) rtFunc(fnName string) Expr {
|
|
||||||
fn := p.prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
|
||||||
name := FullName(fn.Pkg(), fnName)
|
|
||||||
return p.NewFunc(name, fn.Type().(*types.Signature)).Expr
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// String returns a string representation of the package.
|
// String returns a string representation of the package.
|
||||||
|
|||||||
@@ -25,12 +25,15 @@ import (
|
|||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
func TestClosureCtx(t *testing.T) {
|
||||||
func TestMakeInterface(t *testing.T) {
|
defer func() {
|
||||||
var b Builder
|
if r := recover(); r == nil {
|
||||||
b.MakeInterface(types.NewInterfaceType(nil, nil), Expr{}, true).Do(true)
|
t.Log("closureCtx: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var f aFunction
|
||||||
|
f.closureCtx(nil)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
func TestTypes(t *testing.T) {
|
func TestTypes(t *testing.T) {
|
||||||
ctx := llvm.NewContext()
|
ctx := llvm.NewContext()
|
||||||
@@ -52,36 +55,25 @@ func TestIndexType(t *testing.T) {
|
|||||||
indexType(types.Typ[types.Int])
|
indexType(types.Typ[types.Int])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCvtCType(t *testing.T) {
|
func TestCvtType(t *testing.T) {
|
||||||
test := func(typ types.Type) {
|
gt := newGoTypes()
|
||||||
|
callback := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
|
params := types.NewTuple(types.NewParam(0, nil, "", callback))
|
||||||
|
sig := types.NewSignatureType(nil, nil, nil, params, nil, false)
|
||||||
|
ret1 := gt.cvtFunc(sig, nil)
|
||||||
|
if ret1 == sig {
|
||||||
|
t.Fatal("cvtFunc failed")
|
||||||
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r == nil {
|
if r := recover(); r == nil {
|
||||||
t.Log("cvtCType: no error?")
|
t.Log("cvtType: no error?")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
cvtCType(typ)
|
gt.cvtType(nil)
|
||||||
}
|
|
||||||
test(types.NewInterfaceType(nil, nil))
|
|
||||||
|
|
||||||
a := types.NewTypeName(0, nil, "a", nil)
|
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
|
||||||
named := types.NewNamed(a, sig, nil)
|
|
||||||
test(named)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCFuncPtr(t *testing.T) {
|
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
|
||||||
csig := (*CFuncPtr)(sig)
|
|
||||||
_ = csig.String()
|
|
||||||
if csig.Underlying() != sig {
|
|
||||||
t.Fatal("TestCFuncPtr failed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserdefExpr(t *testing.T) {
|
func TestUserdefExpr(t *testing.T) {
|
||||||
a := delayExprTy(nil)
|
|
||||||
b := &phisExprTy{}
|
b := &phisExprTy{}
|
||||||
_ = a.String()
|
|
||||||
_ = b.String()
|
_ = b.String()
|
||||||
test := func(a types.Type) {
|
test := func(a types.Type) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -91,7 +83,6 @@ func TestUserdefExpr(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
a.Underlying()
|
a.Underlying()
|
||||||
}
|
}
|
||||||
test(a)
|
|
||||||
test(b)
|
test(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +109,9 @@ func assertPkg(t *testing.T, p Package, expected string) {
|
|||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
a := pkg.NewVar("a", types.Typ[types.Int])
|
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
||||||
a.Init(prog.Val(100))
|
a.Init(prog.Val(100))
|
||||||
b := pkg.NewVar("b", types.Typ[types.Int])
|
b := pkg.NewVar("b", types.Typ[types.Int], InGo)
|
||||||
b.Init(a.Expr)
|
b.Init(a.Expr)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -135,7 +126,7 @@ func TestConst(t *testing.T) {
|
|||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Bool]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Bool]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, rets, false)
|
||||||
b := pkg.NewFunc("fn", sig).MakeBody(1)
|
b := pkg.NewFunc("fn", sig, InGo).MakeBody(1)
|
||||||
b.Return(b.Const(constant.MakeBool(true), prog.Bool()))
|
b.Return(b.Const(constant.MakeBool(true), prog.Bool()))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -152,7 +143,7 @@ func TestStruct(t *testing.T) {
|
|||||||
|
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
pkg.NewVar("a", empty)
|
pkg.NewVar("a", empty, InGo)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
@@ -169,7 +160,7 @@ func TestNamedStruct(t *testing.T) {
|
|||||||
|
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
pkg.NewVar("a", empty)
|
pkg.NewVar("a", empty, InGo)
|
||||||
if pkg.VarOf("a") == nil {
|
if pkg.VarOf("a") == nil {
|
||||||
t.Fatal("VarOf failed")
|
t.Fatal("VarOf failed")
|
||||||
}
|
}
|
||||||
@@ -187,7 +178,7 @@ func TestDeclFunc(t *testing.T) {
|
|||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, nil, false)
|
||||||
pkg.NewFunc("fn", sig)
|
pkg.NewFunc("fn", sig, InGo)
|
||||||
if pkg.FuncOf("fn") == nil {
|
if pkg.FuncOf("fn") == nil {
|
||||||
t.Fatal("FuncOf failed")
|
t.Fatal("FuncOf failed")
|
||||||
}
|
}
|
||||||
@@ -209,7 +200,7 @@ func TestBasicFunc(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
pkg.NewFunc("fn", sig).MakeBody(1).
|
pkg.NewFunc("fn", sig, InGo).MakeBody(1).
|
||||||
Return(prog.Val(1))
|
Return(prog.Val(1))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -229,7 +220,7 @@ func TestFuncParam(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
fn.MakeBody(1).Return(fn.Param(0))
|
fn.MakeBody(1).Return(fn.Param(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -250,12 +241,12 @@ func TestFuncCall(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
fn.MakeBody(1).
|
fn.MakeBody(1).
|
||||||
Return(prog.Val(1))
|
Return(prog.Val(1))
|
||||||
|
|
||||||
sigMain := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sigMain := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
b := pkg.NewFunc("main", sigMain).MakeBody(1)
|
b := pkg.NewFunc("main", sigMain, InGo).MakeBody(1)
|
||||||
b.Call(fn.Expr, prog.Val(1), prog.Val(1.2))
|
b.Call(fn.Expr, prog.Val(1), prog.Val(1.2))
|
||||||
b.Return()
|
b.Return()
|
||||||
|
|
||||||
@@ -284,8 +275,8 @@ func TestFuncMultiRet(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "c", types.Typ[types.Int]),
|
types.NewVar(0, nil, "c", types.Typ[types.Int]),
|
||||||
types.NewVar(0, nil, "d", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "d", types.Typ[types.Float64]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
a := pkg.NewVar("a", types.Typ[types.Int])
|
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
b.Return(a.Expr, fn.Param(0))
|
b.Return(a.Expr, fn.Param(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
@@ -305,7 +296,7 @@ func TestJump(t *testing.T) {
|
|||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
fn := pkg.NewFunc("loop", sig)
|
fn := pkg.NewFunc("loop", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
b.Jump(fn.Block(0))
|
b.Jump(fn.Block(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
@@ -324,7 +315,7 @@ func TestIf(t *testing.T) {
|
|||||||
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(3)
|
b := fn.MakeBody(3)
|
||||||
iftrue := fn.Block(1)
|
iftrue := fn.Block(1)
|
||||||
iffalse := fn.Block(2)
|
iffalse := fn.Block(2)
|
||||||
@@ -359,7 +350,7 @@ func TestPrintf(t *testing.T) {
|
|||||||
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
pkg.NewFunc("printf", sig)
|
pkg.NewFunc("printf", sig, InGo)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
@@ -375,7 +366,7 @@ func TestBinOp(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
ret := b.BinOp(token.ADD, fn.Param(0), prog.Val(1))
|
ret := b.BinOp(token.ADD, fn.Param(0), prog.Val(1))
|
||||||
b.Return(ret)
|
b.Return(ret)
|
||||||
@@ -398,7 +389,7 @@ func TestUnOp(t *testing.T) {
|
|||||||
)
|
)
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
ptr := fn.Param(0)
|
ptr := fn.Param(0)
|
||||||
val := b.UnOp(token.MUL, ptr)
|
val := b.UnOp(token.MUL, ptr)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (p BasicBlock) Index() int {
|
|||||||
|
|
||||||
type aBuilder struct {
|
type aBuilder struct {
|
||||||
impl llvm.Builder
|
impl llvm.Builder
|
||||||
fn Function
|
Func Function
|
||||||
Prog Program
|
Prog Program
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ type Builder = *aBuilder
|
|||||||
|
|
||||||
// SetBlock sets the current block to the specified basic block.
|
// SetBlock sets the current block to the specified basic block.
|
||||||
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
||||||
if b.fn != blk.fn {
|
if b.Func != blk.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -74,7 +74,7 @@ func (b Builder) Panic(v Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Panic %v\n", v.impl)
|
log.Printf("Panic %v\n", v.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
b.Call(pkg.rtFunc("TracePanic"), v)
|
b.Call(pkg.rtFunc("TracePanic"), v)
|
||||||
b.impl.CreateUnreachable()
|
b.impl.CreateUnreachable()
|
||||||
}
|
}
|
||||||
@@ -101,16 +101,18 @@ func (b Builder) Return(results ...Expr) {
|
|||||||
case 0:
|
case 0:
|
||||||
b.impl.CreateRetVoid()
|
b.impl.CreateRetVoid()
|
||||||
case 1:
|
case 1:
|
||||||
b.impl.CreateRet(results[0].impl)
|
raw := b.Func.raw.Type.(*types.Signature).Results().At(0).Type()
|
||||||
|
ret := checkExpr(results[0], raw, b)
|
||||||
|
b.impl.CreateRet(ret.impl)
|
||||||
default:
|
default:
|
||||||
tret := b.fn.t.(*types.Signature).Results()
|
tret := b.Func.raw.Type.(*types.Signature).Results()
|
||||||
b.impl.CreateAggregateRet(llvmValues(results, tret, b))
|
b.impl.CreateAggregateRet(llvmParams(0, results, tret, b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump emits a jump instruction.
|
// Jump emits a jump instruction.
|
||||||
func (b Builder) Jump(jmpb BasicBlock) {
|
func (b Builder) Jump(jmpb BasicBlock) {
|
||||||
if b.fn != jmpb.fn {
|
if b.Func != jmpb.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -121,7 +123,7 @@ func (b Builder) Jump(jmpb BasicBlock) {
|
|||||||
|
|
||||||
// If emits an if instruction.
|
// If emits an if instruction.
|
||||||
func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
|
func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
|
||||||
if b.fn != thenb.fn || b.fn != elseb.fn {
|
if b.Func != thenb.fn || b.Func != elseb.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
|
|||||||
162
ssa/type.go
162
ssa/type.go
@@ -18,7 +18,6 @@ package ssa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
@@ -41,12 +40,11 @@ const (
|
|||||||
vkString
|
vkString
|
||||||
vkBool
|
vkBool
|
||||||
vkPtr
|
vkPtr
|
||||||
vkFuncDecl // func decl
|
vkFuncDecl
|
||||||
vkFuncPtr // func ptr in C
|
vkFuncPtr
|
||||||
vkClosure // func ptr in Go
|
vkClosure
|
||||||
vkTuple
|
vkTuple
|
||||||
vkDelayExpr = -1
|
vkPhisExpr = -1
|
||||||
vkPhisExpr = -2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -66,32 +64,25 @@ func indexType(t types.Type) types.Type {
|
|||||||
panic("index: type doesn't support index - " + t.String())
|
panic("index: type doesn't support index - " + t.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert method to func
|
|
||||||
func methodToFunc(sig *types.Signature) *types.Signature {
|
|
||||||
if recv := sig.Recv(); recv != nil {
|
|
||||||
tParams := sig.Params()
|
|
||||||
nParams := tParams.Len()
|
|
||||||
params := make([]*types.Var, nParams+1)
|
|
||||||
params[0] = recv
|
|
||||||
for i := 0; i < nParams; i++ {
|
|
||||||
params[i+1] = tParams.At(i)
|
|
||||||
}
|
|
||||||
return types.NewSignatureType(
|
|
||||||
nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
|
|
||||||
}
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type rawType struct {
|
||||||
|
types.Type
|
||||||
|
}
|
||||||
|
|
||||||
type aType struct {
|
type aType struct {
|
||||||
ll llvm.Type
|
ll llvm.Type
|
||||||
t types.Type
|
raw rawType
|
||||||
kind valueKind // value kind of llvm.Type
|
kind valueKind // value kind of llvm.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type = *aType
|
type Type = *aType
|
||||||
|
|
||||||
|
// RawType returns the raw type.
|
||||||
|
func (t Type) RawType() types.Type {
|
||||||
|
return t.raw.Type
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// how to generate platform independent code?
|
// how to generate platform independent code?
|
||||||
func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
||||||
@@ -103,42 +94,37 @@ func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Slice(typ Type) Type {
|
func (p Program) Slice(typ Type) Type {
|
||||||
return p.Type(types.NewSlice(typ.t))
|
return p.rawType(types.NewSlice(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Pointer(typ Type) Type {
|
func (p Program) Pointer(typ Type) Type {
|
||||||
return p.Type(types.NewPointer(typ.t))
|
return p.rawType(types.NewPointer(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Elem(typ Type) Type {
|
func (p Program) Elem(typ Type) Type {
|
||||||
elem := typ.t.(*types.Pointer).Elem()
|
elem := typ.raw.Type.(*types.Pointer).Elem()
|
||||||
return p.Type(elem)
|
return p.rawType(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Index(typ Type) Type {
|
func (p Program) Index(typ Type) Type {
|
||||||
return p.Type(indexType(typ.t))
|
return p.rawType(indexType(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Field(typ Type, i int) Type {
|
func (p Program) Field(typ Type, i int) Type {
|
||||||
tunder := typ.t.Underlying()
|
tunder := typ.raw.Type.Underlying()
|
||||||
tfld := tunder.(*types.Struct).Field(i).Type()
|
tfld := tunder.(*types.Struct).Field(i).Type()
|
||||||
return p.Type(tfld)
|
return p.rawType(tfld)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Type(typ types.Type) Type {
|
func (p Program) rawType(raw types.Type) Type {
|
||||||
if v := p.typs.At(typ); v != nil {
|
if v := p.typs.At(raw); v != nil {
|
||||||
return v.(Type)
|
return v.(Type)
|
||||||
}
|
}
|
||||||
ret := p.toLLVMType(typ)
|
ret := p.toType(raw)
|
||||||
p.typs.Set(typ, ret)
|
p.typs.Set(raw, ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) llvmFuncDecl(sig *types.Signature) Type {
|
|
||||||
sig = methodToFunc(sig)
|
|
||||||
return p.toLLVMFunc(sig, false, true) // don't save func decl to cache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Program) tyVoidPtr() llvm.Type {
|
func (p Program) tyVoidPtr() llvm.Type {
|
||||||
if p.voidPtrTy.IsNil() {
|
if p.voidPtrTy.IsNil() {
|
||||||
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
||||||
@@ -202,8 +188,9 @@ func (p Program) tyInt64() llvm.Type {
|
|||||||
return p.int64Type
|
return p.int64Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMType(typ types.Type) Type {
|
func (p Program) toType(raw types.Type) Type {
|
||||||
switch t := typ.(type) {
|
typ := rawType{raw}
|
||||||
|
switch t := raw.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case types.Int:
|
case types.Int:
|
||||||
@@ -240,7 +227,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
return &aType{p.tyVoidPtr(), typ, vkPtr}
|
return &aType{p.tyVoidPtr(), typ, vkPtr}
|
||||||
}
|
}
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.rawType(t.Elem())
|
||||||
return &aType{llvm.PointerType(elem.ll, 0), typ, vkPtr}
|
return &aType{llvm.PointerType(elem.ll, 0), typ, vkPtr}
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return &aType{p.rtIface(), typ, vkInvalid}
|
return &aType{p.rtIface(), typ, vkInvalid}
|
||||||
@@ -249,39 +236,52 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
case *types.Map:
|
case *types.Map:
|
||||||
return &aType{p.rtMap(), typ, vkInvalid}
|
return &aType{p.rtMap(), typ, vkInvalid}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
return p.toLLVMStruct(t)
|
ll, kind := p.toLLVMStruct(t)
|
||||||
|
return &aType{ll, typ, kind}
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
return p.toLLVMNamed(t)
|
return p.toNamed(t)
|
||||||
case *types.Signature:
|
case *types.Signature: // represents a C function pointer in raw type
|
||||||
return p.toLLVMFunc(t, false, false)
|
return &aType{p.toLLVMFuncPtr(t), typ, vkFuncPtr}
|
||||||
case *CFuncPtr:
|
|
||||||
return p.toLLVMFunc((*types.Signature)(t), true, false)
|
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.rawType(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("toLLVMType: todo - %T\n", typ))
|
panic(fmt.Sprintf("toLLVMType: todo - %T\n", typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
|
func (p Program) toLLVMNamedStruct(name string, raw *types.Struct) llvm.Type {
|
||||||
t := p.ctx.StructCreateNamed(name)
|
t := p.ctx.StructCreateNamed(name)
|
||||||
fields := p.toLLVMFields(typ)
|
fields := p.toLLVMFields(raw)
|
||||||
t.StructSetBody(fields, false)
|
t.StructSetBody(fields, false)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMStruct(typ *types.Struct) Type {
|
func (p Program) toLLVMStruct(raw *types.Struct) (ret llvm.Type, kind valueKind) {
|
||||||
fields := p.toLLVMFields(typ)
|
fields := p.toLLVMFields(raw)
|
||||||
return &aType{p.ctx.StructType(fields, false), typ, vkInvalid}
|
ret = p.ctx.StructType(fields, false)
|
||||||
|
if isClosure(raw) {
|
||||||
|
kind = vkClosure
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMFields(typ *types.Struct) (fields []llvm.Type) {
|
func isClosure(raw *types.Struct) bool {
|
||||||
n := typ.NumFields()
|
n := raw.NumFields()
|
||||||
|
if n == 2 {
|
||||||
|
if _, ok := raw.Field(0).Type().(*types.Signature); ok {
|
||||||
|
return raw.Field(1).Type() == types.Typ[types.UnsafePointer]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) toLLVMFields(raw *types.Struct) (fields []llvm.Type) {
|
||||||
|
n := raw.NumFields()
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
fields = make([]llvm.Type, n)
|
fields = make([]llvm.Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
fields[i] = p.Type(typ.Field(i).Type()).ll
|
fields[i] = p.rawType(raw.Field(i).Type()).ll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -295,14 +295,13 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
|
|||||||
if n > 0 {
|
if n > 0 {
|
||||||
ret = make([]llvm.Type, n)
|
ret = make([]llvm.Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ret[i] = p.Type(t.At(i).Type()).ll
|
ret[i] = p.rawType(t.At(i).Type()).ll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
func (p Program) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||||
if isDecl || inC {
|
|
||||||
tParams := sig.Params()
|
tParams := sig.Params()
|
||||||
n := tParams.Len()
|
n := tParams.Len()
|
||||||
hasVArg := HasVArg(tParams, n)
|
hasVArg := HasVArg(tParams, n)
|
||||||
@@ -312,52 +311,41 @@ func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
|||||||
params := p.toLLVMTypes(tParams, n)
|
params := p.toLLVMTypes(tParams, n)
|
||||||
out := sig.Results()
|
out := sig.Results()
|
||||||
var ret llvm.Type
|
var ret llvm.Type
|
||||||
var kind valueKind
|
|
||||||
switch nret := out.Len(); nret {
|
switch nret := out.Len(); nret {
|
||||||
case 0:
|
case 0:
|
||||||
ret = p.tyVoid()
|
ret = p.tyVoid()
|
||||||
case 1:
|
case 1:
|
||||||
ret = p.Type(out.At(0).Type()).ll
|
ret = p.rawType(out.At(0).Type()).ll
|
||||||
default:
|
default:
|
||||||
ret = p.toLLVMTuple(out)
|
ret = p.toLLVMTuple(out)
|
||||||
}
|
}
|
||||||
ft := llvm.FunctionType(ret, params, hasVArg)
|
return llvm.FunctionType(ret, params, hasVArg)
|
||||||
if isDecl {
|
|
||||||
kind = vkFuncDecl
|
|
||||||
} else {
|
|
||||||
ft = llvm.PointerType(ft, 0)
|
|
||||||
kind = vkFuncPtr
|
|
||||||
}
|
|
||||||
return &aType{ft, sig, kind}
|
|
||||||
}
|
|
||||||
flds := []*types.Var{
|
|
||||||
types.NewField(token.NoPos, nil, "f", (*CFuncPtr)(sig), false),
|
|
||||||
types.NewField(token.NoPos, nil, "data", types.Typ[types.UnsafePointer], false),
|
|
||||||
}
|
|
||||||
t := types.NewStruct(flds, nil)
|
|
||||||
ll := p.ctx.StructType(p.toLLVMFields(t), false)
|
|
||||||
return &aType{ll, t, vkClosure}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) retType(sig *types.Signature) Type {
|
func (p Program) toLLVMFuncPtr(sig *types.Signature) llvm.Type {
|
||||||
out := sig.Results()
|
ft := p.toLLVMFunc(sig)
|
||||||
|
return llvm.PointerType(ft, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) retType(raw *types.Signature) Type {
|
||||||
|
out := raw.Results()
|
||||||
switch n := out.Len(); n {
|
switch n := out.Len(); n {
|
||||||
case 0:
|
case 0:
|
||||||
return p.Void()
|
return p.Void()
|
||||||
case 1:
|
case 1:
|
||||||
return p.Type(out.At(0).Type())
|
return p.rawType(out.At(0).Type())
|
||||||
default:
|
default:
|
||||||
return &aType{p.toLLVMTuple(out), out, vkTuple}
|
return &aType{p.toLLVMTuple(out), rawType{out}, vkTuple}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMNamed(typ *types.Named) Type {
|
func (p Program) toNamed(raw *types.Named) Type {
|
||||||
switch t := typ.Underlying().(type) {
|
switch t := raw.Underlying().(type) {
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
name := NameOf(typ)
|
name := NameOf(raw)
|
||||||
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
return &aType{p.toLLVMNamedStruct(name, t), rawType{raw}, vkInvalid}
|
||||||
default:
|
default:
|
||||||
return p.Type(t)
|
return p.rawType(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
140
ssa/type_c.go
140
ssa/type_c.go
@@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ssa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/types"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const (
|
|
||||||
NameValist = "__llgo_va_list"
|
|
||||||
)
|
|
||||||
|
|
||||||
func VArg() *types.Var {
|
|
||||||
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsVArg(arg *types.Var) bool {
|
|
||||||
return arg.Name() == NameValist
|
|
||||||
}
|
|
||||||
|
|
||||||
func HasVArg(t *types.Tuple, n int) bool {
|
|
||||||
return n > 0 && IsVArg(t.At(n-1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// CFuncPtr represents a C function pointer.
|
|
||||||
type CFuncPtr types.Signature
|
|
||||||
|
|
||||||
func (t *CFuncPtr) String() string { return (*types.Signature)(t).String() }
|
|
||||||
func (t *CFuncPtr) Underlying() types.Type { return (*types.Signature)(t) }
|
|
||||||
|
|
||||||
func (t *CFuncPtr) Hash(h typeutil.Hasher) uint32 {
|
|
||||||
return typeutil.HashSig(h, (*types.Signature)(t))*13 + 97
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// CType convert a C type into Go.
|
|
||||||
func CType(typ types.Type) types.Type {
|
|
||||||
t, _ := cvtCType(typ)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// CFuncDecl convert a C function decl into Go signature.
|
|
||||||
func CFuncDecl(sig *types.Signature) *types.Signature {
|
|
||||||
hasVArg := sig.Variadic()
|
|
||||||
params, cvt1 := cvtTuple(sig.Params(), hasVArg)
|
|
||||||
results, cvt2 := cvtTuple(sig.Results(), false)
|
|
||||||
if cvt1 || cvt2 {
|
|
||||||
return types.NewSignatureType(nil, nil, nil, params, results, hasVArg)
|
|
||||||
}
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtCType(typ types.Type) (types.Type, bool) {
|
|
||||||
switch t := typ.(type) {
|
|
||||||
case *types.Basic:
|
|
||||||
case *types.Pointer:
|
|
||||||
if elem, cvt := cvtCType(t.Elem()); cvt {
|
|
||||||
return types.NewPointer(elem), true
|
|
||||||
}
|
|
||||||
case *types.Struct:
|
|
||||||
return cvtCStruct(t)
|
|
||||||
case *types.Named:
|
|
||||||
if _, cvt := cvtCType(t.Underlying()); cvt {
|
|
||||||
panic("don't define named type")
|
|
||||||
}
|
|
||||||
case *types.Signature:
|
|
||||||
t = CFuncDecl(t)
|
|
||||||
return (*CFuncPtr)(t), true
|
|
||||||
case *types.Array:
|
|
||||||
if elem, cvt := cvtCType(t.Elem()); cvt {
|
|
||||||
return types.NewArray(elem, t.Len()), true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
return typ, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtTuple(t *types.Tuple, hasVArg bool) (*types.Tuple, bool) {
|
|
||||||
n := t.Len()
|
|
||||||
vars := make([]*types.Var, n)
|
|
||||||
needcvt := false
|
|
||||||
if hasVArg {
|
|
||||||
n--
|
|
||||||
vars[n] = t.At(n)
|
|
||||||
}
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
v := t.At(i)
|
|
||||||
if t, cvt := cvtCType(v.Type()); cvt {
|
|
||||||
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
|
|
||||||
needcvt = true
|
|
||||||
}
|
|
||||||
vars[i] = v
|
|
||||||
}
|
|
||||||
if needcvt {
|
|
||||||
return types.NewTuple(vars...), true
|
|
||||||
}
|
|
||||||
return t, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtCStruct(typ *types.Struct) (*types.Struct, bool) {
|
|
||||||
n := typ.NumFields()
|
|
||||||
flds := make([]*types.Var, n)
|
|
||||||
needcvt := false
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
f := typ.Field(i)
|
|
||||||
if t, cvt := cvtCType(f.Type()); cvt {
|
|
||||||
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
|
|
||||||
needcvt = true
|
|
||||||
}
|
|
||||||
flds[i] = f
|
|
||||||
}
|
|
||||||
if needcvt {
|
|
||||||
return types.NewStruct(flds, nil), true
|
|
||||||
}
|
|
||||||
return typ, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
255
ssa/type_cvt.go
Normal file
255
ssa/type_cvt.go
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* 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 ssa
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type goTypes struct {
|
||||||
|
typs map[unsafe.Pointer]unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGoTypes() goTypes {
|
||||||
|
typs := make(map[unsafe.Pointer]unsafe.Pointer)
|
||||||
|
return goTypes{typs}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Background int
|
||||||
|
|
||||||
|
const (
|
||||||
|
inUnknown Background = iota
|
||||||
|
InGo
|
||||||
|
InC
|
||||||
|
)
|
||||||
|
|
||||||
|
// Type convert a Go/C type into raw type.
|
||||||
|
// C type = raw type
|
||||||
|
// Go type: convert to raw type (because of closure)
|
||||||
|
func (p Program) Type(typ types.Type, bg Background) Type {
|
||||||
|
if bg == InGo {
|
||||||
|
typ, _ = p.gocvt.cvtType(typ)
|
||||||
|
}
|
||||||
|
return p.rawType(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncDecl converts a Go/C function declaration into raw type.
|
||||||
|
func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
||||||
|
if bg == InGo {
|
||||||
|
sig = p.gocvt.cvtFunc(sig, sig.Recv())
|
||||||
|
}
|
||||||
|
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closure creates a closture type for a function.
|
||||||
|
func (p Program) Closure(fn Type) Type {
|
||||||
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
|
closure := p.gocvt.cvtClosure(sig)
|
||||||
|
return p.rawType(closure)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) {
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
case *types.Pointer:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewPointer(elem), true
|
||||||
|
}
|
||||||
|
case *types.Interface:
|
||||||
|
return p.cvtInterface(t)
|
||||||
|
case *types.Slice:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewSlice(elem), true
|
||||||
|
}
|
||||||
|
case *types.Map:
|
||||||
|
key, cvt1 := p.cvtType(t.Key())
|
||||||
|
elem, cvt2 := p.cvtType(t.Elem())
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewMap(key, elem), true
|
||||||
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
return p.cvtStruct(t)
|
||||||
|
case *types.Named:
|
||||||
|
return p.cvtNamed(t)
|
||||||
|
case *types.Signature:
|
||||||
|
return p.cvtClosure(t), true
|
||||||
|
case *types.Array:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewArray(elem, t.Len()), true
|
||||||
|
}
|
||||||
|
case *types.Chan:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewChan(t.Dir(), elem), true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("cvtType: unexpected type - %T", typ))
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(t)]; ok {
|
||||||
|
raw = (*types.Named)(v)
|
||||||
|
cvt = t != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(t)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
if tund, cvt := p.cvtType(t.Underlying()); cvt {
|
||||||
|
old := t.Obj()
|
||||||
|
obj := types.NewTypeName(old.Pos(), old.Pkg(), old.Name(), nil)
|
||||||
|
return types.NewNamed(obj, tund, nil), true
|
||||||
|
}
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtClosure(sig *types.Signature) *types.Struct {
|
||||||
|
ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer])
|
||||||
|
raw := p.cvtFunc(sig, ctx)
|
||||||
|
flds := []*types.Var{
|
||||||
|
types.NewField(token.NoPos, nil, "f", raw, false),
|
||||||
|
types.NewField(token.NoPos, nil, "data", types.Typ[types.UnsafePointer], false),
|
||||||
|
}
|
||||||
|
return types.NewStruct(flds, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtFunc(sig *types.Signature, recv *types.Var) (raw *types.Signature) {
|
||||||
|
if recv != nil {
|
||||||
|
sig = FuncAddCtx(recv, sig)
|
||||||
|
}
|
||||||
|
params, cvt1 := p.cvtTuple(sig.Params())
|
||||||
|
results, cvt2 := p.cvtTuple(sig.Results())
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewSignatureType(nil, nil, nil, params, results, sig.Variadic())
|
||||||
|
}
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtTuple(t *types.Tuple) (*types.Tuple, bool) {
|
||||||
|
n := t.Len()
|
||||||
|
vars := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
v := t.At(i)
|
||||||
|
if t, cvt := p.cvtType(v.Type()); cvt {
|
||||||
|
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
vars[i] = v
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewTuple(vars...), true
|
||||||
|
}
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtExplicitMethods(typ *types.Interface) ([]*types.Func, bool) {
|
||||||
|
n := typ.NumExplicitMethods()
|
||||||
|
methods := make([]*types.Func, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
m := typ.ExplicitMethod(i)
|
||||||
|
sig := m.Type().(*types.Signature)
|
||||||
|
if raw := p.cvtFunc(sig, nil); sig != raw {
|
||||||
|
m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), raw)
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
methods[i] = m
|
||||||
|
}
|
||||||
|
return methods, needcvt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtEmbeddedTypes(typ *types.Interface) ([]types.Type, bool) {
|
||||||
|
n := typ.NumEmbeddeds()
|
||||||
|
embeddeds := make([]types.Type, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
t := typ.EmbeddedType(i)
|
||||||
|
if raw, cvt := p.cvtType(t); cvt {
|
||||||
|
t = raw
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
embeddeds[i] = t
|
||||||
|
}
|
||||||
|
return embeddeds, needcvt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtInterface(typ *types.Interface) (raw *types.Interface, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(typ)]; ok {
|
||||||
|
raw = (*types.Interface)(v)
|
||||||
|
cvt = typ != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
methods, cvt1 := p.cvtExplicitMethods(typ)
|
||||||
|
embeddeds, cvt2 := p.cvtEmbeddedTypes(typ)
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewInterfaceType(methods, embeddeds), true
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtStruct(typ *types.Struct) (raw *types.Struct, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(typ)]; ok {
|
||||||
|
raw = (*types.Struct)(v)
|
||||||
|
cvt = typ != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
n := typ.NumFields()
|
||||||
|
flds := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := typ.Field(i)
|
||||||
|
if t, cvt := p.cvtType(f.Type()); cvt {
|
||||||
|
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
flds[i] = f
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewStruct(flds, nil), true
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// FuncAddCtx adds a ctx to a function signature.
|
||||||
|
func FuncAddCtx(ctx *types.Var, sig *types.Signature) *types.Signature {
|
||||||
|
tParams := sig.Params()
|
||||||
|
nParams := tParams.Len()
|
||||||
|
params := make([]*types.Var, nParams+1)
|
||||||
|
params[0] = ctx
|
||||||
|
for i := 0; i < nParams; i++ {
|
||||||
|
params[i+1] = tParams.At(i)
|
||||||
|
}
|
||||||
|
return types.NewSignatureType(
|
||||||
|
nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
262
x/clang/ast/ast.go
Normal file
262
x/clang/ast/ast.go
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* 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 ast
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type IncludedFrom struct {
|
||||||
|
File string `json:"file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Loc struct {
|
||||||
|
Offset int64 `json:"offset,omitempty"` // 432
|
||||||
|
File string `json:"file,omitempty"` // "sqlite3.i"
|
||||||
|
Line int `json:"line,omitempty"`
|
||||||
|
PresumedFile string `json:"presumedFile,omitempty"`
|
||||||
|
PresumedLine int `json:"presumedLine,omitempty"`
|
||||||
|
Col int `json:"col,omitempty"`
|
||||||
|
TokLen int `json:"tokLen,omitempty"`
|
||||||
|
IncludedFrom *IncludedFrom `json:"includedFrom,omitempty"` // "sqlite3.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pos struct {
|
||||||
|
Offset int64 `json:"offset,omitempty"`
|
||||||
|
Col int `json:"col,omitempty"`
|
||||||
|
TokLen int `json:"tokLen,omitempty"`
|
||||||
|
IncludedFrom *IncludedFrom `json:"includedFrom,omitempty"` // "sqlite3.c"
|
||||||
|
SpellingLoc *Loc `json:"spellingLoc,omitempty"`
|
||||||
|
ExpansionLoc *Loc `json:"expansionLoc,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Range struct {
|
||||||
|
Begin Pos `json:"begin"`
|
||||||
|
End Pos `json:"end"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type ID string
|
||||||
|
|
||||||
|
type Kind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TranslationUnitDecl Kind = "TranslationUnitDecl"
|
||||||
|
TypedefType Kind = "TypedefType"
|
||||||
|
TypedefDecl Kind = "TypedefDecl"
|
||||||
|
ElaboratedType Kind = "ElaboratedType"
|
||||||
|
BuiltinType Kind = "BuiltinType"
|
||||||
|
ConstantArrayType Kind = "ConstantArrayType"
|
||||||
|
IncompleteArrayType Kind = "IncompleteArrayType"
|
||||||
|
PointerType Kind = "PointerType"
|
||||||
|
RecordType Kind = "RecordType"
|
||||||
|
RecordDecl Kind = "RecordDecl"
|
||||||
|
FieldDecl Kind = "FieldDecl"
|
||||||
|
IndirectFieldDecl Kind = "IndirectFieldDecl"
|
||||||
|
VarDecl Kind = "VarDecl"
|
||||||
|
EmptyDecl Kind = "EmptyDecl"
|
||||||
|
EnumDecl Kind = "EnumDecl"
|
||||||
|
EnumConstantDecl Kind = "EnumConstantDecl"
|
||||||
|
AlwaysInlineAttr Kind = "AlwaysInlineAttr"
|
||||||
|
AsmLabelAttr Kind = "AsmLabelAttr"
|
||||||
|
AvailabilityAttr Kind = "AvailabilityAttr"
|
||||||
|
DeprecatedAttr Kind = "DeprecatedAttr"
|
||||||
|
BuiltinAttr Kind = "BuiltinAttr"
|
||||||
|
FormatAttr Kind = "FormatAttr"
|
||||||
|
FormatArgAttr Kind = "FormatArgAttr"
|
||||||
|
ColdAttr Kind = "ColdAttr"
|
||||||
|
ConstAttr Kind = "ConstAttr"
|
||||||
|
PureAttr Kind = "PureAttr"
|
||||||
|
PackedAttr Kind = "PackedAttr"
|
||||||
|
GNUInlineAttr Kind = "GNUInlineAttr"
|
||||||
|
StrictFPAttr Kind = "StrictFPAttr"
|
||||||
|
ReturnsTwiceAttr Kind = "ReturnsTwiceAttr"
|
||||||
|
RestrictAttr Kind = "RestrictAttr"
|
||||||
|
NoThrowAttr Kind = "NoThrowAttr"
|
||||||
|
NoInlineAttr Kind = "NoInlineAttr"
|
||||||
|
NoSanitizeAttr Kind = "NoSanitizeAttr"
|
||||||
|
NonNullAttr Kind = "NonNullAttr"
|
||||||
|
MayAliasAttr Kind = "MayAliasAttr"
|
||||||
|
MSAllocatorAttr Kind = "MSAllocatorAttr"
|
||||||
|
MaxFieldAlignmentAttr Kind = "MaxFieldAlignmentAttr"
|
||||||
|
WarnUnusedResultAttr Kind = "WarnUnusedResultAttr"
|
||||||
|
AllocSizeAttr Kind = "AllocSizeAttr"
|
||||||
|
AlignedAttr Kind = "AlignedAttr"
|
||||||
|
VisibilityAttr Kind = "VisibilityAttr"
|
||||||
|
C11NoReturnAttr Kind = "C11NoReturnAttr"
|
||||||
|
FunctionProtoType Kind = "FunctionProtoType"
|
||||||
|
FunctionDecl Kind = "FunctionDecl"
|
||||||
|
ParmVarDecl Kind = "ParmVarDecl"
|
||||||
|
ParenType Kind = "ParenType"
|
||||||
|
DeclStmt Kind = "DeclStmt"
|
||||||
|
CompoundStmt Kind = "CompoundStmt"
|
||||||
|
NullStmt Kind = "NullStmt"
|
||||||
|
ForStmt Kind = "ForStmt"
|
||||||
|
WhileStmt Kind = "WhileStmt"
|
||||||
|
DoStmt Kind = "DoStmt"
|
||||||
|
GotoStmt Kind = "GotoStmt"
|
||||||
|
BreakStmt Kind = "BreakStmt"
|
||||||
|
ContinueStmt Kind = "ContinueStmt"
|
||||||
|
LabelStmt Kind = "LabelStmt"
|
||||||
|
IfStmt Kind = "IfStmt"
|
||||||
|
SwitchStmt Kind = "SwitchStmt"
|
||||||
|
CaseStmt Kind = "CaseStmt"
|
||||||
|
DefaultStmt Kind = "DefaultStmt"
|
||||||
|
ReturnStmt Kind = "ReturnStmt"
|
||||||
|
GCCAsmStmt Kind = "GCCAsmStmt"
|
||||||
|
ParenExpr Kind = "ParenExpr"
|
||||||
|
CallExpr Kind = "CallExpr"
|
||||||
|
ConstantExpr Kind = "ConstantExpr"
|
||||||
|
InitListExpr Kind = "InitListExpr"
|
||||||
|
CStyleCastExpr Kind = "CStyleCastExpr"
|
||||||
|
DeclRefExpr Kind = "DeclRefExpr"
|
||||||
|
MemberExpr Kind = "MemberExpr"
|
||||||
|
ImplicitCastExpr Kind = "ImplicitCastExpr"
|
||||||
|
ImplicitValueInitExpr Kind = "ImplicitValueInitExpr"
|
||||||
|
UnaryExprOrTypeTraitExpr Kind = "UnaryExprOrTypeTraitExpr"
|
||||||
|
OffsetOfExpr Kind = "OffsetOfExpr"
|
||||||
|
ArraySubscriptExpr Kind = "ArraySubscriptExpr"
|
||||||
|
AtomicExpr Kind = "AtomicExpr"
|
||||||
|
VAArgExpr Kind = "VAArgExpr"
|
||||||
|
CompoundAssignOperator Kind = "CompoundAssignOperator"
|
||||||
|
BinaryOperator Kind = "BinaryOperator"
|
||||||
|
UnaryOperator Kind = "UnaryOperator"
|
||||||
|
ConditionalOperator Kind = "ConditionalOperator"
|
||||||
|
CompoundLiteralExpr Kind = "CompoundLiteralExpr"
|
||||||
|
PredefinedExpr Kind = "PredefinedExpr"
|
||||||
|
CharacterLiteral Kind = "CharacterLiteral"
|
||||||
|
IntegerLiteral Kind = "IntegerLiteral"
|
||||||
|
StringLiteral Kind = "StringLiteral"
|
||||||
|
FloatingLiteral Kind = "FloatingLiteral"
|
||||||
|
ImaginaryLiteral Kind = "ImaginaryLiteral"
|
||||||
|
AllocAlignAttr Kind = "AllocAlignAttr"
|
||||||
|
DisableTailCallsAttr Kind = "DisableTailCallsAttr"
|
||||||
|
StaticAssertDecl Kind = "StaticAssertDecl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValueCategory string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RValue ValueCategory = "rvalue"
|
||||||
|
PRValue ValueCategory = "prvalue"
|
||||||
|
LValue ValueCategory = "lvalue"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CC string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CDecl CC = "cdecl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StorageClass string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Static StorageClass = "static"
|
||||||
|
Extern StorageClass = "extern"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CastKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
LValueToRValue CastKind = "LValueToRValue"
|
||||||
|
BitCast CastKind = "BitCast"
|
||||||
|
FloatingToIntegral CastKind = "FloatingToIntegral"
|
||||||
|
FloatingComplexCast CastKind = "FloatingComplexCast"
|
||||||
|
FloatingRealToComplex CastKind = "FloatingRealToComplex"
|
||||||
|
IntegralRealToComplex CastKind = "IntegralRealToComplex"
|
||||||
|
FloatingCast CastKind = "FloatingCast"
|
||||||
|
IntegralCast CastKind = "IntegralCast"
|
||||||
|
IntegralToPointer CastKind = "IntegralToPointer"
|
||||||
|
IntegralToFloating CastKind = "IntegralToFloating"
|
||||||
|
IntegralToBoolean CastKind = "IntegralToBoolean"
|
||||||
|
FloatingToBoolean CastKind = "FloatingToBoolean"
|
||||||
|
IntegralComplexToBoolean CastKind = "IntegralComplexToBoolean"
|
||||||
|
FloatingComplexToBoolean CastKind = "FloatingComplexToBoolean"
|
||||||
|
PointerToBoolean CastKind = "PointerToBoolean"
|
||||||
|
PointerToIntegral CastKind = "PointerToIntegral"
|
||||||
|
FunctionToPointerDecay CastKind = "FunctionToPointerDecay"
|
||||||
|
ArrayToPointerDecay CastKind = "ArrayToPointerDecay"
|
||||||
|
BuiltinFnToFnPtr CastKind = "BuiltinFnToFnPtr"
|
||||||
|
ToVoid CastKind = "ToVoid"
|
||||||
|
NullToPointer CastKind = "NullToPointer"
|
||||||
|
NoOp CastKind = "NoOp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// OpCode can be:
|
||||||
|
// + - * / || >= -- ++ etc
|
||||||
|
OpCode string
|
||||||
|
)
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
// QualType can be:
|
||||||
|
// unsigned int
|
||||||
|
// struct ConstantString
|
||||||
|
// volatile uint32_t
|
||||||
|
// int (*)(void *, int, char **, char **)
|
||||||
|
// int (*)(const char *, ...)
|
||||||
|
// int (*)(void)
|
||||||
|
// const char *restrict
|
||||||
|
// const char [7]
|
||||||
|
// char *
|
||||||
|
// void
|
||||||
|
// ...
|
||||||
|
QualType string `json:"qualType"`
|
||||||
|
DesugaredQualType string `json:"desugaredQualType,omitempty"`
|
||||||
|
TypeAliasDeclID ID `json:"typeAliasDeclId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
ID ID `json:"id,omitempty"`
|
||||||
|
Kind Kind `json:"kind,omitempty"`
|
||||||
|
Loc *Loc `json:"loc,omitempty"`
|
||||||
|
Range *Range `json:"range,omitempty"`
|
||||||
|
ReferencedMemberDecl ID `json:"referencedMemberDecl,omitempty"`
|
||||||
|
PreviousDecl ID `json:"previousDecl,omitempty"`
|
||||||
|
ParentDeclContextID ID `json:"parentDeclContextId,omitempty"`
|
||||||
|
IsImplicit bool `json:"isImplicit,omitempty"` // is this type implicit defined
|
||||||
|
IsReferenced bool `json:"isReferenced,omitempty"` // is this type refered or not
|
||||||
|
IsUsed bool `json:"isUsed,omitempty"` // is this variable used or not
|
||||||
|
IsArrow bool `json:"isArrow,omitempty"` // is ptr->member not obj.member
|
||||||
|
IsPostfix bool `json:"isPostfix,omitempty"`
|
||||||
|
IsPartOfExplicitCast bool `json:"isPartOfExplicitCast,omitempty"`
|
||||||
|
IsBitfield bool `json:"isBitfield,omitempty"`
|
||||||
|
Inline bool `json:"inline,omitempty"`
|
||||||
|
StorageClass StorageClass `json:"storageClass,omitempty"`
|
||||||
|
TagUsed string `json:"tagUsed,omitempty"` // struct | union
|
||||||
|
HasElse bool `json:"hasElse,omitempty"`
|
||||||
|
CompleteDefinition bool `json:"completeDefinition,omitempty"`
|
||||||
|
Complicated bool `json:"-"` // complicated statement
|
||||||
|
Variadic bool `json:"variadic,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
MangledName string `json:"mangledName,omitempty"`
|
||||||
|
Type *Type `json:"type,omitempty"`
|
||||||
|
CC CC `json:"cc,omitempty"`
|
||||||
|
Field *Node `json:"field,omitempty"`
|
||||||
|
Decl *Node `json:"decl,omitempty"`
|
||||||
|
OwnedTagDecl *Node `json:"ownedTagDecl,omitempty"`
|
||||||
|
ReferencedDecl *Node `json:"referencedDecl,omitempty"`
|
||||||
|
OpCode OpCode `json:"opcode,omitempty"`
|
||||||
|
Init string `json:"init,omitempty"`
|
||||||
|
ValueCategory ValueCategory `json:"valueCategory,omitempty"`
|
||||||
|
Value interface{} `json:"value,omitempty"`
|
||||||
|
CastKind CastKind `json:"castKind,omitempty"`
|
||||||
|
Size int `json:"size,omitempty"` // array size
|
||||||
|
Inner []*Node `json:"inner,omitempty"`
|
||||||
|
ArrayFiller []*Node `json:"array_filler,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Cmd represents a nm command.
|
// Cmd represents a clang command.
|
||||||
type Cmd struct {
|
type Cmd struct {
|
||||||
app string
|
app string
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ type Cmd struct {
|
|||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new nm command.
|
// New creates a new clang command.
|
||||||
func New(app string) *Cmd {
|
func New(app string) *Cmd {
|
||||||
if app == "" {
|
if app == "" {
|
||||||
app = "clang"
|
app = "clang"
|
||||||
|
|||||||
122
x/clang/parser/pages.go
Normal file
122
x/clang/parser/pages.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* 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 parser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const pageSize = 1024 * 1024
|
||||||
|
|
||||||
|
type PagedWriter struct {
|
||||||
|
pages []*[pageSize]byte
|
||||||
|
last *[pageSize]byte
|
||||||
|
off int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPagedWriter() *PagedWriter {
|
||||||
|
return &PagedWriter{last: new([pageSize]byte)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedWriter) Write(buf []byte) (written int, err error) {
|
||||||
|
for {
|
||||||
|
n := copy(p.last[p.off:], buf[written:])
|
||||||
|
written += n
|
||||||
|
if written >= len(buf) {
|
||||||
|
p.off += n
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.pages = append(p.pages, p.last)
|
||||||
|
p.last, p.off = new([pageSize]byte), 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedWriter) Len() int {
|
||||||
|
return len(p.pages)*pageSize + p.off
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedWriter) Bytes() []byte {
|
||||||
|
out, n := make([]byte, p.Len()), 0
|
||||||
|
for _, page := range p.pages {
|
||||||
|
n += copy(out[n:], page[:])
|
||||||
|
}
|
||||||
|
copy(out[n:], p.last[:p.off])
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (p *PagedWriter) ToReader() *PagedReader {
|
||||||
|
return &PagedReader{src: p, curr: p.getPage(0)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedWriter) getPage(ipage int) []byte {
|
||||||
|
if ipage == len(p.pages) { // last page
|
||||||
|
return p.last[:p.off]
|
||||||
|
}
|
||||||
|
return p.pages[ipage][:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type PagedReader struct {
|
||||||
|
src *PagedWriter
|
||||||
|
curr []byte
|
||||||
|
off int
|
||||||
|
ipage int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedReader) WriteTo(w io.Writer) (written int64, err error) {
|
||||||
|
n, err := w.Write(p.curr[p.off:])
|
||||||
|
written = int64(n)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
src, ipage := p.src, p.ipage
|
||||||
|
for {
|
||||||
|
if ipage == len(src.pages) { // last page
|
||||||
|
p.ipage, p.off = ipage, len(p.curr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ipage++
|
||||||
|
page := src.getPage(ipage)
|
||||||
|
n, err = w.Write(page)
|
||||||
|
written += int64(n)
|
||||||
|
if err != nil {
|
||||||
|
p.ipage, p.curr, p.off = ipage, page, n
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PagedReader) Read(buf []byte) (nread int, err error) {
|
||||||
|
for {
|
||||||
|
n := copy(buf[nread:], p.curr[p.off:])
|
||||||
|
nread += n
|
||||||
|
p.off += n
|
||||||
|
if nread >= len(buf) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
src := p.src
|
||||||
|
if p.ipage == len(src.pages) { // last page
|
||||||
|
err = io.EOF
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.ipage++
|
||||||
|
p.curr, p.off = src.getPage(p.ipage), 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
104
x/clang/parser/parse.go
Normal file
104
x/clang/parser/parse.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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 parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/x/clang/ast"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Mode uint
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type ParseError struct {
|
||||||
|
Err error
|
||||||
|
Stderr []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ParseError) Error() string {
|
||||||
|
if len(p.Stderr) > 0 {
|
||||||
|
return string(p.Stderr)
|
||||||
|
}
|
||||||
|
return p.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Json *[]byte
|
||||||
|
Flags []string
|
||||||
|
Stderr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpAST(filename string, conf *Config) (result []byte, warning []byte, err error) {
|
||||||
|
if conf == nil {
|
||||||
|
conf = new(Config)
|
||||||
|
}
|
||||||
|
skiperr := strings.HasSuffix(filename, "vfprintf.c.i")
|
||||||
|
stdout := NewPagedWriter()
|
||||||
|
stderr := new(bytes.Buffer)
|
||||||
|
args := []string{"-Xclang", "-ast-dump=json", "-fsyntax-only", filename}
|
||||||
|
if len(conf.Flags) != 0 {
|
||||||
|
args = append(conf.Flags, args...)
|
||||||
|
}
|
||||||
|
cmd := exec.Command("clang", args...)
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = stdout
|
||||||
|
if conf.Stderr && !skiperr {
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
} else {
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
}
|
||||||
|
err = cmd.Run()
|
||||||
|
errmsg := stderr.Bytes()
|
||||||
|
if err != nil && !skiperr {
|
||||||
|
return nil, nil, &ParseError{Err: err, Stderr: errmsg}
|
||||||
|
}
|
||||||
|
return stdout.Bytes(), errmsg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
|
func ParseFileEx(filename string, mode Mode, conf *Config) (file *ast.Node, warning []byte, err error) {
|
||||||
|
out, warning, err := DumpAST(filename, conf)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if conf != nil && conf.Json != nil {
|
||||||
|
*conf.Json = out
|
||||||
|
}
|
||||||
|
file = new(ast.Node)
|
||||||
|
err = json.Unmarshal(out, file)
|
||||||
|
if err != nil {
|
||||||
|
err = &ParseError{Err: err}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseFile(filename string, mode Mode) (file *ast.Node, warning []byte, err error) {
|
||||||
|
return ParseFileEx(filename, mode, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
|
* Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,12 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package gocmd
|
package pathutil
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
type BuildConfig struct {
|
func Canonical(baseDir string, uri string) string {
|
||||||
Output string
|
if filepath.IsAbs(uri) {
|
||||||
|
return filepath.Clean(uri)
|
||||||
|
}
|
||||||
|
return filepath.Join(baseDir, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
99
x/clang/preprocessor/preprocessor.go
Normal file
99
x/clang/preprocessor/preprocessor.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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 preprocessor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/x/clang/pathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DbgFlagExecCmd = 1 << iota
|
||||||
|
DbgFlagAll = DbgFlagExecCmd
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
debugExecCmd bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetDebug(flags int) {
|
||||||
|
debugExecCmd = (flags & DbgFlagExecCmd) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Compiler string // default: clang
|
||||||
|
PPFlag string // default: -E
|
||||||
|
BaseDir string // base of include searching directory, should be absolute path
|
||||||
|
IncludeDirs []string
|
||||||
|
Defines []string
|
||||||
|
Flags []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Do(infile, outfile string, conf *Config) (err error) {
|
||||||
|
if infile, err = filepath.Abs(infile); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if outfile, err = filepath.Abs(outfile); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if conf == nil {
|
||||||
|
conf = new(Config)
|
||||||
|
}
|
||||||
|
base := conf.BaseDir
|
||||||
|
if base == "" {
|
||||||
|
if base, err = os.Getwd(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compiler := conf.Compiler
|
||||||
|
if compiler == "" {
|
||||||
|
compiler = "clang"
|
||||||
|
}
|
||||||
|
ppflag := conf.PPFlag
|
||||||
|
if ppflag == "" {
|
||||||
|
ppflag = "-E"
|
||||||
|
}
|
||||||
|
n := 4 + len(conf.Flags) + len(conf.IncludeDirs) + len(conf.Defines)
|
||||||
|
args := make([]string, 3, n)
|
||||||
|
args[0] = ppflag
|
||||||
|
args[1], args[2] = "-o", outfile
|
||||||
|
args = append(args, conf.Flags...)
|
||||||
|
for _, def := range conf.Defines {
|
||||||
|
args = append(args, "-D"+def)
|
||||||
|
}
|
||||||
|
for _, inc := range conf.IncludeDirs {
|
||||||
|
args = append(args, "-I"+pathutil.Canonical(base, inc))
|
||||||
|
}
|
||||||
|
args = append(args, infile)
|
||||||
|
if debugExecCmd {
|
||||||
|
log.Println("==> runCmd:", compiler, args)
|
||||||
|
}
|
||||||
|
cmd := exec.Command(compiler, args...)
|
||||||
|
cmd.Dir = filepath.Dir(infile)
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
251
x/clang/types/parser/_parser_test.go
Normal file
251
x/clang/types/parser/_parser_test.go
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* 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 parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
ctypes "github.com/goplus/llgo/x/clang/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
var (
|
||||||
|
pkg = types.NewPackage("", "foo")
|
||||||
|
scope = pkg.Scope()
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nameInt128 = types.NewTypeName(token.NoPos, pkg, "__int128", nil)
|
||||||
|
nameUint128 = types.NewTypeName(token.NoPos, pkg, "__uint128", nil)
|
||||||
|
tyInt128 = types.NewNamed(nameInt128, types.Typ[types.String], nil)
|
||||||
|
tyUint128 = types.NewNamed(nameUint128, types.Typ[types.Rune], nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
aliasType(scope, pkg, "char", types.Typ[types.Int8])
|
||||||
|
aliasType(scope, pkg, "void", ctypes.Void)
|
||||||
|
aliasType(scope, pkg, "float", types.Typ[types.Float32])
|
||||||
|
aliasType(scope, pkg, "double", types.Typ[types.Float64])
|
||||||
|
aliasType(scope, pkg, "uint", types.Typ[types.Uint32])
|
||||||
|
aliasType(scope, pkg, ctypes.MangledName("struct", "ConstantString"), tyConstantString)
|
||||||
|
aliasType(scope, pkg, ctypes.MangledName("union", "arg"), tyArg)
|
||||||
|
aliasType(scope, pkg, "va_list", ctypes.Valist)
|
||||||
|
|
||||||
|
scope.Insert(nameInt128)
|
||||||
|
}
|
||||||
|
|
||||||
|
func aliasType(scope *types.Scope, pkg *types.Package, name string, typ types.Type) {
|
||||||
|
o := types.NewTypeName(token.NoPos, pkg, name, typ)
|
||||||
|
scope.Insert(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
tnameConstantString = types.NewTypeName(token.NoPos, pkg, "ConstantString", nil)
|
||||||
|
tnameArg = types.NewTypeName(token.NoPos, pkg, "UnionArg", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
tyChar = types.Typ[types.Int8]
|
||||||
|
tyUchar = types.Typ[types.Uint8]
|
||||||
|
tyInt16 = types.Typ[types.Int16]
|
||||||
|
tyUint16 = types.Typ[types.Uint16]
|
||||||
|
tyInt32 = types.Typ[types.Int32]
|
||||||
|
tyUint32 = types.Typ[types.Uint32]
|
||||||
|
tyInt64 = types.Typ[types.Int64]
|
||||||
|
tyUint64 = types.Typ[types.Uint64]
|
||||||
|
tyInt = ctypes.Int
|
||||||
|
tyInt100 = types.NewArray(tyInt, 100)
|
||||||
|
tyInt3 = types.NewArray(tyInt, 3)
|
||||||
|
tyInt3_100 = types.NewArray(tyInt3, 100)
|
||||||
|
tyPInt3_100 = types.NewPointer(tyInt3_100)
|
||||||
|
tyPInt100 = types.NewPointer(tyInt100)
|
||||||
|
tyUint = ctypes.Uint
|
||||||
|
tyString = types.Typ[types.String]
|
||||||
|
tyCharPtr = types.NewPointer(tyChar)
|
||||||
|
tyCharPtrPtr = types.NewPointer(tyCharPtr)
|
||||||
|
tyConstantString = types.NewNamed(tnameConstantString, tyString, nil)
|
||||||
|
tyArg = types.NewNamed(tnameArg, tyString, nil)
|
||||||
|
tyEmptyInterface = types.NewInterfaceType(nil, nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
paramInt = types.NewParam(token.NoPos, pkg, "", tyInt)
|
||||||
|
paramVoidPtr = types.NewParam(token.NoPos, pkg, "", ctypes.UnsafePointer)
|
||||||
|
paramCharPtrPtr = types.NewParam(token.NoPos, pkg, "", tyCharPtrPtr)
|
||||||
|
paramAnySlice = types.NewParam(token.NoPos, pkg, "", types.NewSlice(tyEmptyInterface))
|
||||||
|
paramPAnySlice = types.NewParam(token.NoPos, pkg, "", types.NewPointer(types.NewSlice(tyEmptyInterface)))
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
typesInt = types.NewTuple(paramInt)
|
||||||
|
typesIntVA = types.NewTuple(paramInt, paramAnySlice)
|
||||||
|
typesIntPVA = types.NewTuple(paramInt, paramPAnySlice)
|
||||||
|
typesVoidPtr = types.NewTuple(paramVoidPtr)
|
||||||
|
typesPICC = types.NewTuple(paramVoidPtr, paramInt, paramCharPtrPtr, paramCharPtrPtr)
|
||||||
|
)
|
||||||
|
|
||||||
|
func newFn(in, out *types.Tuple) types.Type {
|
||||||
|
return types.NewSignature(nil, in, out, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFnv(in, out *types.Tuple) types.Type {
|
||||||
|
return types.NewSignature(nil, in, out, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFnProto(in, out *types.Tuple, variadic bool) types.Type {
|
||||||
|
return ctypes.NewFunc(in, out, variadic)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
tyFnHandle = newFn(typesInt, nil)
|
||||||
|
paramFnHandle = types.NewParam(token.NoPos, pkg, "", tyFnHandle)
|
||||||
|
typesIF = types.NewTuple(paramInt, paramFnHandle)
|
||||||
|
typesF = types.NewTuple(paramFnHandle)
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
qualType string
|
||||||
|
flags int
|
||||||
|
anonym types.Type
|
||||||
|
typ types.Type
|
||||||
|
err string
|
||||||
|
}
|
||||||
|
|
||||||
|
var cases = []testCase{
|
||||||
|
{qualType: "int", typ: tyInt},
|
||||||
|
{qualType: "unsigned int", typ: tyUint},
|
||||||
|
{qualType: "struct ConstantString", typ: tyConstantString},
|
||||||
|
{qualType: "union arg", typ: tyArg},
|
||||||
|
{qualType: "volatile signed int", typ: tyInt},
|
||||||
|
{qualType: "__int128", typ: tyInt128},
|
||||||
|
{qualType: "signed", typ: tyInt},
|
||||||
|
{qualType: "signed short", typ: tyInt16},
|
||||||
|
{qualType: "signed long", typ: ctypes.Long},
|
||||||
|
{qualType: "unsigned", typ: tyUint},
|
||||||
|
{qualType: "uint", typ: tyUint32},
|
||||||
|
{qualType: "unsigned char", typ: tyUchar},
|
||||||
|
{qualType: "unsigned __int128", typ: tyUint128},
|
||||||
|
{qualType: "unsigned long", typ: ctypes.Ulong},
|
||||||
|
{qualType: "unsigned long long", typ: tyUint64},
|
||||||
|
{qualType: "long double", typ: ctypes.LongDouble},
|
||||||
|
{qualType: "_Complex float", typ: types.Typ[types.Complex64]},
|
||||||
|
{qualType: "_Complex double", typ: types.Typ[types.Complex128]},
|
||||||
|
{qualType: "_Complex long double", typ: types.Typ[types.Complex128]},
|
||||||
|
{qualType: "int (*)(void)", typ: newFn(nil, typesInt)},
|
||||||
|
{qualType: "int (void)", typ: newFnProto(nil, typesInt, false)},
|
||||||
|
{qualType: "void (void) __attribute__((noreturn))", typ: newFnProto(nil, nil, false)},
|
||||||
|
{qualType: "void (*)(void *)", typ: newFn(typesVoidPtr, nil)},
|
||||||
|
{qualType: "void (^ _Nonnull)(void)", typ: newFn(nil, nil)},
|
||||||
|
{qualType: "void (int, ...)", typ: newFnProto(typesIntVA, nil, true)},
|
||||||
|
{qualType: "void (int, va_list*)", typ: newFn(typesIntPVA, nil)},
|
||||||
|
{qualType: "va_list *", typ: types.NewPointer(types.NewSlice(tyEmptyInterface))},
|
||||||
|
{qualType: "int (*)()", typ: newFn(nil, typesInt)},
|
||||||
|
{qualType: "int (*)(int, ...)", typ: newFnv(typesIntVA, typesInt)},
|
||||||
|
{qualType: "int (*)(int, struct __va_list_tag*)", typ: newFn(typesIntVA, typesInt)},
|
||||||
|
{qualType: "int (*volatile)(int, struct __va_list_tag* restrict)", typ: newFn(typesIntVA, typesInt)},
|
||||||
|
{qualType: "int (const char *, const char *, unsigned int)", flags: FlagGetRetType, typ: tyInt},
|
||||||
|
{qualType: "const char *restrict", typ: tyCharPtr},
|
||||||
|
{qualType: "const char [7]", typ: types.NewArray(tyChar, 7)},
|
||||||
|
{qualType: "const char [7]", flags: FlagIsParam, typ: tyCharPtr},
|
||||||
|
{qualType: "char []", flags: FlagIsStructField, typ: types.NewArray(tyChar, 0)},
|
||||||
|
{qualType: "char []", flags: FlagIsExtern, typ: types.NewArray(tyChar, -1)},
|
||||||
|
{qualType: "char []", flags: 0, err: emsgDefArrWithoutLen},
|
||||||
|
{qualType: "char []", flags: FlagIsTypedef, typ: types.NewArray(tyChar, -1)},
|
||||||
|
{qualType: "char []", flags: FlagIsParam, typ: tyCharPtr},
|
||||||
|
{qualType: "int [100][3]", typ: tyInt3_100},
|
||||||
|
{qualType: "int (*)[100][3]", typ: tyPInt3_100},
|
||||||
|
{qualType: "int (*)[100]", typ: tyPInt100},
|
||||||
|
{qualType: "int (*const [2])(void *)", typ: types.NewArray(newFn(typesVoidPtr, typesInt), 2)},
|
||||||
|
{qualType: "char *", typ: tyCharPtr},
|
||||||
|
{qualType: "void", typ: ctypes.Void},
|
||||||
|
{qualType: "void *", typ: ctypes.UnsafePointer},
|
||||||
|
{qualType: "int (*_Nullable)(void *, int, char **, char **)", typ: newFn(typesPICC, typesInt)},
|
||||||
|
{qualType: "void (*(*)(int, void (*)(int)))(int)", typ: newFn(typesIF, typesF)},
|
||||||
|
{qualType: "void (*(int, void (*)(int)))(int)", typ: newFnProto(typesIF, typesF, false)},
|
||||||
|
{qualType: "void (*(int, void (*)(int)))(int)", flags: FlagGetRetType, typ: tyFnHandle},
|
||||||
|
{qualType: "int (*)(void *, int, const char *, void (**)(void *, int, void **), void **)"},
|
||||||
|
{qualType: "struct (anonymous) [2]", anonym: tyInt, typ: types.NewArray(tyInt, 2)},
|
||||||
|
{qualType: "enum a", typ: ctypes.Int},
|
||||||
|
}
|
||||||
|
|
||||||
|
type baseEnv struct {
|
||||||
|
pkg *types.Package
|
||||||
|
tyInt128 types.Type
|
||||||
|
tyUint128 types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *baseEnv) Pkg() *types.Package {
|
||||||
|
return p.pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *baseEnv) Int128() types.Type {
|
||||||
|
return p.tyInt128
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *baseEnv) Uint128() types.Type {
|
||||||
|
return p.tyUint128
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCases(t *testing.T) {
|
||||||
|
sel := ""
|
||||||
|
for _, c := range cases {
|
||||||
|
if sel != "" && c.qualType != sel {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Run(c.qualType, func(t *testing.T) {
|
||||||
|
conf := &Config{
|
||||||
|
Scope: scope, Flags: c.flags, Anonym: c.anonym,
|
||||||
|
ParseEnv: &baseEnv{pkg: pkg, tyInt128: tyInt128, tyUint128: tyUint128},
|
||||||
|
}
|
||||||
|
typ, _, err := ParseType(c.qualType, conf)
|
||||||
|
if err != nil {
|
||||||
|
if errMsgOf(err) != c.err {
|
||||||
|
t.Fatal("ParseType:", err, ", expected:", c.err)
|
||||||
|
}
|
||||||
|
} else if c.typ != nil && !ctypes.Identical(typ, c.typ) {
|
||||||
|
t.Fatal("ParseType:", typ, ", expected:", c.typ)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func errMsgOf(err error) string {
|
||||||
|
if e, ok := err.(*ParseTypeError); ok {
|
||||||
|
return e.ErrMsg
|
||||||
|
}
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestIsArrayWithoutLen(t *testing.T) {
|
||||||
|
_, _, err := ParseType("byte[]", &Config{Scope: types.Universe})
|
||||||
|
if !IsArrayWithoutLen(err) {
|
||||||
|
t.Fatal("ParseType:", err)
|
||||||
|
}
|
||||||
|
_, _, err = ParseType("byte[]", &Config{Scope: types.Universe, Flags: FlagIsExtern})
|
||||||
|
if IsArrayWithoutLen(err) {
|
||||||
|
t.Fatal("ParseType:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user