Compare commits

...

36 Commits

Author SHA1 Message Date
Ayke van Laethem 98d55ab070 compiler, runtime: make slice lookup panics recoverable 2025-02-26 12:57:26 +01:00
Ayke van Laethem 88d273da97 compiler, runtime: implement recoverable divide-by-zero panic
This gets the math/bits and go/constant package tests to pass.

Unfortunately, this also has a binary size impact of around 150-200
bytes in many cases. I'm a bit on the edge on whether this is worth it,
since it's mostly used for getting package tests to work. But at the
same time, having working package tests is very valuable.
2025-02-26 12:56:19 +01:00
Ayke van Laethem adc0cae960 compiler: add //go:linkname support for globals
We previously used our own //go:extern but //go:linkname is probably the
better choice since it's used in the math/bits package.
2025-02-26 11:37:31 +01:00
Ayke van Laethem 38e3d55e64 all: add Go 1.24 support 2025-02-25 14:41:42 +01:00
Ayke van Laethem 66da29e89f wasip2: add stubs to get internal/syscall/unix to work
This fixes lots of broken tests in stdlib packages in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c180d6fe2f testing: add Chdir
This method was added in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem cdea833b5c os: add File.Chdir support
We should really be using syscall.Fchdir here, but this is a fix to get
Go 1.24 working.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c2eaa495df os: implement stub Chdir for non-OS systems 2025-02-25 14:41:42 +01:00
Ayke van Laethem 3476100dd0 syscall: add wasip1 RandomGet
This function is needed starting with Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem 07c7eff3c3 runtime: add FIPS helper functions
Not entirely sure what they're for, but the Go runtime also stores this
information per goroutine so let's go with that.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a1be8cd9fe machine/usb/descriptor: avoid bytes package
We can't use the bytes package in Go 1.24 since it would result in an
import cycle. Therefore, use bytealg.Index instead.

