Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9203c366e7 | ||
|
|
11a8af1db2 | ||
|
|
c8fb7eafa0 | ||
|
|
ffc1f712a3 | ||
|
|
cfc8687851 | ||
|
|
953699b2fd | ||
|
|
9a16fff27e | ||
|
|
ac0d104231 | ||
|
|
881efea006 | ||
|
|
f6a380d293 | ||
|
|
a971b93994 | ||
|
|
c4f0dd124d | ||
|
|
93b9b7d44c | ||
|
|
7552bfe39b | ||
|
|
2601faaff2 | ||
|
|
cb2e28d086 | ||
|
|
337877313a | ||
|
|
1693942cee | ||
|
|
867a1ce2f4 | ||
|
|
26b997537f | ||
|
|
19056b8a19 | ||
|
|
10d603b377 | ||
|
|
3f41c313ad | ||
|
|
d440949c1d | ||
|
|
64314dc6cf | ||
|
|
decb9d7f11 | ||
|
|
975b0b74ee | ||
|
|
9aa7807b02 | ||
|
|
337c6cfa25 | ||
|
|
f09a423ee7 | ||
|
|
3bf28f52c4 | ||
|
|
f794592f42 | ||
|
|
98bd05b47b | ||
|
|
3edbde0839 | ||
|
|
a2d92eac0b | ||
|
|
eb47c545ec | ||
|
|
c858f79449 | ||
|
|
27f6efbdec | ||
|
|
bba7494ffd | ||
|
|
0f79cad5a7 | ||
|
|
9e7bacbe23 | ||
|
|
2301a4834d | ||
|
|
40e0f58079 | ||
|
|
c23fb144cf | ||
|
|
caac681ac3 | ||
|
|
9ba3b3ef8f | ||
|
|
d7e523948b | ||
|
|
10a75138d1 | ||
|
|
d48b19c866 | ||
|
|
1fdcb55eba | ||
|
|
16cec9f045 | ||
|
|
438b0bd1b0 | ||
|
|
e8a91696d6 | ||
|
|
8882c31eb4 | ||
|
|
8455ee8226 | ||
|
|
3f74aded8a | ||
|
|
2e19c2013c | ||
|
|
1edaa2d09b | ||
|
|
beee018287 | ||
|
|
34266ea59d | ||
|
|
f26127ce98 | ||
|
|
ccf321d178 | ||
|
|
355721c47a | ||
|
|
d400663e5d | ||
|
|
2203be945a | ||
|
|
b9a2bf4b42 | ||
|
|
cc08195cf2 | ||
|
|
50c40a7828 | ||
|
|
158be3f949 | ||
|
|
0f87c322ca | ||
|
|
d5dd19b64c | ||
|
|
3ac9055493 | ||
|
|
3032d730b7 | ||
|
|
e93e7126b6 | ||
|
|
9bcf41d28f | ||
|
|
604ce47d5e | ||
|
|
e1ebe150d4 | ||
|
|
ae992737e8 | ||
|
|
c59d609eb8 | ||
|
|
9f26d12a3e | ||
|
|
9102577eba | ||
|
|
f0fcfde22b | ||
|
|
d9d813db56 | ||
|
|
a8808855ae | ||
|
|
5583f9418a | ||
|
|
7369ffd2aa | ||
|
|
ab15f30b13 | ||
|
|
8bff07d66b | ||
|
|
e2e2cb38be | ||
|
|
10d84a6a6b | ||
|
|
a4b4c1574b | ||
|
|
94bc39bdb2 | ||
|
|
7c93b37125 | ||
|
|
4371cc10bd | ||
|
|
eaa2628934 | ||
|
|
30e247186c | ||
|
|
2714da8d98 | ||
|
|
0ef3a7ec25 | ||
|
|
489a0069aa | ||
|
|
a257b7bdfa | ||
|
|
739cc66d0d | ||
|
|
28d944c6af | ||
|
|
19b98393a6 | ||
|
|
5a13e7400e | ||
|
|
a56129d675 | ||
|
|
0d75bbace0 | ||
|
|
29ec4a7a0e | ||
|
|
8b26c48d9b | ||
|
|
ddd0535d30 | ||
|
|
adcd370c27 | ||
|
|
dbead0d725 | ||
|
|
207aea813b | ||
|
|
7a771154a7 | ||
|
|
18c6b9b404 | ||
|
|
3110382d88 | ||
|
|
9ee55896e3 | ||
|
|
ad6f41f312 | ||
|
|
8512395985 | ||
|
|
7284042823 | ||
|
|
0ef683bba9 | ||
|
|
d4bf66936a | ||
|
|
be4737461a | ||
|
|
0d22b3be05 | ||
|
|
7c81d9293b | ||
|
|
d1dce65313 | ||
|
|
641f9bbf7c | ||
|
|
be0e42cf82 | ||
|
|
3a883b8821 | ||
|
|
4bbc58d62d | ||
|
|
5f4b09bede | ||
|
|
f0ade21155 | ||
|
|
f35063ee6e | ||
|
|
e6c7627ee8 | ||
|
|
a85d937482 | ||
|
|
b17632a352 |
4
.github/actions/setup-deps/action.yml
vendored
4
.github/actions/setup-deps/action.yml
vendored
@@ -15,7 +15,7 @@ runs:
|
|||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} bdw-gc openssl libffi libuv
|
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} bdw-gc openssl libffi libuv
|
||||||
brew link --overwrite lld@${{inputs.llvm-version}} libffi
|
brew link --overwrite llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} libffi
|
||||||
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH
|
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
# Install optional deps for demos.
|
# Install optional deps for demos.
|
||||||
@@ -35,7 +35,7 @@ runs:
|
|||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libunwind-dev libuv1-dev
|
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libunwind-dev libuv1-dev
|
||||||
echo "/usr/lib/llvm-${{inputs.llvm-version}}/bin" >> $GITHUB_PATH
|
echo "PATH=/usr/lib/llvm-${{inputs.llvm-version}}/bin:$PATH" >> $GITHUB_ENV
|
||||||
|
|
||||||
# Install optional deps for demos.
|
# Install optional deps for demos.
|
||||||
#
|
#
|
||||||
|
|||||||
4
.github/codecov.yml
vendored
4
.github/codecov.yml
vendored
@@ -1,9 +1,11 @@
|
|||||||
coverage:
|
coverage:
|
||||||
ignore:
|
ignore:
|
||||||
- "chore"
|
- "chore"
|
||||||
- "cmd/internal"
|
- "cmd"
|
||||||
- "internal/build"
|
- "internal/build"
|
||||||
- "internal/llgen"
|
- "internal/llgen"
|
||||||
- "internal/mockable"
|
- "internal/mockable"
|
||||||
- "internal/packages"
|
- "internal/packages"
|
||||||
- "internal/typepatch"
|
- "internal/typepatch"
|
||||||
|
- "internal/github"
|
||||||
|
- "xtool"
|
||||||
|
|||||||
9
.github/workflows/doc.yml
vendored
9
.github/workflows/doc.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: "20"
|
||||||
|
|
||||||
- name: Install embedme
|
- name: Install embedme
|
||||||
run: npm install -g embedme
|
run: npm install -g embedme
|
||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: '1.23.6'
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Install dependencies on macOS
|
- name: Install dependencies on macOS
|
||||||
if: startsWith(matrix.os, 'macos')
|
if: startsWith(matrix.os, 'macos')
|
||||||
@@ -79,7 +79,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.23'
|
go-version: "1.23"
|
||||||
|
|
||||||
- name: Install dependencies on macOS
|
- name: Install dependencies on macOS
|
||||||
if: startsWith(matrix.os, 'macos')
|
if: startsWith(matrix.os, 'macos')
|
||||||
@@ -130,7 +130,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.23'
|
go-version: "1.23"
|
||||||
|
|
||||||
- name: Install dependencies on macOS
|
- name: Install dependencies on macOS
|
||||||
if: startsWith(matrix.os, 'macos')
|
if: startsWith(matrix.os, 'macos')
|
||||||
@@ -145,6 +145,7 @@ jobs:
|
|||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
source doc/_readme/scripts/install_ubuntu.sh
|
source doc/_readme/scripts/install_ubuntu.sh
|
||||||
|
echo "PATH=/usr/lib/llvm-19/bin:$PATH" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install llgo with tools
|
- name: Install llgo with tools
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.github/workflows/fmt.yml
vendored
4
.github/workflows/fmt.yml
vendored
@@ -15,13 +15,13 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: '1.24.0'
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: |
|
run: |
|
||||||
for dir in . runtime; do
|
for dir in . runtime; do
|
||||||
pushd $dir
|
pushd $dir
|
||||||
if [ -n "$(go fmt ./...)" ]; then
|
if [ -n "$(go fmt ./... | grep -v gop_autogen.go)" ]; then
|
||||||
echo "Some files are not properly formatted. Please run 'go fmt ./...'"
|
echo "Some files are not properly formatted. Please run 'go fmt ./...'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: "1.24.0"
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: go build -v ./...
|
run: go build -v ./...
|
||||||
|
|||||||
60
.github/workflows/llgo.yml
vendored
60
.github/workflows/llgo.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- macos-latest
|
- macos-latest
|
||||||
- ubuntu-24.04
|
- ubuntu-24.04
|
||||||
llvm: [19]
|
llvm: [19]
|
||||||
go: ['1.21.13', '1.22.12', '1.23.6', '1.24.0']
|
go: ["1.21.13", "1.22.12", "1.23.6", "1.24.2"]
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -58,7 +58,7 @@ jobs:
|
|||||||
- name: Set up Go for build
|
- name: Set up Go for build
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: "1.24.0"
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
@@ -105,7 +105,7 @@ jobs:
|
|||||||
- macos-latest
|
- macos-latest
|
||||||
- ubuntu-24.04
|
- ubuntu-24.04
|
||||||
llvm: [19]
|
llvm: [19]
|
||||||
go: ["1.24.0"]
|
go: ["1.24.2"]
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
- name: Set up Go for build
|
- name: Set up Go for build
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: "1.24.0"
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
@@ -146,7 +146,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, macos-latest]
|
os: [ubuntu-24.04, macos-latest]
|
||||||
llvm: [19]
|
llvm: [19]
|
||||||
go: ['1.21.13', '1.22.12', '1.23.6', '1.24.0']
|
go: ["1.21.13", "1.22.12", "1.23.6", "1.24.2"]
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -158,7 +158,7 @@ jobs:
|
|||||||
- name: Set up Go 1.23 for building llgo
|
- name: Set up Go 1.23 for building llgo
|
||||||
uses: ./.github/actions/setup-go
|
uses: ./.github/actions/setup-go
|
||||||
with:
|
with:
|
||||||
go-version: "1.24.0"
|
go-version: "1.24.2"
|
||||||
|
|
||||||
- name: Install llgo
|
- name: Install llgo
|
||||||
run: |
|
run: |
|
||||||
@@ -197,3 +197,51 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version: ${{matrix.go}}
|
go-version: ${{matrix.go}}
|
||||||
mod-version: "1.24"
|
mod-version: "1.24"
|
||||||
|
|
||||||
|
cross-compile:
|
||||||
|
continue-on-error: true
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest]
|
||||||
|
llvm: [19]
|
||||||
|
runs-on: ${{matrix.os}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
uses: ./.github/actions/setup-deps
|
||||||
|
with:
|
||||||
|
llvm-version: ${{matrix.llvm}}
|
||||||
|
|
||||||
|
- name: Set up Go for building llgo
|
||||||
|
uses: ./.github/actions/setup-go
|
||||||
|
with:
|
||||||
|
go-version: "1.24.2"
|
||||||
|
|
||||||
|
- name: Install wamr
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/bytecodealliance/wasm-micro-runtime.git
|
||||||
|
mkdir wasm-micro-runtime/product-mini/platforms/darwin/build
|
||||||
|
cd wasm-micro-runtime/product-mini/platforms/darwin/build
|
||||||
|
cmake -D WAMR_BUILD_EXCE_HANDLING=1 -D WAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_LIB_WASI_THREADS=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DEBUG_INTERP=1 ..
|
||||||
|
make -j8
|
||||||
|
echo "$PWD" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Install llgo
|
||||||
|
run: |
|
||||||
|
go install ./...
|
||||||
|
echo "LLGO_ROOT=$GITHUB_WORKSPACE" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Test Cross Compilation (wasm)
|
||||||
|
shell: bash
|
||||||
|
working-directory: _demo
|
||||||
|
run: |
|
||||||
|
echo "Testing cross-compilation wasm with Go 1.24.2"
|
||||||
|
|
||||||
|
# Compile for wasm architecture
|
||||||
|
GOOS=wasip1 GOARCH=wasm llgo build -o hello -tags=nogc -v ./helloc
|
||||||
|
|
||||||
|
# Check file type
|
||||||
|
file hello.wasm
|
||||||
|
|
||||||
|
# Run the wasm binary using llgo_wasm
|
||||||
|
iwasm --stack-size=819200000 --heap-size=800000000 hello.wasm
|
||||||
|
|||||||
@@ -335,6 +335,7 @@ Here are the Go packages that can be imported correctly:
|
|||||||
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
||||||
* [go/token](https://pkg.go.dev/go/token)
|
* [go/token](https://pkg.go.dev/go/token)
|
||||||
* [go/scanner](https://pkg.go.dev/go/scanner)
|
* [go/scanner](https://pkg.go.dev/go/scanner)
|
||||||
|
* [go/parser](https://pkg.go.dev/go/parser)
|
||||||
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
@@ -361,7 +362,7 @@ Follow these steps to generate the `llgo` command (its usage is the same as the
|
|||||||
brew update
|
brew update
|
||||||
brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config
|
brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config
|
||||||
brew install python@3.12 # optional
|
brew install python@3.12 # optional
|
||||||
brew link --overwrite lld@19 libffi
|
brew link --overwrite llvm@19 lld@19 libffi
|
||||||
# curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
# curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
||||||
./install.sh
|
./install.sh
|
||||||
```
|
```
|
||||||
|
|||||||
33
_cmptest/_goconstdemo/goconst.go
Normal file
33
_cmptest/_goconstdemo/goconst.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/constant"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Create the complex number 2.3 + 5i.
|
||||||
|
ar := constant.MakeFloat64(2.3)
|
||||||
|
ai := constant.MakeImag(constant.MakeInt64(5))
|
||||||
|
a := constant.BinaryOp(ar, token.ADD, ai)
|
||||||
|
|
||||||
|
// Compute (2.3 + 5i) * 11.
|
||||||
|
b := constant.MakeUint64(11)
|
||||||
|
c := constant.BinaryOp(a, token.MUL, b)
|
||||||
|
|
||||||
|
// Convert c into a complex128.
|
||||||
|
Ar, exact := constant.Float64Val(constant.Real(c))
|
||||||
|
if !exact {
|
||||||
|
fmt.Printf("Could not represent real part %s exactly as float64\n", constant.Real(c))
|
||||||
|
}
|
||||||
|
Ai, exact := constant.Float64Val(constant.Imag(c))
|
||||||
|
if !exact {
|
||||||
|
fmt.Printf("Could not represent imaginary part %s as exactly as float64\n", constant.Imag(c))
|
||||||
|
}
|
||||||
|
C := complex(Ar, Ai)
|
||||||
|
|
||||||
|
fmt.Println("literal", 25.3+55i)
|
||||||
|
fmt.Println("go/constant", c)
|
||||||
|
fmt.Println("complex128", C)
|
||||||
|
}
|
||||||
25
_cmptest/mathbigdemo/big.go
Normal file
25
_cmptest/mathbigdemo/big.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize two big ints with the first two numbers in the sequence.
|
||||||
|
a := big.NewInt(0)
|
||||||
|
b := big.NewInt(1)
|
||||||
|
|
||||||
|
// Initialize limit as 10^99, the smallest integer with 100 digits.
|
||||||
|
var limit big.Int
|
||||||
|
limit.Exp(big.NewInt(10), big.NewInt(99), nil)
|
||||||
|
|
||||||
|
// Loop while a is smaller than 1e100.
|
||||||
|
for a.Cmp(&limit) < 0 {
|
||||||
|
// Compute the next Fibonacci number, storing it in a.
|
||||||
|
a.Add(a, b)
|
||||||
|
// Swap a and b so that b is the next number in the sequence.
|
||||||
|
a, b = b, a
|
||||||
|
}
|
||||||
|
fmt.Println(a) // 100-digit Fibonacci number
|
||||||
|
}
|
||||||
@@ -2,4 +2,4 @@ module github.com/goplus/llgo/_demo
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/goplus/lib v0.1.0
|
require github.com/goplus/lib v0.2.0
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
github.com/goplus/lib v0.1.0 h1:kqMAC6FmVPfrw0q8E5yF6Y12WC4GOfi2L/MYS4QoxbQ=
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
github.com/goplus/lib v0.1.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
|
|||||||
@@ -11,7 +11,3 @@ func main() {
|
|||||||
fmt.Println("hello world by fmt.Println")
|
fmt.Println("hello world by fmt.Println")
|
||||||
c.Printf(c.Str("Hello world by c.Printf\n"))
|
c.Printf(c.Str("Hello world by c.Printf\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expected output:
|
|
||||||
Hello world
|
|
||||||
*/
|
|
||||||
|
|||||||
15
_demo/helloc/helloc.go
Normal file
15
_demo/helloc/helloc.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/lib/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello world by c.Printf\n"))
|
||||||
|
c.Printf(c.Str("%ld\n"), unsafe.Sizeof(int(0)))
|
||||||
|
c.Printf(c.Str("%ld\n"), unsafe.Sizeof(uintptr(0)))
|
||||||
|
// var v any = int(0)
|
||||||
|
// c.Printf(c.Str("%ld\n"), unsafe.Sizeof(v))
|
||||||
|
}
|
||||||
@@ -2,4 +2,4 @@ module github.com/goplus/llgo/_pydemo
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/goplus/lib v0.1.0
|
require github.com/goplus/lib v0.2.0
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
github.com/goplus/lib v0.1.0 h1:kqMAC6FmVPfrw0q8E5yF6Y12WC4GOfi2L/MYS4QoxbQ=
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
github.com/goplus/lib v0.1.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ module github.com/goplus/llgo/_xtool
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/goplus/lib v0.1.0
|
require github.com/goplus/lib v0.2.0
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
github.com/goplus/lib v0.1.0 h1:kqMAC6FmVPfrw0q8E5yF6Y12WC4GOfi2L/MYS4QoxbQ=
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
github.com/goplus/lib v0.1.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ source_filename = "github.com/goplus/llgo/cl/_testdata/vargs"
|
|||||||
@"github.com/goplus/llgo/cl/_testdata/vargs.init$guard" = global i1 false, align 1
|
@"github.com/goplus/llgo/cl/_testdata/vargs.init$guard" = global i1 false, align 1
|
||||||
@_llgo_int = linkonce global ptr null, align 8
|
@_llgo_int = linkonce global ptr null, align 8
|
||||||
@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 [40 x i8] c"type assertion interface{} -> int failed", align 1
|
@1 = private unnamed_addr constant [32 x i8] c"type assertion any -> int failed", align 1
|
||||||
@_llgo_string = linkonce global ptr null, align 8
|
@_llgo_string = linkonce global ptr null, align 8
|
||||||
|
|
||||||
define void @"github.com/goplus/llgo/cl/_testdata/vargs.init"() {
|
define void @"github.com/goplus/llgo/cl/_testdata/vargs.init"() {
|
||||||
@@ -87,7 +87,7 @@ _llgo_4: ; preds = %_llgo_2
|
|||||||
_llgo_5: ; preds = %_llgo_2
|
_llgo_5: ; preds = %_llgo_2
|
||||||
%18 = load ptr, ptr @_llgo_string, align 8
|
%18 = load ptr, ptr @_llgo_string, align 8
|
||||||
%19 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%19 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 40 }, ptr %19, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 32 }, ptr %19, align 8
|
||||||
%20 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %18, 0
|
%20 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %18, 0
|
||||||
%21 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %20, ptr %19, 1
|
%21 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %20, ptr %19, 1
|
||||||
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %21)
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %21)
|
||||||
|
|||||||
737
cl/_testdefer/gobuild/in.go
Normal file
737
cl/_testdefer/gobuild/in.go
Normal file
@@ -0,0 +1,737 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/doc"
|
||||||
|
"go/token"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
pathpkg "path"
|
||||||
|
"runtime"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsLocalImport(path string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAbsPath(path string) bool {
|
||||||
|
return strings.HasPrefix(path, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDir(path string) bool {
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return fi.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFile(path string) bool {
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return fi.Mode().IsRegular()
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinPath(a string, b ...string) string {
|
||||||
|
if isAbsPath(b[0]) {
|
||||||
|
return b[0]
|
||||||
|
}
|
||||||
|
return pathpkg.Join(append([]string{a}, b...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nameExt(path string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func gopath() []string {
|
||||||
|
all := make([]string, 0, 10)
|
||||||
|
for _, p := range strings.Split(os.Getenv("GOPATH"), ":") {
|
||||||
|
if p != "" {
|
||||||
|
all = append(all, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
InstallSuffix string
|
||||||
|
Compiler string
|
||||||
|
GOOS string
|
||||||
|
GOARCH string
|
||||||
|
GOROOT string
|
||||||
|
CgoEnabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
ImportPath string
|
||||||
|
Dir string
|
||||||
|
Goroot bool
|
||||||
|
Root string
|
||||||
|
ConflictDir string
|
||||||
|
SrcRoot string
|
||||||
|
PkgRoot string
|
||||||
|
BinDir string
|
||||||
|
PkgTargetRoot string
|
||||||
|
PkgObj string
|
||||||
|
InvalidGoFiles []string
|
||||||
|
IgnoredGoFiles []string
|
||||||
|
IgnoredOtherFiles []string
|
||||||
|
CgoFiles []string
|
||||||
|
XTestGoFiles []string
|
||||||
|
TestGoFiles []string
|
||||||
|
GoFiles []string
|
||||||
|
Directives []Directive
|
||||||
|
TestDirectives []Directive
|
||||||
|
XTestDirectives []Directive
|
||||||
|
BinaryOnly bool
|
||||||
|
Name string
|
||||||
|
Doc string
|
||||||
|
ImportComment string
|
||||||
|
AllTags []string
|
||||||
|
EmbedPatterns []string
|
||||||
|
TestEmbedPatterns []string
|
||||||
|
XTestEmbedPatterns []string
|
||||||
|
Imports []string
|
||||||
|
TestImports []string
|
||||||
|
XTestImports []string
|
||||||
|
EmbedPatternPos map[string][]token.Position
|
||||||
|
TestEmbedPatternPos map[string][]token.Position
|
||||||
|
XTestEmbedPatternPos map[string][]token.Position
|
||||||
|
ImportPos map[string][]token.Position
|
||||||
|
TestImportPos map[string][]token.Position
|
||||||
|
XTestImportPos map[string][]token.Position
|
||||||
|
SFiles []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Directive struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiplePackageError struct {
|
||||||
|
Dir string
|
||||||
|
Packages []string
|
||||||
|
Files []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MultiplePackageError) Error() string {
|
||||||
|
return fmt.Sprintf("multiple packages in single directory: %s\n\t%s\n\t%s", e.Dir, strings.Join(e.Packages, "\n\t"), strings.Join(e.Files, "\n\t"))
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportMode = uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
IgnoreVendor ImportMode = 1 << iota
|
||||||
|
AllowBinary
|
||||||
|
FindOnly
|
||||||
|
ImportComment
|
||||||
|
)
|
||||||
|
|
||||||
|
func importGo(ctx *Context, p *Package, path, srcDir string, mode ImportMode) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasSubdir(root, sub string) (string, bool) {
|
||||||
|
return sub, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasGoFiles(ctxt *Context, file string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStandardImportPath(path string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func readDir(name string) ([]os.DirEntry, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findImportComment(data []byte) (s string, line int) {
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveCgo(ctxt *Context, filename string, p *Package, doc *ast.CommentGroup) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanDecls(m map[string][]token.Position) ([]string, map[string][]token.Position) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileListForExt(p *Package, ext string) *[]string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfo struct {
|
||||||
|
name string // full name including dir
|
||||||
|
header []byte
|
||||||
|
fset *token.FileSet
|
||||||
|
parsed *ast.File
|
||||||
|
parseErr error
|
||||||
|
imports []fileImport
|
||||||
|
embeds []fileEmbed
|
||||||
|
directives []Directive
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileImport struct {
|
||||||
|
path string
|
||||||
|
pos token.Pos
|
||||||
|
doc *ast.CommentGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileEmbed struct {
|
||||||
|
pattern string
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchFile(ctxt *Context, dir, name string, allTags map[string]bool, binaryOnly *bool, fset *token.FileSet) (*fileInfo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errNoModules = errors.New("no modules")
|
||||||
|
|
||||||
|
type godebug struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGodebug(name string) *godebug {
|
||||||
|
return &godebug{
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *godebug) IncNonDefault() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *godebug) Value() string {
|
||||||
|
return g.name
|
||||||
|
}
|
||||||
|
|
||||||
|
var installgoroot = NewGodebug("installgoroot")
|
||||||
|
|
||||||
|
func IsStandardPackage(a, b, c string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoGoError struct {
|
||||||
|
Dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *NoGoError) Error() string {
|
||||||
|
return "no Go files in " + e.Dir
|
||||||
|
}
|
||||||
|
|
||||||
|
func Import(ctxt *Context, path string, srcDir string, mode ImportMode) (*Package, error) {
|
||||||
|
p := &Package{
|
||||||
|
ImportPath: path,
|
||||||
|
}
|
||||||
|
if path == "" {
|
||||||
|
return p, fmt.Errorf("import %q: invalid import path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkgtargetroot string
|
||||||
|
var pkga string
|
||||||
|
var pkgerr error
|
||||||
|
suffix := ""
|
||||||
|
if ctxt.InstallSuffix != "" {
|
||||||
|
suffix = "_" + ctxt.InstallSuffix
|
||||||
|
}
|
||||||
|
switch ctxt.Compiler {
|
||||||
|
case "gccgo":
|
||||||
|
pkgtargetroot = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
|
||||||
|
case "gc":
|
||||||
|
pkgtargetroot = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
|
||||||
|
default:
|
||||||
|
// Save error for end of function.
|
||||||
|
pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
|
||||||
|
}
|
||||||
|
setPkga := func() {
|
||||||
|
switch ctxt.Compiler {
|
||||||
|
case "gccgo":
|
||||||
|
dir, elem := pathpkg.Split(p.ImportPath)
|
||||||
|
pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a"
|
||||||
|
case "gc":
|
||||||
|
pkga = pkgtargetroot + "/" + p.ImportPath + ".a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setPkga()
|
||||||
|
|
||||||
|
binaryOnly := false
|
||||||
|
if IsLocalImport(path) {
|
||||||
|
pkga = "" // local imports have no installed path
|
||||||
|
if srcDir == "" {
|
||||||
|
return p, fmt.Errorf("import %q: import relative to unknown directory", path)
|
||||||
|
}
|
||||||
|
if !isAbsPath(path) {
|
||||||
|
p.Dir = joinPath(srcDir, path)
|
||||||
|
}
|
||||||
|
// p.Dir directory may or may not exist. Gather partial information first, check if it exists later.
|
||||||
|
// Determine canonical import path, if any.
|
||||||
|
// Exclude results where the import path would include /testdata/.
|
||||||
|
inTestdata := func(sub string) bool {
|
||||||
|
return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata"
|
||||||
|
}
|
||||||
|
if ctxt.GOROOT != "" {
|
||||||
|
root := joinPath(runtime.GOROOT(), "src")
|
||||||
|
if sub, ok := hasSubdir(root, p.Dir); ok && !inTestdata(sub) {
|
||||||
|
p.Goroot = true
|
||||||
|
p.ImportPath = sub
|
||||||
|
p.Root = ctxt.GOROOT
|
||||||
|
setPkga() // p.ImportPath changed
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all := gopath()
|
||||||
|
for i, root := range all {
|
||||||
|
rootsrc := joinPath(root, "src")
|
||||||
|
if sub, ok := hasSubdir(rootsrc, p.Dir); ok && !inTestdata(sub) {
|
||||||
|
// We found a potential import path for dir,
|
||||||
|
// but check that using it wouldn't find something
|
||||||
|
// else first.
|
||||||
|
if runtime.GOROOT() != "" && ctxt.Compiler != "gccgo" {
|
||||||
|
if dir := joinPath(runtime.GOROOT(), "src", sub); isDir(dir) {
|
||||||
|
p.ConflictDir = dir
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, earlyRoot := range all[:i] {
|
||||||
|
if dir := joinPath(earlyRoot, "src", sub); isDir(dir) {
|
||||||
|
p.ConflictDir = dir
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sub would not name some other directory instead of this one.
|
||||||
|
// Record it.
|
||||||
|
p.ImportPath = sub
|
||||||
|
p.Root = root
|
||||||
|
setPkga() // p.ImportPath changed
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It's okay that we didn't find a root containing dir.
|
||||||
|
// Keep going with the information we have.
|
||||||
|
} else {
|
||||||
|
if strings.HasPrefix(path, "/") {
|
||||||
|
return p, fmt.Errorf("import %q: cannot import absolute path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := importGo(ctxt, p, path, srcDir, mode); err == nil {
|
||||||
|
goto Found
|
||||||
|
} else if err != errNoModules {
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gopath := gopath() // needed twice below; avoid computing many times
|
||||||
|
|
||||||
|
// tried records the location of unsuccessful package lookups
|
||||||
|
var tried struct {
|
||||||
|
vendor []string
|
||||||
|
goroot string
|
||||||
|
gopath []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vendor directories get first chance to satisfy import.
|
||||||
|
if mode&IgnoreVendor == 0 && srcDir != "" {
|
||||||
|
searchVendor := func(root string, isGoroot bool) bool {
|
||||||
|
sub, ok := hasSubdir(root, srcDir)
|
||||||
|
if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
vendor := joinPath(root, sub, "vendor")
|
||||||
|
if isDir(vendor) {
|
||||||
|
dir := joinPath(vendor, path)
|
||||||
|
if isDir(dir) && hasGoFiles(ctxt, dir) {
|
||||||
|
p.Dir = dir
|
||||||
|
p.ImportPath = strings.TrimPrefix(pathpkg.Join(sub, "vendor", path), "src/")
|
||||||
|
p.Goroot = isGoroot
|
||||||
|
p.Root = root
|
||||||
|
setPkga() // p.ImportPath changed
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
tried.vendor = append(tried.vendor, dir)
|
||||||
|
}
|
||||||
|
i := strings.LastIndex(sub, "/")
|
||||||
|
if i < 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sub = sub[:i]
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ctxt.Compiler != "gccgo" && ctxt.GOROOT != "" && searchVendor(ctxt.GOROOT, true) {
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
for _, root := range gopath {
|
||||||
|
if searchVendor(root, false) {
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine directory from import path.
|
||||||
|
if ctxt.GOROOT != "" {
|
||||||
|
// If the package path starts with "vendor/", only search GOROOT before
|
||||||
|
// GOPATH if the importer is also within GOROOT. That way, if the user has
|
||||||
|
// vendored in a package that is subsequently included in the standard
|
||||||
|
// distribution, they'll continue to pick up their own vendored copy.
|
||||||
|
gorootFirst := srcDir == "" || !strings.HasPrefix(path, "vendor/")
|
||||||
|
if !gorootFirst {
|
||||||
|
_, gorootFirst = hasSubdir(runtime.GOROOT(), srcDir)
|
||||||
|
}
|
||||||
|
if gorootFirst {
|
||||||
|
dir := joinPath(runtime.GOROOT(), "src", path)
|
||||||
|
if ctxt.Compiler != "gccgo" {
|
||||||
|
isDir := isDir(dir)
|
||||||
|
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && isFile(joinPath(runtime.GOROOT(), pkga))
|
||||||
|
if isDir || binaryOnly {
|
||||||
|
p.Dir = dir
|
||||||
|
p.Goroot = true
|
||||||
|
p.Root = runtime.GOROOT()
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tried.goroot = dir
|
||||||
|
}
|
||||||
|
if ctxt.Compiler == "gccgo" && IsStandardPackage(runtime.GOROOT(), ctxt.Compiler, path) {
|
||||||
|
// TODO(bcmills): Setting p.Dir here is misleading, because gccgo
|
||||||
|
// doesn't actually load its standard-library packages from this
|
||||||
|
// directory. See if we can leave it unset.
|
||||||
|
p.Dir = joinPath(runtime.GOROOT(), "src", path)
|
||||||
|
p.Goroot = true
|
||||||
|
p.Root = runtime.GOROOT()
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, root := range gopath {
|
||||||
|
dir := joinPath(root, "src", path)
|
||||||
|
isDir := isDir(dir)
|
||||||
|
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && isFile(joinPath(root, pkga))
|
||||||
|
if isDir || binaryOnly {
|
||||||
|
p.Dir = dir
|
||||||
|
p.Root = root
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
tried.gopath = append(tried.gopath, dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we tried GOPATH first due to a "vendor/" prefix, fall back to GOPATH.
|
||||||
|
// That way, the user can still get useful results from 'go list' for
|
||||||
|
// standard-vendored paths passed on the command line.
|
||||||
|
if runtime.GOROOT() != "" && tried.goroot == "" {
|
||||||
|
dir := joinPath(runtime.GOROOT(), "src", path)
|
||||||
|
if ctxt.Compiler != "gccgo" {
|
||||||
|
isDir := isDir(dir)
|
||||||
|
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && isFile(joinPath(runtime.GOROOT(), pkga))
|
||||||
|
if isDir || binaryOnly {
|
||||||
|
p.Dir = dir
|
||||||
|
p.Goroot = true
|
||||||
|
p.Root = runtime.GOROOT()
|
||||||
|
goto Found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tried.goroot = dir
|
||||||
|
}
|
||||||
|
|
||||||
|
// package was not found
|
||||||
|
var paths []string
|
||||||
|
format := "\t%s (vendor tree)"
|
||||||
|
for _, dir := range tried.vendor {
|
||||||
|
paths = append(paths, fmt.Sprintf(format, dir))
|
||||||
|
format = "\t%s"
|
||||||
|
}
|
||||||
|
if tried.goroot != "" {
|
||||||
|
paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
|
||||||
|
} else {
|
||||||
|
paths = append(paths, "\t($GOROOT not set)")
|
||||||
|
}
|
||||||
|
format = "\t%s (from $GOPATH)"
|
||||||
|
for _, dir := range tried.gopath {
|
||||||
|
paths = append(paths, fmt.Sprintf(format, dir))
|
||||||
|
format = "\t%s"
|
||||||
|
}
|
||||||
|
if len(tried.gopath) == 0 {
|
||||||
|
paths = append(paths, "\t($GOPATH not set. For more details see: 'go help gopath')")
|
||||||
|
}
|
||||||
|
return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
Found:
|
||||||
|
if p.Root != "" {
|
||||||
|
p.SrcRoot = joinPath(p.Root, "src")
|
||||||
|
p.PkgRoot = joinPath(p.Root, "pkg")
|
||||||
|
p.BinDir = joinPath(p.Root, "bin")
|
||||||
|
if pkga != "" {
|
||||||
|
// Always set PkgTargetRoot. It might be used when building in shared
|
||||||
|
// mode.
|
||||||
|
p.PkgTargetRoot = joinPath(p.Root, pkgtargetroot)
|
||||||
|
|
||||||
|
// Set the install target if applicable.
|
||||||
|
if !p.Goroot || (installgoroot.Value() == "all" && p.ImportPath != "unsafe" && p.ImportPath != "builtin") {
|
||||||
|
if p.Goroot {
|
||||||
|
installgoroot.IncNonDefault()
|
||||||
|
}
|
||||||
|
p.PkgObj = joinPath(p.Root, pkga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a local import path, by the time we get here, we still haven't checked
|
||||||
|
// that p.Dir directory exists. This is the right time to do that check.
|
||||||
|
// We can't do it earlier, because we want to gather partial information for the
|
||||||
|
// non-nil *Package returned when an error occurs.
|
||||||
|
// We need to do this before we return early on FindOnly flag.
|
||||||
|
if IsLocalImport(path) && !isDir(p.Dir) {
|
||||||
|
if ctxt.Compiler == "gccgo" && p.Goroot {
|
||||||
|
// gccgo has no sources for GOROOT packages.
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// package was not found
|
||||||
|
return p, fmt.Errorf("cannot find package %q in:\n\t%s", p.ImportPath, p.Dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode&FindOnly != 0 {
|
||||||
|
return p, pkgerr
|
||||||
|
}
|
||||||
|
if binaryOnly && (mode&AllowBinary) != 0 {
|
||||||
|
return p, pkgerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctxt.Compiler == "gccgo" && p.Goroot {
|
||||||
|
// gccgo has no sources for GOROOT packages.
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dirs, err := readDir(p.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var badGoError error
|
||||||
|
badGoFiles := make(map[string]bool)
|
||||||
|
badGoFile := func(name string, err error) {
|
||||||
|
if badGoError == nil {
|
||||||
|
badGoError = err
|
||||||
|
}
|
||||||
|
if !badGoFiles[name] {
|
||||||
|
p.InvalidGoFiles = append(p.InvalidGoFiles, name)
|
||||||
|
badGoFiles[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
|
||||||
|
var firstFile, firstCommentFile string
|
||||||
|
embedPos := make(map[string][]token.Position)
|
||||||
|
testEmbedPos := make(map[string][]token.Position)
|
||||||
|
xTestEmbedPos := make(map[string][]token.Position)
|
||||||
|
importPos := make(map[string][]token.Position)
|
||||||
|
testImportPos := make(map[string][]token.Position)
|
||||||
|
xTestImportPos := make(map[string][]token.Position)
|
||||||
|
allTags := make(map[string]bool)
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
for _, d := range dirs {
|
||||||
|
if d.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if d.Type() == fs.ModeSymlink {
|
||||||
|
if isDir(joinPath(p.Dir, d.Name())) {
|
||||||
|
// Symlinks to directories are not source files.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.Name()
|
||||||
|
ext := nameExt(name)
|
||||||
|
|
||||||
|
info, err := matchFile(ctxt, p.Dir, name, allTags, &p.BinaryOnly, fset)
|
||||||
|
if err != nil && strings.HasSuffix(name, ".go") {
|
||||||
|
badGoFile(name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info == nil {
|
||||||
|
if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") {
|
||||||
|
// not due to build constraints - don't report
|
||||||
|
} else if ext == ".go" {
|
||||||
|
p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
|
||||||
|
} else if fileListForExt(p, ext) != nil {
|
||||||
|
p.IgnoredOtherFiles = append(p.IgnoredOtherFiles, name)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Going to save the file. For non-Go files, can stop here.
|
||||||
|
switch ext {
|
||||||
|
case ".go":
|
||||||
|
// keep going
|
||||||
|
case ".S", ".sx":
|
||||||
|
// special case for cgo, handled at end
|
||||||
|
Sfiles = append(Sfiles, name)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
if list := fileListForExt(p, ext); list != nil {
|
||||||
|
*list = append(*list, name)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
data, filename := info.header, info.name
|
||||||
|
|
||||||
|
if info.parseErr != nil {
|
||||||
|
badGoFile(name, info.parseErr)
|
||||||
|
// Fall through: we might still have a partial AST in info.parsed,
|
||||||
|
// and we want to list files with parse errors anyway.
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkg string
|
||||||
|
if info.parsed != nil {
|
||||||
|
pkg = info.parsed.Name.Name
|
||||||
|
if pkg == "documentation" {
|
||||||
|
p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isTest := strings.HasSuffix(name, "_test.go")
|
||||||
|
isXTest := false
|
||||||
|
if isTest && strings.HasSuffix(pkg, "_test") && p.Name != pkg {
|
||||||
|
isXTest = true
|
||||||
|
pkg = pkg[:len(pkg)-len("_test")]
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Name == "" {
|
||||||
|
p.Name = pkg
|
||||||
|
firstFile = name
|
||||||
|
} else if pkg != p.Name {
|
||||||
|
// TODO(#45999): The choice of p.Name is arbitrary based on file iteration
|
||||||
|
// order. Instead of resolving p.Name arbitrarily, we should clear out the
|
||||||
|
// existing name and mark the existing files as also invalid.
|
||||||
|
badGoFile(name, &MultiplePackageError{
|
||||||
|
Dir: p.Dir,
|
||||||
|
Packages: []string{p.Name, pkg},
|
||||||
|
Files: []string{firstFile, name},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Grab the first package comment as docs, provided it is not from a test file.
|
||||||
|
if info.parsed != nil && info.parsed.Doc != nil && p.Doc == "" && !isTest && !isXTest {
|
||||||
|
p.Doc = doc.Synopsis(info.parsed.Doc.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode&ImportComment != 0 {
|
||||||
|
qcom, line := findImportComment(data)
|
||||||
|
if line != 0 {
|
||||||
|
com, err := strconv.Unquote(qcom)
|
||||||
|
if err != nil {
|
||||||
|
badGoFile(name, fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
|
||||||
|
} else if p.ImportComment == "" {
|
||||||
|
p.ImportComment = com
|
||||||
|
firstCommentFile = name
|
||||||
|
} else if p.ImportComment != com {
|
||||||
|
badGoFile(name, fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record imports and information about cgo.
|
||||||
|
isCgo := false
|
||||||
|
for _, imp := range info.imports {
|
||||||
|
if imp.path == "C" {
|
||||||
|
if isTest {
|
||||||
|
badGoFile(name, fmt.Errorf("use of cgo in test %s not supported", filename))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
isCgo = true
|
||||||
|
if imp.doc != nil {
|
||||||
|
if err := saveCgo(ctxt, filename, p, imp.doc); err != nil {
|
||||||
|
badGoFile(name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileList *[]string
|
||||||
|
var importMap, embedMap map[string][]token.Position
|
||||||
|
var directives *[]Directive
|
||||||
|
switch {
|
||||||
|
case isCgo:
|
||||||
|
allTags["cgo"] = true
|
||||||
|
if ctxt.CgoEnabled {
|
||||||
|
fileList = &p.CgoFiles
|
||||||
|
importMap = importPos
|
||||||
|
embedMap = embedPos
|
||||||
|
directives = &p.Directives
|
||||||
|
} else {
|
||||||
|
// Ignore imports and embeds from cgo files if cgo is disabled.
|
||||||
|
fileList = &p.IgnoredGoFiles
|
||||||
|
}
|
||||||
|
case isXTest:
|
||||||
|
fileList = &p.XTestGoFiles
|
||||||
|
importMap = xTestImportPos
|
||||||
|
embedMap = xTestEmbedPos
|
||||||
|
directives = &p.XTestDirectives
|
||||||
|
case isTest:
|
||||||
|
fileList = &p.TestGoFiles
|
||||||
|
importMap = testImportPos
|
||||||
|
embedMap = testEmbedPos
|
||||||
|
directives = &p.TestDirectives
|
||||||
|
default:
|
||||||
|
fileList = &p.GoFiles
|
||||||
|
importMap = importPos
|
||||||
|
embedMap = embedPos
|
||||||
|
directives = &p.Directives
|
||||||
|
}
|
||||||
|
*fileList = append(*fileList, name)
|
||||||
|
if importMap != nil {
|
||||||
|
for _, imp := range info.imports {
|
||||||
|
importMap[imp.path] = append(importMap[imp.path], fset.Position(imp.pos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if embedMap != nil {
|
||||||
|
for _, emb := range info.embeds {
|
||||||
|
embedMap[emb.pattern] = append(embedMap[emb.pattern], emb.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if directives != nil {
|
||||||
|
*directives = append(*directives, info.directives...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag := range allTags {
|
||||||
|
p.AllTags = append(p.AllTags, tag)
|
||||||
|
}
|
||||||
|
slices.Sort(p.AllTags)
|
||||||
|
|
||||||
|
p.EmbedPatterns, p.EmbedPatternPos = cleanDecls(embedPos)
|
||||||
|
p.TestEmbedPatterns, p.TestEmbedPatternPos = cleanDecls(testEmbedPos)
|
||||||
|
p.XTestEmbedPatterns, p.XTestEmbedPatternPos = cleanDecls(xTestEmbedPos)
|
||||||
|
|
||||||
|
p.Imports, p.ImportPos = cleanDecls(importPos)
|
||||||
|
p.TestImports, p.TestImportPos = cleanDecls(testImportPos)
|
||||||
|
p.XTestImports, p.XTestImportPos = cleanDecls(xTestImportPos)
|
||||||
|
|
||||||
|
// add the .S/.sx files only if we are using cgo
|
||||||
|
// (which means gcc will compile them).
|
||||||
|
// The standard assemblers expect .s files.
|
||||||
|
if len(p.CgoFiles) > 0 {
|
||||||
|
p.SFiles = append(p.SFiles, Sfiles...)
|
||||||
|
slices.Sort(p.SFiles)
|
||||||
|
} else {
|
||||||
|
p.IgnoredOtherFiles = append(p.IgnoredOtherFiles, Sfiles...)
|
||||||
|
slices.Sort(p.IgnoredOtherFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
if badGoError != nil {
|
||||||
|
return p, badGoError
|
||||||
|
}
|
||||||
|
if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
|
||||||
|
return p, &NoGoError{p.Dir}
|
||||||
|
}
|
||||||
|
return p, pkgerr
|
||||||
|
}
|
||||||
206
cl/_testdefer/gobuild/out.txt
Normal file
206
cl/_testdefer/gobuild/out.txt
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
0: always
|
||||||
|
1: cond
|
||||||
|
2: cond
|
||||||
|
3: cond
|
||||||
|
4: cond
|
||||||
|
6: cond
|
||||||
|
8: cond
|
||||||
|
7: cond
|
||||||
|
9: cond
|
||||||
|
5: cond
|
||||||
|
10: cond
|
||||||
|
11: cond
|
||||||
|
12: cond
|
||||||
|
13: cond
|
||||||
|
33: cond
|
||||||
|
34: cond
|
||||||
|
14: cond
|
||||||
|
35: cond
|
||||||
|
15: cond
|
||||||
|
36: cond
|
||||||
|
37: cond
|
||||||
|
16: cond
|
||||||
|
40: cond
|
||||||
|
19: cond
|
||||||
|
38: cond
|
||||||
|
17: cond
|
||||||
|
18: cond
|
||||||
|
43: cond
|
||||||
|
42: cond
|
||||||
|
41: cond
|
||||||
|
21: loop
|
||||||
|
22: loop
|
||||||
|
24: loop
|
||||||
|
23: cond
|
||||||
|
27: cond
|
||||||
|
25: cond
|
||||||
|
28: cond
|
||||||
|
26: cond
|
||||||
|
29: loop
|
||||||
|
30: loop
|
||||||
|
31: cond
|
||||||
|
32: cond
|
||||||
|
44: loop
|
||||||
|
45: loop
|
||||||
|
39: cond
|
||||||
|
46: cond
|
||||||
|
48: cond
|
||||||
|
49: cond
|
||||||
|
50: cond
|
||||||
|
51: cond
|
||||||
|
52: cond
|
||||||
|
54: cond
|
||||||
|
59: cond
|
||||||
|
58: cond
|
||||||
|
56: cond
|
||||||
|
57: cond
|
||||||
|
61: cond
|
||||||
|
60: cond
|
||||||
|
55: cond
|
||||||
|
53: cond
|
||||||
|
63: cond
|
||||||
|
62: cond
|
||||||
|
47: cond
|
||||||
|
64: loop
|
||||||
|
65: loop
|
||||||
|
68: loop
|
||||||
|
73: loop
|
||||||
|
72: loop
|
||||||
|
66: cond
|
||||||
|
70: cond
|
||||||
|
71: cond
|
||||||
|
76: cond
|
||||||
|
69: cond
|
||||||
|
74: cond
|
||||||
|
67: cond
|
||||||
|
77: cond
|
||||||
|
82: cond
|
||||||
|
81: cond
|
||||||
|
79: cond
|
||||||
|
80: cond
|
||||||
|
84: cond
|
||||||
|
83: cond
|
||||||
|
78: cond
|
||||||
|
20: cond
|
||||||
|
75: cond
|
||||||
|
96: cond
|
||||||
|
98: cond
|
||||||
|
100: cond
|
||||||
|
102: cond
|
||||||
|
101: cond
|
||||||
|
99: cond
|
||||||
|
103: cond
|
||||||
|
104: cond
|
||||||
|
97: cond
|
||||||
|
107: cond
|
||||||
|
106: cond
|
||||||
|
105: cond
|
||||||
|
111: cond
|
||||||
|
112: cond
|
||||||
|
110: cond
|
||||||
|
115: cond
|
||||||
|
108: cond
|
||||||
|
109: cond
|
||||||
|
113: cond
|
||||||
|
114: cond
|
||||||
|
118: cond
|
||||||
|
116: cond
|
||||||
|
117: cond
|
||||||
|
119: cond
|
||||||
|
120: cond
|
||||||
|
85: loop
|
||||||
|
86: loop
|
||||||
|
87: cond
|
||||||
|
88: cond
|
||||||
|
90: cond
|
||||||
|
89: cond
|
||||||
|
91: loop
|
||||||
|
92: loop
|
||||||
|
93: cond
|
||||||
|
94: cond
|
||||||
|
95: cond
|
||||||
|
121: loop
|
||||||
|
122: loop
|
||||||
|
123: cond
|
||||||
|
124: cond
|
||||||
|
125: cond
|
||||||
|
126: cond
|
||||||
|
129: cond
|
||||||
|
127: cond
|
||||||
|
128: cond
|
||||||
|
130: cond
|
||||||
|
131: cond
|
||||||
|
133: cond
|
||||||
|
137: cond
|
||||||
|
139: cond
|
||||||
|
132: cond
|
||||||
|
143: cond
|
||||||
|
140: cond
|
||||||
|
134: cond
|
||||||
|
135: cond
|
||||||
|
144: cond
|
||||||
|
138: cond
|
||||||
|
141: cond
|
||||||
|
136: cond
|
||||||
|
145: cond
|
||||||
|
142: cond
|
||||||
|
147: cond
|
||||||
|
146: cond
|
||||||
|
151: cond
|
||||||
|
150: cond
|
||||||
|
148: cond
|
||||||
|
149: cond
|
||||||
|
152: cond
|
||||||
|
154: cond
|
||||||
|
155: cond
|
||||||
|
153: cond
|
||||||
|
161: cond
|
||||||
|
160: cond
|
||||||
|
159: cond
|
||||||
|
158: cond
|
||||||
|
156: cond
|
||||||
|
157: cond
|
||||||
|
162: cond
|
||||||
|
164: cond
|
||||||
|
165: cond
|
||||||
|
166: cond
|
||||||
|
167: cond
|
||||||
|
168: cond
|
||||||
|
169: cond
|
||||||
|
163: cond
|
||||||
|
170: loop
|
||||||
|
171: loop
|
||||||
|
173: loop
|
||||||
|
174: loop
|
||||||
|
172: cond
|
||||||
|
175: cond
|
||||||
|
179: cond
|
||||||
|
181: cond
|
||||||
|
176: cond
|
||||||
|
182: cond
|
||||||
|
183: cond
|
||||||
|
180: cond
|
||||||
|
185: cond
|
||||||
|
177: cond
|
||||||
|
184: cond
|
||||||
|
186: cond
|
||||||
|
178: cond
|
||||||
|
187: cond
|
||||||
|
189: loop
|
||||||
|
190: loop
|
||||||
|
188: cond
|
||||||
|
191: cond
|
||||||
|
193: loop
|
||||||
|
194: loop
|
||||||
|
192: cond
|
||||||
|
195: cond
|
||||||
|
196: loop
|
||||||
|
197: loop
|
||||||
|
198: cond
|
||||||
|
199: cond
|
||||||
|
201: cond
|
||||||
|
200: cond
|
||||||
|
202: cond
|
||||||
|
203: cond
|
||||||
|
204: cond
|
||||||
|
205: cond
|
||||||
25
cl/_testgo/alias/in.go
Normal file
25
cl/_testgo/alias/in.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
x float64
|
||||||
|
y float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Point) Scale(factor float64) {
|
||||||
|
p.x *= factor
|
||||||
|
p.y *= factor
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyPoint = Point
|
||||||
|
|
||||||
|
func (p *MyPoint) Move(dx, dy float64) {
|
||||||
|
p.x += dx
|
||||||
|
p.y += dy
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pt := &MyPoint{1, 2}
|
||||||
|
pt.Scale(2)
|
||||||
|
pt.Move(3, 4)
|
||||||
|
println(pt.x, pt.y)
|
||||||
|
}
|
||||||
75
cl/_testgo/alias/out.ll
Normal file
75
cl/_testgo/alias/out.ll
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/cl/_testgo/alias'
|
||||||
|
source_filename = "github.com/goplus/llgo/cl/_testgo/alias"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/cl/_testgo/alias.Point" = type { double, double }
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/cl/_testgo/alias.init$guard" = global i1 false, align 1
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/alias.(*Point).Move"(ptr %0, double %1, double %2) {
|
||||||
|
_llgo_0:
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
%4 = load double, ptr %3, align 8
|
||||||
|
%5 = fadd double %4, %1
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
store double %5, ptr %6, align 8
|
||||||
|
%7 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
%8 = load double, ptr %7, align 8
|
||||||
|
%9 = fadd double %8, %2
|
||||||
|
%10 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
store double %9, ptr %10, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/alias.(*Point).Scale"(ptr %0, double %1) {
|
||||||
|
_llgo_0:
|
||||||
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
%3 = load double, ptr %2, align 8
|
||||||
|
%4 = fmul double %3, %1
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
store double %4, ptr %5, align 8
|
||||||
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
%7 = load double, ptr %6, align 8
|
||||||
|
%8 = fmul double %7, %1
|
||||||
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
store double %8, ptr %9, align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/alias.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testgo/alias.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/cl/_testgo/alias.init$guard", align 1
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/alias.main"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
%2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
store double 1.000000e+00, ptr %1, align 8
|
||||||
|
store double 2.000000e+00, ptr %2, align 8
|
||||||
|
call void @"github.com/goplus/llgo/cl/_testgo/alias.(*Point).Scale"(ptr %0, double 2.000000e+00)
|
||||||
|
call void @"github.com/goplus/llgo/cl/_testgo/alias.(*Point).Move"(ptr %0, double 3.000000e+00, double 4.000000e+00)
|
||||||
|
%3 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 0
|
||||||
|
%4 = load double, ptr %3, align 8
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testgo/alias.Point", ptr %0, i32 0, i32 1
|
||||||
|
%6 = load double, ptr %5, align 8
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintFloat"(double %4)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 32)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintFloat"(double %6)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 10)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintFloat"(double)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8)
|
||||||
@@ -319,7 +319,7 @@ _llgo_17: ; preds = %_llgo_4
|
|||||||
%108 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%108 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
%109 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %108, i32 0, i32 0
|
%109 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %108, i32 0, i32 0
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %43, ptr %109, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %43, ptr %109, align 8
|
||||||
%110 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.one$bound", ptr undef }, ptr %108, 1
|
%110 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.one$bound", ptr undef }, ptr %108, 1
|
||||||
%111 = extractvalue { ptr, ptr } %110, 1
|
%111 = extractvalue { ptr, ptr } %110, 1
|
||||||
%112 = extractvalue { ptr, ptr } %110, 0
|
%112 = extractvalue { ptr, ptr } %110, 0
|
||||||
%113 = call i64 %112(ptr %111)
|
%113 = call i64 %112(ptr %111)
|
||||||
@@ -339,7 +339,7 @@ _llgo_19: ; preds = %_llgo_6
|
|||||||
%119 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%119 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
%120 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %119, i32 0, i32 0
|
%120 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %119, i32 0, i32 0
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %51, ptr %120, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %51, ptr %120, align 8
|
||||||
%121 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.one$bound", ptr undef }, ptr %119, 1
|
%121 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.one$bound", ptr undef }, ptr %119, 1
|
||||||
%122 = extractvalue { ptr, ptr } %121, 1
|
%122 = extractvalue { ptr, ptr } %121, 1
|
||||||
%123 = extractvalue { ptr, ptr } %121, 0
|
%123 = extractvalue { ptr, ptr } %121, 0
|
||||||
%124 = call i64 %123(ptr %122)
|
%124 = call i64 %123(ptr %122)
|
||||||
@@ -359,7 +359,7 @@ _llgo_21: ; preds = %_llgo_12
|
|||||||
%130 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%130 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
%131 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %130, i32 0, i32 0
|
%131 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %130, i32 0, i32 0
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %93, ptr %131, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %93, ptr %131, align 8
|
||||||
%132 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.two$bound", ptr undef }, ptr %130, 1
|
%132 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.two$bound", ptr undef }, ptr %130, 1
|
||||||
%133 = extractvalue { ptr, ptr } %132, 1
|
%133 = extractvalue { ptr, ptr } %132, 1
|
||||||
%134 = extractvalue { ptr, ptr } %132, 0
|
%134 = extractvalue { ptr, ptr } %132, 0
|
||||||
%135 = call %"github.com/goplus/llgo/runtime/internal/runtime.String" %134(ptr %133)
|
%135 = call %"github.com/goplus/llgo/runtime/internal/runtime.String" %134(ptr %133)
|
||||||
@@ -380,7 +380,7 @@ _llgo_23: ; preds = %_llgo_14
|
|||||||
%142 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%142 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
%143 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %142, i32 0, i32 0
|
%143 = getelementptr inbounds { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %142, i32 0, i32 0
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %101, ptr %143, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.iface" %101, ptr %143, align 8
|
||||||
%144 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.two$bound", ptr undef }, ptr %142, 1
|
%144 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.two$bound", ptr undef }, ptr %142, 1
|
||||||
%145 = extractvalue { ptr, ptr } %144, 1
|
%145 = extractvalue { ptr, ptr } %144, 1
|
||||||
%146 = extractvalue { ptr, ptr } %144, 0
|
%146 = extractvalue { ptr, ptr } %144, 0
|
||||||
%147 = call %"github.com/goplus/llgo/runtime/internal/runtime.String" %146(ptr %145)
|
%147 = call %"github.com/goplus/llgo/runtime/internal/runtime.String" %146(ptr %145)
|
||||||
@@ -585,7 +585,7 @@ declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamedInterface"
|
|||||||
|
|
||||||
declare void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamedInterface"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.Slice")
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamedInterface"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.Slice")
|
||||||
|
|
||||||
define i64 @"github.com/goplus/llgo/cl/_testgo/ifaceprom.one$bound"(ptr %0) {
|
define i64 @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.one$bound"(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = load { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %0, align 8
|
%1 = load { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %0, align 8
|
||||||
%2 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface" } %1, 0
|
%2 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface" } %1, 0
|
||||||
@@ -603,7 +603,7 @@ _llgo_0:
|
|||||||
|
|
||||||
declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.StringEqual"(%"github.com/goplus/llgo/runtime/internal/runtime.String", %"github.com/goplus/llgo/runtime/internal/runtime.String")
|
declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.StringEqual"(%"github.com/goplus/llgo/runtime/internal/runtime.String", %"github.com/goplus/llgo/runtime/internal/runtime.String")
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/runtime/internal/runtime.String" @"github.com/goplus/llgo/cl/_testgo/ifaceprom.two$bound"(ptr %0) {
|
define %"github.com/goplus/llgo/runtime/internal/runtime.String" @"github.com/goplus/llgo/cl/_testgo/ifaceprom.I.two$bound"(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = load { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %0, align 8
|
%1 = load { %"github.com/goplus/llgo/runtime/internal/runtime.iface" }, ptr %0, align 8
|
||||||
%2 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface" } %1, 0
|
%2 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface" } %1, 0
|
||||||
|
|||||||
24
cl/_testgo/reflectfn/in.go
Normal file
24
cl/_testgo/reflectfn/in.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func demo() {
|
||||||
|
println("demo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v := 100
|
||||||
|
fn := func() {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fdemo := demo
|
||||||
|
fmt.Println(fn)
|
||||||
|
fmt.Println(demo)
|
||||||
|
fmt.Println(fdemo)
|
||||||
|
fmt.Println(reflect.ValueOf(fn).UnsafePointer())
|
||||||
|
fmt.Println(reflect.ValueOf(demo).UnsafePointer())
|
||||||
|
fmt.Println(reflect.ValueOf(fdemo).UnsafePointer())
|
||||||
|
}
|
||||||
244
cl/_testgo/reflectfn/out.ll
Normal file
244
cl/_testgo/reflectfn/out.ll
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/cl/_testgo/reflectfn'
|
||||||
|
source_filename = "github.com/goplus/llgo/cl/_testgo/reflectfn"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.Slice" = type { ptr, i64, i64 }
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.iface" = type { ptr, ptr }
|
||||||
|
%reflect.Value = type { ptr, ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/runtime/abi.StructField" = type { %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 }
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/cl/_testgo/reflectfn.init$guard" = global i1 false, align 1
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"demo", align 1
|
||||||
|
@"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac" = linkonce global ptr null, align 8
|
||||||
|
@_llgo_Pointer = linkonce global ptr null, align 8
|
||||||
|
@"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8" = linkonce global ptr null, align 8
|
||||||
|
@1 = private unnamed_addr constant [2 x i8] c"$f", align 1
|
||||||
|
@2 = private unnamed_addr constant [5 x i8] c"$data", align 1
|
||||||
|
@3 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/_testgo/reflectfn", align 1
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/reflectfn.demo"() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintString"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 4 })
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 10)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/reflectfn.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.init$guard", align 1
|
||||||
|
call void @fmt.init()
|
||||||
|
call void @reflect.init()
|
||||||
|
call void @"github.com/goplus/llgo/cl/_testgo/reflectfn.init$after"()
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/reflectfn.main"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 8)
|
||||||
|
store i64 100, ptr %0, align 4
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
||||||
|
%2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0
|
||||||
|
store ptr %0, ptr %2, align 8
|
||||||
|
%3 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.main$1", ptr undef }, ptr %1, 1
|
||||||
|
%4 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%5 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %4, i64 0
|
||||||
|
%6 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8
|
||||||
|
%7 = load ptr, ptr @_llgo_Pointer, align 8
|
||||||
|
%8 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%9 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } %3, ptr %9, align 8
|
||||||
|
%10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %8, 0
|
||||||
|
%11 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %10, ptr %9, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %11, ptr %5, align 8
|
||||||
|
%12 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %4, 0
|
||||||
|
%13 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %12, i64 1, 1
|
||||||
|
%14 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %13, i64 1, 2
|
||||||
|
%15 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %14)
|
||||||
|
%16 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%17 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %16, i64 0
|
||||||
|
%18 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%19 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/reflectfn.demo", ptr null }, ptr %19, align 8
|
||||||
|
%20 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %18, 0
|
||||||
|
%21 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %20, ptr %19, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %21, ptr %17, align 8
|
||||||
|
%22 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %16, 0
|
||||||
|
%23 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %22, i64 1, 1
|
||||||
|
%24 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %23, i64 1, 2
|
||||||
|
%25 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %24)
|
||||||
|
%26 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%27 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %26, i64 0
|
||||||
|
%28 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%29 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/reflectfn.demo", ptr null }, ptr %29, align 8
|
||||||
|
%30 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %28, 0
|
||||||
|
%31 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %30, ptr %29, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %31, ptr %27, align 8
|
||||||
|
%32 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %26, 0
|
||||||
|
%33 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %32, i64 1, 1
|
||||||
|
%34 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %33, i64 1, 2
|
||||||
|
%35 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %34)
|
||||||
|
%36 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%37 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } %3, ptr %37, align 8
|
||||||
|
%38 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %36, 0
|
||||||
|
%39 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %38, ptr %37, 1
|
||||||
|
%40 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %39)
|
||||||
|
%41 = call ptr @reflect.Value.UnsafePointer(%reflect.Value %40)
|
||||||
|
%42 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%43 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %42, i64 0
|
||||||
|
%44 = load ptr, ptr @_llgo_Pointer, align 8
|
||||||
|
%45 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %44, 0
|
||||||
|
%46 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %45, ptr %41, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %46, ptr %43, align 8
|
||||||
|
%47 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %42, 0
|
||||||
|
%48 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %47, i64 1, 1
|
||||||
|
%49 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %48, i64 1, 2
|
||||||
|
%50 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %49)
|
||||||
|
%51 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%52 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/reflectfn.demo", ptr null }, ptr %52, align 8
|
||||||
|
%53 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %51, 0
|
||||||
|
%54 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %53, ptr %52, 1
|
||||||
|
%55 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %54)
|
||||||
|
%56 = call ptr @reflect.Value.UnsafePointer(%reflect.Value %55)
|
||||||
|
%57 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%58 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %57, i64 0
|
||||||
|
%59 = load ptr, ptr @_llgo_Pointer, align 8
|
||||||
|
%60 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %59, 0
|
||||||
|
%61 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %60, ptr %56, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %61, ptr %58, align 8
|
||||||
|
%62 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %57, 0
|
||||||
|
%63 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %62, i64 1, 1
|
||||||
|
%64 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %63, i64 1, 2
|
||||||
|
%65 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %64)
|
||||||
|
%66 = load ptr, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
%67 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store { ptr, ptr } { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/reflectfn.demo", ptr null }, ptr %67, align 8
|
||||||
|
%68 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %66, 0
|
||||||
|
%69 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %68, ptr %67, 1
|
||||||
|
%70 = call %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %69)
|
||||||
|
%71 = call ptr @reflect.Value.UnsafePointer(%reflect.Value %70)
|
||||||
|
%72 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 16)
|
||||||
|
%73 = getelementptr inbounds %"github.com/goplus/llgo/runtime/internal/runtime.eface", ptr %72, i64 0
|
||||||
|
%74 = load ptr, ptr @_llgo_Pointer, align 8
|
||||||
|
%75 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %74, 0
|
||||||
|
%76 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %75, ptr %71, 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.eface" %76, ptr %73, align 8
|
||||||
|
%77 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %72, 0
|
||||||
|
%78 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %77, i64 1, 1
|
||||||
|
%79 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %78, i64 1, 2
|
||||||
|
%80 = call { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %79)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/reflectfn.main$1"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { ptr }, ptr %0, align 8
|
||||||
|
%2 = extractvalue { ptr } %1, 0
|
||||||
|
%3 = load i64, ptr %2, align 4
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintInt"(i64 %3)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 10)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintString"(%"github.com/goplus/llgo/runtime/internal/runtime.String")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8)
|
||||||
|
|
||||||
|
declare void @fmt.init()
|
||||||
|
|
||||||
|
declare void @reflect.init()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testgo/reflectfn.init$after"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load ptr, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8
|
||||||
|
%1 = icmp eq ptr %0, null
|
||||||
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%3 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %2, 0
|
||||||
|
%4 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %3, i64 0, 1
|
||||||
|
%5 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %4, i64 0, 2
|
||||||
|
%6 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%7 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %6, 0
|
||||||
|
%8 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %7, i64 0, 1
|
||||||
|
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %8, i64 0, 2
|
||||||
|
%10 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %5, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %9, i1 false)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %10)
|
||||||
|
store ptr %10, ptr @"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac", align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
%11 = load ptr, ptr @_llgo_Pointer, align 8
|
||||||
|
%12 = icmp eq ptr %11, null
|
||||||
|
br i1 %12, label %_llgo_3, label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_2
|
||||||
|
%13 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 58)
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %13)
|
||||||
|
store ptr %13, ptr @_llgo_Pointer, align 8
|
||||||
|
br label %_llgo_4
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_3, %_llgo_2
|
||||||
|
%14 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%15 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %14, 0
|
||||||
|
%16 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %15, i64 0, 1
|
||||||
|
%17 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %16, i64 0, 2
|
||||||
|
%18 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%19 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %18, 0
|
||||||
|
%20 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %19, i64 0, 1
|
||||||
|
%21 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %20, i64 0, 2
|
||||||
|
%22 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %17, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %21, i1 false)
|
||||||
|
%23 = call %"github.com/goplus/llgo/runtime/abi.StructField" @"github.com/goplus/llgo/runtime/internal/runtime.StructField"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 2 }, ptr %22, i64 0, %"github.com/goplus/llgo/runtime/internal/runtime.String" zeroinitializer, i1 false)
|
||||||
|
%24 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 58)
|
||||||
|
%25 = call %"github.com/goplus/llgo/runtime/abi.StructField" @"github.com/goplus/llgo/runtime/internal/runtime.StructField"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 5 }, ptr %24, i64 8, %"github.com/goplus/llgo/runtime/internal/runtime.String" zeroinitializer, i1 false)
|
||||||
|
%26 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 112)
|
||||||
|
%27 = getelementptr %"github.com/goplus/llgo/runtime/abi.StructField", ptr %26, i64 0
|
||||||
|
store %"github.com/goplus/llgo/runtime/abi.StructField" %23, ptr %27, align 8
|
||||||
|
%28 = getelementptr %"github.com/goplus/llgo/runtime/abi.StructField", ptr %26, i64 1
|
||||||
|
store %"github.com/goplus/llgo/runtime/abi.StructField" %25, ptr %28, align 8
|
||||||
|
%29 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %26, 0
|
||||||
|
%30 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %29, i64 2, 1
|
||||||
|
%31 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %30, i64 2, 2
|
||||||
|
%32 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Struct"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @3, i64 43 }, i64 16, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %31)
|
||||||
|
store ptr %32, ptr @"github.com/goplus/llgo/cl/_testgo/reflectfn.struct$b7Su1hWaFih-M0M9hMk6nO_RD1K_GQu5WjIXQp6Q2e8", align 8
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice", %"github.com/goplus/llgo/runtime/internal/runtime.Slice", i1)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64)
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Struct"(%"github.com/goplus/llgo/runtime/internal/runtime.String", i64, %"github.com/goplus/llgo/runtime/internal/runtime.Slice")
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/runtime/abi.StructField" @"github.com/goplus/llgo/runtime/internal/runtime.StructField"(%"github.com/goplus/llgo/runtime/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/runtime/internal/runtime.String", i1)
|
||||||
|
|
||||||
|
declare { i64, %"github.com/goplus/llgo/runtime/internal/runtime.iface" } @fmt.Println(%"github.com/goplus/llgo/runtime/internal/runtime.Slice")
|
||||||
|
|
||||||
|
define linkonce void @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/reflectfn.demo"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
tail call void @"github.com/goplus/llgo/cl/_testgo/reflectfn.demo"()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare %reflect.Value @reflect.ValueOf(%"github.com/goplus/llgo/runtime/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare ptr @reflect.Value.UnsafePointer(%reflect.Value)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintInt"(i64)
|
||||||
@@ -5,8 +5,8 @@ source_filename = "github.com/goplus/llgo/cl/_testgo/tpnamed"
|
|||||||
%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 }
|
%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 }
|
||||||
%"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[error]" = type { ptr, ptr }
|
%"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[error]" = type { ptr, ptr }
|
||||||
%"github.com/goplus/llgo/runtime/internal/runtime.iface" = type { ptr, ptr }
|
%"github.com/goplus/llgo/runtime/internal/runtime.iface" = type { ptr, ptr }
|
||||||
%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[[0]byte]" = type { ptr, ptr }
|
%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" = type { ptr, ptr }
|
||||||
%"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" = type { ptr, ptr }
|
%"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" = type { ptr, ptr }
|
||||||
|
|
||||||
@"github.com/goplus/llgo/cl/_testgo/tpnamed.init$guard" = global i1 false, align 1
|
@"github.com/goplus/llgo/cl/_testgo/tpnamed.init$guard" = global i1 false, align 1
|
||||||
|
|
||||||
@@ -40,13 +40,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
|
|||||||
|
|
||||||
define void @"github.com/goplus/llgo/cl/_testgo/tpnamed.main"() {
|
define void @"github.com/goplus/llgo/cl/_testgo/tpnamed.main"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%0 = call [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.RunIO[[0]byte]"(%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[[0]byte]" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1", ptr null })
|
%0 = call [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.RunIO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]"(%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1", ptr null })
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"() {
|
define %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
ret %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1$1", ptr null }
|
ret %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" { ptr @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1$1", ptr null }
|
||||||
}
|
}
|
||||||
|
|
||||||
define [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1$1"() {
|
define [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1$1"() {
|
||||||
@@ -66,19 +66,19 @@ _llgo_0:
|
|||||||
ret %"github.com/goplus/llgo/runtime/internal/runtime.iface" %1
|
ret %"github.com/goplus/llgo/runtime/internal/runtime.iface" %1
|
||||||
}
|
}
|
||||||
|
|
||||||
define linkonce %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"(ptr %0) {
|
define linkonce %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" @"__llgo_stub.github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = tail call %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"()
|
%1 = tail call %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" @"github.com/goplus/llgo/cl/_testgo/tpnamed.main$1"()
|
||||||
ret %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" %1
|
ret %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %1
|
||||||
}
|
}
|
||||||
|
|
||||||
define linkonce [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.RunIO[[0]byte]"(%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[[0]byte]" %0) {
|
define linkonce [0 x i8] @"github.com/goplus/llgo/cl/_testgo/tpnamed.RunIO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]"(%"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[[0]byte]" %0, 1
|
%1 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %0, 1
|
||||||
%2 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[[0]byte]" %0, 0
|
%2 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.IO[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %0, 0
|
||||||
%3 = call %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" %2(ptr %1)
|
%3 = call %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %2(ptr %1)
|
||||||
%4 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" %3, 1
|
%4 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %3, 1
|
||||||
%5 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[[0]byte]" %3, 0
|
%5 = extractvalue %"github.com/goplus/llgo/cl/_testgo/tpnamed.Future[github.com/goplus/llgo/cl/_testgo/tpnamed.Void]" %3, 0
|
||||||
%6 = call [0 x i8] %5(ptr %4)
|
%6 = call [0 x i8] %5(ptr %4)
|
||||||
ret [0 x i8] %6
|
ret [0 x i8] %6
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,10 @@ source_filename = "github.com/goplus/llgo/cl/_testrt/any"
|
|||||||
@"github.com/goplus/llgo/cl/_testrt/any.init$guard" = global i1 false, align 1
|
@"github.com/goplus/llgo/cl/_testrt/any.init$guard" = global i1 false, align 1
|
||||||
@_llgo_int8 = linkonce global ptr null, align 8
|
@_llgo_int8 = linkonce global ptr null, align 8
|
||||||
@"*_llgo_int8" = linkonce global ptr null, align 8
|
@"*_llgo_int8" = linkonce global ptr null, align 8
|
||||||
@0 = private unnamed_addr constant [42 x i8] c"type assertion interface{} -> *int8 failed", align 1
|
@0 = private unnamed_addr constant [58 x i8] c"type assertion any -> *github.com/goplus/lib/c.Char failed", align 1
|
||||||
@_llgo_string = linkonce global ptr null, align 8
|
@_llgo_string = linkonce global ptr null, align 8
|
||||||
@_llgo_int = linkonce global ptr null, align 8
|
@_llgo_int = linkonce global ptr null, align 8
|
||||||
@1 = private unnamed_addr constant [40 x i8] c"type assertion interface{} -> int failed", align 1
|
@1 = private unnamed_addr constant [32 x i8] c"type assertion any -> int failed", align 1
|
||||||
@2 = private unnamed_addr constant [7 x i8] c"%s %d\0A\00", align 1
|
@2 = private unnamed_addr constant [7 x i8] c"%s %d\0A\00", align 1
|
||||||
@3 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
|
@3 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_0
|
_llgo_2: ; preds = %_llgo_0
|
||||||
%6 = load ptr, ptr @_llgo_string, align 8
|
%6 = load ptr, ptr @_llgo_string, align 8
|
||||||
%7 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%7 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 42 }, ptr %7, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 58 }, ptr %7, align 8
|
||||||
%8 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %6, 0
|
%8 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %6, 0
|
||||||
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %8, ptr %7, 1
|
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %8, ptr %7, 1
|
||||||
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %9)
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %9)
|
||||||
@@ -52,7 +52,7 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_0
|
_llgo_2: ; preds = %_llgo_0
|
||||||
%7 = load ptr, ptr @_llgo_string, align 8
|
%7 = load ptr, ptr @_llgo_string, align 8
|
||||||
%8 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%8 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 40 }, ptr %8, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @1, i64 32 }, ptr %8, align 8
|
||||||
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %7, 0
|
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %7, 0
|
||||||
%10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %9, ptr %8, 1
|
%10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %9, ptr %8, 1
|
||||||
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %10)
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %10)
|
||||||
|
|||||||
25
cl/_testrt/closurebound/in.go
Normal file
25
cl/_testrt/closurebound/in.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
se := demo1{}
|
||||||
|
f := se.encode
|
||||||
|
if f() != 1 {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var my = demo2{}.encode
|
||||||
|
|
||||||
|
type demo1 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (se demo1) encode() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
type demo2 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (se demo2) encode() int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
117
cl/_testrt/closurebound/out.ll
Normal file
117
cl/_testrt/closurebound/out.ll
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
; ModuleID = 'github.com/goplus/llgo/cl/_testrt/closurebound'
|
||||||
|
source_filename = "github.com/goplus/llgo/cl/_testrt/closurebound"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" = type {}
|
||||||
|
%"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" = type {}
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
%"github.com/goplus/llgo/runtime/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"github.com/goplus/llgo/cl/_testrt/closurebound.init$guard" = global i1 false, align 1
|
||||||
|
@"github.com/goplus/llgo/cl/_testrt/closurebound.my" = global { ptr, ptr } zeroinitializer, align 8
|
||||||
|
@0 = private unnamed_addr constant [5 x i8] c"error", align 1
|
||||||
|
@_llgo_string = linkonce global ptr null, align 8
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo1.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret i64 1
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.(*demo1).encode"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load %"github.com/goplus/llgo/cl/_testrt/closurebound.demo1", ptr %0, align 1
|
||||||
|
%2 = call i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo1.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo2.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" %0) {
|
||||||
|
_llgo_0:
|
||||||
|
ret i64 2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.(*demo2).encode"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load %"github.com/goplus/llgo/cl/_testrt/closurebound.demo2", ptr %0, align 1
|
||||||
|
%2 = call i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo2.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" %1)
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testrt/closurebound.init"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testrt/closurebound.init$guard", align 1
|
||||||
|
br i1 %0, label %_llgo_2, label %_llgo_1
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
store i1 true, ptr @"github.com/goplus/llgo/cl/_testrt/closurebound.init$guard", align 1
|
||||||
|
call void @"github.com/goplus/llgo/cl/_testrt/closurebound.init$after"()
|
||||||
|
%1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%2 = getelementptr inbounds { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" }, ptr %1, i32 0, i32 0
|
||||||
|
store %"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" zeroinitializer, ptr %2, align 1
|
||||||
|
%3 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closurebound.demo2.encode$bound", ptr undef }, ptr %1, 1
|
||||||
|
store { ptr, ptr } %3, ptr @"github.com/goplus/llgo/cl/_testrt/closurebound.my", align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testrt/closurebound.main"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0)
|
||||||
|
%1 = getelementptr inbounds { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" }, ptr %0, i32 0, i32 0
|
||||||
|
store %"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" zeroinitializer, ptr %1, align 1
|
||||||
|
%2 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closurebound.demo1.encode$bound", ptr undef }, ptr %0, 1
|
||||||
|
%3 = extractvalue { ptr, ptr } %2, 1
|
||||||
|
%4 = extractvalue { ptr, ptr } %2, 0
|
||||||
|
%5 = call i64 %4(ptr %3)
|
||||||
|
%6 = icmp ne i64 %5, 1
|
||||||
|
br i1 %6, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%7 = load ptr, ptr @_llgo_string, align 8
|
||||||
|
%8 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
|
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 5 }, ptr %8, align 8
|
||||||
|
%9 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %7, 0
|
||||||
|
%10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %9, ptr %8, 1
|
||||||
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %10)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo2.encode$bound"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" }, ptr %0, align 1
|
||||||
|
%2 = extractvalue { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" } %1, 0
|
||||||
|
%3 = call i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo2.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo2" %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo1.encode$bound"(ptr %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = load { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" }, ptr %0, align 1
|
||||||
|
%2 = extractvalue { %"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" } %1, 0
|
||||||
|
%3 = call i64 @"github.com/goplus/llgo/cl/_testrt/closurebound.demo1.encode"(%"github.com/goplus/llgo/cl/_testrt/closurebound.demo1" %2)
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @"github.com/goplus/llgo/cl/_testrt/closurebound.init$after"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = load ptr, ptr @_llgo_string, align 8
|
||||||
|
%1 = icmp eq ptr %0, null
|
||||||
|
br i1 %1, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%2 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 24)
|
||||||
|
store ptr %2, ptr @_llgo_string, align 8
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface")
|
||||||
@@ -29,7 +29,7 @@ _llgo_0:
|
|||||||
%3 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
%3 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
||||||
%4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0
|
%4 = getelementptr inbounds { ptr }, ptr %3, i32 0, i32 0
|
||||||
store ptr %1, ptr %4, align 8
|
store ptr %1, ptr %4, align 8
|
||||||
%5 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closureconv.add$bound", ptr undef }, ptr %3, 1
|
%5 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closureconv.(*Call).add$bound", ptr undef }, ptr %3, 1
|
||||||
%6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/closureconv.Call", ptr %1, i32 0, i32 0
|
%6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/closureconv.Call", ptr %1, i32 0, i32 0
|
||||||
%7 = alloca %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", align 8
|
%7 = alloca %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", align 8
|
||||||
store { ptr, ptr } %5, ptr %7, align 8
|
store { ptr, ptr } %5, ptr %7, align 8
|
||||||
@@ -46,7 +46,7 @@ _llgo_0:
|
|||||||
%1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
%1 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
||||||
%2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0
|
%2 = getelementptr inbounds { ptr }, ptr %1, i32 0, i32 0
|
||||||
store ptr %0, ptr %2, align 8
|
store ptr %0, ptr %2, align 8
|
||||||
%3 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closureconv.add$bound", ptr undef }, ptr %1, 1
|
%3 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/closureconv.(*Call).add$bound", ptr undef }, ptr %1, 1
|
||||||
%4 = alloca %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", align 8
|
%4 = alloca %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", align 8
|
||||||
store { ptr, ptr } %3, ptr %4, align 8
|
store { ptr, ptr } %3, ptr %4, align 8
|
||||||
%5 = load %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", ptr %4, align 8
|
%5 = load %"github.com/goplus/llgo/cl/_testrt/closureconv.Func", ptr %4, align 8
|
||||||
@@ -158,7 +158,7 @@ _llgo_0:
|
|||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)
|
||||||
|
|
||||||
define i64 @"github.com/goplus/llgo/cl/_testrt/closureconv.add$bound"(ptr %0, i64 %1, i64 %2) {
|
define i64 @"github.com/goplus/llgo/cl/_testrt/closureconv.(*Call).add$bound"(ptr %0, i64 %1, i64 %2) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%3 = load { ptr }, ptr %0, align 8
|
%3 = load { ptr }, ptr %0, align 8
|
||||||
%4 = extractvalue { ptr } %3, 0
|
%4 = extractvalue { ptr } %3, 0
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ _llgo_6: ; preds = %_llgo_4
|
|||||||
%32 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
%32 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8)
|
||||||
%33 = getelementptr inbounds { ptr }, ptr %32, i32 0, i32 0
|
%33 = getelementptr inbounds { ptr }, ptr %32, i32 0, i32 0
|
||||||
store ptr %30, ptr %33, align 8
|
store ptr %30, ptr %33, align 8
|
||||||
%34 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/intgen.next$bound", ptr undef }, ptr %32, 1
|
%34 = insertvalue { ptr, ptr } { ptr @"github.com/goplus/llgo/cl/_testrt/intgen.(*generator).next$bound", ptr undef }, ptr %32, 1
|
||||||
%35 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/cl/_testrt/intgen.genInts"(i64 5, { ptr, ptr } %34)
|
%35 = call %"github.com/goplus/llgo/runtime/internal/runtime.Slice" @"github.com/goplus/llgo/cl/_testrt/intgen.genInts"(i64 5, { ptr, ptr } %34)
|
||||||
%36 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %35, 1
|
%36 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %35, 1
|
||||||
br label %_llgo_7
|
br label %_llgo_7
|
||||||
@@ -182,7 +182,7 @@ declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64)
|
|||||||
|
|
||||||
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64)
|
declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64)
|
||||||
|
|
||||||
define i32 @"github.com/goplus/llgo/cl/_testrt/intgen.next$bound"(ptr %0) {
|
define i32 @"github.com/goplus/llgo/cl/_testrt/intgen.(*generator).next$bound"(ptr %0) {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%1 = load { ptr }, ptr %0, align 8
|
%1 = load { ptr }, ptr %0, align 8
|
||||||
%2 = extractvalue { ptr } %1, 0
|
%2 = extractvalue { ptr } %1, 0
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ source_filename = "github.com/goplus/llgo/cl/_testrt/tpabi"
|
|||||||
@5 = private unnamed_addr constant [4 x i8] c"Demo", align 1
|
@5 = private unnamed_addr constant [4 x i8] c"Demo", align 1
|
||||||
@"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac" = linkonce global ptr null, align 8
|
@"_llgo_func$2_iS07vIlF2_rZqWB5eU0IvP_9HviM4MYZNkXZDvbac" = linkonce global ptr null, align 8
|
||||||
@6 = private unnamed_addr constant [4 x i8] c"Info", align 1
|
@6 = private unnamed_addr constant [4 x i8] c"Info", align 1
|
||||||
@7 = private unnamed_addr constant [91 x i8] c"type assertion interface{} -> github.com/goplus/llgo/cl/_testrt/tpabi.T[string, int] failed", align 1
|
@7 = private unnamed_addr constant [83 x i8] c"type assertion any -> github.com/goplus/llgo/cl/_testrt/tpabi.T[string, int] failed", align 1
|
||||||
@8 = private unnamed_addr constant [5 x i8] c"hello", align 1
|
@8 = private unnamed_addr constant [5 x i8] c"hello", align 1
|
||||||
@"*_llgo_github.com/goplus/llgo/cl/_testrt/tpabi.T[string,int]" = linkonce global ptr null, align 8
|
@"*_llgo_github.com/goplus/llgo/cl/_testrt/tpabi.T[string,int]" = linkonce global ptr null, align 8
|
||||||
@"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs" = linkonce global ptr null, align 8
|
@"_llgo_iface$BP0p_lUsEd-IbbtJVukGmgrdQkqzcoYzSiwgUvgFvUs" = linkonce global ptr null, align 8
|
||||||
@@ -107,7 +107,7 @@ _llgo_1: ; preds = %_llgo_0
|
|||||||
_llgo_2: ; preds = %_llgo_0
|
_llgo_2: ; preds = %_llgo_0
|
||||||
%38 = load ptr, ptr @_llgo_string, align 8
|
%38 = load ptr, ptr @_llgo_string, align 8
|
||||||
%39 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
%39 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16)
|
||||||
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 91 }, ptr %39, align 8
|
store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 83 }, ptr %39, align 8
|
||||||
%40 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %38, 0
|
%40 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %38, 0
|
||||||
%41 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %40, ptr %39, 1
|
%41 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %40, ptr %39, 1
|
||||||
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %41)
|
call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %41)
|
||||||
|
|||||||
@@ -60,11 +60,14 @@ func findLoop(states []*blockState, path []int, from, iblk int) []int {
|
|||||||
path = append(path, iblk)
|
path = append(path, iblk)
|
||||||
self := states[iblk]
|
self := states[iblk]
|
||||||
for _, succ := range self.succs {
|
for _, succ := range self.succs {
|
||||||
if states[succ].fdel {
|
if s := states[succ]; s.fdel || s.loop {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if pos := find(path, succ); pos >= 0 {
|
if pos := find(path, succ); pos >= 0 {
|
||||||
if pos > 0 {
|
if pos > 0 {
|
||||||
|
for _, i := range path[pos:] { // mark inner loop
|
||||||
|
states[i].loop = true
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, i := range path {
|
for _, i := range path {
|
||||||
@@ -72,6 +75,11 @@ func findLoop(states []*blockState, path []int, from, iblk int) []int {
|
|||||||
s.loop = true
|
s.loop = true
|
||||||
s.fdel = true
|
s.fdel = true
|
||||||
}
|
}
|
||||||
|
for _, s := range states { // clear inner loop mark
|
||||||
|
if !s.fdel {
|
||||||
|
s.loop = false
|
||||||
|
}
|
||||||
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
if ret := findLoop(states, path, from, succ); len(ret) > 0 {
|
if ret := findLoop(states, path, from, succ); len(ret) > 0 {
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ func TestTestdefer(t *testing.T) {
|
|||||||
if strings.HasPrefix(name, "firstloop") {
|
if strings.HasPrefix(name, "firstloop") {
|
||||||
return "Loop"
|
return "Loop"
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(name, "gobuild") {
|
||||||
|
return "Import"
|
||||||
|
}
|
||||||
return "main"
|
return "main"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
23
cl/import.go
23
cl/import.go
@@ -402,6 +402,10 @@ func funcName(pkg *types.Package, fn *ssa.Function, org bool) string {
|
|||||||
recv = parent.Signature.Recv()
|
recv = parent.Signature.Recv()
|
||||||
} else {
|
} else {
|
||||||
recv = fn.Signature.Recv()
|
recv = fn.Signature.Recv()
|
||||||
|
// check $bound
|
||||||
|
if recv == nil && strings.HasSuffix(fn.Name(), "$bound") && len(fn.FreeVars) == 1 {
|
||||||
|
recv = types.NewVar(token.NoPos, nil, "", fn.FreeVars[0].Type())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var fnName string
|
var fnName string
|
||||||
if org := fn.Origin(); org != nil {
|
if org := fn.Origin(); org != nil {
|
||||||
@@ -446,17 +450,18 @@ const (
|
|||||||
llgoAlloca = llgoInstrBase + 2
|
llgoAlloca = llgoInstrBase + 2
|
||||||
llgoAllocaCStr = llgoInstrBase + 3
|
llgoAllocaCStr = llgoInstrBase + 3
|
||||||
llgoAllocaCStrs = llgoInstrBase + 4
|
llgoAllocaCStrs = llgoInstrBase + 4
|
||||||
llgoAdvance = llgoInstrBase + 5
|
llgoAllocCStr = llgoInstrBase + 5
|
||||||
llgoIndex = llgoInstrBase + 6
|
llgoAdvance = llgoInstrBase + 6
|
||||||
llgoStringData = llgoInstrBase + 7
|
llgoIndex = llgoInstrBase + 7
|
||||||
llgoString = llgoInstrBase + 8
|
llgoStringData = llgoInstrBase + 8
|
||||||
llgoDeferData = llgoInstrBase + 9
|
llgoString = llgoInstrBase + 9
|
||||||
|
llgoDeferData = llgoInstrBase + 0xa
|
||||||
|
|
||||||
llgoSigjmpbuf = llgoInstrBase + 0xa
|
llgoSigjmpbuf = llgoInstrBase + 0xb
|
||||||
llgoSigsetjmp = llgoInstrBase + 0xb
|
llgoSigsetjmp = llgoInstrBase + 0xc
|
||||||
llgoSiglongjmp = llgoInstrBase + 0xc
|
llgoSiglongjmp = llgoInstrBase + 0xd
|
||||||
|
|
||||||
llgoFuncAddr = llgoInstrBase + 0xd
|
llgoFuncAddr = llgoInstrBase + 0xe
|
||||||
|
|
||||||
llgoPyList = llgoInstrBase + 0x10
|
llgoPyList = llgoInstrBase + 0x10
|
||||||
llgoPyStr = llgoInstrBase + 0x11
|
llgoPyStr = llgoInstrBase + 0x11
|
||||||
|
|||||||
12
cl/instr.go
12
cl/instr.go
@@ -165,6 +165,15 @@ func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr)
|
|||||||
panic("allocaCStr(s string): invalid arguments")
|
panic("allocaCStr(s string): invalid arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func allocCStr(s string) *int8
|
||||||
|
func (p *context) allocCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 1 {
|
||||||
|
s := p.compileValue(b, args[0])
|
||||||
|
return b.AllocCStr(s)
|
||||||
|
}
|
||||||
|
panic("allocCStr(s string): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
// func allocaCStrs(strs []string, endWithNil bool) **int8
|
// func allocaCStrs(strs []string, endWithNil bool) **int8
|
||||||
func (p *context) allocaCStrs(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
func (p *context) allocaCStrs(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
if len(args) == 2 {
|
if len(args) == 2 {
|
||||||
@@ -281,6 +290,7 @@ var llgoInstrs = map[string]int{
|
|||||||
"advance": llgoAdvance,
|
"advance": llgoAdvance,
|
||||||
"index": llgoIndex,
|
"index": llgoIndex,
|
||||||
"alloca": llgoAlloca,
|
"alloca": llgoAlloca,
|
||||||
|
"allocCStr": llgoAllocCStr,
|
||||||
"allocaCStr": llgoAllocaCStr,
|
"allocaCStr": llgoAllocaCStr,
|
||||||
"allocaCStrs": llgoAllocaCStrs,
|
"allocaCStrs": llgoAllocaCStrs,
|
||||||
"string": llgoString,
|
"string": llgoString,
|
||||||
@@ -470,6 +480,8 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
|
|||||||
ret = p.alloca(b, args)
|
ret = p.alloca(b, args)
|
||||||
case llgoAllocaCStr:
|
case llgoAllocaCStr:
|
||||||
ret = p.allocaCStr(b, args)
|
ret = p.allocaCStr(b, args)
|
||||||
|
case llgoAllocCStr:
|
||||||
|
ret = p.allocCStr(b, args)
|
||||||
case llgoAllocaCStrs:
|
case llgoAllocaCStrs:
|
||||||
ret = p.allocaCStrs(b, args)
|
ret = p.allocaCStrs(b, args)
|
||||||
case llgoString:
|
case llgoString:
|
||||||
|
|||||||
82
cmd/internal/base/pass.go
Normal file
82
cmd/internal/base/pass.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package base
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stringValue struct {
|
||||||
|
p *PassArgs
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *stringValue) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *stringValue) Set(v string) error {
|
||||||
|
p.p.Args = append(p.p.Args, fmt.Sprintf("-%v=%v", p.name, v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type boolValue struct {
|
||||||
|
p *PassArgs
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *boolValue) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *boolValue) Set(v string) error {
|
||||||
|
p.p.Args = append(p.p.Args, fmt.Sprintf("-%v=%v", p.name, v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *boolValue) IsBoolFlag() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassArgs struct {
|
||||||
|
Args []string
|
||||||
|
Flag *flag.FlagSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PassArgs) Tags() string {
|
||||||
|
for _, v := range p.Args {
|
||||||
|
if strings.HasPrefix(v, "-tags=") {
|
||||||
|
return v[6:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PassArgs) Var(names ...string) {
|
||||||
|
for _, name := range names {
|
||||||
|
p.Flag.Var(&stringValue{p: p, name: name}, name, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PassArgs) Bool(names ...string) {
|
||||||
|
for _, name := range names {
|
||||||
|
p.Flag.Var(&boolValue{p: p, name: name}, name, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPassArgs(flag *flag.FlagSet) *PassArgs {
|
||||||
|
p := &PassArgs{Flag: flag}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func PassBuildFlags(cmd *Command) *PassArgs {
|
||||||
|
p := NewPassArgs(&cmd.Flag)
|
||||||
|
p.Bool("n", "x")
|
||||||
|
p.Bool("a")
|
||||||
|
p.Bool("linkshared", "race", "msan", "asan",
|
||||||
|
"trimpath", "work")
|
||||||
|
p.Var("p", "asmflags", "compiler", "buildmode",
|
||||||
|
"gcflags", "gccgoflags", "installsuffix",
|
||||||
|
"ldflags", "pkgdir", "toolexec", "buildvcs")
|
||||||
|
return p
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/flags"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
)
|
)
|
||||||
@@ -34,17 +35,24 @@ var Cmd = &base.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Cmd.Run = runCmd
|
Cmd.Run = runCmd
|
||||||
|
base.PassBuildFlags(Cmd)
|
||||||
|
flags.AddBuildFlags(&Cmd.Flag)
|
||||||
|
flags.AddOutputFlags(&Cmd.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
conf := &build.Config{
|
|
||||||
Mode: build.ModeBuild,
|
if err := cmd.Flag.Parse(args); err != nil {
|
||||||
AppExt: build.DefaultAppExt(),
|
return
|
||||||
}
|
|
||||||
if len(args) >= 2 && args[0] == "-o" {
|
|
||||||
conf.OutFile = args[1]
|
|
||||||
args = args[2:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf := build.NewDefaultConf(build.ModeBuild)
|
||||||
|
conf.Tags = flags.Tags
|
||||||
|
conf.Verbose = flags.Verbose
|
||||||
|
conf.OutFile = flags.OutputFile
|
||||||
|
|
||||||
|
args = cmd.Flag.Args()
|
||||||
|
|
||||||
_, err := build.Do(args, conf)
|
_, err := build.Do(args, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package clean
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/flags"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,9 +31,19 @@ var Cmd = &base.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Cmd.Run = runCmd
|
Cmd.Run = runCmd
|
||||||
|
flags.AddBuildFlags(&Cmd.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
|
|
||||||
|
if err := cmd.Flag.Parse(args); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
conf := build.NewDefaultConf(0)
|
conf := build.NewDefaultConf(0)
|
||||||
|
conf.Tags = flags.Tags
|
||||||
|
conf.Verbose = flags.Verbose
|
||||||
|
|
||||||
|
args = cmd.Flag.Args()
|
||||||
build.Clean(args, conf)
|
build.Clean(args, conf)
|
||||||
}
|
}
|
||||||
|
|||||||
27
cmd/internal/flags/flags.go
Normal file
27
cmd/internal/flags/flags.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
var OutputFile string
|
||||||
|
|
||||||
|
func AddOutputFlags(fs *flag.FlagSet) {
|
||||||
|
fs.StringVar(&OutputFile, "o", "", "Output file")
|
||||||
|
}
|
||||||
|
|
||||||
|
var Verbose bool
|
||||||
|
var BuildEnv string
|
||||||
|
var Tags string
|
||||||
|
|
||||||
|
func AddBuildFlags(fs *flag.FlagSet) {
|
||||||
|
fs.BoolVar(&Verbose, "v", false, "Verbose mode")
|
||||||
|
fs.StringVar(&Tags, "tags", "", "Build tags")
|
||||||
|
fs.StringVar(&BuildEnv, "buildenv", "", "Build environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
var Gen bool
|
||||||
|
|
||||||
|
func AddCmpTestFlags(fs *flag.FlagSet) {
|
||||||
|
fs.BoolVar(&Gen, "gen", false, "Generate llgo.expect file")
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/flags"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
)
|
)
|
||||||
@@ -34,10 +35,20 @@ var Cmd = &base.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Cmd.Run = runCmd
|
Cmd.Run = runCmd
|
||||||
|
flags.AddBuildFlags(&Cmd.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
|
|
||||||
|
if err := cmd.Flag.Parse(args); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
conf := build.NewDefaultConf(build.ModeInstall)
|
conf := build.NewDefaultConf(build.ModeInstall)
|
||||||
|
conf.Tags = flags.Tags
|
||||||
|
conf.Verbose = flags.Verbose
|
||||||
|
|
||||||
|
args = cmd.Flag.Args()
|
||||||
_, err := build.Do(args, conf)
|
_, err := build.Do(args, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/flags"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
)
|
)
|
||||||
@@ -47,6 +47,10 @@ var CmpTestCmd = &base.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
Cmd.Run = runCmd
|
Cmd.Run = runCmd
|
||||||
CmpTestCmd.Run = runCmpTest
|
CmpTestCmd.Run = runCmpTest
|
||||||
|
base.PassBuildFlags(Cmd)
|
||||||
|
flags.AddBuildFlags(&Cmd.Flag)
|
||||||
|
flags.AddBuildFlags(&CmpTestCmd.Flag)
|
||||||
|
flags.AddCmpTestFlags(&CmpTestCmd.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
@@ -57,12 +61,18 @@ func runCmpTest(cmd *base.Command, args []string) {
|
|||||||
runCmdEx(cmd, args, build.ModeCmpTest)
|
runCmdEx(cmd, args, build.ModeCmpTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmdEx(_ *base.Command, args []string, mode build.Mode) {
|
func runCmdEx(cmd *base.Command, args []string, mode build.Mode) {
|
||||||
conf := build.NewDefaultConf(mode)
|
|
||||||
if mode == build.ModeCmpTest && len(args) > 0 && args[0] == "-gen" {
|
if err := cmd.Flag.Parse(args); err != nil {
|
||||||
conf.GenExpect = true
|
return
|
||||||
args = args[1:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf := build.NewDefaultConf(mode)
|
||||||
|
conf.Tags = flags.Tags
|
||||||
|
conf.Verbose = flags.Verbose
|
||||||
|
conf.GenExpect = flags.Gen
|
||||||
|
|
||||||
|
args = cmd.Flag.Args()
|
||||||
args, runArgs, err := parseRunArgs(args)
|
args, runArgs, err := parseRunArgs(args)
|
||||||
check(err)
|
check(err)
|
||||||
conf.RunArgs = runArgs
|
conf.RunArgs = runArgs
|
||||||
@@ -74,24 +84,11 @@ func runCmdEx(_ *base.Command, args []string, mode build.Mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseRunArgs(args []string) ([]string, []string, error) {
|
func parseRunArgs(args []string) ([]string, []string, error) {
|
||||||
n := build.SkipFlagArgs(args)
|
if len(args) == 0 {
|
||||||
if n < 0 {
|
|
||||||
return nil, nil, errNoProj
|
return nil, nil, errNoProj
|
||||||
}
|
}
|
||||||
|
|
||||||
arg := args[n]
|
return args[:1], args[1:], nil
|
||||||
if isGoFile(arg) {
|
|
||||||
n++
|
|
||||||
for n < len(args) && isGoFile(args[n]) {
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
return args[:n], args[n:], nil
|
|
||||||
}
|
|
||||||
return args[:n+1], args[n+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGoFile(fname string) bool {
|
|
||||||
return filepath.Ext(fname) == ".go"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cmd/internal/base"
|
"github.com/goplus/llgo/cmd/internal/base"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/flags"
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,15 +17,20 @@ var Cmd = &base.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Cmd.Run = runCmd
|
Cmd.Run = runCmd
|
||||||
|
flags.AddBuildFlags(&Cmd.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
func runCmd(cmd *base.Command, args []string) {
|
||||||
runCmdEx(cmd, args, build.ModeRun)
|
|
||||||
|
if err := cmd.Flag.Parse(args); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmdEx(_ *base.Command, args []string, mode build.Mode) {
|
conf := build.NewDefaultConf(build.ModeTest)
|
||||||
conf := build.NewDefaultConf(mode)
|
conf.Tags = flags.Tags
|
||||||
conf.Mode = build.ModeTest
|
conf.Verbose = flags.Verbose
|
||||||
|
|
||||||
|
args = cmd.Flag.Args()
|
||||||
_, err := build.Do(args, conf)
|
_, err := build.Do(args, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _TestCommandHandling(t *testing.T) {
|
func TestCommandHandling(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
28
cmd/llgo/build_cmd.gox
Normal file
28
cmd/llgo/build_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "build [flags] [packages]"
|
||||||
|
|
||||||
|
short "Compile packages and dependencies"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.Cmd.Run self.Cmd, args
|
||||||
|
}
|
||||||
28
cmd/llgo/clean_cmd.gox
Normal file
28
cmd/llgo/clean_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/clean"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "clean [flags] [packages]"
|
||||||
|
|
||||||
|
short "Remove object files and cached files"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.Cmd.Run self.Cmd, args
|
||||||
|
}
|
||||||
28
cmd/llgo/cmptest_cmd.gox
Normal file
28
cmd/llgo/cmptest_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/run"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "cmptest [flags] package [arguments...]"
|
||||||
|
|
||||||
|
short "Compile and run with llgo, compare result (stdout/stderr/exitcode) with go or llgo.expect; generate llgo.expect file if -gen is specified"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.CmpTestCmd.Run self.CmpTestCmd, args
|
||||||
|
}
|
||||||
22
cmd/llgo/get_cmd.gox
Normal file
22
cmd/llgo/get_cmd.gox
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use "get [flags] [packages]"
|
||||||
|
|
||||||
|
short "Add dependencies to current module and install them"
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
panic "todo"
|
||||||
|
}
|
||||||
213
cmd/llgo/gop_autogen.go
Normal file
213
cmd/llgo/gop_autogen.go
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
// Code generated by gop (Go+); DO NOT EDIT.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/goplus/cobra/xcmd"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/build"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/clean"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/install"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/run"
|
||||||
|
"github.com/goplus/llgo/cmd/internal/test"
|
||||||
|
"github.com/goplus/llgo/internal/env"
|
||||||
|
"github.com/qiniu/x/stringutil"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const _ = true
|
||||||
|
|
||||||
|
type Cmd_build struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_clean struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_cmptest struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_get struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_install struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type App struct {
|
||||||
|
xcmd.App
|
||||||
|
}
|
||||||
|
type Cmd_run struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_test struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
type Cmd_version struct {
|
||||||
|
xcmd.Command
|
||||||
|
*App
|
||||||
|
}
|
||||||
|
//line cmd/llgo/main_app.gox:1
|
||||||
|
func (this *App) MainEntry() {
|
||||||
|
//line cmd/llgo/main_app.gox:1:1
|
||||||
|
this.Short(`llgo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python.`)
|
||||||
|
}
|
||||||
|
func (this *App) Main() {
|
||||||
|
_gop_obj0 := &Cmd_build{App: this}
|
||||||
|
_gop_obj1 := &Cmd_clean{App: this}
|
||||||
|
_gop_obj2 := &Cmd_cmptest{App: this}
|
||||||
|
_gop_obj3 := &Cmd_get{App: this}
|
||||||
|
_gop_obj4 := &Cmd_install{App: this}
|
||||||
|
_gop_obj5 := &Cmd_run{App: this}
|
||||||
|
_gop_obj6 := &Cmd_test{App: this}
|
||||||
|
_gop_obj7 := &Cmd_version{App: this}
|
||||||
|
xcmd.Gopt_App_Main(this, _gop_obj0, _gop_obj1, _gop_obj2, _gop_obj3, _gop_obj4, _gop_obj5, _gop_obj6, _gop_obj7)
|
||||||
|
}
|
||||||
|
//line cmd/llgo/build_cmd.gox:20
|
||||||
|
func (this *Cmd_build) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/build_cmd.gox:20:1
|
||||||
|
this.Use("build [flags] [packages]")
|
||||||
|
//line cmd/llgo/build_cmd.gox:22:1
|
||||||
|
this.Short("Compile packages and dependencies")
|
||||||
|
//line cmd/llgo/build_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/build_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/build_cmd.gox:27:1
|
||||||
|
build.Cmd.Run(build.Cmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_build) Classfname() string {
|
||||||
|
return "build"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/clean_cmd.gox:20
|
||||||
|
func (this *Cmd_clean) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/clean_cmd.gox:20:1
|
||||||
|
this.Use("clean [flags] [packages]")
|
||||||
|
//line cmd/llgo/clean_cmd.gox:22:1
|
||||||
|
this.Short("Remove object files and cached files")
|
||||||
|
//line cmd/llgo/clean_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/clean_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/clean_cmd.gox:27:1
|
||||||
|
clean.Cmd.Run(clean.Cmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_clean) Classfname() string {
|
||||||
|
return "clean"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:20
|
||||||
|
func (this *Cmd_cmptest) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:20:1
|
||||||
|
this.Use("cmptest [flags] package [arguments...]")
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:22:1
|
||||||
|
this.Short("Compile and run with llgo, compare result (stdout/stderr/exitcode) with go or llgo.expect; generate llgo.expect file if -gen is specified")
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/cmptest_cmd.gox:27:1
|
||||||
|
run.CmpTestCmd.Run(run.CmpTestCmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_cmptest) Classfname() string {
|
||||||
|
return "cmptest"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/get_cmd.gox:16
|
||||||
|
func (this *Cmd_get) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/get_cmd.gox:16:1
|
||||||
|
this.Use("get [flags] [packages]")
|
||||||
|
//line cmd/llgo/get_cmd.gox:18:1
|
||||||
|
this.Short("Add dependencies to current module and install them")
|
||||||
|
//line cmd/llgo/get_cmd.gox:20:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/get_cmd.gox:21:1
|
||||||
|
panic("todo")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_get) Classfname() string {
|
||||||
|
return "get"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/install_cmd.gox:20
|
||||||
|
func (this *Cmd_install) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/install_cmd.gox:20:1
|
||||||
|
this.Use("install [flags] [packages]")
|
||||||
|
//line cmd/llgo/install_cmd.gox:22:1
|
||||||
|
this.Short("Compile and install packages and dependencies")
|
||||||
|
//line cmd/llgo/install_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/install_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/install_cmd.gox:27:1
|
||||||
|
install.Cmd.Run(install.Cmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_install) Classfname() string {
|
||||||
|
return "install"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/run_cmd.gox:20
|
||||||
|
func (this *Cmd_run) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/run_cmd.gox:20:1
|
||||||
|
this.Use("run [flags] package [arguments...]")
|
||||||
|
//line cmd/llgo/run_cmd.gox:22:1
|
||||||
|
this.Short("Compile and run Go program")
|
||||||
|
//line cmd/llgo/run_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/run_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/run_cmd.gox:27:1
|
||||||
|
run.Cmd.Run(run.Cmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_run) Classfname() string {
|
||||||
|
return "run"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/test_cmd.gox:20
|
||||||
|
func (this *Cmd_test) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/test_cmd.gox:20:1
|
||||||
|
this.Use("test [flags] package [arguments...]")
|
||||||
|
//line cmd/llgo/test_cmd.gox:22:1
|
||||||
|
this.Short("Compile and run Go test")
|
||||||
|
//line cmd/llgo/test_cmd.gox:24:1
|
||||||
|
this.FlagOff()
|
||||||
|
//line cmd/llgo/test_cmd.gox:26:1
|
||||||
|
this.Run__1(func(args []string) {
|
||||||
|
//line cmd/llgo/test_cmd.gox:27:1
|
||||||
|
test.Cmd.Run(test.Cmd, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_test) Classfname() string {
|
||||||
|
return "test"
|
||||||
|
}
|
||||||
|
//line cmd/llgo/version_cmd.gox:22
|
||||||
|
func (this *Cmd_version) Main(_gop_arg0 string) {
|
||||||
|
this.Command.Main(_gop_arg0)
|
||||||
|
//line cmd/llgo/version_cmd.gox:22:1
|
||||||
|
this.Use("version")
|
||||||
|
//line cmd/llgo/version_cmd.gox:24:1
|
||||||
|
this.Short("Print LLGo version")
|
||||||
|
//line cmd/llgo/version_cmd.gox:26:1
|
||||||
|
this.Run__0(func() {
|
||||||
|
//line cmd/llgo/version_cmd.gox:27:1
|
||||||
|
fmt.Println(stringutil.Concat("llgo ", env.Version(), " ", runtime.GOOS, "/", runtime.GOARCH))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func (this *Cmd_version) Classfname() string {
|
||||||
|
return "version"
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
new(App).Main()
|
||||||
|
}
|
||||||
28
cmd/llgo/install_cmd.gox
Normal file
28
cmd/llgo/install_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/install"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "install [flags] [packages]"
|
||||||
|
|
||||||
|
short "Compile and install packages and dependencies"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.Cmd.Run self.Cmd, args
|
||||||
|
}
|
||||||
1
cmd/llgo/main_app.gox
Normal file
1
cmd/llgo/main_app.gox
Normal file
@@ -0,0 +1 @@
|
|||||||
|
short `llgo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python.`
|
||||||
28
cmd/llgo/run_cmd.gox
Normal file
28
cmd/llgo/run_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/run"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "run [flags] package [arguments...]"
|
||||||
|
|
||||||
|
short "Compile and run Go program"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.Cmd.Run self.Cmd, args
|
||||||
|
}
|
||||||
28
cmd/llgo/test_cmd.gox
Normal file
28
cmd/llgo/test_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
self "github.com/goplus/llgo/cmd/internal/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "test [flags] package [arguments...]"
|
||||||
|
|
||||||
|
short "Compile and run Go test"
|
||||||
|
|
||||||
|
flagOff
|
||||||
|
|
||||||
|
run args => {
|
||||||
|
self.Cmd.Run self.Cmd, args
|
||||||
|
}
|
||||||
28
cmd/llgo/version_cmd.gox
Normal file
28
cmd/llgo/version_cmd.gox
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/env"
|
||||||
|
)
|
||||||
|
|
||||||
|
use "version"
|
||||||
|
|
||||||
|
short "Print LLGo version"
|
||||||
|
|
||||||
|
run => {
|
||||||
|
echo "llgo ${env.version} ${runtime.GOOS}/${runtime.GOARCH}"
|
||||||
|
}
|
||||||
@@ -2,4 +2,4 @@ module github.com/goplus/llgo/doc/_readme
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/goplus/lib v0.1.0
|
require github.com/goplus/lib v0.2.0
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
github.com/goplus/lib v0.1.0 h1:kqMAC6FmVPfrw0q8E5yF6Y12WC4GOfi2L/MYS4QoxbQ=
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
github.com/goplus/lib v0.1.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
brew update
|
brew update
|
||||||
brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config
|
brew install llvm@19 lld@19 bdw-gc openssl cjson libffi libuv pkg-config
|
||||||
brew install python@3.12 # optional
|
brew install python@3.12 # optional
|
||||||
brew link --overwrite lld@19 libffi
|
brew link --overwrite llvm@19 lld@19 libffi
|
||||||
# curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
# curl https://raw.githubusercontent.com/goplus/llgo/refs/heads/main/install.sh | bash
|
||||||
./install.sh
|
./install.sh
|
||||||
13
go.mod
13
go.mod
@@ -1,16 +1,17 @@
|
|||||||
module github.com/goplus/llgo
|
module github.com/goplus/llgo
|
||||||
|
|
||||||
go 1.22.0
|
go 1.23
|
||||||
|
|
||||||
toolchain go1.24.1
|
toolchain go1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/goplus/gogen v1.16.9
|
github.com/goplus/cobra v1.9.12 //gop:class
|
||||||
github.com/goplus/lib v0.1.0
|
github.com/goplus/gogen v1.18.1
|
||||||
github.com/goplus/llgo/runtime v0.0.0-20250403035532-0a8a4eb6a653
|
github.com/goplus/lib v0.2.0
|
||||||
|
github.com/goplus/llgo/runtime v0.0.0-00010101000000-000000000000
|
||||||
github.com/goplus/llvm v0.8.3
|
github.com/goplus/llvm v0.8.3
|
||||||
github.com/goplus/mod v0.13.17
|
github.com/goplus/mod v0.16.1
|
||||||
github.com/qiniu/x v1.13.12
|
github.com/qiniu/x v1.14.6
|
||||||
golang.org/x/tools v0.30.0
|
golang.org/x/tools v0.30.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -1,15 +1,17 @@
|
|||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/goplus/gogen v1.16.9 h1:BRNAsRzdyMcLBOLUe6+suVMmOe+D2HLfF7mAkS4/QW4=
|
github.com/goplus/cobra v1.9.12 h1:0F9EdEbeGyITGz+mqoHoJ5KpUw97p1CkxV74IexHw5s=
|
||||||
github.com/goplus/gogen v1.16.9/go.mod h1:6TQYbabXDF9LCdDkOOzHmfg1R4ENfXQ3XpHa9RhTSD8=
|
github.com/goplus/cobra v1.9.12/go.mod h1:p4LhfNJDKEpiGjGiNn0crUXL5dUPA5DX2ztYpEJR34E=
|
||||||
github.com/goplus/lib v0.1.0 h1:kqMAC6FmVPfrw0q8E5yF6Y12WC4GOfi2L/MYS4QoxbQ=
|
github.com/goplus/gogen v1.18.1 h1:ys18IiQwQ4QeQ3Mmk4vzql0Yfr6r+hkkQdjaL/M0Isc=
|
||||||
github.com/goplus/lib v0.1.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
github.com/goplus/gogen v1.18.1/go.mod h1:owX2e1EyU5WD+Nm6oH2m/GXjLdlBYcwkLO4wN8HHXZI=
|
||||||
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
github.com/goplus/llvm v0.8.3 h1:is1zOwhiQZWtLnOmSMVPO+1sPa2uK/XJ/FjTSfIjGBU=
|
github.com/goplus/llvm v0.8.3 h1:is1zOwhiQZWtLnOmSMVPO+1sPa2uK/XJ/FjTSfIjGBU=
|
||||||
github.com/goplus/llvm v0.8.3/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
github.com/goplus/llvm v0.8.3/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
|
||||||
github.com/goplus/mod v0.13.17 h1:aWp14xosENrh7t0/0qcIejDmQEiTgI3ou2+KoLDlSlE=
|
github.com/goplus/mod v0.16.1 h1:2O+rKubJTn+Fighz3kckwpW87STSZ6s3m/YECfXuNhE=
|
||||||
github.com/goplus/mod v0.13.17/go.mod h1:XlHf8mnQ4QkRDX14Of2tpywuHDd+JVpPStvh3egog+0=
|
github.com/goplus/mod v0.16.1/go.mod h1:8d1P+pBavZfNQtJo4A742DgsLTtSf26BQn51owhmNqI=
|
||||||
github.com/qiniu/x v1.13.12 h1:UyAwja6dgKUOYWZMzzc02wLodwnZ7wmK/0XzRd0e78g=
|
github.com/qiniu/x v1.14.6 h1:JY8jOumYFshuqNAjVkF6zsYhbcwM8A199ALkUOvJPks=
|
||||||
github.com/qiniu/x v1.13.12/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
|
github.com/qiniu/x v1.14.6/go.mod h1:AiovSOCaRijaf3fj+0CBOpR1457pn24b0Vdb1JpwhII=
|
||||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"debug/macho"
|
"debug/macho"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
@@ -31,23 +30,25 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
|
"github.com/goplus/llgo/internal/crosscompile"
|
||||||
"github.com/goplus/llgo/internal/env"
|
"github.com/goplus/llgo/internal/env"
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
"github.com/goplus/llgo/internal/typepatch"
|
"github.com/goplus/llgo/internal/typepatch"
|
||||||
|
llvmTarget "github.com/goplus/llgo/internal/xtool/llvm"
|
||||||
"github.com/goplus/llgo/ssa/abi"
|
"github.com/goplus/llgo/ssa/abi"
|
||||||
xenv "github.com/goplus/llgo/xtool/env"
|
xenv "github.com/goplus/llgo/xtool/env"
|
||||||
"github.com/goplus/llgo/xtool/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
|
|
||||||
llruntime "github.com/goplus/llgo/runtime"
|
llruntime "github.com/goplus/llgo/runtime"
|
||||||
llssa "github.com/goplus/llgo/ssa"
|
llssa "github.com/goplus/llgo/ssa"
|
||||||
clangCheck "github.com/goplus/llgo/xtool/clang/check"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mode int
|
type Mode int
|
||||||
@@ -66,12 +67,16 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Goos string
|
||||||
|
Goarch string
|
||||||
BinPath string
|
BinPath string
|
||||||
AppExt string // ".exe" on Windows, empty on Unix
|
AppExt string // ".exe" on Windows, empty on Unix
|
||||||
OutFile string // only valid for ModeBuild when len(pkgs) == 1
|
OutFile string // only valid for ModeBuild when len(pkgs) == 1
|
||||||
RunArgs []string // only valid for ModeRun
|
RunArgs []string // only valid for ModeRun
|
||||||
Mode Mode
|
Mode Mode
|
||||||
GenExpect bool // only valid for ModeCmpTest
|
GenExpect bool // only valid for ModeCmpTest
|
||||||
|
Verbose bool
|
||||||
|
Tags string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultConf(mode Mode) *Config {
|
func NewDefaultConf(mode Mode) *Config {
|
||||||
@@ -86,10 +91,19 @@ func NewDefaultConf(mode Mode) *Config {
|
|||||||
if err := os.MkdirAll(bin, 0755); err != nil {
|
if err := os.MkdirAll(bin, 0755); err != nil {
|
||||||
panic(fmt.Errorf("cannot create bin directory: %v", err))
|
panic(fmt.Errorf("cannot create bin directory: %v", err))
|
||||||
}
|
}
|
||||||
|
goos, goarch := os.Getenv("GOOS"), os.Getenv("GOARCH")
|
||||||
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
conf := &Config{
|
conf := &Config{
|
||||||
|
Goos: goos,
|
||||||
|
Goarch: goarch,
|
||||||
BinPath: bin,
|
BinPath: bin,
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
AppExt: DefaultAppExt(),
|
AppExt: DefaultAppExt(goos),
|
||||||
}
|
}
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
@@ -105,9 +119,12 @@ func envGOPATH() (string, error) {
|
|||||||
return filepath.Join(home, "go"), nil
|
return filepath.Join(home, "go"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultAppExt() string {
|
func DefaultAppExt(goos string) string {
|
||||||
if runtime.GOOS == "windows" {
|
switch goos {
|
||||||
|
case "windows":
|
||||||
return ".exe"
|
return ".exe"
|
||||||
|
case "wasi", "wasip1", "js":
|
||||||
|
return ".wasm"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -122,11 +139,21 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Do(args []string, conf *Config) ([]Package, error) {
|
func Do(args []string, conf *Config) ([]Package, error) {
|
||||||
flags, patterns, verbose := ParseArgs(args, buildFlags)
|
if conf.Goos == "" {
|
||||||
flags = append(flags, "-tags", "llgo")
|
conf.Goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
if conf.Goarch == "" {
|
||||||
|
conf.Goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
|
verbose := conf.Verbose
|
||||||
|
patterns := args
|
||||||
|
tags := "llgo"
|
||||||
|
if conf.Tags != "" {
|
||||||
|
tags += "," + conf.Tags
|
||||||
|
}
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
|
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
|
||||||
BuildFlags: flags,
|
BuildFlags: []string{"-tags=" + tags},
|
||||||
Fset: token.NewFileSet(),
|
Fset: token.NewFileSet(),
|
||||||
Tests: conf.Mode == ModeTest,
|
Tests: conf.Mode == ModeTest,
|
||||||
}
|
}
|
||||||
@@ -134,13 +161,12 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
cfg.Mode |= packages.NeedForTest
|
cfg.Mode |= packages.NeedForTest
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(llruntime.OverlayFiles) > 0 {
|
|
||||||
cfg.Overlay = make(map[string][]byte)
|
cfg.Overlay = make(map[string][]byte)
|
||||||
|
clearRuntime(cfg.Overlay, filepath.Join(env.GOROOT(), "src", "runtime"))
|
||||||
for file, src := range llruntime.OverlayFiles {
|
for file, src := range llruntime.OverlayFiles {
|
||||||
overlay := unsafe.Slice(unsafe.StringData(src), len(src))
|
overlay := unsafe.Slice(unsafe.StringData(src), len(src))
|
||||||
cfg.Overlay[filepath.Join(env.GOROOT(), "src", file)] = overlay
|
cfg.Overlay[filepath.Join(env.GOROOT(), "src", file)] = overlay
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cl.EnableDebug(IsDbgEnabled())
|
cl.EnableDebug(IsDbgEnabled())
|
||||||
cl.EnableDbgSyms(IsDbgSymsEnabled())
|
cl.EnableDbgSyms(IsDbgSymsEnabled())
|
||||||
@@ -148,8 +174,8 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
llssa.Initialize(llssa.InitAll)
|
llssa.Initialize(llssa.InitAll)
|
||||||
|
|
||||||
target := &llssa.Target{
|
target := &llssa.Target{
|
||||||
GOOS: build.Default.GOOS,
|
GOOS: conf.Goos,
|
||||||
GOARCH: build.Default.GOARCH,
|
GOARCH: conf.Goarch,
|
||||||
}
|
}
|
||||||
|
|
||||||
prog := llssa.NewProgram(target)
|
prog := llssa.NewProgram(target)
|
||||||
@@ -221,7 +247,9 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
|
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
|
||||||
|
|
||||||
output := conf.OutFile != ""
|
output := conf.OutFile != ""
|
||||||
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0, output, make(map[*packages.Package]bool), make(map[*packages.Package]bool)}
|
export, err := crosscompile.UseCrossCompileSDK(conf.Goos, conf.Goarch, IsWasiThreadsEnabled())
|
||||||
|
check(err)
|
||||||
|
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0, output, make(map[*packages.Package]bool), make(map[*packages.Package]bool), conf, export}
|
||||||
pkgs, err := buildAllPkgs(ctx, initial, verbose)
|
pkgs, err := buildAllPkgs(ctx, initial, verbose)
|
||||||
check(err)
|
check(err)
|
||||||
if mode == ModeGen {
|
if mode == ModeGen {
|
||||||
@@ -235,20 +263,35 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
|
|
||||||
dpkg, err := buildAllPkgs(ctx, altPkgs[noRt:], verbose)
|
dpkg, err := buildAllPkgs(ctx, altPkgs[noRt:], verbose)
|
||||||
check(err)
|
check(err)
|
||||||
var linkArgs []string
|
allPkgs := append([]*aPackage{}, pkgs...)
|
||||||
for _, pkg := range dpkg {
|
allPkgs = append(allPkgs, dpkg...)
|
||||||
linkArgs = append(linkArgs, pkg.LinkArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pkg := range initial {
|
for _, pkg := range initial {
|
||||||
if needLink(pkg, mode) {
|
if needLink(pkg, mode) {
|
||||||
linkMainPkg(ctx, pkg, pkgs, linkArgs, conf, mode, verbose)
|
linkMainPkg(ctx, pkg, allPkgs, conf, mode, verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dpkg, nil
|
return dpkg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clearRuntime(overlay map[string][]byte, runtimePath string) {
|
||||||
|
files, err := filepath.Glob(runtimePath + "/*.go")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
overlay[file] = []byte("package runtime\n")
|
||||||
|
}
|
||||||
|
files, err = filepath.Glob(runtimePath + "/*.s")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
overlay[file] = []byte("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func needLink(pkg *packages.Package, mode Mode) bool {
|
func needLink(pkg *packages.Package, mode Mode) bool {
|
||||||
if mode == ModeTest {
|
if mode == ModeTest {
|
||||||
return strings.HasSuffix(pkg.ID, ".test")
|
return strings.HasSuffix(pkg.ID, ".test")
|
||||||
@@ -286,6 +329,9 @@ type context struct {
|
|||||||
|
|
||||||
needRt map[*packages.Package]bool
|
needRt map[*packages.Package]bool
|
||||||
needPyInit map[*packages.Package]bool
|
needPyInit map[*packages.Package]bool
|
||||||
|
|
||||||
|
buildConf *Config
|
||||||
|
crossCompile crosscompile.Export
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
|
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
|
||||||
@@ -314,16 +360,10 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
pkg.ExportFile = ""
|
pkg.ExportFile = ""
|
||||||
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
|
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
|
||||||
if len(pkg.GoFiles) > 0 {
|
if len(pkg.GoFiles) > 0 {
|
||||||
cgoLdflags, err := buildPkg(ctx, aPkg, verbose)
|
err := buildPkg(ctx, aPkg, verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
linkParts := concatPkgLinkFiles(ctx, pkg, verbose)
|
|
||||||
allParts := append(linkParts, cgoLdflags...)
|
|
||||||
if pkg.ExportFile != "" {
|
|
||||||
allParts = append(allParts, pkg.ExportFile)
|
|
||||||
}
|
|
||||||
aPkg.LinkArgs = allParts
|
|
||||||
} else {
|
} else {
|
||||||
// panic("todo")
|
// panic("todo")
|
||||||
// TODO(xsw): support packages out of llgo
|
// TODO(xsw): support packages out of llgo
|
||||||
@@ -364,22 +404,15 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
ctx.nLibdir++
|
ctx.nLibdir++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := clangCheck.CheckLinkArgs(pkgLinkArgs); err != nil {
|
if err := ctx.env.Clang().CheckLinkArgs(pkgLinkArgs); err != nil {
|
||||||
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %v\n\tresolved to: %v\n\terror: %v", param, expdArgs, pkgLinkArgs, err))
|
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %v\n\tresolved to: %v\n\terror: %v", param, expdArgs, pkgLinkArgs, err))
|
||||||
}
|
}
|
||||||
aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...)
|
aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
cgoLdflags, err := buildPkg(ctx, aPkg, verbose)
|
err := buildPkg(ctx, aPkg, verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
|
||||||
if pkg.ExportFile != "" {
|
|
||||||
aPkg.LinkArgs = append(cgoLdflags, pkg.ExportFile)
|
|
||||||
}
|
|
||||||
aPkg.LinkArgs = append(aPkg.LinkArgs, concatPkgLinkFiles(ctx, pkg, verbose)...)
|
|
||||||
if aPkg.AltPkg != nil {
|
|
||||||
aPkg.LinkArgs = append(aPkg.LinkArgs, concatPkgLinkFiles(ctx, aPkg.AltPkg.Package, verbose)...)
|
|
||||||
}
|
}
|
||||||
setNeedRuntimeOrPyInit(ctx, pkg, aPkg.LPkg.NeedRuntime, aPkg.LPkg.NeedPyInit)
|
setNeedRuntimeOrPyInit(ctx, pkg, aPkg.LPkg.NeedRuntime, aPkg.LPkg.NeedPyInit)
|
||||||
}
|
}
|
||||||
@@ -387,7 +420,7 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs []string, conf *Config, mode Mode, verbose bool) {
|
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, conf *Config, mode Mode, verbose bool) {
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
name := path.Base(pkgPath)
|
name := path.Base(pkgPath)
|
||||||
app := conf.OutFile
|
app := conf.OutFile
|
||||||
@@ -401,49 +434,25 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
} else {
|
} else {
|
||||||
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
||||||
}
|
}
|
||||||
|
} else if !strings.HasSuffix(app, conf.AppExt) {
|
||||||
|
app += conf.AppExt
|
||||||
}
|
}
|
||||||
args := make([]string, 0, len(pkg.Imports)+len(linkArgs)+16)
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-o", app,
|
|
||||||
"-Wl,--error-limit=0",
|
|
||||||
"-fuse-ld=lld",
|
|
||||||
"-Wno-override-module",
|
|
||||||
// "-O2", // FIXME: This will cause TestFinalizer in _test/bdwgc.go to fail on macOS.
|
|
||||||
)
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin": // ld64.lld (macOS)
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-rpath", "@loader_path",
|
|
||||||
"-rpath", "@loader_path/../lib",
|
|
||||||
"-Xlinker", "-dead_strip",
|
|
||||||
)
|
|
||||||
case "windows": // lld-link (Windows)
|
|
||||||
// TODO: Add options for Windows.
|
|
||||||
default: // ld.lld (Unix), wasm-ld (WebAssembly)
|
|
||||||
args = append(
|
|
||||||
args,
|
|
||||||
"-rpath", "$ORIGIN",
|
|
||||||
"-rpath", "$ORIGIN/../lib",
|
|
||||||
"-fdata-sections",
|
|
||||||
"-ffunction-sections",
|
|
||||||
"-Xlinker", "--gc-sections",
|
|
||||||
"-lm",
|
|
||||||
"-latomic",
|
|
||||||
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
|
||||||
)
|
|
||||||
}
|
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
needPyInit := false
|
needPyInit := false
|
||||||
pkgsMap := make(map[*packages.Package]*aPackage, len(pkgs))
|
pkgsMap := make(map[*packages.Package]*aPackage, len(pkgs))
|
||||||
|
allPkgs := []*packages.Package{pkg}
|
||||||
for _, v := range pkgs {
|
for _, v := range pkgs {
|
||||||
pkgsMap[v.Package] = v
|
pkgsMap[v.Package] = v
|
||||||
|
allPkgs = append(allPkgs, v.Package)
|
||||||
}
|
}
|
||||||
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
var llFiles []string
|
||||||
if p.ExportFile != "" { // skip packages that only contain declarations
|
var linkArgs []string
|
||||||
|
packages.Visit(allPkgs, nil, func(p *packages.Package) {
|
||||||
aPkg := pkgsMap[p]
|
aPkg := pkgsMap[p]
|
||||||
args = append(args, aPkg.LinkArgs...)
|
if p.ExportFile != "" && aPkg != nil { // skip packages that only contain declarations
|
||||||
|
linkArgs = append(linkArgs, aPkg.LinkArgs...)
|
||||||
|
llFiles = append(llFiles, aPkg.LLFiles...)
|
||||||
need1, need2 := isNeedRuntimeOrPyInit(ctx, p)
|
need1, need2 := isNeedRuntimeOrPyInit(ctx, p)
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = need1
|
needRuntime = need1
|
||||||
@@ -453,51 +462,29 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
entryLLFile, err := genMainModuleFile(llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
|
entryLLFile, err := genMainModuleFile(conf, llssa.PkgRuntime, pkg.PkgPath, needRuntime, needPyInit)
|
||||||
if err != nil {
|
check(err)
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// defer os.Remove(entryLLFile)
|
// defer os.Remove(entryLLFile)
|
||||||
args = append(args, entryLLFile)
|
llFiles = append(llFiles, entryLLFile)
|
||||||
|
|
||||||
var aPkg *aPackage
|
|
||||||
for _, v := range pkgs {
|
|
||||||
if v.Package == pkg { // found this package
|
|
||||||
aPkg = v
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
args = append(args, linkArgs...)
|
|
||||||
|
|
||||||
if ctx.output {
|
|
||||||
lpkg := aPkg.LPkg
|
|
||||||
os.WriteFile(pkg.ExportFile, []byte(lpkg.String()), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add rpath and find libs
|
// add rpath and find libs
|
||||||
exargs := make([]string, 0, ctx.nLibdir<<1)
|
exargs := make([]string, 0, ctx.nLibdir<<1)
|
||||||
libs := make([]string, 0, ctx.nLibdir*3)
|
libs := make([]string, 0, ctx.nLibdir*3)
|
||||||
for _, arg := range args {
|
if IsRpathChangeEnabled() {
|
||||||
|
for _, arg := range linkArgs {
|
||||||
if strings.HasPrefix(arg, "-L") {
|
if strings.HasPrefix(arg, "-L") {
|
||||||
exargs = append(exargs, "-rpath", arg[2:])
|
exargs = append(exargs, "-rpath", arg[2:])
|
||||||
} else if strings.HasPrefix(arg, "-l") {
|
} else if strings.HasPrefix(arg, "-l") {
|
||||||
libs = append(libs, arg[2:])
|
libs = append(libs, arg[2:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args = append(args, exargs...)
|
|
||||||
if IsDbgSymsEnabled() {
|
|
||||||
args = append(args, "-gdwarf-4")
|
|
||||||
}
|
}
|
||||||
|
linkArgs = append(linkArgs, exargs...)
|
||||||
|
|
||||||
// TODO(xsw): show work
|
err = compileAndLinkLLFiles(ctx, app, llFiles, linkArgs, verbose)
|
||||||
if verbose {
|
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
|
||||||
}
|
|
||||||
err = ctx.env.Clang().Link(args...)
|
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if IsRpathChangeEnabled() && runtime.GOOS == "darwin" {
|
if IsRpathChangeEnabled() && ctx.buildConf.Goos == "darwin" {
|
||||||
dylibDeps := make([]string, 0, len(libs))
|
dylibDeps := make([]string, 0, len(libs))
|
||||||
for _, lib := range libs {
|
for _, lib := range libs {
|
||||||
dylibDep := findDylibDep(app, lib)
|
dylibDep := findDylibDep(app, lib)
|
||||||
@@ -519,11 +506,37 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
fmt.Fprintf(os.Stderr, "%s: exit code %d\n", app, s.ExitCode())
|
fmt.Fprintf(os.Stderr, "%s: exit code %d\n", app, s.ExitCode())
|
||||||
}
|
}
|
||||||
case ModeRun:
|
case ModeRun:
|
||||||
cmd := exec.Command(app, conf.RunArgs...)
|
args := make([]string, 0, len(conf.RunArgs)+1)
|
||||||
|
copy(args, conf.RunArgs)
|
||||||
|
if isWasmTarget(conf.Goos) {
|
||||||
|
wasmer := os.ExpandEnv(WasmRuntime())
|
||||||
|
wasmerArgs := strings.Split(wasmer, " ")
|
||||||
|
wasmerCmd := wasmerArgs[0]
|
||||||
|
wasmerArgs = wasmerArgs[1:]
|
||||||
|
switch wasmer {
|
||||||
|
case "wasmtime":
|
||||||
|
args = append(args, "--wasm", "multi-memory=true", app)
|
||||||
|
args = append(args, conf.RunArgs...)
|
||||||
|
case "iwasm":
|
||||||
|
args = append(args, "--stack-size=819200000", "--heap-size=800000000", app)
|
||||||
|
args = append(args, conf.RunArgs...)
|
||||||
|
default:
|
||||||
|
args = append(args, wasmerArgs...)
|
||||||
|
args = append(args, app)
|
||||||
|
args = append(args, conf.RunArgs...)
|
||||||
|
}
|
||||||
|
app = wasmerCmd
|
||||||
|
} else {
|
||||||
|
args = conf.RunArgs
|
||||||
|
}
|
||||||
|
cmd := exec.Command(app, args...)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Run()
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
if s := cmd.ProcessState; s != nil {
|
if s := cmd.ProcessState; s != nil {
|
||||||
mockable.Exit(s.ExitCode())
|
mockable.Exit(s.ExitCode())
|
||||||
}
|
}
|
||||||
@@ -532,7 +545,133 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genMainModuleFile(rtPkgPath, mainPkgPath string, needRuntime, needPyInit bool) (path string, err error) {
|
func compileAndLinkLLFiles(ctx *context, app string, llFiles, linkArgs []string, verbose bool) error {
|
||||||
|
buildArgs := []string{"-o", app}
|
||||||
|
buildArgs = append(buildArgs, linkArgs...)
|
||||||
|
|
||||||
|
// Add common linker arguments based on target OS and architecture
|
||||||
|
targetTriple := llvmTarget.GetTargetTriple(ctx.buildConf.Goos, ctx.buildConf.Goarch)
|
||||||
|
buildArgs = append(buildArgs, buildLdflags(ctx.buildConf.Goos, ctx.buildConf.Goarch, targetTriple)...)
|
||||||
|
|
||||||
|
if IsDbgSymsEnabled() {
|
||||||
|
buildArgs = append(buildArgs, "-gdwarf-4")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildArgs = append(buildArgs, ctx.crossCompile.CCFLAGS...)
|
||||||
|
buildArgs = append(buildArgs, ctx.crossCompile.LDFLAGS...)
|
||||||
|
buildArgs = append(buildArgs, llFiles...)
|
||||||
|
if verbose {
|
||||||
|
buildArgs = append(buildArgs, "-v")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := ctx.env.Clang()
|
||||||
|
cmd.Verbose = verbose
|
||||||
|
return cmd.Link(buildArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCflags(goos, goarch, targetTriple string) []string {
|
||||||
|
args := []string{}
|
||||||
|
if goarch == "wasm" {
|
||||||
|
args = append(args, "-target", targetTriple)
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildLdflags builds the common linker arguments based on target OS and architecture
|
||||||
|
func buildLdflags(goos, goarch, targetTriple string) []string {
|
||||||
|
args := []string{
|
||||||
|
"-target", targetTriple,
|
||||||
|
"-Wno-override-module",
|
||||||
|
"-Wl,--error-limit=0",
|
||||||
|
}
|
||||||
|
if goos == runtime.GOOS {
|
||||||
|
// Non-cross-compile
|
||||||
|
args = append(args,
|
||||||
|
"-fuse-ld=lld",
|
||||||
|
"-Wno-override-module",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch goos {
|
||||||
|
case "darwin": // ld64.lld (macOS)
|
||||||
|
if IsRpathChangeEnabled() {
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-rpath", "@loader_path",
|
||||||
|
"-rpath", "@loader_path/../lib",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-Xlinker", "-dead_strip",
|
||||||
|
)
|
||||||
|
case "windows": // lld-link (Windows)
|
||||||
|
// TODO(xsw): Add options for Windows.
|
||||||
|
case "wasi", "wasip1", "js": // wasm-ld (WebAssembly)
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
// "-fdata-sections",
|
||||||
|
// "-ffunction-sections",
|
||||||
|
// "-nostdlib",
|
||||||
|
// "-Wl,--no-entry",
|
||||||
|
"-Wl,--export-all",
|
||||||
|
"-Wl,--allow-undefined",
|
||||||
|
"-Wl,--import-memory,", // unknown import: `env::memory` has not been defined
|
||||||
|
"-Wl,--export-memory",
|
||||||
|
"-Wl,--initial-memory=67108864", // 64MB
|
||||||
|
"-mbulk-memory",
|
||||||
|
"-mmultimemory",
|
||||||
|
"-z", "stack-size=10485760", // 10MB
|
||||||
|
"-Wl,--export=malloc", "-Wl,--export=free",
|
||||||
|
"-lc",
|
||||||
|
"-lcrypt",
|
||||||
|
"-lm",
|
||||||
|
"-lrt",
|
||||||
|
"-lutil",
|
||||||
|
// "-lxnet",
|
||||||
|
// "-lresolv",
|
||||||
|
"-lsetjmp",
|
||||||
|
"-lwasi-emulated-mman",
|
||||||
|
"-lwasi-emulated-getpid",
|
||||||
|
"-lwasi-emulated-process-clocks",
|
||||||
|
"-lwasi-emulated-signal",
|
||||||
|
"-fwasm-exceptions",
|
||||||
|
"-mllvm", "-wasm-enable-sjlj",
|
||||||
|
// "-mllvm", "-wasm-enable-eh", // unreachable error if enabled
|
||||||
|
// "-mllvm", "-wasm-disable-explicit-locals", // WASM module load failed: type mismatch: expect data but stack was empty if enabled
|
||||||
|
)
|
||||||
|
if IsWasiThreadsEnabled() {
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"-lwasi-emulated-pthread",
|
||||||
|
"-lpthread",
|
||||||
|
"-pthread", // global is immutable if -pthread is not specified
|
||||||
|
// "-matomics", // undefined symbol: __atomic_load
|
||||||
|
)
|
||||||
|
}
|
||||||
|
default: // ld.lld (Unix)
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
// "-rpath", "$ORIGIN",
|
||||||
|
// "-rpath", "$ORIGIN/../lib",
|
||||||
|
"-fdata-sections",
|
||||||
|
"-ffunction-sections",
|
||||||
|
"-Xlinker",
|
||||||
|
"--gc-sections",
|
||||||
|
"-lm",
|
||||||
|
"-latomic",
|
||||||
|
"-lpthread", // libpthread is built-in since glibc 2.34 (2021-08-01); we need to support earlier versions.
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWasmTarget(goos string) bool {
|
||||||
|
return slices.Contains([]string{"wasi", "js", "wasip1"}, goos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genMainModuleFile(conf *Config, rtPkgPath, mainPkgPath string, needRuntime, needPyInit bool) (path string, err error) {
|
||||||
var (
|
var (
|
||||||
pyInitDecl string
|
pyInitDecl string
|
||||||
pyInit string
|
pyInit string
|
||||||
@@ -547,12 +686,40 @@ func genMainModuleFile(rtPkgPath, mainPkgPath string, needRuntime, needPyInit bo
|
|||||||
pyInit = "call void @Py_Initialize()"
|
pyInit = "call void @Py_Initialize()"
|
||||||
pyInitDecl = "declare void @Py_Initialize()"
|
pyInitDecl = "declare void @Py_Initialize()"
|
||||||
}
|
}
|
||||||
|
declSizeT := "%size_t = type i64"
|
||||||
|
if is32Bits(conf.Goarch) {
|
||||||
|
declSizeT = "%size_t = type i32"
|
||||||
|
}
|
||||||
|
stdioDecl := ""
|
||||||
|
stdioNobuf := ""
|
||||||
|
if IsStdioNobuf() {
|
||||||
|
stdioDecl = `
|
||||||
|
@stdout = external global ptr
|
||||||
|
@stderr = external global ptr
|
||||||
|
@__stdout = external global ptr
|
||||||
|
@__stderr = external global ptr
|
||||||
|
declare i32 @setvbuf(ptr, ptr, i32, %size_t)
|
||||||
|
`
|
||||||
|
stdioNobuf = `
|
||||||
|
; Set stdout with no buffer
|
||||||
|
%stdout_is_null = icmp eq ptr @stdout, null
|
||||||
|
%stdout_ptr = select i1 %stdout_is_null, ptr @__stdout, ptr @stdout
|
||||||
|
call i32 @setvbuf(ptr %stdout_ptr, ptr null, i32 2, %size_t 0)
|
||||||
|
; Set stderr with no buffer
|
||||||
|
%stderr_ptr = select i1 %stdout_is_null, ptr @__stderr, ptr @stderr
|
||||||
|
call i32 @setvbuf(ptr %stderr_ptr, ptr null, i32 2, %size_t 0)
|
||||||
|
`
|
||||||
|
}
|
||||||
|
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
|
if isWasmTarget(conf.Goos) {
|
||||||
|
mainDefine = "define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
|
}
|
||||||
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
%s
|
||||||
@__llgo_argc = global i32 0, align 4
|
@__llgo_argc = global i32 0, align 4
|
||||||
@__llgo_argv = global ptr null, align 8
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
%s
|
||||||
%s
|
%s
|
||||||
%s
|
%s
|
||||||
declare void @"%s.init"()
|
declare void @"%s.init"()
|
||||||
@@ -566,18 +733,21 @@ define weak void @"syscall.init"() {
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define i32 @main(i32 %%0, ptr %%1) {
|
%s {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
%s
|
|
||||||
store i32 %%0, ptr @__llgo_argc, align 4
|
store i32 %%0, ptr @__llgo_argc, align 4
|
||||||
store ptr %%1, ptr @__llgo_argv, align 8
|
store ptr %%1, ptr @__llgo_argv, align 8
|
||||||
%s
|
%s
|
||||||
|
%s
|
||||||
|
%s
|
||||||
call void @runtime.init()
|
call void @runtime.init()
|
||||||
call void @"%s.init"()
|
call void @"%s.init"()
|
||||||
call void @"%s.main"()
|
call void @"%s.main"()
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
`, pyInitDecl, rtInitDecl, mainPkgPath, mainPkgPath,
|
`, declSizeT, stdioDecl,
|
||||||
|
pyInitDecl, rtInitDecl, mainPkgPath, mainPkgPath,
|
||||||
|
mainDefine, stdioNobuf,
|
||||||
pyInit, rtInit, mainPkgPath, mainPkgPath)
|
pyInit, rtInit, mainPkgPath, mainPkgPath)
|
||||||
|
|
||||||
f, err := os.CreateTemp("", "main*.ll")
|
f, err := os.CreateTemp("", "main*.ll")
|
||||||
@@ -595,7 +765,11 @@ _llgo_0:
|
|||||||
return f.Name(), nil
|
return f.Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string, err error) {
|
func is32Bits(goarch string) bool {
|
||||||
|
return goarch == "386" || goarch == "arm" || goarch == "mips" || goarch == "wasm"
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
|
||||||
pkg := aPkg.Package
|
pkg := aPkg.Package
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
if debugBuild || verbose {
|
if debugBuild || verbose {
|
||||||
@@ -603,7 +777,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string,
|
|||||||
}
|
}
|
||||||
if llruntime.SkipToBuild(pkgPath) {
|
if llruntime.SkipToBuild(pkgPath) {
|
||||||
pkg.ExportFile = ""
|
pkg.ExportFile = ""
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
var syntax = pkg.Syntax
|
var syntax = pkg.Syntax
|
||||||
if altPkg := aPkg.AltPkg; altPkg != nil {
|
if altPkg := aPkg.AltPkg; altPkg != nil {
|
||||||
@@ -622,17 +796,26 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string,
|
|||||||
}
|
}
|
||||||
check(err)
|
check(err)
|
||||||
aPkg.LPkg = ret
|
aPkg.LPkg = ret
|
||||||
cgoLdflags, err = buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
||||||
if aPkg.AltPkg != nil {
|
if err != nil {
|
||||||
altLdflags, e := buildCgo(ctx, aPkg, aPkg.AltPkg.Syntax, externs, verbose)
|
return fmt.Errorf("build cgo of %v failed: %v", pkgPath, err)
|
||||||
if e != nil {
|
|
||||||
return nil, fmt.Errorf("build cgo of %v failed: %v", pkgPath, e)
|
|
||||||
}
|
}
|
||||||
cgoLdflags = append(cgoLdflags, altLdflags...)
|
aPkg.LLFiles = append(aPkg.LLFiles, cgoLLFiles...)
|
||||||
|
aPkg.LLFiles = append(aPkg.LLFiles, concatPkgLinkFiles(ctx, pkg, verbose)...)
|
||||||
|
aPkg.LinkArgs = append(aPkg.LinkArgs, cgoLdflags...)
|
||||||
|
if aPkg.AltPkg != nil {
|
||||||
|
altLLFiles, altLdflags, e := buildCgo(ctx, aPkg, aPkg.AltPkg.Syntax, externs, verbose)
|
||||||
|
if e != nil {
|
||||||
|
return fmt.Errorf("build cgo of %v failed: %v", pkgPath, e)
|
||||||
|
}
|
||||||
|
aPkg.LLFiles = append(aPkg.LLFiles, altLLFiles...)
|
||||||
|
aPkg.LLFiles = append(aPkg.LLFiles, concatPkgLinkFiles(ctx, aPkg.AltPkg.Package, verbose)...)
|
||||||
|
aPkg.LinkArgs = append(aPkg.LinkArgs, altLdflags...)
|
||||||
}
|
}
|
||||||
if pkg.ExportFile != "" {
|
if pkg.ExportFile != "" {
|
||||||
pkg.ExportFile += ".ll"
|
pkg.ExportFile += ".ll"
|
||||||
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
|
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
|
||||||
|
aPkg.LLFiles = append(aPkg.LLFiles, pkg.ExportFile)
|
||||||
if debugBuild || verbose {
|
if debugBuild || verbose {
|
||||||
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
fmt.Fprintf(os.Stderr, "==> Export %s: %s\n", aPkg.PkgPath, pkg.ExportFile)
|
||||||
}
|
}
|
||||||
@@ -642,7 +825,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func llcCheck(env *llvm.Env, exportFile string) (err error, msg string) {
|
func llcCheck(env *llvm.Env, exportFile string) (err error, msg string) {
|
||||||
@@ -697,6 +880,7 @@ type aPackage struct {
|
|||||||
LPkg llssa.Package
|
LPkg llssa.Package
|
||||||
|
|
||||||
LinkArgs []string
|
LinkArgs []string
|
||||||
|
LLFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Package = *aPackage
|
type Package = *aPackage
|
||||||
@@ -717,7 +901,7 @@ func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aP
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
all = append(all, &aPackage{p, ssaPkg, altPkg, nil, nil})
|
all = append(all, &aPackage{p, ssaPkg, altPkg, nil, nil, nil})
|
||||||
} else {
|
} else {
|
||||||
errs = append(errs, p)
|
errs = append(errs, p)
|
||||||
}
|
}
|
||||||
@@ -762,6 +946,19 @@ const llgoTrace = "LLGO_TRACE"
|
|||||||
const llgoOptimize = "LLGO_OPTIMIZE"
|
const llgoOptimize = "LLGO_OPTIMIZE"
|
||||||
const llgoCheck = "LLGO_CHECK"
|
const llgoCheck = "LLGO_CHECK"
|
||||||
const llgoRpathChange = "LLGO_RPATH_CHANGE"
|
const llgoRpathChange = "LLGO_RPATH_CHANGE"
|
||||||
|
const llgoWasmRuntime = "LLGO_WASM_RUNTIME"
|
||||||
|
const llgoWasiThreads = "LLGO_WASI_THREADS"
|
||||||
|
const llgoStdioNobuf = "LLGO_STDIO_NOBUF"
|
||||||
|
|
||||||
|
const defaultWasmRuntime = "wasmtime"
|
||||||
|
|
||||||
|
func defaultEnv(env string, defVal string) string {
|
||||||
|
envVal := os.Getenv(env)
|
||||||
|
if envVal == "" {
|
||||||
|
return defVal
|
||||||
|
}
|
||||||
|
return envVal
|
||||||
|
}
|
||||||
|
|
||||||
func isEnvOn(env string, defVal bool) bool {
|
func isEnvOn(env string, defVal bool) bool {
|
||||||
envVal := strings.ToLower(os.Getenv(env))
|
envVal := strings.ToLower(os.Getenv(env))
|
||||||
@@ -775,6 +972,10 @@ func IsTraceEnabled() bool {
|
|||||||
return isEnvOn(llgoTrace, false)
|
return isEnvOn(llgoTrace, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsStdioNobuf() bool {
|
||||||
|
return isEnvOn(llgoStdioNobuf, false)
|
||||||
|
}
|
||||||
|
|
||||||
func IsDbgEnabled() bool {
|
func IsDbgEnabled() bool {
|
||||||
return isEnvOn(llgoDebug, false) || isEnvOn(llgoDbgSyms, false)
|
return isEnvOn(llgoDebug, false) || isEnvOn(llgoDbgSyms, false)
|
||||||
}
|
}
|
||||||
@@ -795,48 +996,12 @@ func IsRpathChangeEnabled() bool {
|
|||||||
return isEnvOn(llgoRpathChange, false)
|
return isEnvOn(llgoRpathChange, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseArgs(args []string, swflags map[string]bool) (flags, patterns []string, verbose bool) {
|
func IsWasiThreadsEnabled() bool {
|
||||||
n := len(args)
|
return isEnvOn(llgoWasiThreads, true)
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
arg := args[i]
|
|
||||||
if strings.HasPrefix(arg, "-") {
|
|
||||||
checkFlag(arg, &i, &verbose, swflags)
|
|
||||||
} else {
|
|
||||||
patterns = append([]string{}, args[i:]...)
|
|
||||||
flags = append([]string{}, args[:i]...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SkipFlagArgs(args []string) int {
|
func WasmRuntime() string {
|
||||||
n := len(args)
|
return defaultEnv(llgoWasmRuntime, defaultWasmRuntime)
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
arg := args[i]
|
|
||||||
if strings.HasPrefix(arg, "-") {
|
|
||||||
checkFlag(arg, &i, nil, buildFlags)
|
|
||||||
} else {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) {
|
|
||||||
if pos := strings.IndexByte(arg, '='); pos > 0 {
|
|
||||||
if verbose != nil && arg == "-v=true" {
|
|
||||||
*verbose = true
|
|
||||||
}
|
|
||||||
} else if hasarg, ok := swflags[arg]; ok {
|
|
||||||
if hasarg {
|
|
||||||
*i++
|
|
||||||
} else if verbose != nil && arg == "-v" {
|
|
||||||
*verbose = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic("unknown flag: " + arg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) {
|
func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) {
|
||||||
@@ -877,11 +1042,17 @@ func clFiles(ctx *context, files string, pkg *packages.Package, procFile func(li
|
|||||||
|
|
||||||
func clFile(ctx *context, args []string, cFile, expFile string, procFile func(linkFile string), verbose bool) {
|
func clFile(ctx *context, args []string, cFile, expFile string, procFile func(linkFile string), verbose bool) {
|
||||||
llFile := expFile + filepath.Base(cFile) + ".ll"
|
llFile := expFile + filepath.Base(cFile) + ".ll"
|
||||||
|
targetTriple := llvmTarget.GetTargetTriple(ctx.buildConf.Goos, ctx.buildConf.Goarch)
|
||||||
|
cflags := buildCflags(ctx.buildConf.Goos, ctx.buildConf.Goarch, targetTriple)
|
||||||
|
args = append(cflags, args...)
|
||||||
args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
|
args = append(args, "-emit-llvm", "-S", "-o", llFile, "-c", cFile)
|
||||||
|
args = append(args, ctx.crossCompile.CCFLAGS...)
|
||||||
|
args = append(args, ctx.crossCompile.CFLAGS...)
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
err := ctx.env.Clang().Compile(args...)
|
cmd := ctx.env.Clang()
|
||||||
|
err := cmd.Compile(args...)
|
||||||
check(err)
|
check(err)
|
||||||
procFile(llFile)
|
procFile(llFile)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,13 +54,13 @@ func mockRun(args []string, cfg *Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRun(t *testing.T) {
|
func TestRun(t *testing.T) {
|
||||||
mockRun([]string{"-v", "../../cl/_testgo/print"}, &Config{Mode: ModeRun})
|
mockRun([]string{"../../cl/_testgo/print"}, &Config{Mode: ModeRun})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTest(t *testing.T) {
|
func TestTest(t *testing.T) {
|
||||||
mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeTest})
|
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeTest})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmpTest(t *testing.T) {
|
func TestCmpTest(t *testing.T) {
|
||||||
mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static void* _Cmalloc(size_t size) {
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string, verbose bool) (cgoLdflags []string, err error) {
|
func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string, verbose bool) (llfiles, cgoLdflags []string, err error) {
|
||||||
cfiles, preambles, cdecls, err := parseCgo_(pkg, files)
|
cfiles, preambles, cdecls, err := parseCgo_(pkg, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -87,7 +87,7 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string,
|
|||||||
}
|
}
|
||||||
for _, cfile := range cfiles {
|
for _, cfile := range cfiles {
|
||||||
clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) {
|
clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) {
|
||||||
cgoLdflags = append(cgoLdflags, linkFile)
|
llfiles = append(llfiles, linkFile)
|
||||||
}, verbose)
|
}, verbose)
|
||||||
}
|
}
|
||||||
re := regexp.MustCompile(`^(_cgo_[^_]+_(Cfunc|Cmacro)_)(.*)$`)
|
re := regexp.MustCompile(`^(_cgo_[^_]+_(Cfunc|Cmacro)_)(.*)$`)
|
||||||
@@ -117,20 +117,20 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs []string,
|
|||||||
for _, preamble := range preambles {
|
for _, preamble := range preambles {
|
||||||
tmpFile, err := os.CreateTemp("", "-cgo-*.c")
|
tmpFile, err := os.CreateTemp("", "-cgo-*.c")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create temp file: %v", err)
|
return nil, nil, fmt.Errorf("failed to create temp file: %v", err)
|
||||||
}
|
}
|
||||||
tmpName := tmpFile.Name()
|
tmpName := tmpFile.Name()
|
||||||
defer os.Remove(tmpName)
|
defer os.Remove(tmpName)
|
||||||
code := cgoHeader + "\n\n" + preamble.src
|
code := cgoHeader + "\n\n" + preamble.src
|
||||||
externDecls, err := genExternDeclsByClang(pkg, code, cflags, cgoSymbols)
|
externDecls, err := genExternDeclsByClang(pkg, code, cflags, cgoSymbols)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to generate extern decls: %v", err)
|
return nil, nil, fmt.Errorf("failed to generate extern decls: %v", err)
|
||||||
}
|
}
|
||||||
if err = os.WriteFile(tmpName, []byte(code+"\n\n"+externDecls), 0644); err != nil {
|
if err = os.WriteFile(tmpName, []byte(code+"\n\n"+externDecls), 0644); err != nil {
|
||||||
return nil, fmt.Errorf("failed to write temp file: %v", err)
|
return nil, nil, fmt.Errorf("failed to write temp file: %v", err)
|
||||||
}
|
}
|
||||||
clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) {
|
clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) {
|
||||||
cgoLdflags = append(cgoLdflags, linkFile)
|
llfiles = append(llfiles, linkFile)
|
||||||
}, verbose)
|
}, verbose)
|
||||||
}
|
}
|
||||||
for _, ldflag := range ldflags {
|
for _, ldflag := range ldflags {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
)
|
)
|
||||||
@@ -32,11 +33,20 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func Clean(args []string, conf *Config) {
|
func Clean(patterns []string, conf *Config) {
|
||||||
flags, patterns, verbose := ParseArgs(args, cleanFlags)
|
if conf.Goos == "" {
|
||||||
|
conf.Goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
if conf.Goarch == "" {
|
||||||
|
conf.Goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
|
tags := "llgo"
|
||||||
|
if conf.Tags != "" {
|
||||||
|
tags += "," + conf.Tags
|
||||||
|
}
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: loadSyntax | packages.NeedExportFile,
|
Mode: loadSyntax | packages.NeedExportFile,
|
||||||
BuildFlags: flags,
|
BuildFlags: []string{"-tags=" + tags},
|
||||||
}
|
}
|
||||||
|
|
||||||
if patterns == nil {
|
if patterns == nil {
|
||||||
@@ -45,11 +55,11 @@ func Clean(args []string, conf *Config) {
|
|||||||
initial, err := packages.LoadEx(nil, nil, cfg, patterns...)
|
initial, err := packages.LoadEx(nil, nil, cfg, patterns...)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
cleanPkgs(initial, verbose)
|
cleanPkgs(initial, conf.Verbose)
|
||||||
|
|
||||||
for _, pkg := range initial {
|
for _, pkg := range initial {
|
||||||
if pkg.Name == "main" {
|
if pkg.Name == "main" {
|
||||||
cleanMainPkg(pkg, conf, verbose)
|
cleanMainPkg(pkg, conf, conf.Verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
internal/crosscompile/cosscompile.go
Normal file
66
internal/crosscompile/cosscompile.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package crosscompile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/env"
|
||||||
|
"github.com/goplus/llgo/internal/xtool/llvm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Export struct {
|
||||||
|
CCFLAGS []string
|
||||||
|
CFLAGS []string
|
||||||
|
LDFLAGS []string
|
||||||
|
}
|
||||||
|
|
||||||
|
const wasiSdkUrl = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-macos.tar.gz"
|
||||||
|
|
||||||
|
func cacheDir() string {
|
||||||
|
return filepath.Join(env.LLGoCacheDir(), "crosscompile")
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseCrossCompileSDK(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
||||||
|
if runtime.GOOS == goos && runtime.GOARCH == goarch {
|
||||||
|
// not cross compile
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if goarch == "wasm" {
|
||||||
|
sdkDir := filepath.Join(cacheDir(), llvm.GetTargetTriple(goos, goarch))
|
||||||
|
if _, err = os.Stat(sdkDir); err != nil {
|
||||||
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = downloadAndExtract(wasiSdkUrl, sdkDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
triple := "wasm32-wasip1"
|
||||||
|
if wasiThreads {
|
||||||
|
triple = "wasm32-wasip1-threads"
|
||||||
|
}
|
||||||
|
// Set up flags for the SDK
|
||||||
|
wasiSdkRoot := filepath.Join(sdkDir, "wasi-sdk-25.0-x86_64-macos")
|
||||||
|
sysrootDir := filepath.Join(wasiSdkRoot, "share", "wasi-sysroot")
|
||||||
|
libclangDir := filepath.Join(wasiSdkRoot, "lib", "clang", "19")
|
||||||
|
includeDir := filepath.Join(sysrootDir, "include", triple)
|
||||||
|
libDir := filepath.Join(sysrootDir, "lib", triple)
|
||||||
|
|
||||||
|
export.CCFLAGS = []string{
|
||||||
|
"--sysroot=" + sysrootDir,
|
||||||
|
"-resource-dir=" + libclangDir,
|
||||||
|
}
|
||||||
|
export.CFLAGS = []string{
|
||||||
|
"-I" + includeDir,
|
||||||
|
}
|
||||||
|
export.LDFLAGS = []string{
|
||||||
|
"-L" + libDir,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO(lijie): supports other platforms
|
||||||
|
return
|
||||||
|
}
|
||||||
156
internal/crosscompile/crosscompile_test.go
Normal file
156
internal/crosscompile/crosscompile_test.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
package crosscompile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysrootPrefix = "--sysroot="
|
||||||
|
resourceDirPrefix = "-resource-dir="
|
||||||
|
includePrefix = "-I"
|
||||||
|
libPrefix = "-L"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUseCrossCompileSDK(t *testing.T) {
|
||||||
|
// Skip long-running tests unless explicitly enabled
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping test in short mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
goos string
|
||||||
|
goarch string
|
||||||
|
expectSDK bool
|
||||||
|
expectCCFlags bool
|
||||||
|
expectCFlags bool
|
||||||
|
expectLDFlags bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Same Platform",
|
||||||
|
goos: runtime.GOOS,
|
||||||
|
goarch: runtime.GOARCH,
|
||||||
|
expectSDK: false,
|
||||||
|
expectCCFlags: false,
|
||||||
|
expectCFlags: false,
|
||||||
|
expectLDFlags: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "WASM Target",
|
||||||
|
goos: "wasip1",
|
||||||
|
goarch: "wasm",
|
||||||
|
expectSDK: true,
|
||||||
|
expectCCFlags: true,
|
||||||
|
expectCFlags: true,
|
||||||
|
expectLDFlags: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unsupported Target",
|
||||||
|
goos: "windows",
|
||||||
|
goarch: "amd64",
|
||||||
|
expectSDK: false,
|
||||||
|
expectCCFlags: false,
|
||||||
|
expectCFlags: false,
|
||||||
|
expectLDFlags: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary directory for the cache
|
||||||
|
tempDir, err := os.MkdirTemp("", "crosscompile_test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
// Set environment variable for cache directory
|
||||||
|
oldEnv := os.Getenv("LLGO_CACHE_DIR")
|
||||||
|
os.Setenv("LLGO_CACHE_DIR", tempDir)
|
||||||
|
defer os.Setenv("LLGO_CACHE_DIR", oldEnv)
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
export, err := UseCrossCompileSDK(tc.goos, tc.goarch, false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("export: %+v", export)
|
||||||
|
|
||||||
|
if tc.expectSDK {
|
||||||
|
// Check if flags are set correctly
|
||||||
|
if tc.expectCCFlags && len(export.CCFLAGS) == 0 {
|
||||||
|
t.Error("Expected CCFLAGS to be set, but they are empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.expectCFlags && len(export.CFLAGS) == 0 {
|
||||||
|
t.Error("Expected CFLAGS to be set, but they are empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.expectLDFlags && len(export.LDFLAGS) == 0 {
|
||||||
|
t.Error("Expected LDFLAGS to be set, but they are empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for specific flags
|
||||||
|
if tc.expectCCFlags {
|
||||||
|
hasSysroot := false
|
||||||
|
hasResourceDir := false
|
||||||
|
|
||||||
|
for _, flag := range export.CCFLAGS {
|
||||||
|
if len(flag) >= len(sysrootPrefix) && flag[:len(sysrootPrefix)] == sysrootPrefix {
|
||||||
|
hasSysroot = true
|
||||||
|
}
|
||||||
|
if len(flag) >= len(resourceDirPrefix) && flag[:len(resourceDirPrefix)] == resourceDirPrefix {
|
||||||
|
hasResourceDir = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasSysroot {
|
||||||
|
t.Error("Missing --sysroot flag in CCFLAGS")
|
||||||
|
}
|
||||||
|
if !hasResourceDir {
|
||||||
|
t.Error("Missing -resource-dir flag in CCFLAGS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.expectCFlags {
|
||||||
|
hasInclude := false
|
||||||
|
|
||||||
|
for _, flag := range export.CFLAGS {
|
||||||
|
if len(flag) >= len(includePrefix) && flag[:len(includePrefix)] == includePrefix {
|
||||||
|
hasInclude = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasInclude {
|
||||||
|
t.Error("Missing -I flag in CFLAGS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.expectLDFlags {
|
||||||
|
hasLib := false
|
||||||
|
|
||||||
|
for _, flag := range export.LDFLAGS {
|
||||||
|
if len(flag) >= len(libPrefix) && flag[:len(libPrefix)] == libPrefix {
|
||||||
|
hasLib = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasLib {
|
||||||
|
t.Error("Missing -L flag in LDFLAGS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(export.CCFLAGS) != 0 || len(export.CFLAGS) != 0 || len(export.LDFLAGS) != 0 {
|
||||||
|
t.Errorf("Expected empty export, got CCFLAGS=%v, CFLAGS=%v, LDFLAGS=%v",
|
||||||
|
export.CCFLAGS, export.CFLAGS, export.LDFLAGS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
109
internal/crosscompile/fetch.go
Normal file
109
internal/crosscompile/fetch.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package crosscompile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func downloadAndExtract(url, dir string) (err error) {
|
||||||
|
if _, err = os.Stat(dir); err == nil {
|
||||||
|
os.RemoveAll(dir)
|
||||||
|
}
|
||||||
|
tempDir := dir + ".temp"
|
||||||
|
os.RemoveAll(tempDir)
|
||||||
|
if err = os.MkdirAll(tempDir, 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
urlPath := strings.Split(url, "/")
|
||||||
|
filename := urlPath[len(urlPath)-1]
|
||||||
|
localFile := filepath.Join(tempDir, filename)
|
||||||
|
if err = downloadFile(url, localFile); err != nil {
|
||||||
|
return fmt.Errorf("failed to download file: %w", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(localFile)
|
||||||
|
|
||||||
|
if strings.HasSuffix(filename, ".tar.gz") || strings.HasSuffix(filename, ".tgz") {
|
||||||
|
err = extractTarGz(localFile, tempDir)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("unsupported archive format: %s", filename)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to extract archive: %w", err)
|
||||||
|
}
|
||||||
|
if err = os.Rename(tempDir, dir); err != nil {
|
||||||
|
return fmt.Errorf("failed to rename directory: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadFile(url, filepath string) error {
|
||||||
|
out, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("bad status: %s", resp.Status)
|
||||||
|
}
|
||||||
|
_, err = io.Copy(out, resp.Body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTarGz(tarGzFile, dest string) error {
|
||||||
|
file, err := os.Open(tarGzFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
gzr, err := gzip.NewReader(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gzr.Close()
|
||||||
|
tr := tar.NewReader(gzr)
|
||||||
|
for {
|
||||||
|
header, err := tr.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
target := filepath.Join(dest, header.Name)
|
||||||
|
if !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||||
|
return fmt.Errorf("%s: illegal file path", target)
|
||||||
|
}
|
||||||
|
switch header.Typeflag {
|
||||||
|
case tar.TypeDir:
|
||||||
|
if err := os.MkdirAll(target, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case tar.TypeReg:
|
||||||
|
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(f, tr); err != nil {
|
||||||
|
f.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
8
internal/env/env.go
vendored
8
internal/env/env.go
vendored
@@ -32,6 +32,14 @@ func GOROOT() string {
|
|||||||
panic("cannot get GOROOT: " + err.Error())
|
panic("cannot get GOROOT: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LLGoCacheDir() string {
|
||||||
|
userCacheDir, err := os.UserCacheDir()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return filepath.Join(userCacheDir, "llgo")
|
||||||
|
}
|
||||||
|
|
||||||
func LLGoRuntimeDir() string {
|
func LLGoRuntimeDir() string {
|
||||||
root := LLGoROOT()
|
root := LLGoROOT()
|
||||||
if root != "" {
|
if root != "" {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/build"
|
"github.com/goplus/llgo/internal/build"
|
||||||
@@ -46,7 +47,7 @@ func genFrom(pkgPath string) (build.Package, error) {
|
|||||||
|
|
||||||
conf := &build.Config{
|
conf := &build.Config{
|
||||||
Mode: build.ModeGen,
|
Mode: build.ModeGen,
|
||||||
AppExt: build.DefaultAppExt(),
|
AppExt: build.DefaultAppExt(runtime.GOOS),
|
||||||
}
|
}
|
||||||
pkgs, err := build.Do([]string{pkgPath}, conf)
|
pkgs, err := build.Do([]string{pkgPath}, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
55
internal/xtool/llvm/llvm.go
Normal file
55
internal/xtool/llvm/llvm.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package llvm
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
func GetTargetTriple(goos, goarch string) string {
|
||||||
|
var llvmarch string
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
switch goarch {
|
||||||
|
case "386":
|
||||||
|
llvmarch = "i386"
|
||||||
|
case "amd64":
|
||||||
|
llvmarch = "x86_64"
|
||||||
|
case "arm64":
|
||||||
|
llvmarch = "aarch64"
|
||||||
|
case "arm":
|
||||||
|
switch goarch {
|
||||||
|
case "5":
|
||||||
|
llvmarch = "armv5"
|
||||||
|
case "6":
|
||||||
|
llvmarch = "armv6"
|
||||||
|
default:
|
||||||
|
llvmarch = "armv7"
|
||||||
|
}
|
||||||
|
case "wasm":
|
||||||
|
llvmarch = "wasm32"
|
||||||
|
default:
|
||||||
|
llvmarch = goarch
|
||||||
|
}
|
||||||
|
llvmvendor := "unknown"
|
||||||
|
llvmos := goos
|
||||||
|
switch goos {
|
||||||
|
case "darwin":
|
||||||
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer
|
||||||
|
// to iOS!
|
||||||
|
llvmos = "macosx"
|
||||||
|
if llvmarch == "aarch64" {
|
||||||
|
// Looks like Apple prefers to call this architecture ARM64
|
||||||
|
// instead of AArch64.
|
||||||
|
llvmarch = "arm64"
|
||||||
|
llvmos = "macosx"
|
||||||
|
}
|
||||||
|
llvmvendor = "apple"
|
||||||
|
case "wasip1":
|
||||||
|
llvmos = "wasip1"
|
||||||
|
}
|
||||||
|
// Target triples (which actually have four components, but are called
|
||||||
|
// triples for historical reasons) have the form:
|
||||||
|
// arch-vendor-os-environment
|
||||||
|
return llvmarch + "-" + llvmvendor + "-" + llvmos
|
||||||
|
}
|
||||||
150
internal/xtool/llvm/llvm_test.go
Normal file
150
internal/xtool/llvm/llvm_test.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
package llvm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetTargetTriple(t *testing.T) {
|
||||||
|
// Get the list of supported architectures from clang
|
||||||
|
cmd := exec.Command("clang", "--print-targets")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to run clang --print-targets: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the output to get the list of supported architectures
|
||||||
|
supportedArchs := make(map[string]bool)
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line != "" && !strings.HasPrefix(line, "Registered Targets:") {
|
||||||
|
// Extract the architecture from the line
|
||||||
|
parts := strings.SplitN(line, " - ", 2)
|
||||||
|
if len(parts) > 0 {
|
||||||
|
arch := strings.TrimSpace(parts[0])
|
||||||
|
supportedArchs[arch] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(supportedArchs) == 0 {
|
||||||
|
t.Fatal("No supported architectures found from clang --print-targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Found %d supported architectures from clang", len(supportedArchs))
|
||||||
|
|
||||||
|
// Map our architecture names to clang's architecture names
|
||||||
|
clangArchMap := map[string][]string{
|
||||||
|
"x86_64": {"x86-64", "x86_64"},
|
||||||
|
"i386": {"x86", "i386"},
|
||||||
|
"aarch64": {"aarch64", "arm64"},
|
||||||
|
"arm64": {"arm64", "aarch64"},
|
||||||
|
"armv7": {"arm", "thumb"},
|
||||||
|
"wasm32": {"wasm32"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to check if the architecture is supported by clang
|
||||||
|
isArchSupported := func(archPart string) (bool, string) {
|
||||||
|
if mappedArchs, ok := clangArchMap[archPart]; ok {
|
||||||
|
for _, mappedArch := range mappedArchs {
|
||||||
|
if supportedArchs[mappedArch] {
|
||||||
|
return true, mappedArch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if supportedArchs[archPart] {
|
||||||
|
// Direct match
|
||||||
|
return true, archPart
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to verify OS name
|
||||||
|
isOSValid := func(os, goos string) bool {
|
||||||
|
validOSMap := map[string][]string{
|
||||||
|
"linux": {"linux", "linux-gnu"},
|
||||||
|
"darwin": {"macosx", "darwin"},
|
||||||
|
"windows": {"windows", "win32"},
|
||||||
|
"wasip1": {"wasip1", "wasi"},
|
||||||
|
"js": {"js", "javascript"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if validVariants, ok := validOSMap[goos]; ok {
|
||||||
|
for _, validVariant := range validVariants {
|
||||||
|
if strings.HasPrefix(os, validVariant) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function to check if vendor is valid
|
||||||
|
isVendorValid := func(vendor string) bool {
|
||||||
|
validVendors := map[string]bool{
|
||||||
|
"unknown": true,
|
||||||
|
"apple": true,
|
||||||
|
"pc": true,
|
||||||
|
"ibm": true,
|
||||||
|
}
|
||||||
|
return validVendors[vendor]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the test function
|
||||||
|
checkTriple := func(t *testing.T, testName, goos, goarch, expected string) {
|
||||||
|
t.Helper()
|
||||||
|
got := GetTargetTriple(goos, goarch)
|
||||||
|
|
||||||
|
// Check if the generated triple matches the expected value
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("getTargetTriple(%q, %q) = %q, want %q",
|
||||||
|
goos, goarch, got, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the architecture part from the triple (first component)
|
||||||
|
parts := strings.Split(got, "-")
|
||||||
|
if len(parts) < 3 {
|
||||||
|
t.Errorf("Invalid target triple format: %s, should have at least 3 components", got)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
archPart := parts[0]
|
||||||
|
vendor := parts[1]
|
||||||
|
os := parts[2]
|
||||||
|
|
||||||
|
// Check if the architecture is supported by clang
|
||||||
|
supported, mappedArch := isArchSupported(archPart)
|
||||||
|
if supported {
|
||||||
|
t.Logf("Architecture %s (mapped to %s) is supported by clang", archPart, mappedArch)
|
||||||
|
} else {
|
||||||
|
t.Logf("WARNING: Architecture %s from triple %q for %s/%s not found in clang's supported architectures",
|
||||||
|
archPart, got, goos, goarch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify vendor
|
||||||
|
if !isVendorValid(vendor) {
|
||||||
|
t.Errorf("Invalid vendor in triple: %s", vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify OS
|
||||||
|
if !isOSValid(os, goos) {
|
||||||
|
t.Errorf("OS in triple %q doesn't match expected OS %q", os, goos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run tests for different OS/arch combinations
|
||||||
|
checkTriple(t, "wasip1/wasm", "wasip1", "wasm", "wasm32-unknown-wasip1")
|
||||||
|
checkTriple(t, "linux/amd64", "linux", "amd64", "x86_64-unknown-linux")
|
||||||
|
checkTriple(t, "linux/386", "linux", "386", "i386-unknown-linux")
|
||||||
|
checkTriple(t, "linux/arm64", "linux", "arm64", "aarch64-unknown-linux")
|
||||||
|
checkTriple(t, "linux/arm", "linux", "arm", "armv7-unknown-linux")
|
||||||
|
checkTriple(t, "darwin/amd64", "darwin", "amd64", "x86_64-apple-macosx")
|
||||||
|
checkTriple(t, "darwin/arm64", "darwin", "arm64", "arm64-apple-macosx")
|
||||||
|
checkTriple(t, "windows/amd64", "windows", "amd64", "x86_64-unknown-windows")
|
||||||
|
checkTriple(t, "windows/386", "windows", "386", "i386-unknown-windows")
|
||||||
|
checkTriple(t, "js/wasm", "js", "wasm", "wasm32-unknown-js")
|
||||||
|
}
|
||||||
11
llgo_wasm
Executable file
11
llgo_wasm
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
WORKDIR=''
|
||||||
|
WORKDIR=$(pwd)
|
||||||
|
LLGO_ROOT=''
|
||||||
|
LLGO_ROOT=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )
|
||||||
|
export LLGO_ROOT
|
||||||
|
cd $LLGO_ROOT
|
||||||
|
go install ./cmd/llgo
|
||||||
|
cd $WORKDIR
|
||||||
|
GOOS=wasip1 GOARCH=wasm llgo "$@"
|
||||||
@@ -24,11 +24,6 @@
|
|||||||
// with a single network connection.
|
// with a single network connection.
|
||||||
package textproto
|
package textproto
|
||||||
|
|
||||||
/*
|
|
||||||
#include <stdint.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -97,55 +92,55 @@ const (
|
|||||||
type SockAddr struct {
|
type SockAddr struct {
|
||||||
Len uint8
|
Len uint8
|
||||||
Family uint8
|
Family uint8
|
||||||
Data [14]C.char
|
Data [14]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddrInfo struct {
|
type AddrInfo struct {
|
||||||
Flags C.int
|
Flags int32
|
||||||
Family C.int
|
Family int32
|
||||||
SockType C.int
|
SockType int32
|
||||||
Protocol C.int
|
Protocol int32
|
||||||
AddrLen C.uint
|
AddrLen uint32
|
||||||
CanOnName *C.char
|
CanOnName *uint8
|
||||||
Addr *SockAddr
|
Addr *SockAddr
|
||||||
Next *AddrInfo
|
Next *AddrInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname Getaddrinfo C.getaddrinfo
|
//go:linkname Getaddrinfo C.getaddrinfo
|
||||||
func Getaddrinfo(host *C.char, port *C.char, addrInfo *AddrInfo, result **AddrInfo) C.int
|
func Getaddrinfo(host *uint8, port *uint8, addrInfo *AddrInfo, result **AddrInfo) int32
|
||||||
|
|
||||||
//go:linkname Freeaddrinfo C.freeaddrinfo
|
//go:linkname Freeaddrinfo C.freeaddrinfo
|
||||||
func Freeaddrinfo(addrInfo *AddrInfo) C.int
|
func Freeaddrinfo(addrInfo *AddrInfo) int32
|
||||||
|
|
||||||
//go:linkname GoString llgo.string
|
//go:linkname GoString llgo.string
|
||||||
func GoString(cstr *C.char, __llgo_va_list /* n */ ...any) string
|
func GoString(cstr *uint8, __llgo_va_list /* n */ ...any) string
|
||||||
|
|
||||||
//go:linkname AllocaCStr llgo.allocaCStr
|
//go:linkname AllocaCStr llgo.allocaCStr
|
||||||
func AllocaCStr(s string) *C.char
|
func AllocaCStr(s string) *uint8
|
||||||
|
|
||||||
//go:linkname Memset C.memset
|
//go:linkname Memset C.memset
|
||||||
func Memset(s unsafe.Pointer, c C.int, n uintptr) unsafe.Pointer
|
func Memset(s unsafe.Pointer, c int32, n uintptr) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname Read C.read
|
//go:linkname Read C.read
|
||||||
func Read(fd C.int, buf unsafe.Pointer, count uintptr) int
|
func Read(fd int32, buf unsafe.Pointer, count uintptr) int
|
||||||
|
|
||||||
//go:linkname Write C.write
|
//go:linkname Write C.write
|
||||||
func Write(fd C.int, buf unsafe.Pointer, count uintptr) int
|
func Write(fd int32, buf unsafe.Pointer, count uintptr) int
|
||||||
|
|
||||||
//go:linkname Close C.close
|
//go:linkname Close C.close
|
||||||
func Close(fd C.int) C.int
|
func Close(fd int32) int32
|
||||||
|
|
||||||
//go:linkname Strerror strerror
|
//go:linkname Strerror strerror
|
||||||
func Strerror(errnum C.int) *C.char
|
func Strerror(errnum int32) *uint8
|
||||||
|
|
||||||
//go:linkname Errno C.cliteErrno
|
//go:linkname Errno C.cliteErrno
|
||||||
func Errno() C.int
|
func Errno() int32
|
||||||
|
|
||||||
//go:linkname Socket C.socket
|
//go:linkname Socket C.socket
|
||||||
func Socket(domain C.int, typ C.int, protocol C.int) C.int
|
func Socket(domain int32, typ int32, protocol int32) int32
|
||||||
|
|
||||||
//go:linkname Connect C.connect
|
//go:linkname Connect C.connect
|
||||||
func Connect(sockfd C.int, addr *SockAddr, addrlen C.uint) C.int
|
func Connect(sockfd int32, addr *SockAddr, addrlen uint32) int32
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -204,7 +199,7 @@ func Dial(network, addr string) (*Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cConn struct {
|
type cConn struct {
|
||||||
socketFd C.int
|
socketFd int32
|
||||||
closed bool
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +213,7 @@ func (conn *cConn) Read(p []byte) (n int, err error) {
|
|||||||
for n < len(p) {
|
for n < len(p) {
|
||||||
result := Read(conn.socketFd, unsafe.Pointer(&p[n:][0]), uintptr(len(p)-n))
|
result := Read(conn.socketFd, unsafe.Pointer(&p[n:][0]), uintptr(len(p)-n))
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
if Errno() == C.int(syscall.EINTR) {
|
if Errno() == int32(syscall.EINTR) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return n, errors.New("read error")
|
return n, errors.New("read error")
|
||||||
@@ -238,7 +233,7 @@ func (conn *cConn) Write(p []byte) (n int, err error) {
|
|||||||
for n < len(p) {
|
for n < len(p) {
|
||||||
result := Write(conn.socketFd, unsafe.Pointer(&p[n:][0]), uintptr(len(p)-n))
|
result := Write(conn.socketFd, unsafe.Pointer(&p[n:][0]), uintptr(len(p)-n))
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
if Errno() == C.int(syscall.EINTR) {
|
if Errno() == int32(syscall.EINTR) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return n, errors.New("write error")
|
return n, errors.New("write error")
|
||||||
|
|||||||
482
runtime/_overlay/runtime/runtime.go
Normal file
482
runtime/_overlay/runtime/runtime.go
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
package runtime
|
||||||
|
|
||||||
|
func Goexit() {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeepAlive(x any) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetFinalizer(obj any, finalizer any) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
const GOOS = ""
|
||||||
|
const GOARCH = ""
|
||||||
|
|
||||||
|
func GOMAXPROCS(n int) int {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GC() {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GOROOT() string {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Callers(skip int, pc []uintptr) int {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Func struct {
|
||||||
|
opaque struct{} // unexported field to disallow conversions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Func) Name() string {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuncForPC(pc uintptr) *Func {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type nih struct{}
|
||||||
|
|
||||||
|
type NotInHeap struct{ _ nih }
|
||||||
|
|
||||||
|
type FuncID uint8
|
||||||
|
|
||||||
|
type FuncFlag uint8
|
||||||
|
|
||||||
|
type _func struct {
|
||||||
|
NotInHeap // Only in static data
|
||||||
|
|
||||||
|
entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart
|
||||||
|
nameOff int32 // function name, as index into moduledata.funcnametab.
|
||||||
|
|
||||||
|
args int32 // in/out args size
|
||||||
|
deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
|
||||||
|
|
||||||
|
pcsp uint32
|
||||||
|
pcfile uint32
|
||||||
|
pcln uint32
|
||||||
|
npcdata uint32
|
||||||
|
cuOffset uint32 // runtime.cutab offset of this function's CU
|
||||||
|
startLine int32 // line number of start of function (func keyword/TEXT directive)
|
||||||
|
funcID FuncID // set for certain special runtime functions
|
||||||
|
flag FuncFlag
|
||||||
|
_ [1]byte // pad
|
||||||
|
nfuncdata uint8 // must be last, must end on a uint32-aligned boundary
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata struct{}
|
||||||
|
|
||||||
|
type funcInfo struct {
|
||||||
|
*_func
|
||||||
|
datap *moduledata
|
||||||
|
}
|
||||||
|
|
||||||
|
type Frame struct {
|
||||||
|
PC uintptr
|
||||||
|
Func *Func
|
||||||
|
Function string
|
||||||
|
File string
|
||||||
|
Line int
|
||||||
|
startLine int
|
||||||
|
Entry uintptr
|
||||||
|
funcInfo funcInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type Frames struct {
|
||||||
|
callers []uintptr
|
||||||
|
nextPC uintptr
|
||||||
|
frames []Frame
|
||||||
|
frameStore [2]Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ci *Frames) Next() (frame Frame, more bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallersFrames(callers []uintptr) *Frames {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stack(buf []byte, all bool) int {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Version() string {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemStats struct {
|
||||||
|
// General statistics.
|
||||||
|
|
||||||
|
// Alloc is bytes of allocated heap objects.
|
||||||
|
//
|
||||||
|
// This is the same as HeapAlloc (see below).
|
||||||
|
Alloc uint64
|
||||||
|
|
||||||
|
// TotalAlloc is cumulative bytes allocated for heap objects.
|
||||||
|
//
|
||||||
|
// TotalAlloc increases as heap objects are allocated, but
|
||||||
|
// unlike Alloc and HeapAlloc, it does not decrease when
|
||||||
|
// objects are freed.
|
||||||
|
TotalAlloc uint64
|
||||||
|
|
||||||
|
// Sys is the total bytes of memory obtained from the OS.
|
||||||
|
//
|
||||||
|
// Sys is the sum of the XSys fields below. Sys measures the
|
||||||
|
// virtual address space reserved by the Go runtime for the
|
||||||
|
// heap, stacks, and other internal data structures. It's
|
||||||
|
// likely that not all of the virtual address space is backed
|
||||||
|
// by physical memory at any given moment, though in general
|
||||||
|
// it all was at some point.
|
||||||
|
Sys uint64
|
||||||
|
|
||||||
|
// Lookups is the number of pointer lookups performed by the
|
||||||
|
// runtime.
|
||||||
|
//
|
||||||
|
// This is primarily useful for debugging runtime internals.
|
||||||
|
Lookups uint64
|
||||||
|
|
||||||
|
// Mallocs is the cumulative count of heap objects allocated.
|
||||||
|
// The number of live objects is Mallocs - Frees.
|
||||||
|
Mallocs uint64
|
||||||
|
|
||||||
|
// Frees is the cumulative count of heap objects freed.
|
||||||
|
Frees uint64
|
||||||
|
|
||||||
|
// Heap memory statistics.
|
||||||
|
//
|
||||||
|
// Interpreting the heap statistics requires some knowledge of
|
||||||
|
// how Go organizes memory. Go divides the virtual address
|
||||||
|
// space of the heap into "spans", which are contiguous
|
||||||
|
// regions of memory 8K or larger. A span may be in one of
|
||||||
|
// three states:
|
||||||
|
//
|
||||||
|
// An "idle" span contains no objects or other data. The
|
||||||
|
// physical memory backing an idle span can be released back
|
||||||
|
// to the OS (but the virtual address space never is), or it
|
||||||
|
// can be converted into an "in use" or "stack" span.
|
||||||
|
//
|
||||||
|
// An "in use" span contains at least one heap object and may
|
||||||
|
// have free space available to allocate more heap objects.
|
||||||
|
//
|
||||||
|
// A "stack" span is used for goroutine stacks. Stack spans
|
||||||
|
// are not considered part of the heap. A span can change
|
||||||
|
// between heap and stack memory; it is never used for both
|
||||||
|
// simultaneously.
|
||||||
|
|
||||||
|
// HeapAlloc is bytes of allocated heap objects.
|
||||||
|
//
|
||||||
|
// "Allocated" heap objects include all reachable objects, as
|
||||||
|
// well as unreachable objects that the garbage collector has
|
||||||
|
// not yet freed. Specifically, HeapAlloc increases as heap
|
||||||
|
// objects are allocated and decreases as the heap is swept
|
||||||
|
// and unreachable objects are freed. Sweeping occurs
|
||||||
|
// incrementally between GC cycles, so these two processes
|
||||||
|
// occur simultaneously, and as a result HeapAlloc tends to
|
||||||
|
// change smoothly (in contrast with the sawtooth that is
|
||||||
|
// typical of stop-the-world garbage collectors).
|
||||||
|
HeapAlloc uint64
|
||||||
|
|
||||||
|
// HeapSys is bytes of heap memory obtained from the OS.
|
||||||
|
//
|
||||||
|
// HeapSys measures the amount of virtual address space
|
||||||
|
// reserved for the heap. This includes virtual address space
|
||||||
|
// that has been reserved but not yet used, which consumes no
|
||||||
|
// physical memory, but tends to be small, as well as virtual
|
||||||
|
// address space for which the physical memory has been
|
||||||
|
// returned to the OS after it became unused (see HeapReleased
|
||||||
|
// for a measure of the latter).
|
||||||
|
//
|
||||||
|
// HeapSys estimates the largest size the heap has had.
|
||||||
|
HeapSys uint64
|
||||||
|
|
||||||
|
// HeapIdle is bytes in idle (unused) spans.
|
||||||
|
//
|
||||||
|
// Idle spans have no objects in them. These spans could be
|
||||||
|
// (and may already have been) returned to the OS, or they can
|
||||||
|
// be reused for heap allocations, or they can be reused as
|
||||||
|
// stack memory.
|
||||||
|
//
|
||||||
|
// HeapIdle minus HeapReleased estimates the amount of memory
|
||||||
|
// that could be returned to the OS, but is being retained by
|
||||||
|
// the runtime so it can grow the heap without requesting more
|
||||||
|
// memory from the OS. If this difference is significantly
|
||||||
|
// larger than the heap size, it indicates there was a recent
|
||||||
|
// transient spike in live heap size.
|
||||||
|
HeapIdle uint64
|
||||||
|
|
||||||
|
// HeapInuse is bytes in in-use spans.
|
||||||
|
//
|
||||||
|
// In-use spans have at least one object in them. These spans
|
||||||
|
// can only be used for other objects of roughly the same
|
||||||
|
// size.
|
||||||
|
//
|
||||||
|
// HeapInuse minus HeapAlloc estimates the amount of memory
|
||||||
|
// that has been dedicated to particular size classes, but is
|
||||||
|
// not currently being used. This is an upper bound on
|
||||||
|
// fragmentation, but in general this memory can be reused
|
||||||
|
// efficiently.
|
||||||
|
HeapInuse uint64
|
||||||
|
|
||||||
|
// HeapReleased is bytes of physical memory returned to the OS.
|
||||||
|
//
|
||||||
|
// This counts heap memory from idle spans that was returned
|
||||||
|
// to the OS and has not yet been reacquired for the heap.
|
||||||
|
HeapReleased uint64
|
||||||
|
|
||||||
|
// HeapObjects is the number of allocated heap objects.
|
||||||
|
//
|
||||||
|
// Like HeapAlloc, this increases as objects are allocated and
|
||||||
|
// decreases as the heap is swept and unreachable objects are
|
||||||
|
// freed.
|
||||||
|
HeapObjects uint64
|
||||||
|
|
||||||
|
// Stack memory statistics.
|
||||||
|
//
|
||||||
|
// Stacks are not considered part of the heap, but the runtime
|
||||||
|
// can reuse a span of heap memory for stack memory, and
|
||||||
|
// vice-versa.
|
||||||
|
|
||||||
|
// StackInuse is bytes in stack spans.
|
||||||
|
//
|
||||||
|
// In-use stack spans have at least one stack in them. These
|
||||||
|
// spans can only be used for other stacks of the same size.
|
||||||
|
//
|
||||||
|
// There is no StackIdle because unused stack spans are
|
||||||
|
// returned to the heap (and hence counted toward HeapIdle).
|
||||||
|
StackInuse uint64
|
||||||
|
|
||||||
|
// StackSys is bytes of stack memory obtained from the OS.
|
||||||
|
//
|
||||||
|
// StackSys is StackInuse, plus any memory obtained directly
|
||||||
|
// from the OS for OS thread stacks.
|
||||||
|
//
|
||||||
|
// In non-cgo programs this metric is currently equal to StackInuse
|
||||||
|
// (but this should not be relied upon, and the value may change in
|
||||||
|
// the future).
|
||||||
|
//
|
||||||
|
// In cgo programs this metric includes OS thread stacks allocated
|
||||||
|
// directly from the OS. Currently, this only accounts for one stack in
|
||||||
|
// c-shared and c-archive build modes and other sources of stacks from
|
||||||
|
// the OS (notably, any allocated by C code) are not currently measured.
|
||||||
|
// Note this too may change in the future.
|
||||||
|
StackSys uint64
|
||||||
|
|
||||||
|
// Off-heap memory statistics.
|
||||||
|
//
|
||||||
|
// The following statistics measure runtime-internal
|
||||||
|
// structures that are not allocated from heap memory (usually
|
||||||
|
// because they are part of implementing the heap). Unlike
|
||||||
|
// heap or stack memory, any memory allocated to these
|
||||||
|
// structures is dedicated to these structures.
|
||||||
|
//
|
||||||
|
// These are primarily useful for debugging runtime memory
|
||||||
|
// overheads.
|
||||||
|
|
||||||
|
// MSpanInuse is bytes of allocated mspan structures.
|
||||||
|
MSpanInuse uint64
|
||||||
|
|
||||||
|
// MSpanSys is bytes of memory obtained from the OS for mspan
|
||||||
|
// structures.
|
||||||
|
MSpanSys uint64
|
||||||
|
|
||||||
|
// MCacheInuse is bytes of allocated mcache structures.
|
||||||
|
MCacheInuse uint64
|
||||||
|
|
||||||
|
// MCacheSys is bytes of memory obtained from the OS for
|
||||||
|
// mcache structures.
|
||||||
|
MCacheSys uint64
|
||||||
|
|
||||||
|
// BuckHashSys is bytes of memory in profiling bucket hash tables.
|
||||||
|
BuckHashSys uint64
|
||||||
|
|
||||||
|
// GCSys is bytes of memory in garbage collection metadata.
|
||||||
|
GCSys uint64
|
||||||
|
|
||||||
|
// OtherSys is bytes of memory in miscellaneous off-heap
|
||||||
|
// runtime allocations.
|
||||||
|
OtherSys uint64
|
||||||
|
|
||||||
|
// Garbage collector statistics.
|
||||||
|
|
||||||
|
// NextGC is the target heap size of the next GC cycle.
|
||||||
|
//
|
||||||
|
// The garbage collector's goal is to keep HeapAlloc ≤ NextGC.
|
||||||
|
// At the end of each GC cycle, the target for the next cycle
|
||||||
|
// is computed based on the amount of reachable data and the
|
||||||
|
// value of GOGC.
|
||||||
|
NextGC uint64
|
||||||
|
|
||||||
|
// LastGC is the time the last garbage collection finished, as
|
||||||
|
// nanoseconds since 1970 (the UNIX epoch).
|
||||||
|
LastGC uint64
|
||||||
|
|
||||||
|
// PauseTotalNs is the cumulative nanoseconds in GC
|
||||||
|
// stop-the-world pauses since the program started.
|
||||||
|
//
|
||||||
|
// During a stop-the-world pause, all goroutines are paused
|
||||||
|
// and only the garbage collector can run.
|
||||||
|
PauseTotalNs uint64
|
||||||
|
|
||||||
|
// PauseNs is a circular buffer of recent GC stop-the-world
|
||||||
|
// pause times in nanoseconds.
|
||||||
|
//
|
||||||
|
// The most recent pause is at PauseNs[(NumGC+255)%256]. In
|
||||||
|
// general, PauseNs[N%256] records the time paused in the most
|
||||||
|
// recent N%256th GC cycle. There may be multiple pauses per
|
||||||
|
// GC cycle; this is the sum of all pauses during a cycle.
|
||||||
|
PauseNs [256]uint64
|
||||||
|
|
||||||
|
// PauseEnd is a circular buffer of recent GC pause end times,
|
||||||
|
// as nanoseconds since 1970 (the UNIX epoch).
|
||||||
|
//
|
||||||
|
// This buffer is filled the same way as PauseNs. There may be
|
||||||
|
// multiple pauses per GC cycle; this records the end of the
|
||||||
|
// last pause in a cycle.
|
||||||
|
PauseEnd [256]uint64
|
||||||
|
|
||||||
|
// NumGC is the number of completed GC cycles.
|
||||||
|
NumGC uint32
|
||||||
|
|
||||||
|
// NumForcedGC is the number of GC cycles that were forced by
|
||||||
|
// the application calling the GC function.
|
||||||
|
NumForcedGC uint32
|
||||||
|
|
||||||
|
// GCCPUFraction is the fraction of this program's available
|
||||||
|
// CPU time used by the GC since the program started.
|
||||||
|
//
|
||||||
|
// GCCPUFraction is expressed as a number between 0 and 1,
|
||||||
|
// where 0 means GC has consumed none of this program's CPU. A
|
||||||
|
// program's available CPU time is defined as the integral of
|
||||||
|
// GOMAXPROCS since the program started. That is, if
|
||||||
|
// GOMAXPROCS is 2 and a program has been running for 10
|
||||||
|
// seconds, its "available CPU" is 20 seconds. GCCPUFraction
|
||||||
|
// does not include CPU time used for write barrier activity.
|
||||||
|
//
|
||||||
|
// This is the same as the fraction of CPU reported by
|
||||||
|
// GODEBUG=gctrace=1.
|
||||||
|
GCCPUFraction float64
|
||||||
|
|
||||||
|
// EnableGC indicates that GC is enabled. It is always true,
|
||||||
|
// even if GOGC=off.
|
||||||
|
EnableGC bool
|
||||||
|
|
||||||
|
// DebugGC is currently unused.
|
||||||
|
DebugGC bool
|
||||||
|
|
||||||
|
// BySize reports per-size class allocation statistics.
|
||||||
|
//
|
||||||
|
// BySize[N] gives statistics for allocations of size S where
|
||||||
|
// BySize[N-1].Size < S ≤ BySize[N].Size.
|
||||||
|
//
|
||||||
|
// This does not report allocations larger than BySize[60].Size.
|
||||||
|
BySize [61]struct {
|
||||||
|
// Size is the maximum byte size of an object in this
|
||||||
|
// size class.
|
||||||
|
Size uint32
|
||||||
|
|
||||||
|
// Mallocs is the cumulative count of heap objects
|
||||||
|
// allocated in this size class. The cumulative bytes
|
||||||
|
// of allocation is Size*Mallocs. The number of live
|
||||||
|
// objects in this size class is Mallocs - Frees.
|
||||||
|
Mallocs uint64
|
||||||
|
|
||||||
|
// Frees is the cumulative count of heap objects freed
|
||||||
|
// in this size class.
|
||||||
|
Frees uint64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMemStats(m *MemStats) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemProfileRecord struct {
|
||||||
|
AllocBytes, FreeBytes int64 // number of bytes allocated, freed
|
||||||
|
AllocObjects, FreeObjects int64 // number of objects allocated, freed
|
||||||
|
Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// InUseBytes returns the number of bytes in use (AllocBytes - FreeBytes).
|
||||||
|
func (r *MemProfileRecord) InUseBytes() int64 { return r.AllocBytes - r.FreeBytes }
|
||||||
|
|
||||||
|
// InUseObjects returns the number of objects in use (AllocObjects - FreeObjects).
|
||||||
|
func (r *MemProfileRecord) InUseObjects() int64 {
|
||||||
|
return r.AllocObjects - r.FreeObjects
|
||||||
|
}
|
||||||
|
|
||||||
|
var MemProfileRate int = 512 * 1024
|
||||||
|
|
||||||
|
func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartTrace() error {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopTrace() {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadTrace() []byte {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBlockProfileRate(rate int) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetMutexProfileFraction(rate int) int {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func LockOSThread() {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnlockOSThread() {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type StackRecord struct {
|
||||||
|
Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func NumGoroutine() int {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCPUProfileRate(hz int) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
type BlockProfileRecord struct {
|
||||||
|
Count int64
|
||||||
|
Cycles int64
|
||||||
|
StackRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func BlockProfile(p []BlockProfileRecord) (n int, ok bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func MutexProfile(p []BlockProfileRecord) (n int, ok bool) {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
@@ -342,14 +342,28 @@ func (t *UncommonType) Methods() []Method {
|
|||||||
if t.Mcount == 0 {
|
if t.Mcount == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
|
methodsPtr := addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0")
|
||||||
|
methods := make([]Method, t.Mcount)
|
||||||
|
for i := 0; i < int(t.Mcount); i++ {
|
||||||
|
elemPtr := addChecked(methodsPtr, uintptr(i)*unsafe.Sizeof(Method{}), "accessing method element")
|
||||||
|
elem := (*Method)(elemPtr)
|
||||||
|
methods[i] = *elem
|
||||||
|
}
|
||||||
|
return methods
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UncommonType) ExportedMethods() []Method {
|
func (t *UncommonType) ExportedMethods() []Method {
|
||||||
if t.Xcount == 0 {
|
if t.Xcount == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
|
mthdsPtr := addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0")
|
||||||
|
mthds := make([]Method, t.Xcount)
|
||||||
|
for i := 0; i < int(t.Xcount); i++ {
|
||||||
|
elemPtr := addChecked(mthdsPtr, uintptr(i)*unsafe.Sizeof(Method{}), "accessing method element")
|
||||||
|
elem := (*Method)(elemPtr)
|
||||||
|
mthds[i] = *elem
|
||||||
|
}
|
||||||
|
return mthds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Imethod represents a method on an interface type
|
// Imethod represents a method on an interface type
|
||||||
|
|||||||
@@ -26,12 +26,17 @@ var hasAltPkg = map[string]none{
|
|||||||
"hash/crc32": {},
|
"hash/crc32": {},
|
||||||
"internal/abi": {},
|
"internal/abi": {},
|
||||||
"internal/bytealg": {},
|
"internal/bytealg": {},
|
||||||
|
"internal/chacha8rand": {},
|
||||||
"internal/cpu": {},
|
"internal/cpu": {},
|
||||||
"internal/itoa": {},
|
"internal/itoa": {},
|
||||||
"internal/godebug": {},
|
"internal/godebug": {},
|
||||||
"internal/oserror": {},
|
"internal/oserror": {},
|
||||||
"internal/poll": {},
|
"internal/poll": {},
|
||||||
"internal/reflectlite": {},
|
"internal/reflectlite": {},
|
||||||
|
"internal/runtime/atomic": {},
|
||||||
|
"internal/runtime/maps": {},
|
||||||
|
"internal/runtime/sys": {},
|
||||||
|
"internal/sync": {},
|
||||||
"internal/syscall/execenv": {},
|
"internal/syscall/execenv": {},
|
||||||
"internal/syscall/unix": {},
|
"internal/syscall/unix": {},
|
||||||
"math": {},
|
"math": {},
|
||||||
@@ -52,4 +57,5 @@ var hasAltPkg = map[string]none{
|
|||||||
"runtime/trace": {},
|
"runtime/trace": {},
|
||||||
"runtime/internal/syscall": {},
|
"runtime/internal/syscall": {},
|
||||||
"io": {},
|
"io": {},
|
||||||
|
"io/fs": {},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,34 @@
|
|||||||
typedef union {
|
typedef union
|
||||||
|
{
|
||||||
double d;
|
double d;
|
||||||
float f;
|
float f;
|
||||||
long v;
|
long v;
|
||||||
|
long long ll;
|
||||||
} castUnion;
|
} castUnion;
|
||||||
|
|
||||||
double llgoToFloat64(long v) {
|
double llgoToFloat64(long long v)
|
||||||
|
{
|
||||||
castUnion k;
|
castUnion k;
|
||||||
k.v = v;
|
k.ll = v;
|
||||||
return k.d;
|
return k.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float llgoToFloat32(long v) {
|
float llgoToFloat32(int v)
|
||||||
|
{
|
||||||
castUnion k;
|
castUnion k;
|
||||||
k.v = v;
|
k.v = v;
|
||||||
return k.f;
|
return k.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
long llgoFromFloat64(double v) {
|
long long llgoFromFloat64(double v)
|
||||||
|
{
|
||||||
castUnion k;
|
castUnion k;
|
||||||
k.d = v;
|
k.d = v;
|
||||||
return k.v;
|
return k.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
long llgoFromFloat32(float v) {
|
int llgoFromFloat32(float v)
|
||||||
|
{
|
||||||
castUnion k;
|
castUnion k;
|
||||||
k.f = v;
|
k.f = v;
|
||||||
return k.v;
|
return k.v;
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname ToFloat64 C.llgoToFloat64
|
//go:linkname ToFloat64 C.llgoToFloat64
|
||||||
func ToFloat64(v uintptr) float64
|
func ToFloat64(v int64) float64
|
||||||
|
|
||||||
//go:linkname ToFloat32 C.llgoToFloat32
|
//go:linkname ToFloat32 C.llgoToFloat32
|
||||||
func ToFloat32(v uintptr) float32
|
func ToFloat32(v int32) float32
|
||||||
|
|
||||||
//go:linkname FromFloat64 C.llgoFromFloat64
|
//go:linkname FromFloat64 C.llgoFromFloat64
|
||||||
func FromFloat64(v float64) uintptr
|
func FromFloat64(v float64) int64
|
||||||
|
|
||||||
//go:linkname FromFloat32 C.llgoFromFloat32
|
//go:linkname FromFloat32 C.llgoFromFloat32
|
||||||
func FromFloat32(v float32) uintptr
|
func FromFloat32(v float32) int32
|
||||||
|
|||||||
149
runtime/internal/clite/byteorder/byteorder.go
Normal file
149
runtime/internal/clite/byteorder/byteorder.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package byteorder provides functions for decoding and encoding
|
||||||
|
// little and big endian integer types from/to byte slices.
|
||||||
|
package byteorder
|
||||||
|
|
||||||
|
func LEUint16(b []byte) uint16 {
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint16(b[0]) | uint16(b[1])<<8
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEPutUint16(b []byte, v uint16) {
|
||||||
|
_ = b[1] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEAppendUint16(b []byte, v uint16) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v),
|
||||||
|
byte(v>>8),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEUint32(b []byte) uint32 {
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEPutUint32(b []byte, v uint32) {
|
||||||
|
_ = b[3] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEAppendUint32(b []byte, v uint32) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v),
|
||||||
|
byte(v>>8),
|
||||||
|
byte(v>>16),
|
||||||
|
byte(v>>24),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEUint64(b []byte) uint64 {
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||||
|
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEPutUint64(b []byte, v uint64) {
|
||||||
|
_ = b[7] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v)
|
||||||
|
b[1] = byte(v >> 8)
|
||||||
|
b[2] = byte(v >> 16)
|
||||||
|
b[3] = byte(v >> 24)
|
||||||
|
b[4] = byte(v >> 32)
|
||||||
|
b[5] = byte(v >> 40)
|
||||||
|
b[6] = byte(v >> 48)
|
||||||
|
b[7] = byte(v >> 56)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LEAppendUint64(b []byte, v uint64) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v),
|
||||||
|
byte(v>>8),
|
||||||
|
byte(v>>16),
|
||||||
|
byte(v>>24),
|
||||||
|
byte(v>>32),
|
||||||
|
byte(v>>40),
|
||||||
|
byte(v>>48),
|
||||||
|
byte(v>>56),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEUint16(b []byte) uint16 {
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint16(b[1]) | uint16(b[0])<<8
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEPutUint16(b []byte, v uint16) {
|
||||||
|
_ = b[1] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v >> 8)
|
||||||
|
b[1] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEAppendUint16(b []byte, v uint16) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v>>8),
|
||||||
|
byte(v),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEUint32(b []byte) uint32 {
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEPutUint32(b []byte, v uint32) {
|
||||||
|
_ = b[3] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v >> 24)
|
||||||
|
b[1] = byte(v >> 16)
|
||||||
|
b[2] = byte(v >> 8)
|
||||||
|
b[3] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEAppendUint32(b []byte, v uint32) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v>>24),
|
||||||
|
byte(v>>16),
|
||||||
|
byte(v>>8),
|
||||||
|
byte(v),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEUint64(b []byte) uint64 {
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEPutUint64(b []byte, v uint64) {
|
||||||
|
_ = b[7] // early bounds check to guarantee safety of writes below
|
||||||
|
b[0] = byte(v >> 56)
|
||||||
|
b[1] = byte(v >> 48)
|
||||||
|
b[2] = byte(v >> 40)
|
||||||
|
b[3] = byte(v >> 32)
|
||||||
|
b[4] = byte(v >> 24)
|
||||||
|
b[5] = byte(v >> 16)
|
||||||
|
b[6] = byte(v >> 8)
|
||||||
|
b[7] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BEAppendUint64(b []byte, v uint64) []byte {
|
||||||
|
return append(b,
|
||||||
|
byte(v>>56),
|
||||||
|
byte(v>>48),
|
||||||
|
byte(v>>40),
|
||||||
|
byte(v>>32),
|
||||||
|
byte(v>>24),
|
||||||
|
byte(v>>16),
|
||||||
|
byte(v>>8),
|
||||||
|
byte(v),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -14,14 +14,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package clite
|
package c
|
||||||
|
|
||||||
// typedef unsigned int uint;
|
import (
|
||||||
// typedef unsigned long ulong;
|
"unsafe"
|
||||||
// typedef unsigned long long ulonglong;
|
)
|
||||||
// typedef long long longlong;
|
|
||||||
import "C"
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = "decl"
|
LLGoPackage = "decl"
|
||||||
@@ -41,14 +38,16 @@ type FILE struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Int C.int
|
Int = int32
|
||||||
Uint C.uint
|
Uint = uint32
|
||||||
|
|
||||||
Long C.long
|
// Long and Ulong are defined in platform-specific files
|
||||||
Ulong C.ulong
|
// Windows (both 32-bit and 64-bit): int32/uint32
|
||||||
|
// Unix/Linux/macOS 32-bit: int32/uint32
|
||||||
|
// Unix/Linux/macOS 64-bit: int64/uint64
|
||||||
|
|
||||||
LongLong C.longlong
|
LongLong = int64
|
||||||
UlongLong C.ulonglong
|
UlongLong = uint64
|
||||||
)
|
)
|
||||||
|
|
||||||
type integer interface {
|
type integer interface {
|
||||||
@@ -56,6 +55,7 @@ type integer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SizeT = uintptr
|
type SizeT = uintptr
|
||||||
|
type SsizeT = Long
|
||||||
|
|
||||||
type IntptrT = uintptr
|
type IntptrT = uintptr
|
||||||
type UintptrT = uintptr
|
type UintptrT = uintptr
|
||||||
@@ -72,6 +72,8 @@ type Uint64T = uint64
|
|||||||
type IntmaxT = LongLong
|
type IntmaxT = LongLong
|
||||||
type UintmaxT = UlongLong
|
type UintmaxT = UlongLong
|
||||||
|
|
||||||
|
type VaList = Pointer
|
||||||
|
|
||||||
//go:linkname Str llgo.cstr
|
//go:linkname Str llgo.cstr
|
||||||
func Str(string) *Char
|
func Str(string) *Char
|
||||||
|
|
||||||
@@ -90,6 +92,9 @@ func Alloca(size uintptr) Pointer
|
|||||||
//go:linkname AllocaCStr llgo.allocaCStr
|
//go:linkname AllocaCStr llgo.allocaCStr
|
||||||
func AllocaCStr(s string) *Char
|
func AllocaCStr(s string) *Char
|
||||||
|
|
||||||
|
//go:linkname AllocCStr llgo.allocCStr
|
||||||
|
func AllocCStr(s string) *Char
|
||||||
|
|
||||||
//go:linkname AllocaCStrs llgo.allocaCStrs
|
//go:linkname AllocaCStrs llgo.allocaCStrs
|
||||||
func AllocaCStrs(strs []string, endWithNil bool) **Char
|
func AllocaCStrs(strs []string, endWithNil bool) **Char
|
||||||
|
|
||||||
@@ -257,6 +262,14 @@ func Perror(s *Char)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type IconvT = Pointer
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type LocaleT = Pointer
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Usleep C.usleep
|
//go:linkname Usleep C.usleep
|
||||||
func Usleep(useconds Uint) Int
|
func Usleep(useconds Uint) Int
|
||||||
|
|
||||||
@@ -297,6 +310,3 @@ func GetoptLong(argc Int, argv **Char, optstring *Char, longopts *Option, longin
|
|||||||
func GetoptLongOnly(argc Int, argv **Char, optstring *Char, longopts *Option, longindex *Int) Int
|
func GetoptLongOnly(argc Int, argv **Char, optstring *Char, longopts *Option, longindex *Int) Int
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
//go:linkname Sysconf C.sysconf
|
|
||||||
func Sysconf(name Int) Long
|
|
||||||
|
|||||||
27
runtime/internal/clite/ctypes_32bit.go
Normal file
27
runtime/internal/clite/ctypes_32bit.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//go:build (linux || darwin || freebsd || netbsd || openbsd || solaris) && (386 || arm || mips || mipsle)
|
||||||
|
// +build linux darwin freebsd netbsd openbsd solaris
|
||||||
|
// +build 386 arm mips mipsle
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// For 32-bit Unix/Linux/macOS, Long is 32-bit
|
||||||
|
type (
|
||||||
|
Long = int32
|
||||||
|
Ulong = uint32
|
||||||
|
)
|
||||||
27
runtime/internal/clite/ctypes_unix64.go
Normal file
27
runtime/internal/clite/ctypes_unix64.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//go:build (linux || darwin || freebsd || netbsd || openbsd || solaris) && (amd64 || arm64 || ppc64 || ppc64le || mips64 || mips64le || s390x || riscv64)
|
||||||
|
// +build linux darwin freebsd netbsd openbsd solaris
|
||||||
|
// +build amd64 arm64 ppc64 ppc64le mips64 mips64le s390x riscv64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// For 64-bit Unix/Linux/macOS, Long is 64-bit
|
||||||
|
type (
|
||||||
|
Long = int64
|
||||||
|
Ulong = uint64
|
||||||
|
)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
//go:build linux
|
//go:build wasip1 || js
|
||||||
|
// +build wasip1 js
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
@@ -16,14 +17,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package os
|
package c
|
||||||
|
|
||||||
import "C"
|
// For WebAssembly targets, Long is 32-bit per the spec
|
||||||
|
type (
|
||||||
const (
|
Long = int32
|
||||||
LLGoFiles = "_os/os.c"
|
Ulong = uint32
|
||||||
LLGoPackage = "link"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname Clearenv C.clearenv
|
|
||||||
func Clearenv()
|
|
||||||
26
runtime/internal/clite/ctypes_windows.go
Normal file
26
runtime/internal/clite/ctypes_windows.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// For Windows (LLP64 model), Long is 32-bit, regardless of architecture
|
||||||
|
type (
|
||||||
|
Long = int32
|
||||||
|
Ulong = uint32
|
||||||
|
)
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
|
//go:build !wasm
|
||||||
|
|
||||||
package debug
|
package debug
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo linux LDFLAGS: -lunwind
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -11,7 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LLGoPackage = "link"
|
|
||||||
LLGoFiles = "_wrap/debug.c"
|
LLGoFiles = "_wrap/debug.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
33
runtime/internal/clite/debug/debug_wasm.go
Normal file
33
runtime/internal/clite/debug/debug_wasm.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package debug
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Info struct {
|
||||||
|
Fname *c.Char
|
||||||
|
Fbase c.Pointer
|
||||||
|
Sname *c.Char
|
||||||
|
Saddr c.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func Address() unsafe.Pointer {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Addrinfo(addr unsafe.Pointer, info *Info) c.Int {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Frame struct {
|
||||||
|
PC uintptr
|
||||||
|
Offset uintptr
|
||||||
|
SP unsafe.Pointer
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func StackTrace(skip int, fn func(fr *Frame) bool) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
7
runtime/internal/clite/debug/libunwind.go
Normal file
7
runtime/internal/clite/debug/libunwind.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package debug
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link"
|
||||||
|
)
|
||||||
7
runtime/internal/clite/debug/libunwind_linux.go
Normal file
7
runtime/internal/clite/debug/libunwind_linux.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package debug
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: -lunwind"
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build ((freebsd || linux || darwin) && arm64) || (windows && (amd64 || arm64))
|
//go:build !amd64
|
||||||
|
|
||||||
package ffi
|
package ffi
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build freebsd || linux || darwin
|
|
||||||
|
|
||||||
package ffi
|
package ffi
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import (
|
|||||||
c "github.com/goplus/llgo/runtime/internal/clite"
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
LLGoPackage = "link: $(pkg-config --libs libffi); -lffi"
|
|
||||||
LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Void = iota
|
Void = iota
|
||||||
Int
|
Int
|
||||||
@@ -67,62 +62,9 @@ type Cif struct {
|
|||||||
//Extra c.Uint
|
//Extra c.Uint
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_cif(ffi_cif *cif,
|
|
||||||
ffi_abi abi,
|
|
||||||
unsigned int nargs,
|
|
||||||
ffi_type *rtype,
|
|
||||||
ffi_type **atypes);
|
|
||||||
*/
|
|
||||||
//go:linkname PrepCif C.ffi_prep_cif
|
|
||||||
func PrepCif(cif *Cif, abi c.Uint, nargs c.Uint, rtype *Type, atype **Type) c.Uint
|
|
||||||
|
|
||||||
/*
|
|
||||||
ffi_status ffi_prep_cif_var(ffi_cif *cif,
|
|
||||||
ffi_abi abi,
|
|
||||||
unsigned int nfixedargs,
|
|
||||||
unsigned int ntotalargs,
|
|
||||||
ffi_type *rtype,
|
|
||||||
ffi_type **atypes);
|
|
||||||
*/
|
|
||||||
//go:linkname PrepCifVar C.ffi_prep_cif_var
|
|
||||||
func PrepCifVar(cif *Cif, abi c.Uint, nfixedargs c.Uint, ntotalargs c.Uint, rtype *Type, atype **Type) c.Uint
|
|
||||||
|
|
||||||
/*
|
|
||||||
void ffi_call(ffi_cif *cif,
|
|
||||||
void (*fn)(void),
|
|
||||||
void *rvalue,
|
|
||||||
void **avalue);
|
|
||||||
*/
|
|
||||||
//go:linkname Call C.ffi_call
|
|
||||||
func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer)
|
|
||||||
|
|
||||||
// void *ffi_closure_alloc (size_t size, void **code);
|
|
||||||
//
|
|
||||||
//go:linkname ClosureAlloc C.llog_ffi_closure_alloc
|
|
||||||
func ClosureAlloc(code *unsafe.Pointer) unsafe.Pointer
|
|
||||||
|
|
||||||
// void ffi_closure_free (void *);
|
|
||||||
//
|
|
||||||
//go:linkname ClosureFree C.ffi_closure_free
|
|
||||||
func ClosureFree(unsafe.Pointer)
|
|
||||||
|
|
||||||
/*
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_closure_loc (ffi_closure*,
|
|
||||||
ffi_cif *,
|
|
||||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
|
||||||
void *user_data,
|
|
||||||
void *codeloc);
|
|
||||||
*/
|
|
||||||
|
|
||||||
//llgo:type C
|
//llgo:type C
|
||||||
type ClosureFunc func(cif *Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer)
|
type ClosureFunc func(cif *Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname PreClosureLoc C.ffi_prep_closure_loc
|
|
||||||
func PreClosureLoc(closure unsafe.Pointer, cif *Cif, fn ClosureFunc, userdata unsafe.Pointer, codeloc unsafe.Pointer) c.Uint
|
|
||||||
|
|
||||||
func add(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer {
|
func add(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer {
|
||||||
return unsafe.Pointer(uintptr(ptr) + offset)
|
return unsafe.Pointer(uintptr(ptr) + offset)
|
||||||
}
|
}
|
||||||
|
|||||||
67
runtime/internal/clite/ffi/ffi_other.go
Normal file
67
runtime/internal/clite/ffi/ffi_other.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
//go:build !wasm
|
||||||
|
|
||||||
|
package ffi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "link: $(pkg-config --libs libffi); -lffi"
|
||||||
|
LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ffi_status
|
||||||
|
ffi_prep_cif(ffi_cif *cif,
|
||||||
|
ffi_abi abi,
|
||||||
|
unsigned int nargs,
|
||||||
|
ffi_type *rtype,
|
||||||
|
ffi_type **atypes);
|
||||||
|
*/
|
||||||
|
//go:linkname PrepCif C.ffi_prep_cif
|
||||||
|
func PrepCif(cif *Cif, abi c.Uint, nargs c.Uint, rtype *Type, atype **Type) c.Uint
|
||||||
|
|
||||||
|
/*
|
||||||
|
ffi_status ffi_prep_cif_var(ffi_cif *cif,
|
||||||
|
ffi_abi abi,
|
||||||
|
unsigned int nfixedargs,
|
||||||
|
unsigned int ntotalargs,
|
||||||
|
ffi_type *rtype,
|
||||||
|
ffi_type **atypes);
|
||||||
|
*/
|
||||||
|
//go:linkname PrepCifVar C.ffi_prep_cif_var
|
||||||
|
func PrepCifVar(cif *Cif, abi c.Uint, nfixedargs c.Uint, ntotalargs c.Uint, rtype *Type, atype **Type) c.Uint
|
||||||
|
|
||||||
|
/*
|
||||||
|
void ffi_call(ffi_cif *cif,
|
||||||
|
void (*fn)(void),
|
||||||
|
void *rvalue,
|
||||||
|
void **avalue);
|
||||||
|
*/
|
||||||
|
//go:linkname Call C.ffi_call
|
||||||
|
func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer)
|
||||||
|
|
||||||
|
// void *ffi_closure_alloc (size_t size, void **code);
|
||||||
|
//
|
||||||
|
//go:linkname ClosureAlloc C.llog_ffi_closure_alloc
|
||||||
|
func ClosureAlloc(code *unsafe.Pointer) unsafe.Pointer
|
||||||
|
|
||||||
|
// void ffi_closure_free (void *);
|
||||||
|
//
|
||||||
|
//go:linkname ClosureFree C.ffi_closure_free
|
||||||
|
func ClosureFree(unsafe.Pointer)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ffi_status
|
||||||
|
ffi_prep_closure_loc (ffi_closure*,
|
||||||
|
ffi_cif *,
|
||||||
|
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||||
|
void *user_data,
|
||||||
|
void *codeloc);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//go:linkname PreClosureLoc C.ffi_prep_closure_loc
|
||||||
|
func PreClosureLoc(closure unsafe.Pointer, cif *Cif, fn ClosureFunc, userdata unsafe.Pointer, codeloc unsafe.Pointer) c.Uint
|
||||||
31
runtime/internal/clite/ffi/ffi_wasm.go
Normal file
31
runtime/internal/clite/ffi/ffi_wasm.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package ffi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
c "github.com/goplus/llgo/runtime/internal/clite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrepCif(cif *Cif, abi c.Uint, nargs c.Uint, rtype *Type, atype **Type) c.Uint {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrepCifVar(cif *Cif, abi c.Uint, nfixedargs c.Uint, ntotalargs c.Uint, rtype *Type, atype **Type) c.Uint {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosureAlloc(code *unsafe.Pointer) unsafe.Pointer {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClosureFree(unsafe.Pointer) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func PreClosureLoc(closure unsafe.Pointer, cif *Cif, fn ClosureFunc, userdata unsafe.Pointer, codeloc unsafe.Pointer) c.Uint {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
7
runtime/internal/clite/goarch/endian_big.go
Normal file
7
runtime/internal/clite/goarch/endian_big.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build 386 || amd64 || arm || arm64 || ppc64le || mips64le || mipsle || riscv64 || wasm
|
||||||
|
// +build 386 amd64 arm arm64 ppc64le mips64le mipsle riscv64 wasm
|
||||||
|
|
||||||
|
package goarch
|
||||||
|
|
||||||
|
const BigEndian = true
|
||||||
|
const LittleEndian = false
|
||||||
9
runtime/internal/clite/goarch/endian_little.go
Normal file
9
runtime/internal/clite/goarch/endian_little.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build ppc64 || s390x || mips || mips64
|
||||||
|
// +build ppc64 s390x mips mips64
|
||||||
|
|
||||||
|
package goarch
|
||||||
|
|
||||||
|
const (
|
||||||
|
BigEndian = false
|
||||||
|
LittleEndian = true
|
||||||
|
)
|
||||||
3
runtime/internal/clite/goarch/goarch.go
Normal file
3
runtime/internal/clite/goarch/goarch.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package goarch
|
||||||
|
|
||||||
|
const PtrSize = 4 << (^uintptr(0) >> 63)
|
||||||
5
runtime/internal/clite/libuv/_demo/go.mod
Normal file
5
runtime/internal/clite/libuv/_demo/go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module github.com/goplus/llgo/runtime/internal/clite/libuv/_demo
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require github.com/goplus/lib v0.2.0
|
||||||
2
runtime/internal/clite/libuv/_demo/go.sum
Normal file
2
runtime/internal/clite/libuv/_demo/go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/goplus/lib v0.2.0 h1:AjqkN1XK5H23wZMMlpaUYAMCDAdSBQ2NMFrLtSh7W4g=
|
||||||
|
github.com/goplus/lib v0.2.0/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0=
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user