(I'm not sure this code is correct - just searching for a range of bytes
seems brittle. But at least this commit shouldn't change the code).
2025-02-25 14:41:42 +01:00
Ayke van Laethem 52b9fcd57f machine: remove bytes package dependency in flash code
This also moves flash padding code to a single place, since it was
copied 5 times.

This change is necessary in Go 1.24 to avoid an import cycle.
2025-02-25 14:41:42 +01:00
Ayke van Laethem ea53ace270 cgo: mangle identifier names
This mangles CGo identifier names to something like "_Cgo_foo" instead
of using literal identifiers like "C.foo". This works around
https://github.com/golang/go/issues/71777.

I don't like this solution, but I hope we'll find a better solution in
the future. In that case we can revert this commit.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a6cd072fa1 Revert "fix: implement testing {Skip,Fail}Now"
This reverts commit c5879c682c.

It doesn't look like this is working (see
https://github.com/tinygo-org/tinygo/pull/4736#issuecomment-2679670226),
and it doesn't have any tests anyway to prove that it does work. So I
think it's best to revert it for now and add a working implementation
with tests in the future.
2025-02-25 12:38:52 +01:00
Ayke van Laethem 4372dbdd41 ci: use older image for cross-compiling builds
This ensures that the resulting binaries are compatible with a wide
range of Linux systems, not just the most recent ones.
2025-02-24 19:22:27 +01:00
deadprogram 17bb1fec44 feature: add buildmode=wasi-legacy to support existing base of users who expected the
older behavior for wasi modules to not return an exit code as if they were reactors.

See #4726 for some details on what this is intended to address.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-21 13:06:14 +01:00
Ayke van Laethem f4fd79f7be runtime: manually initialize xorshift state
This ensures:

 1. The xorshift state is initialized during interp.
 2. The xorshift state gets initialized to a real random number on
    hardware that supports it at runtime.

This fixes a big binary size regression from the previous commit. It's
still not perfect: most programs increase binary size by a few bytes.
But it's not nearly as bad as before.
2025-02-21 11:36:17 +01:00
Ayke van Laethem 811b13a9d3 interp: correctly mark functions as modifying memory
Previously, if a function couldn't be interpreted in the interp pass, it
would just be run at runtime and the parameters would be marked as
potentially being modified. However, this is incorrect: the function
itself can also modify memory. So the function itself also needs to be
marked (recursively).

This fixes a number of regressions while upgrading to Go 1.24.

This results in a significant size regression that is mostly worked
around in the next commit.
2025-02-21 11:36:17 +01:00
Ron Evans 6e97079367 target: add Pimoroni Pico Plus2 (#4735)
* machine: separate definitions for ADC pins on rp2350/rp2350b

Signed-off-by: deadprogram <ron@hybridgroup.com>

* targets: add support for Pimoroni Pico Plus2

Signed-off-by: deadprogram <ron@hybridgroup.com>

---------

Signed-off-by: deadprogram <ron@hybridgroup.com>
Co-authored-by: Patricio Whittingslow <graded.sp@gmail.com>
2025-02-21 09:56:52 +01:00
soypat 9c7bbce029 rp2350: add pll generalized solution; fix ADC handles; pwm period fix 2025-02-21 09:56:52 +01:00
soypat 0ec1cb1e19 machine/rp2350: extending support to include the rp2350b 2025-02-21 09:56:52 +01:00
Scott Feldman e7118e5bda add comboat_fw tag for elecrow W5 boards with Combo-AT Wifi firmware 2025-02-21 07:22:17 +01:00
Ron Evans 150d9d1c6b fix: correctly handle id lookup for finalizeRef call
Modify the ID used for looking up the reference, based on suggestion made by @prochac

Also use console.error in the caase that the reference is not found, since it is now actually
known to be an error.
2025-02-20 22:17:38 +01:00
Laurent Demailly 8fe039156b fix: Avoid total failure on wasm finalizer call 2025-02-20 22:17:38 +01:00
leongross 2d17dec7bf os/file: add file.Chmod
Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-19 22:12:51 +01:00
JP Hastings-Spital c1b267a208 Ensure build output directory is created
`tinygo build -o /path/to/out .` expected `/path/to/out` to already exist, which is different behaviour to `go build`. This change ensures tinygo creates any directories needed to be able to build to the specified output dir.
2025-02-19 19:55:48 +01:00
deadprogram f02c56c9e0 net: update to latest submodule with httptest subpackage and
ResolveIPAddress implementation.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-17 13:16:56 +01:00
leongross c5879c682c fix: implement testing {Skip,Fail}Now
PR https://github.com/tinygo-org/tinygo/pull/4623 implements
runtime.GoExit() with which we can improve the testing package
and align it more to upstream testing behavour https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/testing/testing.go;l=1150

Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-15 21:30:22 +01:00
deadprogram 190c20825f targets: turn on GC for TKey1 device, since it does in fact work
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-14 12:49:20 +01:00
deadprogram d04eea7185 fix: add NoSandbox flag to chrome headless that is run during WASM tests, since
this is now required for Ubuntu 23+ and we are using Ubuntu 24+ when running
Github Actions.

See https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
deadprogram f24cd31895 build: update Linux builds to run on ubuntu-latest since 20.04 is being retired
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
m00874241 2044f6fbcc Added VersionTLS constants and VersionName(version uint16) method that turns it into a string, copied from big go 2025-01-30 07:30:57 +01:00
HattoriHanzo031 d55a89f96a board: support for NRF51 HW-651 (#4712)
NRF51: Support for NRF51 HW-651 board
* smoketest
* removed redundant flash-method
* smoketest fix
* description and links
* link fix
2025-01-30 05:46:52 +01:00
Elias Naur 080a6648e9 targets: match Pico2 stack size to Pico
Took me a while to debug weird crashes after switching from Pico to
Pico2.
2025-01-26 17:04:04 +08:00
deadprogram ec0a142190 build: update wasmtime used for CI to 29.0.1 to fix issue with install during CI tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-01-23 17:56:02 +08:00
Yurii Soldak b7fcf6ad68 nrf: fix adc read near zero 2025-01-23 13:03:25 +08:00
82 changed files with 1444 additions and 602 deletions
+3 -3
View File
@@ -109,9 +109,9 @@ jobs:
# "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21 # "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21
fmt-check: false fmt-check: false
resource_class: large resource_class: large
test-llvm19-go123: test-llvm19-go124:
docker: docker:
- image: golang:1.23-bullseye - image: golang:1.24-bullseye
steps: steps:
- test-linux: - test-linux:
llvm: "19" llvm: "19"
@@ -124,4 +124,4 @@ workflows:
# least the smoke tests still pass. # least the smoke tests still pass.
- test-llvm15-go119 - test-llvm15-go119
# This tests LLVM 19 support when linking against system libraries. # This tests LLVM 19 support when linking against system libraries.
- test-llvm19-go123 - test-llvm19-go124
+2 -2
View File
@@ -39,7 +39,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Restore LLVM source cache - name: Restore LLVM source cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
@@ -143,7 +143,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Build TinyGo (LLVM ${{ matrix.version }}) - name: Build TinyGo (LLVM ${{ matrix.version }})
run: go install -tags=llvm${{ matrix.version }} run: go install -tags=llvm${{ matrix.version }}
+9 -9
View File
@@ -18,7 +18,7 @@ jobs:
# statically linked binary. # statically linked binary.
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: golang:1.23-alpine image: golang:1.24-alpine
outputs: outputs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
@@ -146,12 +146,12 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Install wasmtime - name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1 uses: bytecodealliance/actions/wasmtime/setup@v1
with: with:
version: "19.0.1" version: "29.0.1"
- name: Install wasm-tools - name: Install wasm-tools
uses: bytecodealliance/actions/wasm-tools/setup@v1 uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Download release artifact - name: Download release artifact
@@ -169,7 +169,7 @@ jobs:
assert-test-linux: assert-test-linux:
# Run all tests that can run on Linux, with LLVM assertions enabled to catch # Run all tests that can run on Linux, with LLVM assertions enabled to catch
# potential bugs. # potential bugs.
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -189,7 +189,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
@@ -198,7 +198,7 @@ jobs:
- name: Install wasmtime - name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1 uses: bytecodealliance/actions/wasmtime/setup@v1
with: with:
version: "19.0.1" version: "29.0.1"
- name: Setup `wasm-tools` - name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1 uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Restore LLVM source cache - name: Restore LLVM source cache
@@ -297,7 +297,7 @@ jobs:
- goarch: arm - goarch: arm
toolchain: arm-linux-gnueabihf toolchain: arm-linux-gnueabihf
libc: armhf libc: armhf
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04 # note: use the oldest image available! (see above)
needs: build-linux needs: build-linux
steps: steps:
- name: Checkout - name: Checkout
@@ -315,7 +315,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Restore LLVM source cache - name: Restore LLVM source cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
@@ -346,7 +346,7 @@ jobs:
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-19-linux-${{ matrix.goarch }}-v2 key: llvm-build-19-linux-${{ matrix.goarch }}-v3
path: llvm-build path: llvm-build
- name: Build LLVM - name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true' if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+6 -6
View File
@@ -41,7 +41,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Restore cached LLVM source - name: Restore cached LLVM source
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
@@ -109,7 +109,7 @@ jobs:
C:/Users/runneradmin/go/pkg/mod C:/Users/runneradmin/go/pkg/mod
- name: Install wasmtime - name: Install wasmtime
run: | run: |
scoop install wasmtime@14.0.4 scoop install wasmtime@29.0.1
- name: make gen-device - name: make gen-device
run: make -j3 gen-device run: make -j3 gen-device
- name: Test TinyGo - name: Test TinyGo
@@ -156,7 +156,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -186,7 +186,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -216,13 +216,13 @@ jobs:
- name: Install Dependencies - name: Install Dependencies
shell: bash shell: bash
run: | run: |
scoop install binaryen && scoop install wasmtime@14.0.4 scoop install binaryen && scoop install wasmtime@29.0.1
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Go - name: Install Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.23' go-version: '1.24'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
+2 -2
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo # tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.23 AS tinygo-llvm FROM golang:1.24 AS tinygo-llvm
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-15 ninja-build && \ apt-get install -y apt-utils make cmake clang-15 ninja-build && \
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
# tinygo-compiler copies the compiler build over to a base Go container (without # tinygo-compiler copies the compiler build over to a base Go container (without
# all the build tools etc). # all the build tools etc).
FROM golang:1.23 AS tinygo-compiler FROM golang:1.24 AS tinygo-compiler
# Copy tinygo build. # Copy tinygo build.
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
+19 -10
View File
@@ -309,11 +309,9 @@ TEST_PACKAGES_FAST = \
container/heap \ container/heap \
container/list \ container/list \
container/ring \ container/ring \
crypto/des \
crypto/ecdsa \ crypto/ecdsa \
crypto/elliptic \ crypto/elliptic \
crypto/md5 \ crypto/md5 \
crypto/rc4 \
crypto/sha1 \ crypto/sha1 \
crypto/sha256 \ crypto/sha256 \
crypto/sha512 \ crypto/sha512 \
@@ -355,21 +353,16 @@ TEST_PACKAGES_FAST = \
unique \ unique \
$(nil) $(nil)
# Assume this will go away before Go2, so only check minor version.
ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
else
TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
endif
# archive/zip requires os.ReadAt, which is not yet supported on windows # archive/zip requires os.ReadAt, which is not yet supported on windows
# bytes requires mmap # bytes requires mmap
# compress/flate appears to hang on wasi # compress/flate appears to hang on wasi
# crypto/aes fails on wasi, needs panic()/recover() # crypto/aes fails on wasi, needs panic()/recover()
# crypto/des fails on wasi, needs panic()/recover()
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic # crypto/hmac fails on wasi, it exits with a "slice out of range" panic
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows # debug/plan9obj requires os.ReadAt, which is not yet supported on windows
# image requires recover(), which is not yet supported on wasi # image requires recover(), which is not yet supported on wasi
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi # io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
# math/bits: needs panic()/recover()
# mime: fail on wasi; neds panic()/recover() # mime: fail on wasi; neds panic()/recover()
# mime/multipart: needs wasip1 syscall.FDFLAG_NONBLOCK # mime/multipart: needs wasip1 syscall.FDFLAG_NONBLOCK
# mime/quotedprintable requires syscall.Faccessat # mime/quotedprintable requires syscall.Faccessat
@@ -386,11 +379,15 @@ TEST_PACKAGES_LINUX := \
archive/zip \ archive/zip \
compress/flate \ compress/flate \
crypto/aes \ crypto/aes \
crypto/des \
crypto/hmac \ crypto/hmac \
debug/dwarf \ debug/dwarf \
debug/plan9obj \ debug/plan9obj \
encoding/binary \
go/constant \
image \ image \
io/ioutil \ io/ioutil \
math/bits \
mime \ mime \
mime/multipart \ mime/multipart \
mime/quotedprintable \ mime/quotedprintable \
@@ -405,10 +402,14 @@ TEST_PACKAGES_LINUX := \
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX) TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
# os/user requires t.Skip() support
TEST_PACKAGES_WINDOWS := \ TEST_PACKAGES_WINDOWS := \
compress/flate \ compress/flate \
crypto/des \
crypto/hmac \ crypto/hmac \
os/user \ encoding/binary \
go/constant \
math/bits \
strconv \ strconv \
text/template/parse \ text/template/parse \
$(nil) $(nil)
@@ -523,6 +524,8 @@ smoketest: testchdir
# regression test for #2563 # regression test for #2563
cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test
# test all examples (except pwm) # test all examples (except pwm)
$(TINYGO) build -size short -o test.hex -target=pga2350 examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/adc $(TINYGO) build -size short -o test.hex -target=pca10040 examples/adc
@@ -745,6 +748,8 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=tiny2350 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=tiny2350 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo $(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
# test pwm # test pwm
@@ -867,6 +872,10 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=elecrow-rp2350 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=elecrow-rp2350 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hw-651 examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8 examples/machinetest
@$(MD5SUM) test.hex
ifneq ($(WASM), 0) ifneq ($(WASM), 0)
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export $(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main $(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
+15
View File
@@ -604,6 +604,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
}, },
} }
// Create the output directory, if needed
if err := os.MkdirAll(filepath.Dir(outpath), 0777); err != nil {
return result, err
}
// Check whether we only need to create an object file. // Check whether we only need to create an object file.
// If so, we don't need to link anything and will be finished quickly. // If so, we don't need to link anything and will be finished quickly.
outext := filepath.Ext(outpath) outext := filepath.Ext(outpath)
@@ -667,6 +672,16 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
ldflags = append(ldflags, "--no-entry") ldflags = append(ldflags, "--no-entry")
} }
if config.Options.BuildMode == "wasi-legacy" {
if !strings.HasPrefix(config.Triple(), "wasm32-") {
return result, fmt.Errorf("buildmode wasi-legacy is only supported on wasm")
}
if config.Options.Scheduler != "none" {
return result, fmt.Errorf("buildmode wasi-legacy only supports scheduler=none")
}
}
// Add compiler-rt dependency if needed. Usually this is a simple load from // Add compiler-rt dependency if needed. Usually this is a simple load from
// a cache. // a cache.
if config.Target.RTLib == "compiler-rt" { if config.Target.RTLib == "compiler-rt" {
+2 -2
View File
@@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
// Version range supported by TinyGo. // Version range supported by TinyGo.
const minorMin = 19 const minorMin = 19
const minorMax = 23 const minorMax = 24
// Check that we support this Go toolchain version. // Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion() gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
@@ -36,7 +36,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax { if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
// Note: when this gets updated, also update the Go compatibility matrix: // Note: when this gets updated, also update the Go compatibility matrix:
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md // https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor) return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor)
} }
// Check that the Go toolchain version isn't too new, if we haven't been // Check that the Go toolchain version isn't too new, if we haven't been
+2 -2
View File
@@ -43,8 +43,8 @@ func TestBinarySize(t *testing.T) {
tests := []sizeTest{ tests := []sizeTest{
// microcontrollers // microcontrollers
{"hifive1b", "examples/echo", 4560, 280, 0, 2268}, {"hifive1b", "examples/echo", 4560, 280, 0, 2268},
{"microbit", "examples/serial", 2908, 388, 8, 2272}, {"microbit", "examples/serial", 2916, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7293, 1487, 116, 6912}, {"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912},
// TODO: also check wasm. Right now this is difficult, because // TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the // wasm binaries are run through wasm-opt and therefore the
+45 -64
View File
@@ -92,18 +92,18 @@ type noescapingFunc struct {
// cgoAliases list type aliases between Go and C, for types that are equivalent // cgoAliases list type aliases between Go and C, for types that are equivalent
// in both languages. See addTypeAliases. // in both languages. See addTypeAliases.
var cgoAliases = map[string]string{ var cgoAliases = map[string]string{
"C.int8_t": "int8", "_Cgo_int8_t": "int8",
"C.int16_t": "int16", "_Cgo_int16_t": "int16",
"C.int32_t": "int32", "_Cgo_int32_t": "int32",
"C.int64_t": "int64", "_Cgo_int64_t": "int64",
"C.uint8_t": "uint8", "_Cgo_uint8_t": "uint8",
"C.uint16_t": "uint16", "_Cgo_uint16_t": "uint16",
"C.uint32_t": "uint32", "_Cgo_uint32_t": "uint32",
"C.uint64_t": "uint64", "_Cgo_uint64_t": "uint64",
"C.uintptr_t": "uintptr", "_Cgo_uintptr_t": "uintptr",
"C.float": "float32", "_Cgo_float": "float32",
"C.double": "float64", "_Cgo_double": "float64",
"C._Bool": "bool", "_Cgo__Bool": "bool",
} }
// builtinAliases are handled specially because they only exist on the Go side // builtinAliases are handled specially because they only exist on the Go side
@@ -145,48 +145,46 @@ typedef unsigned long long _Cgo_ulonglong;
// The string/bytes functions below implement C.CString etc. To make sure the // The string/bytes functions below implement C.CString etc. To make sure the
// runtime doesn't need to know the C int type, lengths are converted to uintptr // runtime doesn't need to know the C int type, lengths are converted to uintptr
// first. // first.
// These functions will be modified to get a "C." prefix, so the source below
// doesn't reflect the final AST.
const generatedGoFilePrefixBase = ` const generatedGoFilePrefixBase = `
import "syscall" import "syscall"
import "unsafe" import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func __GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func __GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func __CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func __get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
` `
const generatedGoFilePrefixOther = generatedGoFilePrefixBase + ` const generatedGoFilePrefixOther = generatedGoFilePrefixBase + `
func __get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
` `
@@ -197,7 +195,7 @@ func __get_errno() error {
// map the errno values to match the values in the syscall package. // map the errno values to match the values in the syscall package.
// Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h // Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h
const generatedGoFilePrefixWindows = generatedGoFilePrefixBase + ` const generatedGoFilePrefixWindows = generatedGoFilePrefixBase + `
var __errno_mapping = [...]syscall.Errno{ var _Cgo___errno_mapping = [...]syscall.Errno{
1: syscall.EPERM, 1: syscall.EPERM,
2: syscall.ENOENT, 2: syscall.ENOENT,
3: syscall.ESRCH, 3: syscall.ESRCH,
@@ -238,10 +236,10 @@ var __errno_mapping = [...]syscall.Errno{
42: syscall.EILSEQ, 42: syscall.EILSEQ,
} }
func __get_errno() error { func _Cgo___get_errno() error {
num := C.__get_errno_num() num := _Cgo___get_errno_num()
if num < uintptr(len(__errno_mapping)) { if num < uintptr(len(_Cgo___errno_mapping)) {
if mapped := __errno_mapping[num]; mapped != 0 { if mapped := _Cgo___errno_mapping[num]; mapped != 0 {
return mapped return mapped
} }
} }
@@ -304,23 +302,6 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
// If the Comments field is not set to nil, the go/format package will get // If the Comments field is not set to nil, the go/format package will get
// confused about where comments should go. // confused about where comments should go.
p.generated.Comments = nil p.generated.Comments = nil
// Adjust some of the functions in there.
for _, decl := range p.generated.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
switch decl.Name.Name {
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes", "__get_errno_num", "__get_errno", "__errno_mapping":
// Adjust the name to have a "C." prefix so it is correctly
// resolved.
decl.Name.Name = "C." + decl.Name.Name
}
}
}
// Patch some types, for example *C.char in C.CString.
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
return cf.walker(cursor, nil)
}, nil)
// Find `import "C"` C fragments in the file. // Find `import "C"` C fragments in the file.
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
@@ -399,7 +380,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
Tok: token.TYPE, Tok: token.TYPE,
} }
for _, name := range builtinAliases { for _, name := range builtinAliases {
typeSpec := p.getIntegerType("C."+name, names["_Cgo_"+name]) typeSpec := p.getIntegerType("_Cgo_"+name, names["_Cgo_"+name])
gen.Specs = append(gen.Specs, typeSpec) gen.Specs = append(gen.Specs, typeSpec)
} }
p.generated.Decls = append(p.generated.Decls, gen) p.generated.Decls = append(p.generated.Decls, gen)
@@ -1272,7 +1253,7 @@ func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {
func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string { func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string {
// Some types are defined in stdint.h and map directly to a particular Go // Some types are defined in stdint.h and map directly to a particular Go
// type. // type.
if alias := cgoAliases["C."+name]; alias != "" { if alias := cgoAliases["_Cgo_"+name]; alias != "" {
return alias return alias
} }
node := f.getASTDeclNode(name, found) node := f.getASTDeclNode(name, found)
@@ -1282,7 +1263,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
} }
return node.Name.Name return node.Name.Name
} }
return "C." + name return "_Cgo_" + name
} }
// getASTDeclNode will declare the given C AST node (if not already defined) and // getASTDeclNode will declare the given C AST node (if not already defined) and
@@ -1382,8 +1363,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
case *elaboratedTypeInfo: case *elaboratedTypeInfo:
// Add struct bitfields. // Add struct bitfields.
for _, bitfield := range elaboratedType.bitfields { for _, bitfield := range elaboratedType.bitfields {
f.createBitfieldGetter(bitfield, "C."+name) f.createBitfieldGetter(bitfield, "_Cgo_"+name)
f.createBitfieldSetter(bitfield, "C."+name) f.createBitfieldSetter(bitfield, "_Cgo_"+name)
} }
if elaboratedType.unionSize != 0 { if elaboratedType.unionSize != 0 {
// Create union getters/setters. // Create union getters/setters.
@@ -1392,7 +1373,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
f.addError(elaboratedType.pos, fmt.Sprintf("union must have field with a single name, it has %d names", len(field.Names))) f.addError(elaboratedType.pos, fmt.Sprintf("union must have field with a single name, it has %d names", len(field.Names)))
continue continue
} }
f.createUnionAccessor(field, "C."+name) f.createUnionAccessor(field, "_Cgo_"+name)
} }
} }
} }
@@ -1441,7 +1422,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
node.Rhs = append(node.Rhs, &ast.CallExpr{ node.Rhs = append(node.Rhs, &ast.CallExpr{
Fun: &ast.Ident{ Fun: &ast.Ident{
NamePos: node.Lhs[1].End(), NamePos: node.Lhs[1].End(),
Name: "C.__get_errno", Name: "_Cgo___get_errno",
}, },
}) })
} }
@@ -1466,7 +1447,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
return true return true
} }
if x.Name == "C" { if x.Name == "C" {
name := "C." + node.Sel.Name name := "_Cgo_" + node.Sel.Name
if found, ok := names[node.Sel.Name]; ok { if found, ok := names[node.Sel.Name]; ok {
name = f.getASTDeclName(node.Sel.Name, found, false) name = f.getASTDeclName(node.Sel.Name, found, false)
} }
+27 -27
View File
@@ -219,7 +219,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c)) numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Fun, Kind: ast.Fun,
Name: "C." + name, Name: "_Cgo_" + name,
} }
exportName := name exportName := name
localName := name localName := name
@@ -257,7 +257,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
}, },
Name: &ast.Ident{ Name: &ast.Ident{
NamePos: pos, NamePos: pos,
Name: "C." + localName, Name: "_Cgo_" + localName,
Obj: obj, Obj: obj,
}, },
Type: &ast.FuncType{ Type: &ast.FuncType{
@@ -319,7 +319,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
return decl, stringSignature return decl, stringSignature
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl: case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
typ := f.makeASTRecordType(c, pos) typ := f.makeASTRecordType(c, pos)
typeName := "C." + name typeName := "_Cgo_" + name
typeExpr := typ.typeExpr typeExpr := typ.typeExpr
if typ.unionSize != 0 { if typ.unionSize != 0 {
// Convert to a single-field struct type. // Convert to a single-field struct type.
@@ -340,7 +340,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
obj.Decl = typeSpec obj.Decl = typeSpec
return typeSpec, typ return typeSpec, typ
case C.CXCursor_TypedefDecl: case C.CXCursor_TypedefDecl:
typeName := "C." + name typeName := "_Cgo_" + name
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c) underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Typ, Kind: ast.Typ,
@@ -378,12 +378,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
} }
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Var, Kind: ast.Var,
Name: "C." + name, Name: "_Cgo_" + name,
} }
valueSpec := &ast.ValueSpec{ valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{ Names: []*ast.Ident{{
NamePos: pos, NamePos: pos,
Name: "C." + name, Name: "_Cgo_" + name,
Obj: obj, Obj: obj,
}}, }},
Type: typeExpr, Type: typeExpr,
@@ -407,12 +407,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
} }
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Con, Kind: ast.Con,
Name: "C." + name, Name: "_Cgo_" + name,
} }
valueSpec := &ast.ValueSpec{ valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{ Names: []*ast.Ident{{
NamePos: pos, NamePos: pos,
Name: "C." + name, Name: "_Cgo_" + name,
Obj: obj, Obj: obj,
}}, }},
Values: []ast.Expr{expr}, Values: []ast.Expr{expr},
@@ -423,7 +423,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
case C.CXCursor_EnumDecl: case C.CXCursor_EnumDecl:
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Typ, Kind: ast.Typ,
Name: "C." + name, Name: "_Cgo_" + name,
} }
underlying := C.tinygo_clang_getEnumDeclIntegerType(c) underlying := C.tinygo_clang_getEnumDeclIntegerType(c)
// TODO: gc's CGo implementation uses types such as `uint32` for enums // TODO: gc's CGo implementation uses types such as `uint32` for enums
@@ -431,7 +431,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
typeSpec := &ast.TypeSpec{ typeSpec := &ast.TypeSpec{
Name: &ast.Ident{ Name: &ast.Ident{
NamePos: pos, NamePos: pos,
Name: "C." + name, Name: "_Cgo_" + name,
Obj: obj, Obj: obj,
}, },
Assign: pos, Assign: pos,
@@ -454,12 +454,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
} }
obj := &ast.Object{ obj := &ast.Object{
Kind: ast.Con, Kind: ast.Con,
Name: "C." + name, Name: "_Cgo_" + name,
} }
valueSpec := &ast.ValueSpec{ valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{ Names: []*ast.Ident{{
NamePos: pos, NamePos: pos,
Name: "C." + name, Name: "_Cgo_" + name,
Obj: obj, Obj: obj,
}}, }},
Values: []ast.Expr{expr}, Values: []ast.Expr{expr},
@@ -745,27 +745,27 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
var typeName string var typeName string
switch typ.kind { switch typ.kind {
case C.CXType_Char_S, C.CXType_Char_U: case C.CXType_Char_S, C.CXType_Char_U:
typeName = "C.char" typeName = "_Cgo_char"
case C.CXType_SChar: case C.CXType_SChar:
typeName = "C.schar" typeName = "_Cgo_schar"
case C.CXType_UChar: case C.CXType_UChar:
typeName = "C.uchar" typeName = "_Cgo_uchar"
case C.CXType_Short: case C.CXType_Short:
typeName = "C.short" typeName = "_Cgo_short"
case C.CXType_UShort: case C.CXType_UShort:
typeName = "C.ushort" typeName = "_Cgo_ushort"
case C.CXType_Int: case C.CXType_Int:
typeName = "C.int" typeName = "_Cgo_int"
case C.CXType_UInt: case C.CXType_UInt:
typeName = "C.uint" typeName = "_Cgo_uint"
case C.CXType_Long: case C.CXType_Long:
typeName = "C.long" typeName = "_Cgo_long"
case C.CXType_ULong: case C.CXType_ULong:
typeName = "C.ulong" typeName = "_Cgo_ulong"
case C.CXType_LongLong: case C.CXType_LongLong:
typeName = "C.longlong" typeName = "_Cgo_longlong"
case C.CXType_ULongLong: case C.CXType_ULongLong:
typeName = "C.ulonglong" typeName = "_Cgo_ulonglong"
case C.CXType_Bool: case C.CXType_Bool:
typeName = "bool" typeName = "bool"
case C.CXType_Float, C.CXType_Double, C.CXType_LongDouble: case C.CXType_Float, C.CXType_Double, C.CXType_LongDouble:
@@ -896,7 +896,7 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
typeSpelling := getString(C.clang_getTypeSpelling(typ)) typeSpelling := getString(C.clang_getTypeSpelling(typ))
typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind)) typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))
f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling)) f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling))
typeName = "C.<unknown>" typeName = "_Cgo_<unknown>"
} }
return &ast.Ident{ return &ast.Ident{
NamePos: pos, NamePos: pos,
@@ -913,7 +913,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
var goName string var goName string
typeSize := C.clang_Type_getSizeOf(underlyingType) typeSize := C.clang_Type_getSizeOf(underlyingType)
switch name { switch name {
case "C.char": case "_Cgo_char":
if typeSize != 1 { if typeSize != 1 {
// This happens for some very special purpose architectures // This happens for some very special purpose architectures
// (DSPs etc.) that are not currently targeted. // (DSPs etc.) that are not currently targeted.
@@ -926,7 +926,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
case C.CXType_Char_U: case C.CXType_Char_U:
goName = "uint8" goName = "uint8"
} }
case "C.schar", "C.short", "C.int", "C.long", "C.longlong": case "_Cgo_schar", "_Cgo_short", "_Cgo_int", "_Cgo_long", "_Cgo_longlong":
switch typeSize { switch typeSize {
case 1: case 1:
goName = "int8" goName = "int8"
@@ -937,7 +937,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
case 8: case 8:
goName = "int64" goName = "int64"
} }
case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong": case "_Cgo_uchar", "_Cgo_ushort", "_Cgo_uint", "_Cgo_ulong", "_Cgo_ulonglong":
switch typeSize { switch typeSize {
case 1: case 1:
goName = "uint8" goName = "uint8"
+31 -31
View File
@@ -5,50 +5,50 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
+38 -38
View File
@@ -5,58 +5,58 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
const C.foo = 3 const _Cgo_foo = 3
const C.bar = C.foo const _Cgo_bar = _Cgo_foo
const C.unreferenced = 4 const _Cgo_unreferenced = 4
const C.referenced = C.unreferenced const _Cgo_referenced = _Cgo_unreferenced
const C.fnlike_val = 5 const _Cgo_fnlike_val = 5
const C.square_val = (20 * 20) const _Cgo_square_val = (20 * 20)
const C.add_val = (3 + 5) const _Cgo_add_val = (3 + 5)
+46 -46
View File
@@ -14,16 +14,16 @@
// testdata/errors.go:3:1: function "unusedFunction" in #cgo noescape line is not used // testdata/errors.go:3:1: function "unusedFunction" in #cgo noescape line is not used
// Type checking errors after CGo processing: // Type checking errors after CGo processing:
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows) // testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as _Cgo_char value in variable declaration (overflows)
// testdata/errors.go:105: unknown field z in struct literal // testdata/errors.go:105: unknown field z in struct literal
// testdata/errors.go:108: undefined: C.SOME_CONST_1 // testdata/errors.go:108: undefined: _Cgo_SOME_CONST_1
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows) // testdata/errors.go:110: cannot use _Cgo_SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
// testdata/errors.go:112: undefined: C.SOME_CONST_4 // testdata/errors.go:112: undefined: _Cgo_SOME_CONST_4
// testdata/errors.go:114: undefined: C.SOME_CONST_b // testdata/errors.go:114: undefined: _Cgo_SOME_CONST_b
// testdata/errors.go:116: undefined: C.SOME_CONST_startspace // testdata/errors.go:116: undefined: _Cgo_SOME_CONST_startspace
// testdata/errors.go:119: undefined: C.SOME_PARAM_CONST_invalid // testdata/errors.go:119: undefined: _Cgo_SOME_PARAM_CONST_invalid
// testdata/errors.go:122: undefined: C.add_toomuch // testdata/errors.go:122: undefined: _Cgo_add_toomuch
// testdata/errors.go:123: undefined: C.add_toolittle // testdata/errors.go:123: undefined: _Cgo_add_toolittle
package main package main
@@ -32,58 +32,58 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
type C.struct_point_t struct { type _Cgo_struct_point_t struct {
x C.int x _Cgo_int
y C.int y _Cgo_int
} }
type C.point_t = C.struct_point_t type _Cgo_point_t = _Cgo_struct_point_t
const C.SOME_CONST_3 = 1234 const _Cgo_SOME_CONST_3 = 1234
const C.SOME_PARAM_CONST_valid = 3 + 4 const _Cgo_SOME_PARAM_CONST_valid = 3 + 4
+33 -33
View File
@@ -10,53 +10,53 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
const C.BAR = 3 const _Cgo_BAR = 3
const C.FOO_H = 1 const _Cgo_FOO_H = 1
+42 -42
View File
@@ -5,80 +5,80 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
//export foo //export foo
func C.foo(a C.int, b C.int) C.int func _Cgo_foo(a _Cgo_int, b _Cgo_int) _Cgo_int
var C.foo$funcaddr unsafe.Pointer var _Cgo_foo$funcaddr unsafe.Pointer
//export variadic0 //export variadic0
//go:variadic //go:variadic
func C.variadic0() func _Cgo_variadic0()
var C.variadic0$funcaddr unsafe.Pointer var _Cgo_variadic0$funcaddr unsafe.Pointer
//export variadic2 //export variadic2
//go:variadic //go:variadic
func C.variadic2(x C.int, y C.int) func _Cgo_variadic2(x _Cgo_int, y _Cgo_int)
var C.variadic2$funcaddr unsafe.Pointer var _Cgo_variadic2$funcaddr unsafe.Pointer
//export _Cgo_static_173c95a79b6df1980521_staticfunc //export _Cgo_static_173c95a79b6df1980521_staticfunc
func C.staticfunc!symbols.go(x C.int) func _Cgo_staticfunc!symbols.go(x _Cgo_int)
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer var _Cgo_staticfunc!symbols.go$funcaddr unsafe.Pointer
//export notEscapingFunction //export notEscapingFunction
//go:noescape //go:noescape
func C.notEscapingFunction(a *C.int) func _Cgo_notEscapingFunction(a *_Cgo_int)
var C.notEscapingFunction$funcaddr unsafe.Pointer var _Cgo_notEscapingFunction$funcaddr unsafe.Pointer
//go:extern someValue //go:extern someValue
var C.someValue C.int var _Cgo_someValue _Cgo_int
+103 -99
View File
@@ -5,158 +5,162 @@ import "unsafe"
var _ unsafe.Pointer var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString //go:linkname _Cgo_CString runtime.cgo_CString
func C.CString(string) *C.char func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString //go:linkname _Cgo_GoString runtime.cgo_GoString
func C.GoString(*C.char) string func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN //go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string { func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return C.__GoStringN(cstr, uintptr(length)) return _Cgo___GoStringN(cstr, uintptr(length))
} }
//go:linkname C.__GoBytes runtime.cgo_GoBytes //go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte { func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return C.__GoBytes(ptr, uintptr(length)) return _Cgo___GoBytes(ptr, uintptr(length))
} }
//go:linkname C.__CBytes runtime.cgo_CBytes //go:linkname _Cgo___CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer { func _Cgo_CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b) return _Cgo___CBytes(b)
} }
//go:linkname C.__get_errno_num runtime.cgo_errno //go:linkname _Cgo___get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr func _Cgo___get_errno_num() uintptr
func C.__get_errno() error { func _Cgo___get_errno() error {
return syscall.Errno(C.__get_errno_num()) return syscall.Errno(_Cgo___get_errno_num())
} }
type ( type (
C.char uint8 _Cgo_char uint8
C.schar int8 _Cgo_schar int8
C.uchar uint8 _Cgo_uchar uint8
C.short int16 _Cgo_short int16
C.ushort uint16 _Cgo_ushort uint16
C.int int32 _Cgo_int int32
C.uint uint32 _Cgo_uint uint32
C.long int32 _Cgo_long int32
C.ulong uint32 _Cgo_ulong uint32
C.longlong int64 _Cgo_longlong int64
C.ulonglong uint64 _Cgo_ulonglong uint64
) )
type C.myint = C.int type _Cgo_myint = _Cgo_int
type C.struct_point2d_t struct { type _Cgo_struct_point2d_t struct {
x C.int x _Cgo_int
y C.int y _Cgo_int
} }
type C.point2d_t = C.struct_point2d_t type _Cgo_point2d_t = _Cgo_struct_point2d_t
type C.struct_point3d struct { type _Cgo_struct_point3d struct {
x C.int x _Cgo_int
y C.int y _Cgo_int
z C.int z _Cgo_int
} }
type C.point3d_t = C.struct_point3d type _Cgo_point3d_t = _Cgo_struct_point3d
type C.struct_type1 struct { type _Cgo_struct_type1 struct {
_type C.int _type _Cgo_int
__type C.int __type _Cgo_int
___type C.int ___type _Cgo_int
} }
type C.struct_type2 struct{ _type C.int } type _Cgo_struct_type2 struct{ _type _Cgo_int }
type C.union_union1_t struct{ i C.int } type _Cgo_union_union1_t struct{ i _Cgo_int }
type C.union1_t = C.union_union1_t type _Cgo_union1_t = _Cgo_union_union1_t
type C.union_union3_t struct{ $union uint64 } type _Cgo_union_union3_t struct{ $union uint64 }
func (union *C.union_union3_t) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) } func (union *_Cgo_union_union3_t) unionfield_i() *_Cgo_int {
func (union *C.union_union3_t) unionfield_d() *float64 { return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union3_t) unionfield_d() *float64 {
return (*float64)(unsafe.Pointer(&union.$union)) return (*float64)(unsafe.Pointer(&union.$union))
} }
func (union *C.union_union3_t) unionfield_s() *C.short { func (union *_Cgo_union_union3_t) unionfield_s() *_Cgo_short {
return (*C.short)(unsafe.Pointer(&union.$union)) return (*_Cgo_short)(unsafe.Pointer(&union.$union))
} }
type C.union3_t = C.union_union3_t type _Cgo_union3_t = _Cgo_union_union3_t
type C.union_union2d struct{ $union [2]uint64 } type _Cgo_union_union2d struct{ $union [2]uint64 }
func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) } func (union *_Cgo_union_union2d) unionfield_i() *_Cgo_int {
func (union *C.union_union2d) unionfield_d() *[2]float64 { return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union2d) unionfield_d() *[2]float64 {
return (*[2]float64)(unsafe.Pointer(&union.$union)) return (*[2]float64)(unsafe.Pointer(&union.$union))
} }
type C.union2d_t = C.union_union2d type _Cgo_union2d_t = _Cgo_union_union2d
type C.union_unionarray_t struct{ arr [10]C.uchar } type _Cgo_union_unionarray_t struct{ arr [10]_Cgo_uchar }
type C.unionarray_t = C.union_unionarray_t type _Cgo_unionarray_t = _Cgo_union_unionarray_t
type C._Ctype_union___0 struct{ $union [3]uint32 } type _Cgo__Ctype_union___0 struct{ $union [3]uint32 }
func (union *C._Ctype_union___0) unionfield_area() *C.point2d_t { func (union *_Cgo__Ctype_union___0) unionfield_area() *_Cgo_point2d_t {
return (*C.point2d_t)(unsafe.Pointer(&union.$union)) return (*_Cgo_point2d_t)(unsafe.Pointer(&union.$union))
} }
func (union *C._Ctype_union___0) unionfield_solid() *C.point3d_t { func (union *_Cgo__Ctype_union___0) unionfield_solid() *_Cgo_point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union)) return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
} }
type C.struct_struct_nested_t struct { type _Cgo_struct_struct_nested_t struct {
begin C.point2d_t begin _Cgo_point2d_t
end C.point2d_t end _Cgo_point2d_t
tag C.int tag _Cgo_int
coord C._Ctype_union___0 coord _Cgo__Ctype_union___0
} }
type C.struct_nested_t = C.struct_struct_nested_t type _Cgo_struct_nested_t = _Cgo_struct_struct_nested_t
type C.union_union_nested_t struct{ $union [2]uint64 } type _Cgo_union_union_nested_t struct{ $union [2]uint64 }
func (union *C.union_union_nested_t) unionfield_point() *C.point3d_t { func (union *_Cgo_union_union_nested_t) unionfield_point() *_Cgo_point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union)) return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
} }
func (union *C.union_union_nested_t) unionfield_array() *C.unionarray_t { func (union *_Cgo_union_union_nested_t) unionfield_array() *_Cgo_unionarray_t {
return (*C.unionarray_t)(unsafe.Pointer(&union.$union)) return (*_Cgo_unionarray_t)(unsafe.Pointer(&union.$union))
} }
func (union *C.union_union_nested_t) unionfield_thing() *C.union3_t { func (union *_Cgo_union_union_nested_t) unionfield_thing() *_Cgo_union3_t {
return (*C.union3_t)(unsafe.Pointer(&union.$union)) return (*_Cgo_union3_t)(unsafe.Pointer(&union.$union))
} }
type C.union_nested_t = C.union_union_nested_t type _Cgo_union_nested_t = _Cgo_union_union_nested_t
type C.enum_option = C.int type _Cgo_enum_option = _Cgo_int
type C.option_t = C.enum_option type _Cgo_option_t = _Cgo_enum_option
type C.enum_option2_t = C.uint type _Cgo_enum_option2_t = _Cgo_uint
type C.option2_t = C.enum_option2_t type _Cgo_option2_t = _Cgo_enum_option2_t
type C.struct_types_t struct { type _Cgo_struct_types_t struct {
f float32 f float32
d float64 d float64
ptr *C.int ptr *_Cgo_int
} }
type C.types_t = C.struct_types_t type _Cgo_types_t = _Cgo_struct_types_t
type C.myIntArray = [10]C.int type _Cgo_myIntArray = [10]_Cgo_int
type C.struct_bitfield_t struct { type _Cgo_struct_bitfield_t struct {
start C.uchar start _Cgo_uchar
__bitfield_1 C.uchar __bitfield_1 _Cgo_uchar
d C.uchar d _Cgo_uchar
e C.uchar e _Cgo_uchar
} }
func (s *C.struct_bitfield_t) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f } func (s *_Cgo_struct_bitfield_t) bitfield_a() _Cgo_uchar { return s.__bitfield_1 & 0x1f }
func (s *C.struct_bitfield_t) set_bitfield_a(value C.uchar) { func (s *_Cgo_struct_bitfield_t) set_bitfield_a(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0 s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
} }
func (s *C.struct_bitfield_t) bitfield_b() C.uchar { func (s *_Cgo_struct_bitfield_t) bitfield_b() _Cgo_uchar {
return s.__bitfield_1 >> 5 & 0x1 return s.__bitfield_1 >> 5 & 0x1
} }
func (s *C.struct_bitfield_t) set_bitfield_b(value C.uchar) { func (s *_Cgo_struct_bitfield_t) set_bitfield_b(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5 s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
} }
func (s *C.struct_bitfield_t) bitfield_c() C.uchar { func (s *_Cgo_struct_bitfield_t) bitfield_c() _Cgo_uchar {
return s.__bitfield_1 >> 6 return s.__bitfield_1 >> 6
} }
func (s *C.struct_bitfield_t) set_bitfield_c(value C.uchar, func (s *_Cgo_struct_bitfield_t) set_bitfield_c(value _Cgo_uchar,
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 } ) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
type C.bitfield_t = C.struct_bitfield_t type _Cgo_bitfield_t = _Cgo_struct_bitfield_t
+1 -1
View File
@@ -8,7 +8,7 @@ import (
) )
var ( var (
validBuildModeOptions = []string{"default", "c-shared"} validBuildModeOptions = []string{"default", "c-shared", "wasi-legacy"}
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"} validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
validSchedulerOptions = []string{"none", "tasks", "asyncify"} validSchedulerOptions = []string{"none", "tasks", "asyncify"}
validSerialOptions = []string{"none", "uart", "usb", "rtt"} validSerialOptions = []string{"none", "uart", "usb", "rtt"}
+6 -5
View File
@@ -18,11 +18,12 @@ var stdlibAliases = map[string]string{
// crypto packages // crypto packages
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric", "crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
"crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric", "crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
"crypto/md5.block": "crypto/md5.blockGeneric", "crypto/md5.block": "crypto/md5.blockGeneric",
"crypto/sha1.block": "crypto/sha1.blockGeneric", "crypto/sha1.block": "crypto/sha1.blockGeneric",
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric", "crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
"crypto/sha256.block": "crypto/sha256.blockGeneric", "crypto/sha256.block": "crypto/sha256.blockGeneric",
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric", "crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
"internal/chacha8rand.block": "internal/chacha8rand.block_generic",
// AES // AES
"crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock", "crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock",
+11 -11
View File
@@ -31,7 +31,7 @@ func (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value) {
// Now do the bounds check: index >= arrayLen // Now do the bounds check: index >= arrayLen
outOfBounds := b.CreateICmp(llvm.IntUGE, index, arrayLen, "") outOfBounds := b.CreateICmp(llvm.IntUGE, index, arrayLen, "")
b.createRuntimeAssert(outOfBounds, "lookup", "lookupPanic") b.createRuntimeAssert(outOfBounds, "lookup", "lookupPanic", true)
} }
// createSliceBoundsCheck emits a bounds check before a slicing operation to make // createSliceBoundsCheck emits a bounds check before a slicing operation to make
@@ -74,7 +74,7 @@ func (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lo
outOfBounds3 := b.CreateICmp(llvm.IntUGT, max, capacity, "slice.maxcap") outOfBounds3 := b.CreateICmp(llvm.IntUGT, max, capacity, "slice.maxcap")
outOfBounds := b.CreateOr(outOfBounds1, outOfBounds2, "slice.lowmax") outOfBounds := b.CreateOr(outOfBounds1, outOfBounds2, "slice.lowmax")
outOfBounds = b.CreateOr(outOfBounds, outOfBounds3, "slice.lowcap") outOfBounds = b.CreateOr(outOfBounds, outOfBounds3, "slice.lowcap")
b.createRuntimeAssert(outOfBounds, "slice", "slicePanic") b.createRuntimeAssert(outOfBounds, "slice", "slicePanic", false)
} }
// createSliceToArrayPointerCheck adds a check for slice-to-array pointer // createSliceToArrayPointerCheck adds a check for slice-to-array pointer
@@ -86,7 +86,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen i
// > run-time panic occurs. // > run-time panic occurs.
arrayLenValue := llvm.ConstInt(b.uintptrType, uint64(arrayLen), false) arrayLenValue := llvm.ConstInt(b.uintptrType, uint64(arrayLen), false)
isLess := b.CreateICmp(llvm.IntULT, sliceLen, arrayLenValue, "") isLess := b.CreateICmp(llvm.IntULT, sliceLen, arrayLenValue, "")
b.createRuntimeAssert(isLess, "slicetoarray", "sliceToArrayPointerPanic") b.createRuntimeAssert(isLess, "slicetoarray", "sliceToArrayPointerPanic", false)
} }
// createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice // createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice
@@ -118,7 +118,7 @@ func (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value,
lenIsNotZero := b.CreateICmp(llvm.IntNE, len, zero, "") lenIsNotZero := b.CreateICmp(llvm.IntNE, len, zero, "")
assert := b.CreateAnd(ptrIsNil, lenIsNotZero, "") assert := b.CreateAnd(ptrIsNil, lenIsNotZero, "")
assert = b.CreateOr(assert, lenOutOfBounds, "") assert = b.CreateOr(assert, lenOutOfBounds, "")
b.createRuntimeAssert(assert, name, "unsafeSlicePanic") b.createRuntimeAssert(assert, name, "unsafeSlicePanic", false)
} }
// createChanBoundsCheck creates a bounds check before creating a new channel to // createChanBoundsCheck creates a bounds check before creating a new channel to
@@ -155,7 +155,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
// Do the check for a too large (or negative) buffer size. // Do the check for a too large (or negative) buffer size.
bufSizeTooBig := b.CreateICmp(llvm.IntUGE, bufSize, maxBufSize, "") bufSizeTooBig := b.CreateICmp(llvm.IntUGE, bufSize, maxBufSize, "")
b.createRuntimeAssert(bufSizeTooBig, "chan", "chanMakePanic") b.createRuntimeAssert(bufSizeTooBig, "chan", "chanMakePanic", false)
} }
// createNilCheck checks whether the given pointer is nil, and panics if it is. // createNilCheck checks whether the given pointer is nil, and panics if it is.
@@ -199,7 +199,7 @@ func (b *builder) createNilCheck(inst ssa.Value, ptr llvm.Value, blockPrefix str
isnil := b.CreateICmp(llvm.IntEQ, ptr, nilptr, "") isnil := b.CreateICmp(llvm.IntEQ, ptr, nilptr, "")
// Emit the nil check in IR. // Emit the nil check in IR.
b.createRuntimeAssert(isnil, blockPrefix, "nilPanic") b.createRuntimeAssert(isnil, blockPrefix, "nilPanic", false)
} }
// createNegativeShiftCheck creates an assertion that panics if the given shift value is negative. // createNegativeShiftCheck creates an assertion that panics if the given shift value is negative.
@@ -212,7 +212,7 @@ func (b *builder) createNegativeShiftCheck(shift llvm.Value) {
// isNegative = shift < 0 // isNegative = shift < 0
isNegative := b.CreateICmp(llvm.IntSLT, shift, llvm.ConstInt(shift.Type(), 0, false), "") isNegative := b.CreateICmp(llvm.IntSLT, shift, llvm.ConstInt(shift.Type(), 0, false), "")
b.createRuntimeAssert(isNegative, "shift", "negativeShiftPanic") b.createRuntimeAssert(isNegative, "shift", "negativeShiftPanic", false)
} }
// createDivideByZeroCheck asserts that y is not zero. If it is, a runtime panic // createDivideByZeroCheck asserts that y is not zero. If it is, a runtime panic
@@ -225,12 +225,12 @@ func (b *builder) createDivideByZeroCheck(y llvm.Value) {
// isZero = y == 0 // isZero = y == 0
isZero := b.CreateICmp(llvm.IntEQ, y, llvm.ConstInt(y.Type(), 0, false), "") isZero := b.CreateICmp(llvm.IntEQ, y, llvm.ConstInt(y.Type(), 0, false), "")
b.createRuntimeAssert(isZero, "divbyzero", "divideByZeroPanic") b.createRuntimeAssert(isZero, "divbyzero", "divideByZeroPanic", true)
} }
// createRuntimeAssert is a common function to create a new branch on an assert // createRuntimeAssert is a common function to create a new branch on an assert
// bool, calling an assert func if the assert value is true (1). // bool, calling an assert func if the assert value is true (1).
func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string) { func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string, isInvoke bool) {
// Check whether we can resolve this check at compile time. // Check whether we can resolve this check at compile time.
if !assert.IsAConstantInt().IsNil() { if !assert.IsAConstantInt().IsNil() {
val := assert.ZExtValue() val := assert.ZExtValue()
@@ -245,17 +245,17 @@ func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc
// current insert position. // current insert position.
faultBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+".throw") faultBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+".throw")
nextBlock := b.insertBasicBlock(blockPrefix + ".next") nextBlock := b.insertBasicBlock(blockPrefix + ".next")
b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
// Now branch to the out-of-bounds or the regular block. // Now branch to the out-of-bounds or the regular block.
b.CreateCondBr(assert, faultBlock, nextBlock) b.CreateCondBr(assert, faultBlock, nextBlock)
// Fail: the assert triggered so panic. // Fail: the assert triggered so panic.
b.SetInsertPointAtEnd(faultBlock) b.SetInsertPointAtEnd(faultBlock)
b.createRuntimeCall(assertFunc, nil, "") b.createRuntimeCallCommon(assertFunc, nil, "", isInvoke)
b.CreateUnreachable() b.CreateUnreachable()
// Ok: assert didn't trigger so continue normally. // Ok: assert didn't trigger so continue normally.
b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
b.SetInsertPointAtEnd(nextBlock) b.SetInsertPointAtEnd(nextBlock)
} }
+14 -5
View File
@@ -283,6 +283,11 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
info.wasmName = "_start" info.wasmName = "_start"
info.exported = true info.exported = true
} }
if info.linkName == "runtime.wasmEntryLegacy" && c.BuildMode == "wasi-legacy" {
info.linkName = "_start"
info.wasmName = "_start"
info.exported = true
}
// Check for //go: pragmas, which may change the link name (among others). // Check for //go: pragmas, which may change the link name (among others).
c.parsePragmas(&info, f) c.parsePragmas(&info, f)
@@ -427,9 +432,8 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
// pass for C variadic functions. This includes both explicit // pass for C variadic functions. This includes both explicit
// (with ...) and implicit (no parameters in signature) // (with ...) and implicit (no parameters in signature)
// functions. // functions.
if strings.HasPrefix(f.Name(), "C.") { if strings.HasPrefix(f.Name(), "_Cgo_") {
// This prefix cannot naturally be created, it must have // This prefix was created as a result of CGo preprocessing.
// been created as a result of CGo preprocessing.
info.variadic = true info.variadic = true
} }
} }
@@ -684,20 +688,25 @@ func (c *compilerContext) getGlobalInfo(g *ssa.Global) globalInfo {
// Check for //go: pragmas, which may change the link name (among others). // Check for //go: pragmas, which may change the link name (among others).
doc := c.astComments[info.linkName] doc := c.astComments[info.linkName]
if doc != nil { if doc != nil {
info.parsePragmas(doc) info.parsePragmas(doc, g)
} }
return info return info
} }
// Parse //go: pragma comments from the source. In particular, it parses the // Parse //go: pragma comments from the source. In particular, it parses the
// //go:extern pragma on globals. // //go:extern pragma on globals.
func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) { func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, g *ssa.Global) {
for _, comment := range doc.List { for _, comment := range doc.List {
if !strings.HasPrefix(comment.Text, "//go:") { if !strings.HasPrefix(comment.Text, "//go:") {
continue continue
} }
parts := strings.Fields(comment.Text) parts := strings.Fields(comment.Text)
switch parts[0] { switch parts[0] {
case "//go:linkname":
if len(parts) == 3 && g.Name() == parts[1] {
info.linkName = parts[2]
info.extern = true
}
case "//go:extern": case "//go:extern":
info.extern = true info.extern = true
if len(parts) == 2 { if len(parts) == 2 {
+6
View File
@@ -2,6 +2,12 @@ package main
import _ "unsafe" import _ "unsafe"
// Use the go:linkname mechanism to link this global to a different package.
// This is used in math/bits.
//
//go:linkname linknamedGlobal runtime.testLinknamedGlobal
var linknamedGlobal int
// Creates an external global with name extern_global. // Creates an external global with name extern_global.
// //
//go:extern extern_global //go:extern extern_global
+1
View File
@@ -3,6 +3,7 @@ source_filename = "pragma.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi" target triple = "wasm32-unknown-wasi"
@runtime.testLinknamedGlobal = external global i32, align 4
@extern_global = external global [0 x i8], align 1 @extern_global = external global [0 x i8], align 1
@main.alignedGlobal = hidden global [4 x i32] zeroinitializer, align 32 @main.alignedGlobal = hidden global [4 x i32] zeroinitializer, align 32
@main.alignedGlobal16 = hidden global [4 x i32] zeroinitializer, align 16 @main.alignedGlobal16 = hidden global [4 x i32] zeroinitializer, align 16
+3 -3
View File
@@ -970,9 +970,9 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me
case llvm.Call: case llvm.Call:
llvmFn := operands[len(operands)-1] llvmFn := operands[len(operands)-1]
args := operands[:len(operands)-1] args := operands[:len(operands)-1]
for _, arg := range args { for _, op := range operands {
if arg.Type().TypeKind() == llvm.PointerTypeKind { if op.Type().TypeKind() == llvm.PointerTypeKind {
err := mem.markExternalStore(arg) err := mem.markExternalStore(op)
if err != nil { if err != nil {
return r.errorAt(inst, err) return r.errorAt(inst, err)
} }
+1 -1
View File
@@ -1501,7 +1501,7 @@ func main() {
var tags buildutil.TagsFlag var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags") flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file") target := flag.String("target", "", "chip/board name or JSON target specification file")
buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared)") buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared, wasi-legacy)")
var stackSize uint64 var stackSize uint64
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error { flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
size, err := bytesize.Parse(s) size, err := bytesize.Parse(s)
+9
View File
@@ -594,6 +594,15 @@ func TestWasmExport(t *testing.T) {
noOutput: true, // wasm-unknown cannot produce output noOutput: true, // wasm-unknown cannot produce output
command: true, command: true,
}, },
// Test buildmode=wasi-legacy with WASI.
{
name: "WASIp1-legacy",
target: "wasip1",
buildMode: "wasi-legacy",
scheduler: "none",
file: "wasmexport-noscheduler.go",
command: true,
},
} }
for _, tc := range tests { for _, tc := range tests {
+31
View File
@@ -17,6 +17,37 @@ import (
"time" "time"
) )
const (
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
VersionTLS13 = 0x0304
// Deprecated: SSLv3 is cryptographically broken, and is no longer
// supported by this package. See golang.org/issue/32716.
VersionSSL30 = 0x0300
)
// VersionName returns the name for the provided TLS version number
// (e.g. "TLS 1.3"), or a fallback representation of the value if the
// version is not implemented by this package.
func VersionName(version uint16) string {
switch version {
case VersionSSL30:
return "SSLv3"
case VersionTLS10:
return "TLS 1.0"
case VersionTLS11:
return "TLS 1.1"
case VersionTLS12:
return "TLS 1.2"
case VersionTLS13:
return "TLS 1.3"
default:
return fmt.Sprintf("0x%04X", version)
}
}
// CurveID is the type of a TLS identifier for an elliptic curve. See // CurveID is the type of a TLS identifier for an elliptic curve. See
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8. // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
// //
+7
View File
@@ -0,0 +1,7 @@
package abi
type Type struct {
// Intentionally left empty. TinyGo uses a different way to represent types,
// so this is unimplementable. The type definition here is purely for
// compatibility.
}
+3
View File
@@ -21,6 +21,9 @@ type Task struct {
// state is the underlying running state of the task. // state is the underlying running state of the task.
state state state state
// This is needed for some crypto packages.
FipsIndicator uint8
// DeferFrame stores a pointer to the (stack allocated) defer frame of the // DeferFrame stores a pointer to the (stack allocated) defer frame of the
// goroutine that is used for the recover builtin. // goroutine that is used for the recover builtin.
DeferFrame unsafe.Pointer DeferFrame unsafe.Pointer
+77
View File
@@ -0,0 +1,77 @@
//go:build hw_651
package machine
// No-name brand board based on the nRF51822 chip with low frequency crystal on board.
// Pinout (reverse engineered from the board) can be found here:
// https://aviatorahmet.blogspot.com/2020/12/pinout-of-nrf51822-board.html
// https://cr0wg4n.medium.com/pinout-nrf51822-board-hw-651-78da2eda8894
const HasLowFrequencyCrystal = true
var DefaultUART = UART0
// GPIO pins on header J1
const (
J1_01 = P0_21
J1_03 = P0_23
J1_04 = P0_22
J1_05 = P0_25
J1_06 = P0_24
J1_09 = P0_29
J1_10 = P0_28
J1_11 = P0_30
J1_13 = P0_00
J1_15 = P0_02
J1_17 = P0_04
J1_16 = P0_01
J1_18 = P0_03
)
// GPIO pins on header J2
const (
J2_01 = P0_20
J2_03 = P0_18
J2_04 = P0_19
J2_07 = P0_16
J2_08 = P0_15
J2_09 = P0_14
J2_10 = P0_13
J2_11 = P0_12
J2_12 = P0_11
J2_13 = P0_10
J2_14 = P0_09
J2_15 = P0_08
J2_16 = P0_07
J2_17 = P0_06
J2_18 = P0_05
)
// UART pins
const (
UART_TX_PIN = P0_24 // J1_06 on the board
UART_RX_PIN = P0_25 // J1_05 on the board
)
// ADC pins
const (
ADC0 = P0_03 // J1_18 on the board
ADC1 = P0_02 // J1_15 on the board
ADC2 = P0_01 // J1_16 on the board
ADC3 = P0_04 // J1_17 on the board
ADC4 = P0_05 // J2_18 on the board
ADC5 = P0_06 // J2_17 on the board
)
// I2C pins
const (
SDA_PIN = P0_30 // J1_11 on the board
SCL_PIN = P0_00 // J1_13 on the board
)
// SPI pins
const (
SPI0_SCK_PIN = P0_23 // J1_03 on the board
SPI0_SDO_PIN = P0_21 // J1_01 on the board
SPI0_SDI_PIN = P0_22 // J1_04 on the board
)
+98
View File
@@ -0,0 +1,98 @@
//go:build pga2350
package machine
// PGA2350 pin definitions.
const (
GP0 = GPIO0
GP1 = GPIO1
GP2 = GPIO2
GP3 = GPIO3
GP4 = GPIO4
GP5 = GPIO5
GP6 = GPIO6
GP7 = GPIO7
GP8 = GPIO8
GP9 = GPIO9
GP10 = GPIO10
GP11 = GPIO11
GP12 = GPIO12
GP13 = GPIO13
GP14 = GPIO14
GP15 = GPIO15
GP16 = GPIO16
GP17 = GPIO17
GP18 = GPIO18
GP19 = GPIO19
GP20 = GPIO20
GP21 = GPIO21
GP22 = GPIO22
GP26 = GPIO26
GP27 = GPIO27
GP28 = GPIO28
GP29 = GPIO29
GP30 = GPIO30 // peripherals: PWM7 channel A
GP31 = GPIO31 // peripherals: PWM7 channel B
GP32 = GPIO32 // peripherals: PWM8 channel A
GP33 = GPIO33 // peripherals: PWM8 channel B
GP34 = GPIO34 // peripherals: PWM9 channel A
GP35 = GPIO35 // peripherals: PWM9 channel B
GP36 = GPIO36 // peripherals: PWM10 channel A
GP37 = GPIO37 // peripherals: PWM10 channel B
GP38 = GPIO38 // peripherals: PWM11 channel A
GP39 = GPIO39 // peripherals: PWM11 channel B
GP40 = GPIO40 // peripherals: PWM8 channel A
GP41 = GPIO41 // peripherals: PWM8 channel B
GP42 = GPIO42 // peripherals: PWM9 channel A
GP43 = GPIO43 // peripherals: PWM9 channel B
GP44 = GPIO44 // peripherals: PWM10 channel A
GP45 = GPIO45 // peripherals: PWM10 channel B
GP46 = GPIO46 // peripherals: PWM11 channel A
GP47 = GPIO47 // peripherals: PWM11 channel B
)
var DefaultUART = UART0
// Peripheral defaults.
const (
xoscFreq = 12 // MHz
I2C0_SDA_PIN = GP4
I2C0_SCL_PIN = GP5
I2C1_SDA_PIN = GP2
I2C1_SCL_PIN = GP3
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO18
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO19 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO16 // Rx
// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO10
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO11 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO12 // Rx
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART1_TX_PIN = GPIO8
UART1_RX_PIN = GPIO9
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
// USB identifiers
const (
usb_STRING_PRODUCT = "PGA2350"
usb_STRING_MANUFACTURER = "Pimoroni"
)
var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000A
)
+93
View File
@@ -0,0 +1,93 @@
//go:build pico_plus2
package machine
// GPIO pins
const (
GP0 Pin = GPIO0
GP1 Pin = GPIO1
GP2 Pin = GPIO2
GP3 Pin = GPIO3
GP4 Pin = GPIO4
GP5 Pin = GPIO5
GP6 Pin = GPIO6
GP7 Pin = GPIO7
GP8 Pin = GPIO8
GP9 Pin = GPIO9
GP10 Pin = GPIO10
GP11 Pin = GPIO11
GP12 Pin = GPIO12
GP13 Pin = GPIO13
GP14 Pin = GPIO14
GP15 Pin = GPIO15
GP16 Pin = GPIO16
GP17 Pin = GPIO17
GP18 Pin = GPIO18
GP19 Pin = GPIO19
GP20 Pin = GPIO20
GP21 Pin = GPIO21
GP22 Pin = GPIO22
GP26 Pin = GPIO26
GP27 Pin = GPIO27
GP28 Pin = GPIO28
GP32 Pin = GPIO32
GP33 Pin = GPIO33
GP34 Pin = GPIO34
GP35 Pin = GPIO35
GP36 Pin = GPIO36
// Onboard LED
LED Pin = GPIO25
// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)
// I2C Default pins on Raspberry Pico.
const (
I2C0_SDA_PIN = GP4
I2C0_SCL_PIN = GP5
I2C1_SDA_PIN = GP2
I2C1_SCL_PIN = GP3
)
// SPI default pins
const (
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO18
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO19 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO16 // Rx
// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO10
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO11 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO12 // Rx
)
// UART pins
const (
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART1_TX_PIN = GPIO8
UART1_RX_PIN = GPIO9
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
var DefaultUART = UART0
// USB identifiers
const (
usb_STRING_PRODUCT = "Pico Plus2"
usb_STRING_MANUFACTURER = "Pimoroni"
)
var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000F
)
+11
View File
@@ -64,3 +64,14 @@ type BlockDevice interface {
// EraseBlockSize to map addresses to blocks. // EraseBlockSize to map addresses to blocks.
EraseBlocks(start, len int64) error EraseBlocks(start, len int64) error
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func flashPad(p []byte, writeBlockSize int) []byte {
overflow := len(p) % writeBlockSize
if overflow != 0 {
for i := 0; i < writeBlockSize-overflow; i++ {
p = append(p, 0xff)
}
}
return p
}
+1 -13
View File
@@ -7,7 +7,6 @@
package machine package machine
import ( import (
"bytes"
"device/arm" "device/arm"
"device/sam" "device/sam"
"errors" "errors"
@@ -1917,7 +1916,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
f.ensureInitComplete() f.ensureInitComplete()
address := FlashDataStart() + uintptr(off) address := FlashDataStart() + uintptr(off)
padded := f.pad(p) padded := flashPad(p, int(f.WriteBlockSize()))
waitWhileFlashBusy() waitWhileFlashBusy()
@@ -1992,17 +1991,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil return nil
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func (f flashBlockDevice) ensureInitComplete() { func (f flashBlockDevice) ensureInitComplete() {
if f.initComplete { if f.initComplete {
return return
+1 -13
View File
@@ -7,7 +7,6 @@
package machine package machine
import ( import (
"bytes"
"device/arm" "device/arm"
"device/sam" "device/sam"
"errors" "errors"
@@ -2174,7 +2173,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
} }
address := FlashDataStart() + uintptr(off) address := FlashDataStart() + uintptr(off)
padded := f.pad(p) padded := flashPad(p, int(f.WriteBlockSize()))
settings := disableFlashCache() settings := disableFlashCache()
defer restoreFlashCache(settings) defer restoreFlashCache(settings)
@@ -2263,17 +2262,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil return nil
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func disableFlashCache() uint16 { func disableFlashCache() uint16 {
settings := sam.NVMCTRL.CTRLA.Get() settings := sam.NVMCTRL.CTRLA.Get()
+1 -13
View File
@@ -3,7 +3,6 @@
package machine package machine
import ( import (
"bytes"
"device/nrf" "device/nrf"
"internal/binary" "internal/binary"
"runtime/interrupt" "runtime/interrupt"
@@ -386,7 +385,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
} }
address := FlashDataStart() + uintptr(off) address := FlashDataStart() + uintptr(off)
padded := f.pad(p) padded := flashPad(p, int(f.WriteBlockSize()))
waitWhileFlashBusy() waitWhileFlashBusy()
@@ -444,17 +443,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil return nil
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func waitWhileFlashBusy() { func waitWhileFlashBusy() {
for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready { for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready {
} }
+6 -1
View File
@@ -183,7 +183,12 @@ func (a *ADC) Get() uint16 {
resolutionAdjustment = 4 // 12bit resolutionAdjustment = 4 // 12bit
} }
return rawValue.Get() << resolutionAdjustment value := int16(rawValue.Get())
if value < 0 {
value = 0
}
return uint16(value << resolutionAdjustment)
} }
// SPI on the NRF. // SPI on the NRF.
+2
View File
@@ -16,6 +16,8 @@ const (
// Note: On RP2350, most spinlocks are unusable due to Errata 2 // Note: On RP2350, most spinlocks are unusable due to Errata 2
_NUMSPINLOCKS = 32 _NUMSPINLOCKS = 32
_PICO_SPINLOCK_ID_IRQ = 9 _PICO_SPINLOCK_ID_IRQ = 9
// is48Pin notes whether the chip is RP2040 with 32 pins or RP2350 with 48 pins.
is48Pin = _NUMBANK0_GPIOS == 48
) )
// UART on the RP2040 // UART on the RP2040
-12
View File
@@ -3,7 +3,6 @@
package machine package machine
import ( import (
"bytes"
"unsafe" "unsafe"
) )
@@ -101,17 +100,6 @@ func (f flashBlockDevice) EraseBlocks(start, length int64) error {
return f.eraseBlocks(start, length) return f.eraseBlocks(start, length)
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
// return the correct address to be used for write // return the correct address to be used for write
func writeAddress(off int64) uintptr { func writeAddress(off int64) uintptr {
return readAddress(off) - uintptr(memoryStart) return readAddress(off) - uintptr(memoryStart)
+1 -1
View File
@@ -230,7 +230,7 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {
// e.g. real address 0x10003000 is written to at // e.g. real address 0x10003000 is written to at
// 0x00003000 // 0x00003000
address := writeAddress(off) address := writeAddress(off)
padded := f.pad(p) padded := flashPad(p, int(f.WriteBlockSize()))
C.flash_range_write(C.uint32_t(address), C.flash_range_write(C.uint32_t(address),
(*C.uint8_t)(unsafe.Pointer(&padded[0])), (*C.uint8_t)(unsafe.Pointer(&padded[0])),
+10
View File
@@ -45,6 +45,16 @@ const (
PinPIO1 PinPIO1
) )
// Analog pins on RP2040.
const (
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
thermADC = 30
)
const ( const (
clkGPOUT0 clockIndex = iota // GPIO Muxing 0 clkGPOUT0 clockIndex = iota // GPIO Muxing 0
clkGPOUT1 // GPIO Muxing 1 clkGPOUT1 // GPIO Muxing 1
+8 -2
View File
@@ -126,11 +126,17 @@ func (p Pin) Configure(config PinConfig) {
return return
} }
p.init() p.init()
mask := uint32(1) << p
switch config.Mode { switch config.Mode {
case PinOutput: case PinOutput:
p.setFunc(fnSIO) p.setFunc(fnSIO)
rp.SIO.GPIO_OE_SET.Set(mask) if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OE_SET.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OE_SET.Set(mask)
}
case PinInput: case PinInput:
p.setFunc(fnSIO) p.setFunc(fnSIO)
p.pulloff() p.pulloff()
+14
View File
@@ -0,0 +1,14 @@
//go:build rp2350 && !rp2350b
package machine
// Analog pins on RP2350a.
const (
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
// fifth ADC channel.
thermADC = 30
)
+48
View File
@@ -0,0 +1,48 @@
//go:build rp2350b
package machine
// RP2350B has additional pins.
const (
GPIO30 Pin = 30 // peripherals: PWM7 channel A
GPIO31 Pin = 31 // peripherals: PWM7 channel B
GPIO32 Pin = 32 // peripherals: PWM8 channel A
GPIO33 Pin = 33 // peripherals: PWM8 channel B
GPIO34 Pin = 34 // peripherals: PWM9 channel A
GPIO35 Pin = 35 // peripherals: PWM9 channel B
GPIO36 Pin = 36 // peripherals: PWM10 channel A
GPIO37 Pin = 37 // peripherals: PWM10 channel B
GPIO38 Pin = 38 // peripherals: PWM11 channel A
GPIO39 Pin = 39 // peripherals: PWM11 channel B
GPIO40 Pin = 40 // peripherals: PWM8 channel A
GPIO41 Pin = 41 // peripherals: PWM8 channel B
GPIO42 Pin = 42 // peripherals: PWM9 channel A
GPIO43 Pin = 43 // peripherals: PWM9 channel B
GPIO44 Pin = 44 // peripherals: PWM10 channel A
GPIO45 Pin = 45 // peripherals: PWM10 channel B
GPIO46 Pin = 46 // peripherals: PWM11 channel A
GPIO47 Pin = 47 // peripherals: PWM11 channel B
)
// Analog pins on 2350b.
const (
ADC0 Pin = GPIO40
ADC1 Pin = GPIO41
ADC2 Pin = GPIO42
ADC3 Pin = GPIO43
ADC4 Pin = GPIO44
ADC5 Pin = GPIO45
ADC6 Pin = GPIO46
ADC7 Pin = GPIO47
// Ninth ADC channel.
thermADC = 48
)
// Additional PWMs on the RP2350B.
var (
PWM8 = getPWMGroup(8)
PWM9 = getPWMGroup(9)
PWM10 = getPWMGroup(10)
PWM11 = getPWMGroup(11)
)
+6 -38
View File
@@ -11,15 +11,6 @@ import (
// ADCChannel is the ADC peripheral mux channel. 0-4. // ADCChannel is the ADC peripheral mux channel. 0-4.
type ADCChannel uint8 type ADCChannel uint8
// ADC channels. Only ADC_TEMP_SENSOR is public. The other channels are accessed via Machine.ADC objects
const (
adc0_CH ADCChannel = iota
adc1_CH
adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board
adcTempSensor // Internal temperature sensor channel
)
// Used to serialise ADC sampling // Used to serialise ADC sampling
var adcLock sync.Mutex var adcLock sync.Mutex
@@ -58,20 +49,10 @@ func (a ADC) Get() uint16 {
// GetADCChannel returns the channel associated with the ADC pin. // GetADCChannel returns the channel associated with the ADC pin.
func (a ADC) GetADCChannel() (c ADCChannel, err error) { func (a ADC) GetADCChannel() (c ADCChannel, err error) {
err = nil if a.Pin < ADC0 {
switch a.Pin { return 0, errors.New("no ADC channel for pin value")
case ADC0:
c = adc0_CH
case ADC1:
c = adc1_CH
case ADC2:
c = adc2_CH
case ADC3:
c = adc3_CH
default:
err = errors.New("no ADC channel for pin value")
} }
return c, err return ADCChannel(a.Pin - ADC0), nil
} }
// Configure sets the channel's associated pin to analog input mode. // Configure sets the channel's associated pin to analog input mode.
@@ -113,12 +94,12 @@ func ReadTemperature() (millicelsius int32) {
if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 { if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
InitADC() InitADC()
} }
thermChan, _ := ADC{Pin: thermADC}.GetADCChannel()
// Enable temperature sensor bias source // Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN) rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
// T = 27 - (ADC_voltage - 0.706)/0.001721 // T = 27 - (ADC_voltage - 0.706)/0.001721
return (27000<<16 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16 return (27000<<16 - (int32(thermChan.getVoltage())-706<<16)*581) >> 16
} }
// waitForReady spins waiting for the ADC peripheral to become ready. // waitForReady spins waiting for the ADC peripheral to become ready.
@@ -129,18 +110,5 @@ func waitForReady() {
// The Pin method returns the GPIO Pin associated with the ADC mux channel, if it has one. // The Pin method returns the GPIO Pin associated with the ADC mux channel, if it has one.
func (c ADCChannel) Pin() (p Pin, err error) { func (c ADCChannel) Pin() (p Pin, err error) {
err = nil return Pin(c) + ADC0, nil
switch c {
case adc0_CH:
p = ADC0
case adc1_CH:
p = ADC1
case adc2_CH:
p = ADC2
case adc3_CH:
p = ADC3
default:
err = errors.New("no associated pin for channel")
}
return p, err
} }
+4 -8
View File
@@ -13,12 +13,6 @@ func CPUFrequency() uint32 {
return 125 * MHz return 125 * MHz
} }
// Returns the period of a clock cycle for the raspberry pi pico in nanoseconds.
// Used in PWM API.
func cpuPeriod() uint32 {
return 1e9 / CPUFrequency()
}
// clockIndex identifies a hardware clock // clockIndex identifies a hardware clock
type clockIndex uint8 type clockIndex uint8
@@ -143,6 +137,8 @@ func (clk *clock) configure(src, auxsrc, srcFreq, freq uint32) {
} }
const pllsysFB, pllsysPD1, pllsysPD2 uint32 = 125, 6, 2 // RP2040 running 125MHz with 1500MHz VCO.
// init initializes the clock hardware. // init initializes the clock hardware.
// //
// Must be called before any other clock function. // Must be called before any other clock function.
@@ -169,8 +165,8 @@ func (clks *clocksType) init() {
// REF FBDIV VCO POSTDIV // REF FBDIV VCO POSTDIV
// pllSys: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz // pllSys: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz
// pllUSB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz // pllUSB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz
pllSys.init(1, 1500*MHz, 6, 2) pllSys.init(1, uint32(pllsysFB), uint32(pllsysPD1), uint32(pllsysPD2))
pllUSB.init(1, 480*MHz, 5, 2) pllUSB.init(1, 40, 5, 2)
// Configure clocks // Configure clocks
// clkRef = xosc (12MHz) / 1 = 12MHz // clkRef = xosc (12MHz) / 1 = 12MHz
+31 -8
View File
@@ -63,8 +63,13 @@ func (p Pin) PortMaskSet() (*uint32, uint32) {
// set drives the pin high // set drives the pin high
func (p Pin) set() { func (p Pin) set() {
mask := uint32(1) << p if is48Pin && p >= 32 {
rp.SIO.GPIO_OUT_SET.Set(mask) mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_SET.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_SET.Set(mask)
}
} }
func (p Pin) PortMaskClear() (*uint32, uint32) { func (p Pin) PortMaskClear() (*uint32, uint32) {
@@ -73,18 +78,31 @@ func (p Pin) PortMaskClear() (*uint32, uint32) {
// clr drives the pin low // clr drives the pin low
func (p Pin) clr() { func (p Pin) clr() {
mask := uint32(1) << p if is48Pin && p >= 32 {
rp.SIO.GPIO_OUT_CLR.Set(mask) mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_CLR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_CLR.Set(mask)
}
} }
// xor toggles the pin // xor toggles the pin
func (p Pin) xor() { func (p Pin) xor() {
mask := uint32(1) << p if is48Pin && p >= 32 {
rp.SIO.GPIO_OUT_XOR.Set(mask) mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_XOR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_XOR.Set(mask)
}
} }
// get returns the pin value // get returns the pin value
func (p Pin) get() bool { func (p Pin) get() bool {
if is48Pin && p >= 32 {
return rp.SIO.GPIO_HI_IN.HasBits(1 << (p % 32))
}
return rp.SIO.GPIO_IN.HasBits(1 << p) return rp.SIO.GPIO_IN.HasBits(1 << p)
} }
@@ -134,8 +152,13 @@ func (p Pin) setFunc(fn pinFunc) {
// init initializes the gpio pin // init initializes the gpio pin
func (p Pin) init() { func (p Pin) init() {
mask := uint32(1) << p if is48Pin && p >= 32 {
rp.SIO.GPIO_OE_CLR.Set(mask) mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OE_CLR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OE_CLR.Set(mask)
}
p.clr() p.clr()
} }
+1 -7
View File
@@ -1,4 +1,4 @@
//go:build rp2040 || rp2350 || ae_rp2040 || badger2040 || challenger_rp2040 || feather_rp2040 || gopher_badge || kb2040 || macropad_rp2040 || nano_rp2040 || pico || qtpy_rp2040 || thingplus_rp2040 || thumby || tufty2040 || waveshare_rp2040_zero || xiao_rp2040 //go:build rp2040 || rp2350 || gopher_badge
package machine package machine
@@ -34,10 +34,4 @@ const (
GPIO27 Pin = 27 // peripherals: PWM5 channel B GPIO27 Pin = 27 // peripherals: PWM5 channel B
GPIO28 Pin = 28 // peripherals: PWM6 channel A GPIO28 Pin = 28 // peripherals: PWM6 channel A
GPIO29 Pin = 29 // peripherals: PWM6 channel B GPIO29 Pin = 29 // peripherals: PWM6 channel B
// Analog pins
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
) )
+183 -4
View File
@@ -4,6 +4,9 @@ package machine
import ( import (
"device/rp" "device/rp"
"errors"
"math"
"math/bits"
"runtime/volatile" "runtime/volatile"
"unsafe" "unsafe"
) )
@@ -29,12 +32,11 @@ var (
// Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2. // Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2.
// //
// Post Divider 2, postDiv2 with range 1-7. // Post Divider 2, postDiv2 with range 1-7.
func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) { func (pll *pll) init(refdiv, fbdiv, postDiv1, postDiv2 uint32) {
refFreq := xoscFreq / refdiv refFreq := xoscFreq / refdiv
// What are we multiplying the reference clock by to get the vco freq // What are we multiplying the reference clock by to get the vco freq
// (The regs are called div, because you divide the vco output and compare it to the refclk) // (The regs are called div, because you divide the vco output and compare it to the refclk)
fbdiv := vcoFreq / (refFreq * MHz)
// Check fbdiv range // Check fbdiv range
if !(fbdiv >= 16 && fbdiv <= 320) { if !(fbdiv >= 16 && fbdiv <= 320) {
@@ -54,13 +56,14 @@ func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
panic("postdiv1 should be greater than or equal to postdiv2") panic("postdiv1 should be greater than or equal to postdiv2")
} }
// Check that reference frequency is no greater than vco / 16 // Check that reference frequency is no greater than vcoFreq / 16
vcoFreq := calcVCO(xoscFreq, fbdiv, refdiv)
if refFreq > vcoFreq/16 { if refFreq > vcoFreq/16 {
panic("reference frequency should not be greater than vco frequency divided by 16") panic("reference frequency should not be greater than vco frequency divided by 16")
} }
// div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10 // div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10
pdiv := postDiv1<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | postDiv2<<rp.PLL_SYS_PRIM_POSTDIV2_Pos pdiv := uint32(postDiv1)<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | uint32(postDiv2)<<rp.PLL_SYS_PRIM_POSTDIV2_Pos
if pll.cs.HasBits(rp.PLL_SYS_CS_LOCK) && if pll.cs.HasBits(rp.PLL_SYS_CS_LOCK) &&
refdiv == pll.cs.Get()&rp.PLL_SYS_CS_REFDIV_Msk && refdiv == pll.cs.Get()&rp.PLL_SYS_CS_REFDIV_Msk &&
@@ -98,3 +101,179 @@ func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
pll.pwr.ClearBits(rp.PLL_SYS_PWR_POSTDIVPD) pll.pwr.ClearBits(rp.PLL_SYS_PWR_POSTDIVPD)
} }
var errVCOOverflow = errors.New("VCO calculation overflow; use lower MHz")
// pllSearch enables searching for a good PLL configuration.
// Example for 12MHz crystal and RP2040:
//
// fbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 125*MHz, MHz)
//
// Example for 12MHz crystal and RP2350:
//
// fbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 133*MHz, MHz)
type pllSearch struct {
LowerVCO bool
LockRefDiv uint8
}
func (ps pllSearch) CalcDivs(xoscRef, targetFreq, MHz uint64) (fbdiv uint64, refdiv, pd1, pd2 uint8, err error) {
genTable()
var bestFreq, bestFbdiv uint64
var bestRefdiv, bestpd1, bestpd2 uint8
maxVCO, minVCO := 1600*MHz, 750*MHz
var bestMargin int64 = int64(maxVCO)
iters := 0
for refdiv = 1; refdiv < 64; refdiv++ {
if ps.LockRefDiv != 0 && refdiv != ps.LockRefDiv {
continue
}
firstFBDiv := minVCO * uint64(refdiv) / xoscRef
for fbdiv = firstFBDiv; fbdiv < 321; fbdiv++ {
overflow, vco := bits.Mul64(xoscRef, fbdiv)
vco /= uint64(refdiv)
if overflow != 0 {
return fbdiv, refdiv, pd1, pd2, errVCOOverflow
} else if vco > maxVCO {
break
}
calcPD12 := vco / targetFreq
if calcPD12 < 1 {
calcPD12 = 1
} else if calcPD12 > 49 {
calcPD12 = 49
}
iters++
pd1 = pdTable[calcPD12].hivco[0]
pd2 = pdTable[calcPD12].hivco[1]
fout, err := pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)
found := false
margin := abs(int64(fout) - int64(targetFreq))
if err == nil && margin <= bestMargin {
found = true
bestFreq = fout
bestFbdiv = fbdiv
bestpd1 = pd1
bestpd2 = pd2
bestRefdiv = refdiv
bestMargin = margin
}
pd1 = pdTable[calcPD12].lovco[0]
pd2 = pdTable[calcPD12].lovco[1]
fout, err = pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)
margin = abs(int64(fout) - int64(targetFreq))
if err == nil && margin <= bestMargin {
found = true
bestFreq = fout
bestFbdiv = fbdiv
bestpd1 = pd1
bestpd2 = pd2
bestRefdiv = refdiv
bestMargin = margin
}
if found && ps.LowerVCO {
break
}
}
}
if bestFreq == 0 {
return fbdiv, refdiv, pd1, pd2, errors.New("no best frequency found")
}
return bestFbdiv, bestRefdiv, bestpd1, bestpd2, nil
}
func abs(a int64) int64 {
if a == math.MinInt64 {
return math.MaxInt64
} else if a < 0 {
return -a
}
return a
}
func pllFreqOutPostdiv(xosc, fbdiv, MHz uint64, refdiv, postdiv1, postdiv2 uint8) (foutpostdiv uint64, err error) {
// testing grounds.
const (
mhz = 1
cfref = 12 * mhz // given by crystal oscillator selection.
crefd = 1
cfbdiv = 100
cvco = cfref * cfbdiv / crefd
cpd1 = 6
cpd2 = 2
foutpd = (cfref / crefd) * cfbdiv / (cpd1 * cpd2)
)
refFreq := xosc / uint64(refdiv)
overflow, vco := bits.Mul64(xosc, fbdiv)
vco /= uint64(refdiv)
foutpostdiv = vco / uint64(postdiv1*postdiv2)
switch {
case refdiv < 1 || refdiv > 63:
err = errors.New("reference divider out of range")
case fbdiv < 16 || fbdiv > 320:
err = errors.New("feedback divider out of range")
case postdiv1 < 1 || postdiv1 > 7:
err = errors.New("postdiv1 out of range")
case postdiv2 < 1 || postdiv2 > 7:
err = errors.New("postdiv2 out of range")
case postdiv1 < postdiv2:
err = errors.New("user error: use higher value for postdiv1 for lower power consumption")
case vco < 750*MHz || vco > 1600*MHz:
err = errors.New("VCO out of range")
case refFreq < 5*MHz:
err = errors.New("minimum reference frequency breach")
case refFreq > vco/16:
err = errors.New("maximum reference frequency breach")
case vco > 1200*MHz && vco < 1600*MHz && xosc < 75*MHz && refdiv != 1:
err = errors.New("refdiv should be 1 for given VCO and reference frequency")
case overflow != 0:
err = errVCOOverflow
}
if err != nil {
return 0, err
}
return foutpostdiv, nil
}
func calcVCO(xoscFreq, fbdiv, refdiv uint32) uint32 {
const maxXoscMHz = math.MaxUint32 / 320 / MHz // 13MHz maximum xosc apparently.
if fbdiv > 320 || xoscFreq > math.MaxUint32/320 {
panic("invalid VCO calculation args")
}
return xoscFreq * fbdiv / refdiv
}
var pdTable = [50]struct {
hivco [2]uint8
lovco [2]uint8
}{}
func genTable() {
if pdTable[1].hivco[1] != 0 {
return // Already generated.
}
for product := 1; product < len(pdTable); product++ {
bestProdhi := 255
bestProdlo := 255
for pd1 := 7; pd1 > 0; pd1-- {
for pd2 := pd1; pd2 > 0; pd2-- {
gotprod := pd1 * pd2
if abs(int64(gotprod-product)) < abs(int64(bestProdlo-product)) {
bestProdlo = gotprod
pdTable[product].lovco[0] = uint8(pd1)
pdTable[product].lovco[1] = uint8(pd2)
}
}
}
for pd1 := 1; pd1 < 8; pd1++ {
for pd2 := 1; pd2 <= pd1; pd2++ {
gotprod := pd1 * pd2
if abs(int64(gotprod-product)) < abs(int64(bestProdhi-product)) {
bestProdhi = gotprod
pdTable[product].hivco[0] = uint8(pd1)
pdTable[product].hivco[1] = uint8(pd2)
}
}
}
}
}
@@ -1,4 +1,4 @@
//go:build rp2040 //go:build rp2040 || rp2350
package machine package machine
@@ -15,7 +15,7 @@ var (
) )
const ( const (
maxPWMPins = 29 maxPWMPins = _NUMBANK0_GPIOS - 1
) )
// pwmGroup is one PWM peripheral, which consists of a counter and two output // pwmGroup is one PWM peripheral, which consists of a counter and two output
@@ -146,12 +146,14 @@ func (p *pwmGroup) Counter() uint32 {
// Period returns the used PWM period in nanoseconds. // Period returns the used PWM period in nanoseconds.
func (p *pwmGroup) Period() uint64 { func (p *pwmGroup) Period() uint64 {
periodPerCycle := cpuPeriod() // Lines below can overflow if operations done without care.
// maxInt=255, maxFrac=15, maxTop=65536, maxPHC=1 => maxProduct= (16*255+15) * (65536*2*1e9) = 5.3673e17 < MaxUint64=1.8e19 (close call.)
const compileTimeCheckPeriod uint64 = (255*16 + 15) * (65535 + 1) * 2 * 1e9
freq := uint64(CPUFrequency())
top := p.getWrap() top := p.getWrap()
phc := p.getPhaseCorrect() phc := p.getPhaseCorrect()
Int, frac := p.getClockDiv() Int, frac := p.getClockDiv()
// Line below can overflow if operations done without care. return (16*uint64(Int) + uint64(frac)) * uint64((top+1)*(phc+1)*1e9) / (16 * freq) // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
return (16*uint64(Int) + uint64(frac)) * uint64((top+1)*(phc+1)*periodPerCycle) / 16 // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
} }
// SetInverting sets whether to invert the output of this channel. // SetInverting sets whether to invert the output of this channel.
@@ -266,6 +268,9 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// Maximum Period is 268369920ns on rp2040, given by (16*255+15)*8*(1+0xffff)*(1+1)/16 // Maximum Period is 268369920ns on rp2040, given by (16*255+15)*8*(1+0xffff)*(1+1)/16
// With no phase shift max period is half of this value. // With no phase shift max period is half of this value.
maxPeriod = 268 * milliseconds maxPeriod = 268 * milliseconds
// This will be a compile time error if this method is at risk of overflowing. cpufreq=155MHz for typical RP2350.
maxCPUFreq = 4 * GHz // Can go up to 4GHz without overflowing :)
compileTimeCheckSetPeriod uint64 = 16 * maxPeriod * maxCPUFreq
) )
if period > maxPeriod || period < 8 { if period > maxPeriod || period < 8 {
@@ -279,11 +284,13 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// DIV_INT + DIV_FRAC/16 = cycles / ( (TOP+1) * (CSRPHCorrect+1) ) // DIV_FRAC/16 is always 0 in this equation // DIV_INT + DIV_FRAC/16 = cycles / ( (TOP+1) * (CSRPHCorrect+1) ) // DIV_FRAC/16 is always 0 in this equation
// where cycles must be converted to time: // where cycles must be converted to time:
// target_period = cycles * period_per_cycle ==> cycles = target_period/period_per_cycle // target_period = cycles * period_per_cycle ==> cycles = target_period/period_per_cycle
periodPerCycle := uint64(cpuPeriod()) var (
phc := uint64(pwm.getPhaseCorrect()) freq = uint64(CPUFrequency())
rhs := 16 * period / ((1 + phc) * periodPerCycle * (1 + topStart)) // right-hand-side of equation, scaled so frac is not divided phc = uint64(pwm.getPhaseCorrect())
whole := rhs / 16 rhs = 16 * period * freq / ((1 + phc) * 1e9 * (1 + topStart)) // right-hand-side of equation, scaled so frac is not divided
frac := rhs % 16 whole = rhs / 16
frac = rhs % 16
)
switch { switch {
case whole > 0xff: case whole > 0xff:
whole = 0xff whole = 0xff
@@ -296,7 +303,7 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// Step 2 is acquiring a better top value. Clearing the equation: // Step 2 is acquiring a better top value. Clearing the equation:
// TOP = cycles / ( (DIVINT+DIVFRAC/16) * (CSRPHCorrect+1) ) - 1 // TOP = cycles / ( (DIVINT+DIVFRAC/16) * (CSRPHCorrect+1) ) - 1
top := 16*period/((16*whole+frac)*periodPerCycle*(1+phc)) - 1 top := 16*period*freq/((1+phc)*1e9*(16*whole+frac)) - 1
if top > maxTop { if top > maxTop {
top = maxTop top = maxTop
} }
@@ -400,6 +407,9 @@ func (pwm *pwmGroup) getClockDiv() (Int, frac uint8) {
// pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO. // pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO.
// gpio must be less than 30. Returns the PWM slice number that controls the specified GPIO. // gpio must be less than 30. Returns the PWM slice number that controls the specified GPIO.
func pwmGPIOToSlice(gpio Pin) (slicenum uint8) { func pwmGPIOToSlice(gpio Pin) (slicenum uint8) {
if is48Pin && gpio >= 32 {
return uint8(8 + ((gpio-32)/2)%4)
}
return (uint8(gpio) >> 1) & 7 return (uint8(gpio) >> 1) & 7
} }
+2 -13
View File
@@ -5,7 +5,6 @@ package machine
import ( import (
"device/stm32" "device/stm32"
"bytes"
"unsafe" "unsafe"
) )
@@ -41,7 +40,8 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
unlockFlash() unlockFlash()
defer lockFlash() defer lockFlash()
return writeFlashData(FlashDataStart()+uintptr(off), f.pad(p)) p = flashPad(p, int(f.WriteBlockSize()))
return writeFlashData(FlashDataStart()+uintptr(off), p)
} }
// Size returns the number of bytes in this block device. // Size returns the number of bytes in this block device.
@@ -90,17 +90,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil return nil
} }
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
const memoryStart = 0x08000000 const memoryStart = 0x08000000
func unlockFlash() { func unlockFlash() {
+2 -2
View File
@@ -1,9 +1,9 @@
package descriptor package descriptor
import ( import (
"bytes"
"errors" "errors"
"internal/binary" "internal/binary"
"internal/bytealg"
) )
var configurationCDCHID = [configurationTypeLen]byte{ var configurationCDCHID = [configurationTypeLen]byte{
@@ -87,7 +87,7 @@ func FindClassHIDType(des, class []byte) (ClassHIDType, error) {
// search only for ClassHIDType without the ClassLength, // search only for ClassHIDType without the ClassLength,
// in case it has already been set. // in case it has already been set.
idx := bytes.Index(des, class[:ClassHIDTypeLen-2]) idx := bytealg.Index(des, class[:ClassHIDTypeLen-2])
if idx == -1 { if idx == -1 {
return ClassHIDType{}, errNoClassHIDFound return ClassHIDType{}, errNoClassHIDFound
} }
+1 -1
Submodule src/net updated: a237059610...ca7cd08f85
+22
View File
@@ -307,6 +307,28 @@ func (f *File) Sync() (err error) {
return return
} }
// Chmod changes the mode of the file to mode. If there is an error, it will be
// of type *PathError.
func (f *File) Chmod(mode FileMode) (err error) {
if f.handle == nil {
err = ErrClosed
} else {
err = f.chmod(mode)
}
return
}
// Chdir changes the current working directory to the file, which must be a
// directory. If there is an error, it will be of type *PathError.
func (f *File) Chdir() (err error) {
if f.handle == nil {
err = ErrClosed
} else {
err = f.chdir()
}
return
}
// LinkError records an error during a link or symlink or rename system call and // LinkError records an error during a link or symlink or rename system call and
// the paths that caused it. // the paths that caused it.
type LinkError struct { type LinkError struct {
+14
View File
@@ -42,6 +42,12 @@ func NewFile(fd uintptr, name string) *File {
return &File{&file{handle: stdioFileHandle(fd), name: name}} return &File{&file{handle: stdioFileHandle(fd), name: name}}
} }
// Chdir changes the current working directory to the named directory.
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
return ErrNotImplemented
}
// Rename renames (moves) oldpath to newpath. // Rename renames (moves) oldpath to newpath.
// If newpath already exists and is not a directory, Rename replaces it. // If newpath already exists and is not a directory, Rename replaces it.
// OS-specific restrictions may apply when oldpath and newpath are in different directories. // OS-specific restrictions may apply when oldpath and newpath are in different directories.
@@ -149,3 +155,11 @@ func (f *File) Truncate(size int64) (err error) {
return Truncate(f.name, size) return Truncate(f.name, size)
} }
func (f *File) chmod(mode FileMode) error {
return ErrUnsupported
}
func (f *File) chdir() error {
return ErrNotImplemented
}
+31
View File
@@ -151,6 +151,37 @@ func (f *File) Truncate(size int64) (err error) {
return Truncate(f.name, size) return Truncate(f.name, size)
} }
func (f *File) chmod(mode FileMode) error {
if f.handle == nil {
return ErrClosed
}
longName := fixLongPath(f.name)
e := ignoringEINTR(func() error {
return syscall.Chmod(longName, syscallMode(mode))
})
if e != nil {
return &PathError{Op: "chmod", Path: f.name, Err: e}
}
return nil
}
func (f *File) chdir() error {
if f.handle == nil {
return ErrClosed
}
// TODO: use syscall.Fchdir instead
longName := fixLongPath(f.name)
e := ignoringEINTR(func() error {
return syscall.Chdir(longName)
})
if e != nil {
return &PathError{Op: "chdir", Path: f.name, Err: e}
}
return nil
}
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset. // ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
// It returns the number of bytes read and any error encountered, possibly io.EOF. // It returns the number of bytes read and any error encountered, possibly io.EOF.
// At end of file, Pread returns 0, io.EOF. // At end of file, Pread returns 0, io.EOF.
+8
View File
@@ -142,3 +142,11 @@ func isWindowsNulName(name string) bool {
} }
return true return true
} }
func (f *File) chmod(mode FileMode) error {
return ErrNotImplemented
}
func (f *File) chdir() error {
return ErrNotImplemented
}
+4
View File
@@ -271,6 +271,10 @@ func (v Value) Comparable() bool {
} }
} }
func (v Value) Equal(u Value) bool {
panic("unimplemented: reflect.Value.Equal")
}
func (v Value) Addr() Value { func (v Value) Addr() Value {
if !v.CanAddr() { if !v.CanAddr() {
panic("reflect.Value.Addr of unaddressable value") panic("reflect.Value.Addr of unaddressable value")
+3 -3
View File
@@ -23,13 +23,13 @@ func fastrand() uint32 {
return xorshift32State return xorshift32State
} }
func init() { func initRand() {
r, _ := hardwareRand() r, _ := hardwareRand()
xorshift64State = uint64(r | 1) // protect against 0 xorshift64State = uint64(r | 1) // protect against 0
xorshift32State = uint32(xorshift64State) xorshift32State = uint32(xorshift64State)
} }
var xorshift32State uint32 var xorshift32State uint32 = 1
func xorshift32(x uint32) uint32 { func xorshift32(x uint32) uint32 {
// Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs". // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs".
@@ -49,7 +49,7 @@ func fastrand64() uint64 {
return xorshift64State return xorshift64State
} }
var xorshift64State uint64 var xorshift64State uint64 = 1
// 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf // 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf
func xorshiftMult64(x uint64) uint64 { func xorshiftMult64(x uint64) uint64 {
+18
View File
@@ -4,5 +4,23 @@ package runtime
type Error interface { type Error interface {
error error
// Method to indicate this is indeed a runtime error.
RuntimeError() RuntimeError()
} }
type runtimeError struct {
msg string
}
func (r runtimeError) Error() string {
return r.msg
}
// Purely here to satisfy the Error interface.
func (r runtimeError) RuntimeError() {}
var (
divideError error = runtimeError{"runtime error: integer divide by zero"}
lookupError error = runtimeError{"runtime error: index out of range"}
overflowError error = runtimeError{"runtime error: integer overflow"}
)
+7 -2
View File
@@ -187,7 +187,7 @@ func nilMapPanic() {
// Panic when trying to access an array or slice out of bounds. // Panic when trying to access an array or slice out of bounds.
func lookupPanic() { func lookupPanic() {
runtimePanicAt(returnAddress(0), "index out of range") _panic(lookupError)
} }
// Panic when trying to slice a slice out of bounds. // Panic when trying to slice a slice out of bounds.
@@ -220,9 +220,14 @@ func negativeShiftPanic() {
// Panic when there is a divide by zero. // Panic when there is a divide by zero.
func divideByZeroPanic() { func divideByZeroPanic() {
runtimePanicAt(returnAddress(0), "divide by zero") _panic(divideError)
} }
func blockingPanic() { func blockingPanic() {
runtimePanicAt(returnAddress(0), "trying to do blocking operation in exported function") runtimePanicAt(returnAddress(0), "trying to do blocking operation in exported function")
} }
//go:linkname fips_fatal crypto/internal/fips140.fatal
func fips_fatal(msg string) {
runtimePanic(msg)
}
+10
View File
@@ -35,6 +35,7 @@ func wasmEntryReactor() {
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize) heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
initHeap() initHeap()
initRand()
if hasScheduler { if hasScheduler {
// A package initializer might do funky stuff like start a goroutine and // A package initializer might do funky stuff like start a goroutine and
@@ -51,6 +52,15 @@ func wasmEntryReactor() {
} }
} }
// This is the _start entry point, when using -buildmode=wasi-legacy.
func wasmEntryLegacy() {
// These need to be initialized early so that the heap can be initialized.
initializeCalled = true
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
run()
}
// Whether the runtime was initialized by a call to _initialize or _start. // Whether the runtime was initialized by a call to _initialize or _start.
var initializeCalled bool var initializeCalled bool
+11
View File
@@ -31,3 +31,14 @@ func scheduleLogChan(msg string, ch *channel, t *task.Task) {
func Goexit() { func Goexit() {
panicOrGoexit(nil, panicGoexit) panicOrGoexit(nil, panicGoexit)
} }
//go:linkname fips_getIndicator crypto/internal/fips140.getIndicator
func fips_getIndicator() uint8 {
return task.Current().FipsIndicator
}
//go:linkname fips_setIndicator crypto/internal/fips140.setIndicator
func fips_setIndicator(indicator uint8) {
// This indicator is stored per goroutine.
task.Current().FipsIndicator = indicator
}
+1
View File
@@ -247,6 +247,7 @@ func sleep(duration int64) {
// With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler. // With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler.
func run() { func run() {
initHeap() initHeap()
initRand()
go func() { go func() {
initAll() initAll()
callMain() callMain()
+1
View File
@@ -13,6 +13,7 @@ const hasParallelism = false
// With the "none" scheduler, init and the main function are invoked directly. // With the "none" scheduler, init and the main function are invoked directly.
func run() { func run() {
initHeap() initHeap()
initRand()
initAll() initAll()
callMain() callMain()
mainExited = true mainExited = true
+15
View File
@@ -0,0 +1,15 @@
package runtime
// Dummy implementation of synctest functions (we don't support synctest at the
// moment).
//go:linkname synctest_acquire internal/synctest.acquire
func synctest_acquire() any {
// Dummy: we don't support synctest.
return nil
}
//go:linkname synctest_release internal/synctest.release
func synctest_release(sg any) {
// Dummy: we don't support synctest.
}
+13
View File
@@ -1,5 +1,18 @@
package runtime package runtime
//go:linkname time_runtimeNano time.runtimeNano
func time_runtimeNano() int64 {
// Note: we're ignoring sync groups here (package testing/synctest).
// See: https://github.com/golang/go/issues/67434
return nanotime()
}
//go:linkname time_runtimeNow time.runtimeNow
func time_runtimeNow() (sec int64, nsec int32, mono int64) {
// Also ignoring the sync group here, like time_runtimeNano above.
return now()
}
// timerNode is an element in a linked list of timers. // timerNode is an element in a linked list of timers.
type timerNode struct { type timerNode struct {
next *timerNode next *timerNode
+4
View File
@@ -233,6 +233,10 @@ func (w WaitStatus) Continued() bool { return false }
func (w WaitStatus) StopSignal() Signal { return 0 } func (w WaitStatus) StopSignal() Signal { return 0 }
func (w WaitStatus) TrapCause() int { return 0 } func (w WaitStatus) TrapCause() int { return 0 }
// Purely here for compatibility.
type Rusage struct {
}
// since rusage is quite a big struct and we stub it out anyway no need to define it here // since rusage is quite a big struct and we stub it out anyway no need to define it here
func Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) {
return 0, ENOSYS // TODO return 0, ENOSYS // TODO
+15
View File
@@ -120,8 +120,11 @@ const (
SYS_FCNTL64 SYS_FCNTL64
SYS_FSTATAT64 SYS_FSTATAT64
SYS_IOCTL SYS_IOCTL
SYS_MKDIRAT
SYS_OPENAT SYS_OPENAT
SYS_READLINKAT
SYS_UNLINKAT SYS_UNLINKAT
SYS_WAITID
PATH_MAX = 4096 PATH_MAX = 4096
) )
@@ -438,6 +441,13 @@ type RawSockaddrInet6 struct {
// stub // stub
} }
func RandomGet(b []byte) error {
if len(b) > 0 {
libc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b)))
}
return nil
}
// This is a stub, it is not functional. // This is a stub, it is not functional.
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
@@ -483,3 +493,8 @@ func libc_fdclosedir(unsafe.Pointer) int32
// //
//export readdir //export readdir
func libc_readdir(unsafe.Pointer) *Dirent func libc_readdir(unsafe.Pointer) *Dirent
// void arc4random_buf(void *buf, size_t buflen);
//
//export arc4random_buf
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
+45
View File
@@ -17,6 +17,8 @@ import (
"io/fs" "io/fs"
"math/rand" "math/rand"
"os" "os"
"path/filepath"
"runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -390,6 +392,49 @@ func (c *common) Setenv(key, value string) {
} }
} }
// Chdir calls os.Chdir(dir) and uses Cleanup to restore the current
// working directory to its original value after the test. On Unix, it
// also sets PWD environment variable for the duration of the test.
//
// Because Chdir affects the whole process, it cannot be used
// in parallel tests or tests with parallel ancestors.
func (c *common) Chdir(dir string) {
// Note: function copied from the Go 1.24.0 source tree.
oldwd, err := os.Open(".")
if err != nil {
c.Fatal(err)
}
if err := os.Chdir(dir); err != nil {
c.Fatal(err)
}
// On POSIX platforms, PWD represents “an absolute pathname of the
// current working directory.” Since we are changing the working
// directory, we should also set or update PWD to reflect that.
switch runtime.GOOS {
case "windows", "plan9":
// Windows and Plan 9 do not use the PWD variable.
default:
if !filepath.IsAbs(dir) {
dir, err = os.Getwd()
if err != nil {
c.Fatal(err)
}
}
c.Setenv("PWD", dir)
}
c.Cleanup(func() {
err := oldwd.Chdir()
oldwd.Close()
if err != nil {
// It's not safe to continue with tests if we can't
// get back to the original working directory. Since
// we are holding a dirfd, this is highly unlikely.
panic("testing.Chdir: " + err.Error())
}
})
}
// runCleanup is called at the end of the test. // runCleanup is called at the end of the test.
func (c *common) runCleanup() { func (c *common) runCleanup() {
for { for {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"inherits": ["rp2040"], "inherits": ["rp2040"],
"build-tags": ["elecrow_rp2040"], "build-tags": ["elecrow_rp2040", "comboat_fw"],
"serial-port": ["2e8a:000a"], "serial-port": ["2e8a:000a"],
"default-stack-size": 8192, "default-stack-size": 8192,
"ldflags": [ "ldflags": [
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"inherits": ["rp2350"], "inherits": ["rp2350"],
"build-tags": ["elecrow_rp2350"], "build-tags": ["elecrow_rp2350", "comboat_fw"],
"serial-port": ["2e8a:000f"], "serial-port": ["2e8a:000f"],
"default-stack-size": 8192, "default-stack-size": 8192,
"ldflags": [ "ldflags": [
+3
View File
@@ -0,0 +1,3 @@
{
"inherits": ["hw-651", "nrf51-s110v8"]
}
+7
View File
@@ -0,0 +1,7 @@
{
"inherits": ["nrf51"],
"build-tags": ["hw_651"],
"serial": "uart",
"flash-method": "openocd",
"openocd-interface": "cmsis-dap"
}
+4
View File
@@ -0,0 +1,4 @@
{
"inherits": ["rp2350b"],
"build-tags": ["pga2350"]
}
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"rp2350b"
],
"build-tags": ["pico_plus2"],
"ldflags": [
"--defsym=__flash_size=16M"
],
"serial-port": ["2e8a:000F"],
"default-stack-size": 8192
}
+2 -1
View File
@@ -3,5 +3,6 @@
"rp2350" "rp2350"
], ],
"build-tags": ["pico2"], "build-tags": ["pico2"],
"serial-port": ["2e8a:000A"] "serial-port": ["2e8a:000A"],
"default-stack-size": 8192
} }
+5
View File
@@ -0,0 +1,5 @@
{
"inherits": ["rp2350"],
"build-tags": ["rp2350b"],
"serial-port": ["2e8a:000f"]
}
+1 -1
View File
@@ -7,7 +7,7 @@
], ],
"linkerscript": "targets/tkey.ld", "linkerscript": "targets/tkey.ld",
"scheduler": "none", "scheduler": "none",
"gc": "leaking", "gc": "conservative",
"flash-command": "tkey-runapp {bin}", "flash-command": "tkey-runapp {bin}",
"serial": "uart" "serial": "uart"
} }
+14 -3
View File
@@ -303,9 +303,20 @@
// func finalizeRef(v ref) // func finalizeRef(v ref)
"syscall/js.finalizeRef": (v_ref) => { "syscall/js.finalizeRef": (v_ref) => {
// Note: TinyGo does not support finalizers so this should never be // Note: TinyGo does not support finalizers so this is only called
// called. // for one specific case, by js.go:jsString. and can/might leak memory.
console.error('syscall/js.finalizeRef not implemented'); const id = v_ref & 0xffffffffn;
if (this._goRefCounts?.[id] !== undefined) {
this._goRefCounts[id]--;
if (this._goRefCounts[id] === 0) {
const v = this._values[id];
this._values[id] = null;
this._ids.delete(v);
this._idPool.push(id);
}
} else {
console.error("syscall/js.finalizeRef: unknown id", id);
}
}, },
// func stringVal(value string) ref // func stringVal(value string) ref
+24
View File
@@ -30,6 +30,10 @@ func main() {
println("\n# defer panic") println("\n# defer panic")
deferPanic() deferPanic()
println("\n# runtime panics")
runtimePanicDivByZero(1, 0)
runtimePanicLookup([]int{1, 2, 3}, 10)
println("\n# runtime.Goexit") println("\n# runtime.Goexit")
runtimeGoexit() runtimeGoexit()
} }
@@ -114,6 +118,26 @@ func deferPanic() {
println("defer panic") println("defer panic")
} }
func runtimePanicDivByZero(a, b int) int {
defer func() {
if err := recover(); err != nil {
println("recovered:", err)
}
}()
return a / b
}
func runtimePanicLookup(slice []int, index int) int {
defer func() {
if err := recover(); err != nil {
println("recovered:", err)
}
}()
return slice[index]
}
func runtimeGoexit() { func runtimeGoexit() {
wg.Add(1) wg.Add(1)
go func() { go func() {
+9 -1
View File
@@ -33,8 +33,16 @@ func runargs(t *testing.T, args ...string) error {
} }
func chromectx(t *testing.T) context.Context { func chromectx(t *testing.T) context.Context {
// see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.NoSandbox,
)
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
t.Cleanup(cancel)
// looks for locally installed Chrome // looks for locally installed Chrome
ctx, ccancel := chromedp.NewContext(context.Background(), chromedp.WithErrorf(t.Errorf), chromedp.WithDebugf(t.Logf), chromedp.WithLogf(t.Logf)) ctx, ccancel := chromedp.NewContext(allocCtx, chromedp.WithErrorf(t.Errorf), chromedp.WithDebugf(t.Logf), chromedp.WithLogf(t.Logf))
t.Cleanup(ccancel) t.Cleanup(ccancel)
// Wait for browser to be ready. // Wait for browser to be ready.