Compare commits

..

1 Commits

Author SHA1 Message Date
Ayke van Laethem e0bdf2b070 WIP x509 on macOS 2025-08-04 14:27:20 +02:00
183 changed files with 1700 additions and 4427 deletions
+8 -10
View File
@@ -92,20 +92,16 @@ commands:
- /go/pkg/mod - /go/pkg/mod
jobs: jobs:
test-oldest: test-llvm15-go122:
# This tests our lowest supported versions of Go and LLVM, to make sure at
# least the smoke tests still pass.
docker: docker:
- image: golang:1.22-bullseye - image: golang:1.22-bullseye
steps: steps:
- test-linux: - test-linux:
llvm: "15" llvm: "15"
resource_class: large resource_class: large
test-newest: test-llvm20-go124:
# This tests the latest supported LLVM version when linking against system
# libraries.
docker: docker:
- image: golang:1.25-bullseye - image: golang:1.24-bullseye
steps: steps:
- test-linux: - test-linux:
llvm: "20" llvm: "20"
@@ -114,6 +110,8 @@ jobs:
workflows: workflows:
test-all: test-all:
jobs: jobs:
- test-oldest # This tests our lowest supported versions of Go and LLVM, to make sure at
# disable this test, since CircleCI seems unable to download due to rate-limits on Dockerhub. # least the smoke tests still pass.
# - test-newest - test-llvm15-go122
# This tests LLVM 20 support when linking against system libraries.
- test-llvm20-go124
+14 -15
View File
@@ -16,37 +16,36 @@ jobs:
name: build-macos name: build-macos
strategy: strategy:
matrix: matrix:
# macos-14: arm64 (oldest supported version as of 18-11-2025) # macos-13: amd64 (oldest supported version as of 18-10-2024)
# macos-15-intel: amd64 (last intel version to be supported by github runners) # macos-14: arm64 (oldest arm64 version)
# See https://github.com/actions/runner-images/issues/13046 os: [macos-13, macos-14]
os: [macos-14, macos-15-intel]
include: include:
- os: macos-13
goarch: amd64
- os: macos-14 - os: macos-14
goarch: arm64 goarch: arm64
- os: macos-15-intel
goarch: amd64
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Extract TinyGo version - name: Extract TinyGo version
id: version id: version
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT" run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-${{ matrix.os }}-v1 key: llvm-source-19-${{ matrix.os }}-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@@ -71,7 +70,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-20-${{ matrix.os }}-v2 key: llvm-build-19-${{ matrix.os }}-v1
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'
@@ -80,7 +79,7 @@ jobs:
rm -rf llvm-project rm -rf llvm-project
make llvm-source make llvm-source
# install dependencies # install dependencies
HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake ninja
# build! # build!
make llvm-build make llvm-build
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
@@ -131,11 +130,11 @@ jobs:
run: | run: |
brew install llvm@${{ matrix.version }} brew install llvm@${{ matrix.version }}
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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 }}
+2 -2
View File
@@ -31,7 +31,7 @@ jobs:
sudo rm -rf /usr/local/share/boost sudo rm -rf /usr/local/share/boost
df -h df -h
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -58,7 +58,7 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v5
with: with:
context: . context: .
push: true push: true
+18 -18
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.25-alpine image: golang:1.24-alpine
outputs: outputs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
@@ -26,12 +26,12 @@ jobs:
# tar: needed for actions/cache@v4 # tar: needed for actions/cache@v4
# git+openssh: needed for checkout (I think?) # git+openssh: needed for checkout (I think?)
# ruby: needed to install fpm # ruby: needed to install fpm
run: apk add tar git openssh make g++ ruby-dev mold run: apk add tar git openssh make g++ ruby-dev
- name: Work around CVE-2022-24765 - name: Work around CVE-2022-24765
# We're not on a multi-user machine, so this is safe. # We're not on a multi-user machine, so this is safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE" run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Extract TinyGo version - name: Extract TinyGo version
@@ -48,7 +48,7 @@ jobs:
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-linux-alpine-v1 key: llvm-source-19-linux-alpine-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@@ -73,7 +73,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-20-linux-alpine-v1 key: llvm-build-19-linux-alpine-v1
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'
@@ -131,13 +131,13 @@ jobs:
needs: build-linux needs: build-linux
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
@@ -164,7 +164,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Install apt dependencies - name: Install apt dependencies
@@ -179,9 +179,9 @@ jobs:
simavr \ simavr \
ninja-build ninja-build
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
@@ -197,7 +197,7 @@ jobs:
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-linux-asserts-v1 key: llvm-source-19-linux-asserts-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@@ -222,7 +222,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-20-linux-asserts-v1 key: llvm-build-19-linux-asserts-v1
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'
@@ -284,7 +284,7 @@ jobs:
needs: build-linux needs: build-linux
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Get TinyGo version - name: Get TinyGo version
id: version id: version
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT" run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
@@ -296,15 +296,15 @@ jobs:
g++-${{ matrix.toolchain }} \ g++-${{ matrix.toolchain }} \
libc6-dev-${{ matrix.libc }}-cross libc6-dev-${{ matrix.libc }}-cross
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-linux-v1 key: llvm-source-19-linux-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@@ -329,7 +329,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-20-linux-${{ matrix.goarch }}-v1 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'
+4 -4
View File
@@ -25,7 +25,7 @@ jobs:
contents: read contents: read
steps: steps:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -35,8 +35,8 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: | images: |
tinygo/llvm-20 tinygo/llvm-19
ghcr.io/${{ github.repository_owner }}/llvm-20 ghcr.io/${{ github.repository_owner }}/llvm-19
tags: | tags: |
type=sha,format=long type=sha,format=long
type=raw,value=latest type=raw,value=latest
@@ -52,7 +52,7 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v5
with: with:
target: tinygo-llvm-build target: tinygo-llvm-build
context: . context: .
+2 -2
View File
@@ -21,7 +21,7 @@ jobs:
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668 # See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
run: sudo apt-get remove llvm-18 run: sudo apt-get remove llvm-18
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Pull musl, bdwgc - name: Pull musl, bdwgc
run: | run: |
git submodule update --init lib/musl lib/bdwgc git submodule update --init lib/musl lib/bdwgc
@@ -29,7 +29,7 @@ jobs:
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-linux-nix-v1 key: llvm-source-19-linux-nix-v1
path: | path: |
llvm-project/compiler-rt llvm-project/compiler-rt
- name: Download LLVM source - name: Download LLVM source
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
run: | run: |
echo "$HOME/go/bin" >> $GITHUB_PATH echo "$HOME/go/bin" >> $GITHUB_PATH
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
fetch-depth: 0 # fetch all history (no sparse checkout) fetch-depth: 0 # fetch all history (no sparse checkout)
submodules: true submodules: true
@@ -30,7 +30,7 @@ jobs:
uses: actions/cache@v4 uses: actions/cache@v4
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-sizediff-v1 key: llvm-source-19-sizediff-v1
path: | path: |
llvm-project/compiler-rt llvm-project/compiler-rt
- name: Download LLVM source - name: Download LLVM source
+14 -14
View File
@@ -31,7 +31,7 @@ jobs:
run: | run: |
scoop install ninja binaryen scoop install ninja binaryen
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Extract TinyGo version - name: Extract TinyGo version
@@ -39,15 +39,15 @@ jobs:
shell: bash shell: bash
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT" run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-20-windows-v1 key: llvm-source-19-windows-v1
path: | path: |
llvm-project/clang/lib/Headers llvm-project/clang/lib/Headers
llvm-project/clang/include llvm-project/clang/include
@@ -72,7 +72,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-20-windows-v2 key: llvm-build-19-windows-v1
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'
@@ -143,11 +143,11 @@ jobs:
run: | run: |
scoop install binaryen scoop install binaryen
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
@@ -173,11 +173,11 @@ jobs:
maximum-size: 24GB maximum-size: 24GB
disk-root: "C:" disk-root: "C:"
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
@@ -209,11 +209,11 @@ jobs:
run: | run: |
scoop install binaryen && scoop install wasmtime@29.0.1 scoop install binaryen && scoop install wasmtime@29.0.1
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v5
with: with:
go-version: '1.25.5' 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
+1 -1
View File
@@ -22,7 +22,7 @@
url = https://github.com/tinygo-org/stm32-svd url = https://github.com/tinygo-org/stm32-svd
[submodule "lib/musl"] [submodule "lib/musl"]
path = lib/musl path = lib/musl
url = https://github.com/tinygo-org/musl-libc.git url = git://git.musl-libc.org/musl
[submodule "lib/binaryen"] [submodule "lib/binaryen"]
path = lib/binaryen path = lib/binaryen
url = https://github.com/WebAssembly/binaryen.git url = https://github.com/WebAssembly/binaryen.git
-141
View File
@@ -1,144 +1,3 @@
0.40.0
---
* **general**
- all: add full LLVM 20 support
- core: feat: enable //go:linkname pragma for globals
- core: feature: Add flag to ignore go compatibility matrix (#5078)
- chore: update version for 0.40 development cycle
* **compiler**
- emit an error when the actual arch doesn't match GOARCH
- mark string parameters as readonly
- use Tarjan's SCC algorithm to detect loops for defer
- lower "large stack" limit to 16kb
* **core**
- shrink bdwgc library
- Fix linker errors for runtime.vgetrandom and crypto/internal/sysrand.fatal
- fix: add TryLock to sync.RWMutex
- fix: correct linter issues exposed by the fix in #4679
- fix: don't hardcode success return state
- fix: expand RTT debugger compatibility
- internal/task (threads): save stack bounds instead of scanning under a lock
- internal/task: create detached threads and fix error handling
- interp: better errors when debugging interp
- transform (gc): create stack slots in callers of external functions
- internal/task: prevent semaphore resource leak for threads scheduler
* **machine**
- cortexm: optimize code size for the HardFault_Handler
- fe310: add I2C pins for the HiFive1b
- clarify WriteAt semantics of BlockDevice
- fix deprecated AsmFull comment (#5005)
- make sure DMA buffers do not escape unnecessarily
- only enable USB-CDC when needed
- use larger SPI MAXCNT on nrf52833 and nrf52840
- fix: update m.queuedBytes when clamping output to avoid corrupting sentBytes
- fix: use int64 in ReadTemperature to avoid overflow
- fix(rp2): disable DBGPAUSE on startup
- fix(rp2): possible integer overflow while computing factors for SPI baudrate
- fix(rp2): reset spinlocks at startup
- fix(rp2): switch spinlock busy loop to wfe
- fix(rp2): use side-effect-free spinlocks
- nrf: add ADC_VDDH which is an ADC pin for VDDH
- nrf: don't block SPI transfer
- nrf: don't set PSELN, it's ignored in single ended mode anyway
- nrf: fix typo in ADC configuration
- nrf: refactor SoftDevice enabled check
- nrf: rename pwmPin to adcPin
- nrf: support flash operations while the SoftDevice is enabled
- rp2040: allow writing to the UART inside interrupts
- machine,nrf528: stop the bus only once on I2C bus error and ensures the first error is returned
* **net**
- update submodule to latest commits
* **runtime**
- (avr): fix infinite longjmp loop if stack is aligned to 256 bytes
- (gc_blocks.go): clear full size of allocation
- (gc_blocks.go): make sweep branchless
- (gc_blocks.go): simplify scanning logic
- (gc_blocks.go): use a linked stack to scan marked objects
- (gc_blocks.go): use best-fit allocation
- (gc_boehm.go): fix world already stopped check
- (wasm): scan the system stack
- fix sleep duration for long sleeps
- remove copied code for nrf52840
- src/syscall: update src buffer after write
- wasm: fix C realloc and optimize it a bit
* **targets**
- add xiao-esp32s3 board target
- Add ESP32-S3 support (#5091)
- Added Gopher ARCADE board
- Create "pico2-ice" target board (#5062)
* **build/test**
- Add testing.T.Context() and testing.B.Context()
- create separate go.mod file for testing dependencies for wasm tests that use Chromium headless browser to avoid use of older incompatible version.
- go back to normal scheduler instead of tasks scheduler for macos CI
- update CI to use Go 1.25.5
- update macOS GH actions builds to handle sunset of macOS 13
- use task scheduler on macOS builds to avoid test race condition lockups
- update all CI builds to use latest stable Go release. Also update some of the actions to their latest releases.
- update GH actions builds to use Go 1.25.4
- uninstall cmake before install
- fix: point the submodule for musl-lib to a mirror in the TinyGo GitHub org
- fix: remove macOS 15 from CI build matrix (conflicts with macOS 14 build)
- fix: separate host expected bytes from device intended bytes
- fix/typo: makeESPFirmwareImage
- make: GNUmakefile: shrink TinyGo binaries on Linux
- move the directory list into a variable
- several improvements to the macOS GH actions build
- Fix for #4678: top-level 'make lint' wasn't working
- fix: increase the timeout for chromedp to connect to the headless browser used for running the wasm tests.
- testdata: some more packages for the test corpus
0.39.0
---
* **general**
- all: add Go 1.25 support
- net: update to latest tinygo net package
- docs: clarify build verification step for macOS users
- Add flag to skip Renesas SVD builds
* **build**
- Makefile: install missing dlmalloc files
- flash: add -o flag support to save built binary (Fixes #4937) (#4942)
- fix: update version of clang to 17 to accommodate latest Go 1.25 docker base image
* **ci**
- chore: update all CI builds to test Go 1.25 release
- fix: disable test-newest since CircleCI seems unable to download due to rate-limits on Dockerhub
- ci: rename some jobs to avoid churn on every Go/LLVM version bump
- ci: make the goroutines test less racy
- tests: de-flake goroutines test
* **compiler**
- compiler: implement internal/abi.Escape
* **main**
- main: show the compiler error (if any) for `tinygo test -c`
- chore: correct GOOS=js name in error messages for WASM
* **machine**
- machine: add international keys
- machine: remove some unnecessary "// peripherals:" comments
- machine: add I2C pin comments
- machine: standardize I2C errors with "i2c:" prefix
- machine: make I2C usable in the simulator
- fix: add SPI and I2C to teensy 4.1 (#4943)
- `rp2`: use the correct channel mask for rp2350 ADC; hold lock during read (#4938)
- `rp2`: disable digital input for analog inputs
* **runtime**
- runtime: ensure time.Sleep(d) sleeps at least d
- runtime: stub out weak pointer support
- runtime: implement dummy AddCleanup
- runtime: enable multi-core scheduler for rp2350
- `internal/task`: use -stack-size flag when starting a new thread
- `internal/task`: add SA_RESTART flag to GC interrupts
- `internal/task`: a few small correctness fixes
- `internal/gclayout`: make gclayout values constants
- darwin: add threading support and use it by default
* **standard library**
- `sync`: implement sync.Swap
- `reflect`: implement Method.IsExported
* **testing**
- testing: stub out testing.B.Loop
* **targets**
- `stm32`: add support for the STM32L031G6U6
- add metro-rp2350 board definition (#4989)
- `rp2040/rp2350`: set the default stack size to 8k for rp2040/rp2350 based boards where this was not already the case
0.38.0 0.38.0
--- ---
* **general** * **general**
+3 -3
View File
@@ -1,8 +1,8 @@
# tinygo-llvm stage obtains the llvm source for TinyGo # tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.25 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-17 ninja-build && \ apt-get install -y apt-utils make cmake clang-15 ninja-build && \
rm -rf \ rm -rf \
/var/lib/apt/lists/* \ /var/lib/apt/lists/* \
/var/log/* \ /var/log/* \
@@ -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.25 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
+12 -49
View File
@@ -79,26 +79,6 @@ ifeq (1, $(STATIC))
BINARYEN_OPTION += -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static" BINARYEN_OPTION += -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static"
endif endif
# Optimize the binary size for Linux.
# These flags may work on other platforms, but have only been tested on Linux.
ifeq ($(uname),Linux)
HAS_MOLD := $(shell command -v ld.mold 2> /dev/null)
HAS_LLD := $(shell command -v ld.lld 2> /dev/null)
LLVM_CFLAGS := -ffunction-sections -fdata-sections -fvisibility=hidden
LLVM_LDFLAGS := -Wl,--gc-sections
ifneq ($(HAS_MOLD),)
# Mold might be slightly faster.
LLVM_LDFLAGS += -fuse-ld=mold -Wl,--icf=all
else ifneq ($(HAS_LLD),)
# LLD is more commonly available.
LLVM_LDFLAGS += -fuse-ld=lld -Wl,--icf=all
endif
LLVM_OPTION += \
-DCMAKE_C_FLAGS="$(LLVM_CFLAGS)" \
-DCMAKE_CXX_FLAGS="$(LLVM_CFLAGS)"
CGO_LDFLAGS += $(LLVM_LDFLAGS)
endif
# Cross compiling support. # Cross compiling support.
ifneq ($(CROSS),) ifneq ($(CROSS),)
CC = $(CROSS)-gcc CC = $(CROSS)-gcc
@@ -263,7 +243,7 @@ gen-device-renesas: build/gen-device-svd
GO111MODULE=off $(GO) fmt ./src/device/renesas GO111MODULE=off $(GO) fmt ./src/device/renesas
$(LLVM_PROJECTDIR)/llvm: $(LLVM_PROJECTDIR)/llvm:
git clone -b tinygo_20.x --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR) git clone -b xtensa_release_19.1.2 --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR)
llvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources llvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources
# Configure LLVM. # Configure LLVM.
@@ -480,16 +460,11 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
TEST_IOFS := false TEST_IOFS := false
endif endif
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic'
TEST_ADDITIONAL_FLAGS ?=
# Test known-working standard library packages. # Test known-working standard library packages.
# TODO: parallelize, and only show failing tests (no implied -v flag). # TODO: parallelize, and only show failing tests (no implied -v flag).
.PHONY: tinygo-test .PHONY: tinygo-test
tinygo-test: tinygo-test:
@# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented. $(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
@# TestParseAndBytesRoundTrip/P256/Generic: relies on t.Skip() which is not implemented
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also @# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
@# requires a large stack-size. Hence, io/fs is only run conditionally. @# requires a large stack-size. Hence, io/fs is only run conditionally.
@# For more details, see the comments on issue #3143. @# For more details, see the comments on issue #3143.
@@ -497,7 +472,7 @@ ifeq ($(TEST_IOFS),true)
$(TINYGO) test -stack-size=6MB io/fs $(TINYGO) test -stack-size=6MB io/fs
endif endif
tinygo-test-fast: tinygo-test-fast:
$(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST) $(TINYGO) test $(TEST_PACKAGES_HOST)
tinygo-bench: tinygo-bench:
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW) $(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
tinygo-bench-fast: tinygo-bench-fast:
@@ -505,18 +480,18 @@ tinygo-bench-fast:
# Same thing, except for wasi rather than the current platform. # Same thing, except for wasi rather than the current platform.
tinygo-test-wasm: tinygo-test-wasm:
$(TINYGO) test -target wasm $(TEST_SKIP_FLAG) $(TEST_PACKAGES_WASM) $(TINYGO) test -target wasm $(TEST_PACKAGES_WASM)
tinygo-test-wasi: tinygo-test-wasi:
$(TINYGO) test -target wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi $(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasip1: tinygo-test-wasip1:
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasip1-fast: tinygo-test-wasip1-fast:
$(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi $(TINYGO) test -target=wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-test-wasip2-slow: tinygo-test-wasip2-slow:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW) $(TINYGO) test -target=wasip2 $(TEST_PACKAGES_SLOW)
tinygo-test-wasip2-fast: tinygo-test-wasip2-fast:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi $(TINYGO) test -target=wasip2 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-test-wasip2-sum-slow: tinygo-test-wasip2-sum-slow:
TINYGO=$(TINYGO) \ TINYGO=$(TINYGO) \
@@ -542,7 +517,7 @@ tinygo-bench-wasip2-fast:
# Run tests on riscv-qemu since that one provides a large amount of memory. # Run tests on riscv-qemu since that one provides a large amount of memory.
tinygo-test-baremetal: tinygo-test-baremetal:
$(TINYGO) test -target riscv-qemu $(TEST_SKIP_FLAG) $(TEST_PACKAGES_BAREMETAL) $(TINYGO) test -target riscv-qemu $(TEST_PACKAGES_BAREMETAL)
# Test external packages in a large corpus. # Test external packages in a large corpus.
test-corpus: test-corpus:
@@ -622,8 +597,6 @@ smoketest: testchdir
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/device-id $(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/device-id
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pico2-ice examples/blinky1
@$(MD5SUM) test.hex
# test simulated boards on play.tinygo.org # test simulated boards on play.tinygo.org
ifneq ($(WASM), 0) ifneq ($(WASM), 0)
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1 GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
@@ -798,8 +771,6 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=gopher-badge examples/blinky1 $(TINYGO) build -size short -o test.hex -target=gopher-badge examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=gopher-arcade examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=ae-rp2040 examples/echo $(TINYGO) build -size short -o test.hex -target=ae-rp2040 examples/echo
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=thumby examples/echo $(TINYGO) build -size short -o test.hex -target=thumby examples/echo
@@ -810,8 +781,6 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=metro-rp2350 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
@@ -915,8 +884,6 @@ ifneq ($(XTENSA), 0)
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest $(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/blinky1
@$(MD5SUM) test.bin
endif endif
$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1 $(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
@@ -978,7 +945,7 @@ endif
wasmtest: wasmtest:
cd ./tests/wasm && $(GO) test . $(GO) test ./tests/wasm
build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binaryen) build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binaryen)
@mkdir -p build/release/tinygo/bin @mkdir -p build/release/tinygo/bin
@@ -1125,7 +1092,6 @@ endif
tools: tools:
cd internal/tools && go generate -tags tools ./ cd internal/tools && go generate -tags tools ./
LINTDIRS=src/os/ src/reflect/
.PHONY: lint .PHONY: lint
lint: tools ## Lint source tree lint: tools ## Lint source tree
revive -version revive -version
@@ -1133,10 +1099,7 @@ lint: tools ## Lint source tree
# revive.toml isn't flexible enough to filter out just one kind of error from a checker, so do it with grep here. # revive.toml isn't flexible enough to filter out just one kind of error from a checker, so do it with grep here.
# Can't use grep with friendly formatter. Plain output isn't too bad, though. # Can't use grep with friendly formatter. Plain output isn't too bad, though.
# Use 'grep .' to get rid of stray blank line # Use 'grep .' to get rid of stray blank line
revive -config revive.toml compiler/... $$( find $(LINTDIRS) -type f -name '*.go' ) \ revive -config revive.toml compiler/... src/{os,reflect}/*.go | grep -v "should have comment or be unexported" | grep '.' | awk '{print}; END {exit NR>0}'
| grep -v "should have comment or be unexported" \
| grep '.' \
| awk '{print}; END {exit NR>0}'
SPELLDIRSCMD=find . -depth 1 -type d | egrep -wv '.git|lib|llvm|src'; find src -depth 1 | egrep -wv 'device|internal|net|vendor'; find src/internal -depth 1 -type d | egrep -wv src/internal/wasi SPELLDIRSCMD=find . -depth 1 -type d | egrep -wv '.git|lib|llvm|src'; find src -depth 1 | egrep -wv 'device|internal|net|vendor'; find src/internal -depth 1 -type d | egrep -wv src/internal/wasi
.PHONY: spell .PHONY: spell
+3 -6
View File
@@ -30,10 +30,7 @@ var BoehmGC = Library{
// Use a minimal environment. // Use a minimal environment.
"-DNO_MSGBOX_ON_ERROR", // don't call MessageBoxA on Windows "-DNO_MSGBOX_ON_ERROR", // don't call MessageBoxA on Windows
"-DDONT_USE_ATEXIT", "-DDONT_USE_ATEXIT",
"-DNO_GETENV", // smaller binary, more predictable configuration "-DNO_GETENV",
"-DNO_CLOCK", // don't use system clock
"-DNO_DEBUGGING", // reduce code size
"-DGC_NO_FINALIZATION", // finalization is not used at the moment
// Special flag to work around the lack of __data_start in ld.lld. // Special flag to work around the lack of __data_start in ld.lld.
// TODO: try to fix this in LLVM/lld directly so we don't have to // TODO: try to fix this in LLVM/lld directly so we don't have to
@@ -42,8 +39,6 @@ var BoehmGC = Library{
// Do not scan the stack. We have our own mechanism to do this. // Do not scan the stack. We have our own mechanism to do this.
"-DSTACK_NOT_SCANNED", "-DSTACK_NOT_SCANNED",
"-DNO_PROC_STAT", // we scan the stack manually (don't read /proc/self/stat on Linux)
"-DSTACKBOTTOM=0", // dummy value, we scan the stack manually
// Assertions can be enabled while debugging GC issues. // Assertions can be enabled while debugging GC issues.
//"-DGC_ASSERTIONS", //"-DGC_ASSERTIONS",
@@ -68,6 +63,7 @@ var BoehmGC = Library{
"blacklst.c", "blacklst.c",
"dbg_mlc.c", "dbg_mlc.c",
"dyn_load.c", "dyn_load.c",
"finalize.c",
"headers.c", "headers.c",
"mach_dep.c", "mach_dep.c",
"malloc.c", "malloc.c",
@@ -75,6 +71,7 @@ var BoehmGC = Library{
"mark_rts.c", "mark_rts.c",
"misc.c", "misc.c",
"new_hblk.c", "new_hblk.c",
"obj_map.c",
"os_dep.c", "os_dep.c",
"reclaim.c", "reclaim.c",
} }
+2 -2
View File
@@ -1042,11 +1042,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
if err != nil { if err != nil {
return result, err return result, err
} }
case "esp32", "esp32-img", "esp32c3", "esp32s3", "esp8266": case "esp32", "esp32-img", "esp32c3", "esp8266":
// Special format for the ESP family of chips (parsed by the ROM // Special format for the ESP family of chips (parsed by the ROM
// bootloader). // bootloader).
result.Binary = filepath.Join(tmpdir, "main"+outext) result.Binary = filepath.Join(tmpdir, "main"+outext)
err := makeESPFirmwareImage(result.Executable, result.Binary, outputBinaryFormat) err := makeESPFirmareImage(result.Executable, result.Binary, outputBinaryFormat)
if err != nil { if err != nil {
return result, err return result, err
} }
-1
View File
@@ -28,7 +28,6 @@ func TestClangAttributes(t *testing.T) {
"cortex-m4", "cortex-m4",
"cortex-m7", "cortex-m7",
"esp32c3", "esp32c3",
"esp32s3",
"fe310", "fe310",
"gameboy-advance", "gameboy-advance",
"k210", "k210",
+8 -13
View File
@@ -144,6 +144,8 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
.Default(llvm::DebugCompressionType::None); .Default(llvm::DebugCompressionType::None);
} }
Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
Opts.SSE2AVX = Args.hasArg(OPT_msse2avx);
if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32)) if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))
Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64); Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
@@ -234,9 +236,6 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical =
Args.hasArg(OPT_femit_compact_unwind_non_canonical); Args.hasArg(OPT_femit_compact_unwind_non_canonical);
Opts.Crel = Args.hasArg(OPT_crel); Opts.Crel = Args.hasArg(OPT_crel);
Opts.ImplicitMapsyms = Args.hasArg(OPT_mmapsyms_implicit);
Opts.X86RelaxRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
Opts.X86Sse2Avx = Args.hasArg(OPT_msse2avx);
Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file); Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
@@ -295,9 +294,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels; MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;
MCOptions.Crel = Opts.Crel; MCOptions.Crel = Opts.Crel;
MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms; MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;
MCOptions.X86RelaxRelocations = Opts.X86RelaxRelocations; MCOptions.X86Sse2Avx = Opts.SSE2AVX;
MCOptions.X86Sse2Avx = Opts.X86Sse2Avx;
MCOptions.CompressDebugSections = Opts.CompressDebugSections; MCOptions.CompressDebugSections = Opts.CompressDebugSections;
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
@@ -345,6 +343,10 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
// MCObjectFileInfo needs a MCContext reference in order to initialize itself. // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
std::unique_ptr<MCObjectFileInfo> MOFI( std::unique_ptr<MCObjectFileInfo> MOFI(
TheTarget->createMCObjectFileInfo(Ctx, PIC)); TheTarget->createMCObjectFileInfo(Ctx, PIC));
if (Opts.DarwinTargetVariantTriple)
MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
if (!Opts.DarwinTargetVariantSDKVersion.empty())
MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);
Ctx.setObjectFileInfo(MOFI.get()); Ctx.setObjectFileInfo(MOFI.get());
if (Opts.GenDwarfForAssembly) if (Opts.GenDwarfForAssembly)
@@ -426,13 +428,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
Str.reset(TheTarget->createMCObjectStreamer( Str.reset(TheTarget->createMCObjectStreamer(
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI)); T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));
Str.get()->initSections(Opts.NoExecStack, *STI); Str.get()->initSections(Opts.NoExecStack, *STI);
if (T.isOSBinFormatMachO() && T.isOSDarwin()) {
Triple *TVT = Opts.DarwinTargetVariantTriple
? &*Opts.DarwinTargetVariantTriple
: nullptr;
Str->emitVersionForTarget(T, VersionTuple(), TVT,
Opts.DarwinTargetVariantSDKVersion);
}
} }
// When -fembed-bitcode is passed to clang_as, a 1-byte marker // When -fembed-bitcode is passed to clang_as, a 1-byte marker
+5 -10
View File
@@ -45,6 +45,10 @@ struct AssemblerInvocation {
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned GenDwarfForAssembly : 1; unsigned GenDwarfForAssembly : 1;
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned RelaxELFRelocations : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SSE2AVX : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned Dwarf64 : 1; unsigned Dwarf64 : 1;
unsigned DwarfVersion; unsigned DwarfVersion;
std::string DwarfDebugFlags; std::string DwarfDebugFlags;
@@ -113,13 +117,6 @@ struct AssemblerInvocation {
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned Crel : 1; unsigned Crel : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned ImplicitMapsyms : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned X86RelaxRelocations : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned X86Sse2Avx : 1;
/// The name of the relocation model to use. /// The name of the relocation model to use.
std::string RelocationModel; std::string RelocationModel;
@@ -151,6 +148,7 @@ public:
ShowInst = 0; ShowInst = 0;
ShowEncoding = 0; ShowEncoding = 0;
RelaxAll = 0; RelaxAll = 0;
SSE2AVX = 0;
NoExecStack = 0; NoExecStack = 0;
FatalWarnings = 0; FatalWarnings = 0;
NoWarn = 0; NoWarn = 0;
@@ -162,9 +160,6 @@ public:
EmitDwarfUnwind = EmitDwarfUnwindType::Default; EmitDwarfUnwind = EmitDwarfUnwindType::Default;
EmitCompactUnwindNonCanonical = false; EmitCompactUnwindNonCanonical = false;
Crel = false; Crel = false;
ImplicitMapsyms = 0;
X86RelaxRelocations = 0;
X86Sse2Avx = 0;
} }
static bool CreateFromArgs(AssemblerInvocation &Res, static bool CreateFromArgs(AssemblerInvocation &Res,
+1 -1
View File
@@ -60,7 +60,7 @@ bool tinygo_clang_driver(int argc, char **argv) {
} }
// Create the actual diagnostics engine. // Create the actual diagnostics engine.
Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); Clang->createDiagnostics();
if (!Clang->hasDiagnostics()) { if (!Clang->hasDiagnostics()) {
return false; return false;
} }
+5 -8
View File
@@ -26,20 +26,17 @@ 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 = 25 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()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
if options.GoCompatibility { // Note: when this gets updated, also update the Go compatibility matrix:
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax { // https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
// Note: when this gets updated, also update the Go compatibility matrix: return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor)
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
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
+3 -4
View File
@@ -23,7 +23,7 @@ type espImageSegment struct {
data []byte data []byte
} }
// makeESPFirmwareImage converts an input ELF file to an image file for an ESP32 or // makeESPFirmareImage converts an input ELF file to an image file for an ESP32 or
// ESP8266 chip. This is a special purpose image format just for the ESP chip // ESP8266 chip. This is a special purpose image format just for the ESP chip
// family, and is parsed by the on-chip mask ROM bootloader. // family, and is parsed by the on-chip mask ROM bootloader.
// //
@@ -31,7 +31,7 @@ type espImageSegment struct {
// https://github.com/espressif/esptool/wiki/Firmware-Image-Format // https://github.com/espressif/esptool/wiki/Firmware-Image-Format
// https://github.com/espressif/esp-idf/blob/8fbb63c2a701c22ccf4ce249f43aded73e134a34/components/bootloader_support/include/esp_image_format.h#L58 // https://github.com/espressif/esp-idf/blob/8fbb63c2a701c22ccf4ce249f43aded73e134a34/components/bootloader_support/include/esp_image_format.h#L58
// https://github.com/espressif/esptool/blob/master/esptool.py // https://github.com/espressif/esptool/blob/master/esptool.py
func makeESPFirmwareImage(infile, outfile, format string) error { func makeESPFirmareImage(infile, outfile, format string) error {
inf, err := elf.Open(infile) inf, err := elf.Open(infile)
if err != nil { if err != nil {
return err return err
@@ -100,12 +100,11 @@ func makeESPFirmwareImage(infile, outfile, format string) error {
chip_id := map[string]uint16{ chip_id := map[string]uint16{
"esp32": 0x0000, "esp32": 0x0000,
"esp32c3": 0x0005, "esp32c3": 0x0005,
"esp32s3": 0x0009,
}[chip] }[chip]
// Image header. // Image header.
switch chip { switch chip {
case "esp32", "esp32c3", "esp32s3": case "esp32", "esp32c3":
// Header format: // Header format:
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71 // https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
// Note: not adding a SHA256 hash as the binary is modified by // Note: not adding a SHA256 hash as the binary is modified by
+3 -3
View File
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test. // This is a small number of very diverse targets that we want to test.
tests := []sizeTest{ tests := []sizeTest{
// microcontrollers // microcontrollers
{"hifive1b", "examples/echo", 3668, 280, 0, 2244}, {"hifive1b", "examples/echo", 4556, 280, 0, 2264},
{"microbit", "examples/serial", 2694, 342, 8, 2248}, {"microbit", "examples/serial", 2920, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7187, 1489, 116, 6888}, {"wioterminal", "examples/pininterrupt", 7379, 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
+1 -1
View File
@@ -226,7 +226,7 @@ func (c *Config) StackSize() uint64 {
// MaxStackAlloc returns the size of the maximum allocation to put on the stack vs heap. // MaxStackAlloc returns the size of the maximum allocation to put on the stack vs heap.
func (c *Config) MaxStackAlloc() uint64 { func (c *Config) MaxStackAlloc() uint64 {
if c.StackSize() >= 16*1024 { if c.StackSize() > 32*1024 {
return 1024 return 1024
} }
-1
View File
@@ -59,7 +59,6 @@ type Options struct {
WITPackage string // pass through to wasm-tools component embed invocation WITPackage string // pass through to wasm-tools component embed invocation
WITWorld string // pass through to wasm-tools component embed -w option WITWorld string // pass through to wasm-tools component embed -w option
ExtLDFlags []string ExtLDFlags []string
GoCompatibility bool // enable to check for Go version compatibility
} }
// Verify performs a validation on the given options, raising an error if options are not valid. // Verify performs a validation on the given options, raising an error if options are not valid.
+1 -1
View File
@@ -245,7 +245,7 @@ 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.currentBlockInfo.exit = nextBlock // adjust outgoing block for phi nodes 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)
-8
View File
@@ -32,9 +32,6 @@ const (
// Whether this is a full or partial Go parameter (int, slice, etc). // Whether this is a full or partial Go parameter (int, slice, etc).
// The extra context parameter is not a Go parameter. // The extra context parameter is not a Go parameter.
paramIsGoParam = 1 << iota paramIsGoParam = 1 << iota
// Whether this is a readonly parameter (for example, a string pointer).
paramIsReadonly
) )
// createRuntimeCallCommon creates a runtime call. Use createRuntimeCall or // createRuntimeCallCommon creates a runtime call. Use createRuntimeCall or
@@ -170,7 +167,6 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
continue continue
} }
suffix := strconv.Itoa(i) suffix := strconv.Itoa(i)
isString := false
if goType != nil { if goType != nil {
// Try to come up with a good suffix for this struct field, // Try to come up with a good suffix for this struct field,
// depending on which Go type it's based on. // depending on which Go type it's based on.
@@ -187,16 +183,12 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
suffix = []string{"r", "i"}[i] suffix = []string{"r", "i"}[i]
case types.String: case types.String:
suffix = []string{"data", "len"}[i] suffix = []string{"data", "len"}[i]
isString = true
} }
case *types.Signature: case *types.Signature:
suffix = []string{"context", "funcptr"}[i] suffix = []string{"context", "funcptr"}[i]
} }
} }
subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i)) subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
if isString {
subInfos[0].flags |= paramIsReadonly
}
paramInfos = append(paramInfos, subInfos...) paramInfos = append(paramInfos, subInfos...)
} }
return paramInfos return paramInfos
+13 -42
View File
@@ -152,12 +152,10 @@ type builder struct {
llvmFnType llvm.Type llvmFnType llvm.Type
llvmFn llvm.Value llvmFn llvm.Value
info functionInfo info functionInfo
locals map[ssa.Value]llvm.Value // local variables locals map[ssa.Value]llvm.Value // local variables
blockInfo []blockInfo blockEntries map[*ssa.BasicBlock]llvm.BasicBlock // a *ssa.BasicBlock may be split up
blockExits map[*ssa.BasicBlock]llvm.BasicBlock // these are the exit blocks
currentBlock *ssa.BasicBlock currentBlock *ssa.BasicBlock
currentBlockInfo *blockInfo
tarjanStack []uint
tarjanIndex uint
phis []phiNode phis []phiNode
deferPtr llvm.Value deferPtr llvm.Value
deferFrame llvm.Value deferFrame llvm.Value
@@ -189,22 +187,11 @@ func newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *bu
info: c.getFunctionInfo(f), info: c.getFunctionInfo(f),
locals: make(map[ssa.Value]llvm.Value), locals: make(map[ssa.Value]llvm.Value),
dilocals: make(map[*types.Var]llvm.Metadata), dilocals: make(map[*types.Var]llvm.Metadata),
blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock),
blockExits: make(map[*ssa.BasicBlock]llvm.BasicBlock),
} }
} }
type blockInfo struct {
// entry is the LLVM basic block corresponding to the start of this *ssa.Block.
entry llvm.BasicBlock
// exit is the LLVM basic block corresponding to the end of this *ssa.Block.
// It will be different than entry if any of the block's instructions contain internal branches.
exit llvm.BasicBlock
// tarjan holds state for applying Tarjan's strongly connected components algorithm to the CFG.
// This is used by defer.go to determine whether to stack- or heap-allocate defer data.
tarjan tarjanNode
}
type deferBuiltin struct { type deferBuiltin struct {
callName string callName string
pos token.Pos pos token.Pos
@@ -1233,29 +1220,14 @@ func (b *builder) createFunctionStart(intrinsic bool) {
// intrinsic (like an atomic operation). Create the entry block // intrinsic (like an atomic operation). Create the entry block
// manually. // manually.
entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry") entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry")
// Intrinsics may create internal branches (e.g. nil checks).
// They will attempt to access b.currentBlockInfo to update the exit block.
// Create some fake block info for them to access.
blockInfo := []blockInfo{
{
entry: entryBlock,
exit: entryBlock,
},
}
b.blockInfo = blockInfo
b.currentBlockInfo = &blockInfo[0]
} else { } else {
blocks := b.fn.Blocks
blockInfo := make([]blockInfo, len(blocks))
for _, block := range b.fn.DomPreorder() { for _, block := range b.fn.DomPreorder() {
info := &blockInfo[block.Index]
llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment) llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
info.entry = llvmBlock b.blockEntries[block] = llvmBlock
info.exit = llvmBlock b.blockExits[block] = llvmBlock
} }
b.blockInfo = blockInfo
// Normal functions have an entry block. // Normal functions have an entry block.
entryBlock = blockInfo[0].entry entryBlock = b.blockEntries[b.fn.Blocks[0]]
} }
b.SetInsertPointAtEnd(entryBlock) b.SetInsertPointAtEnd(entryBlock)
@@ -1351,9 +1323,8 @@ func (b *builder) createFunction() {
if b.DumpSSA { if b.DumpSSA {
fmt.Printf("%d: %s:\n", block.Index, block.Comment) fmt.Printf("%d: %s:\n", block.Index, block.Comment)
} }
b.SetInsertPointAtEnd(b.blockEntries[block])
b.currentBlock = block b.currentBlock = block
b.currentBlockInfo = &b.blockInfo[block.Index]
b.SetInsertPointAtEnd(b.currentBlockInfo.entry)
for _, instr := range block.Instrs { for _, instr := range block.Instrs {
if instr, ok := instr.(*ssa.DebugRef); ok { if instr, ok := instr.(*ssa.DebugRef); ok {
if !b.Debug { if !b.Debug {
@@ -1413,7 +1384,7 @@ func (b *builder) createFunction() {
block := phi.ssa.Block() block := phi.ssa.Block()
for i, edge := range phi.ssa.Edges { for i, edge := range phi.ssa.Edges {
llvmVal := b.getValue(edge, getPos(phi.ssa)) llvmVal := b.getValue(edge, getPos(phi.ssa))
llvmBlock := b.blockInfo[block.Preds[i].Index].exit llvmBlock := b.blockExits[block.Preds[i]]
phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock}) phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})
} }
} }
@@ -1527,11 +1498,11 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
case *ssa.If: case *ssa.If:
cond := b.getValue(instr.Cond, getPos(instr)) cond := b.getValue(instr.Cond, getPos(instr))
block := instr.Block() block := instr.Block()
blockThen := b.blockInfo[block.Succs[0].Index].entry blockThen := b.blockEntries[block.Succs[0]]
blockElse := b.blockInfo[block.Succs[1].Index].entry blockElse := b.blockEntries[block.Succs[1]]
b.CreateCondBr(cond, blockThen, blockElse) b.CreateCondBr(cond, blockThen, blockElse)
case *ssa.Jump: case *ssa.Jump:
blockJump := b.blockInfo[instr.Block().Succs[0].Index].entry blockJump := b.blockEntries[instr.Block().Succs[0]]
b.CreateBr(blockJump) b.CreateBr(blockJump)
case *ssa.MapUpdate: case *ssa.MapUpdate:
m := b.getValue(instr.Map, getPos(instr)) m := b.getValue(instr.Map, getPos(instr))
+29 -99
View File
@@ -100,7 +100,7 @@ func (b *builder) createLandingPad() {
// Continue at the 'recover' block, which returns to the parent in an // Continue at the 'recover' block, which returns to the parent in an
// appropriate way. // appropriate way.
b.CreateBr(b.blockInfo[b.fn.Recover.Index].entry) b.CreateBr(b.blockEntries[b.fn.Recover])
} }
// Create a checkpoint (similar to setjmp). This emits inline assembly that // Create a checkpoint (similar to setjmp). This emits inline assembly that
@@ -234,108 +234,41 @@ func (b *builder) createInvokeCheckpoint() {
continueBB := b.insertBasicBlock("") continueBB := b.insertBasicBlock("")
b.CreateCondBr(isZero, continueBB, b.landingpad) b.CreateCondBr(isZero, continueBB, b.landingpad)
b.SetInsertPointAtEnd(continueBB) b.SetInsertPointAtEnd(continueBB)
b.currentBlockInfo.exit = continueBB b.blockExits[b.currentBlock] = continueBB
} }
// isInLoop checks if there is a path from the current block to itself. // isInLoop checks if there is a path from a basic block to itself.
// Use Tarjan's strongly connected components algorithm to search for cycles. func isInLoop(start *ssa.BasicBlock) bool {
// A one-node SCC is a cycle iff there is an edge from the node to itself. // Use a breadth-first search to scan backwards through the block graph.
// A multi-node SCC is always a cycle. queue := []*ssa.BasicBlock{start}
// https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm checked := map[*ssa.BasicBlock]struct{}{}
func (b *builder) isInLoop() bool {
if b.currentBlockInfo.tarjan.lowLink == 0 {
b.strongConnect(b.currentBlock)
}
return b.currentBlockInfo.tarjan.cyclic
}
func (b *builder) strongConnect(block *ssa.BasicBlock) { for len(queue) > 0 {
// Assign a new index. // pop a block off of the queue
// Indices start from 1 so that 0 can be used as a sentinel. block := queue[len(queue)-1]
assignedIndex := b.tarjanIndex + 1 queue = queue[:len(queue)-1]
b.tarjanIndex = assignedIndex
// Apply the new index. // Search through predecessors.
blockIndex := block.Index // Searching backwards means that this is pretty fast when the block is close to the start of the function.
node := &b.blockInfo[blockIndex].tarjan // Defers are often placed near the start of the function.
node.lowLink = assignedIndex for _, pred := range block.Preds {
if pred == start {
// Push the node onto the stack. // cycle found
node.onStack = true return true
b.tarjanStack = append(b.tarjanStack, uint(blockIndex))
// Process the successors.
for _, successor := range block.Succs {
// Look up the successor's state.
successorIndex := successor.Index
if successorIndex == blockIndex {
// Handle a self-cycle specially.
node.cyclic = true
continue
}
successorNode := &b.blockInfo[successorIndex].tarjan
switch {
case successorNode.lowLink == 0:
// This node has not yet been visisted.
b.strongConnect(successor)
case !successorNode.onStack:
// This node has been visited, but is in a different SCC.
// Ignore it, and do not update lowLink.
continue
}
// Update the lowLink index.
// This always uses the min-of-lowlink instead of using index in the on-stack case.
// This is done for two reasons:
// 1. The lowLink update can be shared between the new-node and on-stack cases.
// 2. The assigned index does not need to be saved - it is only needed for root node detection.
if successorNode.lowLink < node.lowLink {
node.lowLink = successorNode.lowLink
}
}
if node.lowLink == assignedIndex {
// This is a root node.
// Pop the SCC off the stack.
stack := b.tarjanStack
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
blocks := b.blockInfo
topNode := &blocks[top].tarjan
topNode.onStack = false
if top != uint(blockIndex) {
// The root node is not the only node in the SCC.
// Mark all nodes in this SCC as cyclic.
topNode.cyclic = true
for top != uint(blockIndex) {
top = stack[len(stack)-1]
stack = stack[:len(stack)-1]
topNode = &blocks[top].tarjan
topNode.onStack = false
topNode.cyclic = true
} }
if _, ok := checked[pred]; ok {
// block already checked
continue
}
// add to queue and checked map
queue = append(queue, pred)
checked[pred] = struct{}{}
} }
b.tarjanStack = stack
} }
}
// tarjanNode holds per-block state for isInLoop and strongConnect. return false
type tarjanNode struct {
// lowLink is the index of the first visited node that is reachable from this block.
// The lowLink indices are assigned by the SCC search, and do not correspond to b.Index.
// A lowLink of 0 is used as a sentinel to mark a node which has not yet been visited.
lowLink uint
// onStack tracks whether this node is currently on the SCC search stack.
onStack bool
// cyclic indicates whether this block is in a loop.
// If lowLink is 0, strongConnect must be called before reading this field.
cyclic bool
} }
// createDefer emits a single defer instruction, to be run when this function // createDefer emits a single defer instruction, to be run when this function
@@ -477,10 +410,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// Put this struct in an allocation. // Put this struct in an allocation.
var alloca llvm.Value var alloca llvm.Value
if instr.Block() != b.currentBlock { if !isInLoop(instr.Block()) {
panic("block mismatch")
}
if !b.isInLoop() {
// This can safely use a stack allocation. // This can safely use a stack allocation.
alloca = llvmutil.CreateEntryBlockAlloca(b.Builder, deferredCallType, "defer.alloca") alloca = llvmutil.CreateEntryBlockAlloca(b.Builder, deferredCallType, "defer.alloca")
} else { } else {
+3 -3
View File
@@ -38,10 +38,10 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
// provided immediately. For example: // provided immediately. For example:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, [{result}]", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1, // "value": 1
// "result": uintptr(unsafe.Pointer(&dest)), // "result": &dest,
// }) // })
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) { func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value) asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
+1 -1
View File
@@ -737,7 +737,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
prevBlock := b.GetInsertBlock() prevBlock := b.GetInsertBlock()
okBlock := b.insertBasicBlock("typeassert.ok") okBlock := b.insertBasicBlock("typeassert.ok")
nextBlock := b.insertBasicBlock("typeassert.next") nextBlock := b.insertBasicBlock("typeassert.next")
b.currentBlockInfo.exit = nextBlock // adjust outgoing block for phi nodes b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
b.CreateCondBr(commaOk, okBlock, nextBlock) b.CreateCondBr(commaOk, okBlock, nextBlock)
// Retrieve the value from the interface if the type assert was // Retrieve the value from the interface if the type assert was
-39
View File
@@ -27,8 +27,6 @@ func (b *builder) defineIntrinsicFunction() {
b.createStackSaveImpl() b.createStackSaveImpl()
case name == "runtime.KeepAlive": case name == "runtime.KeepAlive":
b.createKeepAliveImpl() b.createKeepAliveImpl()
case name == "machine.keepAliveNoEscape":
b.createMachineKeepAliveImpl()
case strings.HasPrefix(name, "runtime/volatile.Load"): case strings.HasPrefix(name, "runtime/volatile.Load"):
b.createVolatileLoad() b.createVolatileLoad()
case strings.HasPrefix(name, "runtime/volatile.Store"): case strings.HasPrefix(name, "runtime/volatile.Store"):
@@ -123,43 +121,6 @@ func (b *builder) createKeepAliveImpl() {
b.CreateRetVoid() b.CreateRetVoid()
} }
// createAbiEscapeImpl implements the generic internal/abi.Escape function. It
// currently only supports pointer types.
func (b *builder) createAbiEscapeImpl() {
b.createFunctionStart(true)
// The first parameter is assumed to be a pointer. This is checked at the
// call site of createAbiEscapeImpl.
pointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))
// Create an equivalent of the following C code, which is basically just a
// nop but ensures the pointerValue is kept alive:
//
// __asm__ __volatile__("" : : "r"(pointerValue))
//
// It should be portable to basically everything as the "r" register type
// exists basically everywhere.
asmType := llvm.FunctionType(b.dataPtrType, []llvm.Type{b.dataPtrType}, false)
asmFn := llvm.InlineAsm(asmType, "", "=r,0", true, false, 0, false)
result := b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, "")
b.CreateRet(result)
}
// Implement machine.keepAliveNoEscape, which makes sure the compiler keeps the
// pointer parameter alive until this point (for GC).
func (b *builder) createMachineKeepAliveImpl() {
b.createFunctionStart(true)
pointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))
// See createKeepAliveImpl for details.
asmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType}, false)
asmFn := llvm.InlineAsm(asmType, "", "r", true, false, 0, false)
b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, "")
b.CreateRetVoid()
}
var mathToLLVMMapping = map[string]string{ var mathToLLVMMapping = map[string]string{
"math.Ceil": "llvm.ceil.f64", "math.Ceil": "llvm.ceil.f64",
"math.Exp": "llvm.exp.f64", "math.Exp": "llvm.exp.f64",
+1 -1
View File
@@ -218,7 +218,7 @@ func Version() int {
return major return major
} }
// ByteOrder returns the byte order for the given target triple. Most targets are little // Return the byte order for the given target triple. Most targets are little
// endian, but for example MIPS can be big-endian. // endian, but for example MIPS can be big-endian.
func ByteOrder(target string) binary.ByteOrder { func ByteOrder(target string) binary.ByteOrder {
if strings.HasPrefix(target, "mips-") { if strings.HasPrefix(target, "mips-") {
-3
View File
@@ -250,9 +250,6 @@ func (b *builder) createMapIteratorNext(rangeVal ssa.Value, llvmRangeVal, it llv
func hashmapIsBinaryKey(keyType types.Type) bool { func hashmapIsBinaryKey(keyType types.Type) bool {
switch keyType := keyType.Underlying().(type) { switch keyType := keyType.Underlying().(type) {
case *types.Basic: case *types.Basic:
// TODO: unsafe.Pointer is also a binary key, but to support that we
// need to fix an issue with interp first (see
// https://github.com/tinygo-org/tinygo/pull/4898).
return keyType.Info()&(types.IsBoolean|types.IsInteger) != 0 return keyType.Info()&(types.IsBoolean|types.IsInteger) != 0
case *types.Pointer: case *types.Pointer:
return true return true
+4 -39
View File
@@ -142,11 +142,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
nocapture := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0) nocapture := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)
llvmFn.AddAttributeAtIndex(i+1, nocapture) llvmFn.AddAttributeAtIndex(i+1, nocapture)
} }
if paramInfo.flags&paramIsReadonly != 0 && paramInfo.llvmType.TypeKind() == llvm.PointerTypeKind {
// Readonly pointer parameters (like strings) benefit from being marked as readonly.
readonly := c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)
llvmFn.AddAttributeAtIndex(i+1, readonly)
}
} }
// Set a number of function or parameter attributes, depending on the // Set a number of function or parameter attributes, depending on the
@@ -159,8 +154,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("noreturn"), 0)) llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("noreturn"), 0))
case "internal/abi.NoEscape": case "internal/abi.NoEscape":
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
case "machine.keepAliveNoEscape", "machine.unsafeNoEscape":
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
case "runtime.alloc": case "runtime.alloc":
// Tell the optimizer that runtime.alloc is an allocator, meaning that it // Tell the optimizer that runtime.alloc is an allocator, meaning that it
// returns values that are never null and never alias to an existing value. // returns values that are never null and never alias to an existing value.
@@ -260,23 +253,6 @@ func (c *compilerContext) maybeCreateSyntheticFunction(fn *ssa.Function, llvmFn
// The exception is the package initializer, which does appear in the // The exception is the package initializer, which does appear in the
// *ssa.Package members and so shouldn't be created here. // *ssa.Package members and so shouldn't be created here.
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" { if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" {
if origin := fn.Origin(); origin != nil && origin.RelString(nil) == "internal/abi.Escape" {
// This is a special implementation or internal/abi.Escape, which
// can only really be implemented in the compiler.
// For simplicity we'll only implement pointer parameters for now.
if _, ok := fn.Params[0].Type().Underlying().(*types.Pointer); ok {
irbuilder := c.ctx.NewBuilder()
defer irbuilder.Dispose()
b := newBuilder(c, irbuilder, fn)
b.createAbiEscapeImpl()
llvmFn.SetLinkage(llvm.LinkOnceODRLinkage)
llvmFn.SetUnnamedAddr(true)
}
// If the parameter is not of a pointer type, it will be left
// unimplemented. This will result in a linker error if the function
// is really called, making it clear it needs to be implemented.
return
}
if len(fn.Blocks) == 0 { if len(fn.Blocks) == 0 {
c.addError(fn.Pos(), "missing function body") c.addError(fn.Pos(), "missing function body")
return return
@@ -637,7 +613,7 @@ func (c *compilerContext) addStandardAttributes(llvmFn llvm.Value) {
// linkName is equal to .RelString(nil) on a global and extern is false, but for // linkName is equal to .RelString(nil) on a global and extern is false, but for
// some symbols this is different (due to //go:extern for example). // some symbols this is different (due to //go:extern for example).
type globalInfo struct { type globalInfo struct {
linkName string // go:extern, go:linkname linkName string // go:extern
extern bool // go:extern extern bool // go:extern
align int // go:align align int // go:align
section string // go:section section string // go:section
@@ -722,14 +698,14 @@ 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, c, g) info.parsePragmas(doc)
} }
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 and //go:linkname pragmas on globals. // //go:extern pragma on globals.
func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext, g *ssa.Global) { func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) {
for _, comment := range doc.List { for _, comment := range doc.List {
if !strings.HasPrefix(comment.Text, "//go:") { if !strings.HasPrefix(comment.Text, "//go:") {
continue continue
@@ -750,17 +726,6 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext,
if len(parts) == 2 { if len(parts) == 2 {
info.section = parts[1] info.section = parts[1]
} }
case "//go:linkname":
if len(parts) != 3 || parts[1] != g.Name() {
continue
}
// Only enable go:linkname when the package imports "unsafe".
// This is a slightly looser requirement than what gc uses: gc
// requires the file to import "unsafe", not the package as a
// whole.
if hasUnsafeImport(g.Pkg.Pkg) {
info.linkName = parts[2]
}
} }
} }
} }
-8
View File
@@ -74,14 +74,6 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
return b.CreateCall(fnType, target, args, ""), nil return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "arm" && b.GOOS == "linux": case b.GOARCH == "arm" && b.GOOS == "linux":
if arch := b.archFamily(); arch != "arm" {
// Some targets pretend to be linux/arm for compatibility but aren't
// actually such a system. Make sure we emit an error instead of
// creating inline assembly that will fail to compile.
// See: https://github.com/tinygo-org/tinygo/issues/4959
return llvm.Value{}, b.makeError(call.Pos(), "system calls are not supported: target emulates a linux/arm system on "+arch)
}
// Implement the EABI system call convention for Linux. // Implement the EABI system call convention for Linux.
// Source: syscall(2) man page. // Source: syscall(2) man page.
args := []llvm.Value{} args := []llvm.Value{}
+4 -4
View File
@@ -1,6 +1,6 @@
; ModuleID = 'basic.go' ; ModuleID = 'basic.go'
source_filename = "basic.go" source_filename = "basic.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
%main.kv = type { float, i32, i32, i32 } %main.kv = type { float, i32, i32, i32 }
@@ -206,7 +206,7 @@ entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+7 -7
View File
@@ -1,6 +1,6 @@
; ModuleID = 'channel.go' ; ModuleID = 'channel.go'
source_filename = "channel.go" source_filename = "channel.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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.channelOp = type { ptr, ptr, i32, ptr } %runtime.channelOp = type { ptr, ptr, i32, ptr }
@@ -82,11 +82,11 @@ entry:
store i32 1, ptr %select.send.value, align 4 store i32 1, ptr %select.send.value, align 4
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
store ptr %ch1, ptr %select.states.alloca, align 4 store ptr %ch1, ptr %select.states.alloca, align 4
%select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4 %select.states.alloca.repack1 = getelementptr inbounds i8, ptr %select.states.alloca, i32 4
store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4 store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
%0 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 8 %0 = getelementptr inbounds i8, ptr %select.states.alloca, i32 8
store ptr %ch2, ptr %0, align 4 store ptr %ch2, ptr %0, align 4
%.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12 %.repack3 = getelementptr inbounds i8, ptr %select.states.alloca, i32 12
store ptr null, ptr %.repack3, align 4 store ptr null, ptr %.repack3, align 4
%select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #4 %select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #4
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
@@ -107,8 +107,8 @@ select.body: ; preds = %select.next
declare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32, i32, ptr, i32, i32, ptr) #1 declare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32, i32, ptr, i32, i32, ptr) #1
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nounwind } attributes #4 = { nounwind }
+7 -242
View File
@@ -27,7 +27,7 @@ entry:
%0 = call ptr @llvm.stacksave.p0() %0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4 call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
store i32 0, ptr %defer.alloca, align 4 store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack15 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4 %defer.alloca.repack15 = getelementptr inbounds i8, ptr %defer.alloca, i32 4
store ptr null, ptr %defer.alloca.repack15, align 4 store ptr null, ptr %defer.alloca.repack15, align 4
store ptr %defer.alloca, ptr %deferPtr, align 4 store ptr %defer.alloca, ptr %deferPtr, align 4
%setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #5 %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #5
@@ -51,7 +51,7 @@ rundefers.loophead: ; preds = %3, %rundefers.block
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds nuw i8, ptr %2, i32 4 %stack.next.gep = getelementptr inbounds i8, ptr %2, i32 4
%stack.next = load ptr, ptr %stack.next.gep, align 4 %stack.next = load ptr, ptr %stack.next.gep, align 4
store ptr %stack.next, ptr %deferPtr, align 4 store ptr %stack.next, ptr %deferPtr, align 4
%callback = load i32, ptr %2, align 4 %callback = load i32, ptr %2, align 4
@@ -87,7 +87,7 @@ rundefers.loophead6: ; preds = %5, %lpad
br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5 br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5
rundefers.loop5: ; preds = %rundefers.loophead6 rundefers.loop5: ; preds = %rundefers.loophead6
%stack.next.gep8 = getelementptr inbounds nuw i8, ptr %4, i32 4 %stack.next.gep8 = getelementptr inbounds i8, ptr %4, i32 4
%stack.next9 = load ptr, ptr %stack.next.gep8, align 4 %stack.next9 = load ptr, ptr %stack.next.gep8, align 4
store ptr %stack.next9, ptr %deferPtr, align 4 store ptr %stack.next9, ptr %deferPtr, align 4
%callback11 = load i32, ptr %4, align 4 %callback11 = load i32, ptr %4, align 4
@@ -144,11 +144,11 @@ entry:
%0 = call ptr @llvm.stacksave.p0() %0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4 call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
store i32 0, ptr %defer.alloca, align 4 store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack22 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4 %defer.alloca.repack22 = getelementptr inbounds i8, ptr %defer.alloca, i32 4
store ptr null, ptr %defer.alloca.repack22, align 4 store ptr null, ptr %defer.alloca.repack22, align 4
store ptr %defer.alloca, ptr %deferPtr, align 4 store ptr %defer.alloca, ptr %deferPtr, align 4
store i32 1, ptr %defer.alloca2, align 4 store i32 1, ptr %defer.alloca2, align 4
%defer.alloca2.repack23 = getelementptr inbounds nuw i8, ptr %defer.alloca2, i32 4 %defer.alloca2.repack23 = getelementptr inbounds i8, ptr %defer.alloca2, i32 4
store ptr %defer.alloca, ptr %defer.alloca2.repack23, align 4 store ptr %defer.alloca, ptr %defer.alloca2.repack23, align 4
store ptr %defer.alloca2, ptr %deferPtr, align 4 store ptr %defer.alloca2, ptr %deferPtr, align 4
%setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #5 %setjmp = call i32 asm "\0Amovs r0, #0\0Amov r2, pc\0Astr r2, [r1, #4]", "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"(ptr nonnull %deferframe.buf) #5
@@ -172,7 +172,7 @@ rundefers.loophead: ; preds = %4, %3, %rundefers.b
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds nuw i8, ptr %2, i32 4 %stack.next.gep = getelementptr inbounds i8, ptr %2, i32 4
%stack.next = load ptr, ptr %stack.next.gep, align 4 %stack.next = load ptr, ptr %stack.next.gep, align 4
store ptr %stack.next, ptr %deferPtr, align 4 store ptr %stack.next, ptr %deferPtr, align 4
%callback = load i32, ptr %2, align 4 %callback = load i32, ptr %2, align 4
@@ -218,7 +218,7 @@ rundefers.loophead10: ; preds = %7, %6, %lpad
br i1 %stackIsNil11, label %rundefers.end7, label %rundefers.loop9 br i1 %stackIsNil11, label %rundefers.end7, label %rundefers.loop9
rundefers.loop9: ; preds = %rundefers.loophead10 rundefers.loop9: ; preds = %rundefers.loophead10
%stack.next.gep12 = getelementptr inbounds nuw i8, ptr %5, i32 4 %stack.next.gep12 = getelementptr inbounds i8, ptr %5, i32 4
%stack.next13 = load ptr, ptr %stack.next.gep12, align 4 %stack.next13 = load ptr, ptr %stack.next.gep12, align 4
store ptr %stack.next13, ptr %deferPtr, align 4 store ptr %stack.next13, ptr %deferPtr, align 4
%callback15 = load i32, ptr %5, align 4 %callback15 = load i32, ptr %5, align 4
@@ -270,241 +270,6 @@ entry:
ret void ret void
} }
; Function Attrs: nounwind
define hidden void @main.deferInfiniteLoop(ptr %context) unnamed_addr #1 {
entry:
%deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4
%0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
br label %for.body
for.body: ; preds = %for.body, %entry
%defer.next = load ptr, ptr %deferPtr, align 4
%defer.alloc.call = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #4
store i32 0, ptr %defer.alloc.call, align 4
%defer.alloc.call.repack1 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 4
store ptr %defer.next, ptr %defer.alloc.call.repack1, align 4
%defer.alloc.call.repack3 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 8
store i32 8, ptr %defer.alloc.call.repack3, align 4
store ptr %defer.alloc.call, ptr %deferPtr, align 4
br label %for.body
recover: ; preds = %rundefers.end
ret void
lpad: ; No predecessors!
br label %rundefers.loophead
rundefers.loophead: ; preds = %rundefers.callback0, %lpad
br i1 poison, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead
switch i32 poison, label %rundefers.default [
i32 0, label %rundefers.callback0
]
rundefers.callback0: ; preds = %rundefers.loop
br label %rundefers.loophead
rundefers.default: ; preds = %rundefers.loop
unreachable
rundefers.end: ; preds = %rundefers.loophead
br label %recover
}
; Function Attrs: nounwind
define hidden void @main.deferLoop(ptr %context) unnamed_addr #1 {
entry:
%deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4
%0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
br label %for.loop
for.loop: ; preds = %for.body, %entry
%1 = phi i32 [ 0, %entry ], [ %3, %for.body ]
%2 = icmp slt i32 %1, 10
br i1 %2, label %for.body, label %for.done
for.body: ; preds = %for.loop
%defer.next = load ptr, ptr %deferPtr, align 4
%defer.alloc.call = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #4
store i32 0, ptr %defer.alloc.call, align 4
%defer.alloc.call.repack13 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 4
store ptr %defer.next, ptr %defer.alloc.call.repack13, align 4
%defer.alloc.call.repack15 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 8
store i32 %1, ptr %defer.alloc.call.repack15, align 4
store ptr %defer.alloc.call, ptr %deferPtr, align 4
%3 = add i32 %1, 1
br label %for.loop
for.done: ; preds = %for.loop
br label %rundefers.block
rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
ret void
rundefers.block: ; preds = %for.done
br label %rundefers.loophead
rundefers.loophead: ; preds = %rundefers.callback0, %rundefers.block
%4 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq ptr %4, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds nuw i8, ptr %4, i32 4
%stack.next = load ptr, ptr %stack.next.gep, align 4
store ptr %stack.next, ptr %deferPtr, align 4
%callback = load i32, ptr %4, align 4
switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0
]
rundefers.callback0: ; preds = %rundefers.loop
%gep = getelementptr inbounds nuw i8, ptr %4, i32 8
%param = load i32, ptr %gep, align 4
call void @runtime.printlock(ptr undef) #4
call void @runtime.printint32(i32 %param, ptr undef) #4
call void @runtime.printunlock(ptr undef) #4
br label %rundefers.loophead
rundefers.default: ; preds = %rundefers.loop
unreachable
rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after
recover: ; preds = %rundefers.end1
ret void
lpad: ; No predecessors!
br label %rundefers.loophead4
rundefers.loophead4: ; preds = %rundefers.callback010, %lpad
br i1 poison, label %rundefers.end1, label %rundefers.loop3
rundefers.loop3: ; preds = %rundefers.loophead4
switch i32 poison, label %rundefers.default2 [
i32 0, label %rundefers.callback010
]
rundefers.callback010: ; preds = %rundefers.loop3
br label %rundefers.loophead4
rundefers.default2: ; preds = %rundefers.loop3
unreachable
rundefers.end1: ; preds = %rundefers.loophead4
br label %recover
}
; Function Attrs: nounwind
define hidden void @main.deferBetweenLoops(ptr %context) unnamed_addr #1 {
entry:
%defer.alloca = alloca { i32, ptr, i32 }, align 4
%deferPtr = alloca ptr, align 4
store ptr null, ptr %deferPtr, align 4
%deferframe.buf = alloca %runtime.deferFrame, align 4
%0 = call ptr @llvm.stacksave.p0()
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
br label %for.loop
for.loop: ; preds = %for.body, %entry
%1 = phi i32 [ 0, %entry ], [ %3, %for.body ]
%2 = icmp slt i32 %1, 10
br i1 %2, label %for.body, label %for.done
for.body: ; preds = %for.loop
%3 = add i32 %1, 1
br label %for.loop
for.done: ; preds = %for.loop
%defer.next = load ptr, ptr %deferPtr, align 4
store i32 0, ptr %defer.alloca, align 4
%defer.alloca.repack16 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4
store ptr %defer.next, ptr %defer.alloca.repack16, align 4
%defer.alloca.repack18 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 8
store i32 1, ptr %defer.alloca.repack18, align 4
store ptr %defer.alloca, ptr %deferPtr, align 4
br label %for.loop1
for.loop1: ; preds = %for.body2, %for.done
%4 = phi i32 [ 0, %for.done ], [ %6, %for.body2 ]
%5 = icmp slt i32 %4, 10
br i1 %5, label %for.body2, label %for.done3
for.body2: ; preds = %for.loop1
%6 = add i32 %4, 1
br label %for.loop1
for.done3: ; preds = %for.loop1
br label %rundefers.block
rundefers.after: ; preds = %rundefers.end
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
ret void
rundefers.block: ; preds = %for.done3
br label %rundefers.loophead
rundefers.loophead: ; preds = %rundefers.callback0, %rundefers.block
%7 = load ptr, ptr %deferPtr, align 4
%stackIsNil = icmp eq ptr %7, null
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
rundefers.loop: ; preds = %rundefers.loophead
%stack.next.gep = getelementptr inbounds nuw i8, ptr %7, i32 4
%stack.next = load ptr, ptr %stack.next.gep, align 4
store ptr %stack.next, ptr %deferPtr, align 4
%callback = load i32, ptr %7, align 4
switch i32 %callback, label %rundefers.default [
i32 0, label %rundefers.callback0
]
rundefers.callback0: ; preds = %rundefers.loop
%gep = getelementptr inbounds nuw i8, ptr %7, i32 8
%param = load i32, ptr %gep, align 4
call void @runtime.printlock(ptr undef) #4
call void @runtime.printint32(i32 %param, ptr undef) #4
call void @runtime.printunlock(ptr undef) #4
br label %rundefers.loophead
rundefers.default: ; preds = %rundefers.loop
unreachable
rundefers.end: ; preds = %rundefers.loophead
br label %rundefers.after
recover: ; preds = %rundefers.end4
ret void
lpad: ; No predecessors!
br label %rundefers.loophead7
rundefers.loophead7: ; preds = %rundefers.callback013, %lpad
br i1 poison, label %rundefers.end4, label %rundefers.loop6
rundefers.loop6: ; preds = %rundefers.loophead7
switch i32 poison, label %rundefers.default5 [
i32 0, label %rundefers.callback013
]
rundefers.callback013: ; preds = %rundefers.loop6
br label %rundefers.loophead7
rundefers.default5: ; preds = %rundefers.loop6
unreachable
rundefers.end4: ; preds = %rundefers.loophead7
br label %recover
}
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
attributes #2 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" } attributes #2 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
-20
View File
@@ -18,23 +18,3 @@ func deferMultiple() {
}() }()
external() external()
} }
func deferInfiniteLoop() {
for {
defer print(8)
}
}
func deferLoop() {
for i := 0; i < 10; i++ {
defer print(i)
}
}
func deferBetweenLoops() {
for i := 0; i < 10; i++ {
}
defer print(1)
for i := 0; i < 10; i++ {
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
; ModuleID = 'float.go' ; ModuleID = 'float.go'
source_filename = "float.go" source_filename = "float.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
@@ -93,6 +93,6 @@ entry:
ret i8 %0 ret i8 %0
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
+4 -4
View File
@@ -1,6 +1,6 @@
; ModuleID = 'func.go' ; ModuleID = 'func.go'
source_filename = "func.go" source_filename = "func.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
@@ -44,7 +44,7 @@ entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+11 -11
View File
@@ -1,6 +1,6 @@
; ModuleID = 'gc.go' ; ModuleID = 'gc.go'
source_filename = "gc.go" source_filename = "gc.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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._interface = type { ptr, ptr } %runtime._interface = type { ptr, ptr }
@@ -105,18 +105,18 @@ entry:
%makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice, ptr @main.slice1, align 4 store ptr %makeslice, ptr @main.slice1, align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice1, i32 4), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice1, i32 4), align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice1, i32 8), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice1, i32 8), align 4
%makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 %makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice1, ptr @main.slice2, align 4 store ptr %makeslice1, ptr @main.slice2, align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice2, i32 4), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice2, i32 4), align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice2, i32 8), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice2, i32 8), align 4
%makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3 %makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice3, ptr @main.slice3, align 4 store ptr %makeslice3, ptr @main.slice3, align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice3, i32 4), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice3, i32 4), align 4
store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice3, i32 8), align 4 store i32 5, ptr getelementptr inbounds (i8, ptr @main.slice3, i32 8), align 4
ret void ret void
} }
@@ -127,7 +127,7 @@ entry:
%0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3 %0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3
store double %v.r, ptr %0, align 8 store double %v.r, ptr %0, align 8
%.repack1 = getelementptr inbounds nuw i8, ptr %0, i32 8 %.repack1 = getelementptr inbounds i8, ptr %0, i32 8
store double %v.i, ptr %.repack1, align 8 store double %v.i, ptr %.repack1, align 8
%1 = insertvalue %runtime._interface { ptr @"reflect/types.type:basic:complex128", ptr undef }, ptr %0, 1 %1 = insertvalue %runtime._interface { ptr @"reflect/types.type:basic:complex128", ptr undef }, ptr %0, 1
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:complex128", ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:complex128", ptr nonnull %stackalloc, ptr undef) #3
@@ -135,7 +135,7 @@ entry:
ret %runtime._interface %1 ret %runtime._interface %1
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+5 -5
View File
@@ -1,6 +1,6 @@
; ModuleID = 'go1.20.go' ; ModuleID = 'go1.20.go'
source_filename = "go1.20.go" source_filename = "go1.20.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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._string = type { ptr, i32 } %runtime._string = type { ptr, i32 }
@@ -50,14 +50,14 @@ unsafe.String.throw: ; preds = %entry
declare void @runtime.unsafeSlicePanic(ptr) #1 declare void @runtime.unsafeSlicePanic(ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden ptr @main.unsafeStringData(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 { define hidden ptr @main.unsafeStringData(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {
entry: entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3
ret ptr %s.data ret ptr %s.data
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+9 -9
View File
@@ -1,6 +1,6 @@
; ModuleID = 'go1.21.go' ; ModuleID = 'go1.21.go'
source_filename = "go1.21.go" source_filename = "go1.21.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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._string = type { ptr, i32 } %runtime._string = type { ptr, i32 }
@@ -77,7 +77,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.minString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.minString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0 %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1 %1 = insertvalue %runtime._string %0, i32 %a.len, 1
@@ -86,12 +86,12 @@ entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%4 = call i1 @runtime.stringLess(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr undef) #5 %4 = call i1 @runtime.stringLess(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr undef) #5
%5 = select i1 %4, %runtime._string %1, %runtime._string %3 %5 = select i1 %4, %runtime._string %1, %runtime._string %3
%6 = select i1 %4, ptr %a.data, ptr %b.data %6 = extractvalue %runtime._string %5, 0
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5 call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5
ret %runtime._string %5 ret %runtime._string %5
} }
declare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1 declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 { define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
@@ -116,7 +116,7 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 { define hidden %runtime._string @main.maxString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0 %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0
%1 = insertvalue %runtime._string %0, i32 %a.len, 1 %1 = insertvalue %runtime._string %0, i32 %a.len, 1
@@ -125,7 +125,7 @@ entry:
%stackalloc = alloca i8, align 1 %stackalloc = alloca i8, align 1
%4 = call i1 @runtime.stringLess(ptr %b.data, i32 %b.len, ptr %a.data, i32 %a.len, ptr undef) #5 %4 = call i1 @runtime.stringLess(ptr %b.data, i32 %b.len, ptr %a.data, i32 %a.len, ptr undef) #5
%5 = select i1 %4, %runtime._string %1, %runtime._string %3 %5 = select i1 %4, %runtime._string %1, %runtime._string %3
%6 = select i1 %4, ptr %a.data, ptr %b.data %6 = extractvalue %runtime._string %5, 0
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5 call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5
ret %runtime._string %5 ret %runtime._string %5
} }
@@ -171,9 +171,9 @@ declare i32 @llvm.smax.i32(i32, i32) #4
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.umax.i32(i32, i32) #4 declare i32 @llvm.umax.i32(i32, i32) #4
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) } attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #5 = { nounwind } attributes #5 = { nounwind }
+12 -12
View File
@@ -65,7 +65,7 @@ entry:
store i32 3, ptr %n, align 4 store i32 3, ptr %n, align 4
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr %n, ptr %1, align 4 store ptr %n, ptr %1, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
@@ -87,7 +87,7 @@ entry:
define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #5 { define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #5 {
entry: entry:
%1 = load i32, ptr %0, align 4 %1 = load i32, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3) call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
ret void ret void
@@ -104,9 +104,9 @@ define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %co
entry: entry:
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr %fn.context, ptr %1, align 4 store ptr %fn.context, ptr %1, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8 %2 = getelementptr inbounds i8, ptr %0, i32 8
store ptr %fn.funcptr, ptr %2, align 4 store ptr %fn.funcptr, ptr %2, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #9 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #9
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
@@ -117,9 +117,9 @@ entry:
define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 { define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 {
entry: entry:
%1 = load i32, ptr %0, align 4 %1 = load i32, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8 %4 = getelementptr inbounds i8, ptr %0, i32 8
%5 = load ptr, ptr %4, align 4 %5 = load ptr, ptr %4, align 4
call void %5(i32 %1, ptr %3) #9 call void %5(i32 %1, ptr %3) #9
ret void ret void
@@ -154,11 +154,11 @@ define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value,
entry: entry:
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
store ptr %itf.value, ptr %0, align 4 store ptr %itf.value, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr @"main$string", ptr %1, align 4 store ptr @"main$string", ptr %1, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8 %2 = getelementptr inbounds i8, ptr %0, i32 8
store i32 4, ptr %2, align 4 store i32 4, ptr %2, align 4
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12 %3 = getelementptr inbounds i8, ptr %0, i32 12
store ptr %itf.typecode, ptr %3, align 4 store ptr %itf.typecode, ptr %3, align 4
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #9 %stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #9
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
@@ -171,11 +171,11 @@ declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 { define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 {
entry: entry:
%1 = load ptr, ptr %0, align 4 %1 = load ptr, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8 %4 = getelementptr inbounds i8, ptr %0, i32 8
%5 = load i32, ptr %4, align 4 %5 = load i32, ptr %4, align 4
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12 %6 = getelementptr inbounds i8, ptr %0, i32 12
%7 = load ptr, ptr %6, align 4 %7 = load ptr, ptr %6, align 4
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9 call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9
ret void ret void
+22 -22
View File
@@ -1,6 +1,6 @@
; ModuleID = 'goroutine.go' ; ModuleID = 'goroutine.go'
source_filename = "goroutine.go" source_filename = "goroutine.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
@"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1 @"main$string" = internal unnamed_addr constant [4 x i8] c"test", align 1
@@ -72,7 +72,7 @@ entry:
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr %n, ptr %1, align 4 store ptr %n, ptr %1, align 4
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
%2 = load i32, ptr %n, align 4 %2 = load i32, ptr %n, align 4
@@ -93,7 +93,7 @@ entry:
define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #5 { define linkonce_odr void @"main.closureFunctionGoroutine$1$gowrapper"(ptr %0) unnamed_addr #5 {
entry: entry:
%1 = load i32, ptr %0, align 4 %1 = load i32, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3) call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
call void @runtime.deadlock(ptr undef) #9 call void @runtime.deadlock(ptr undef) #9
@@ -113,9 +113,9 @@ entry:
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store i32 5, ptr %0, align 4 store i32 5, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr %fn.context, ptr %1, align 4 store ptr %fn.context, ptr %1, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8 %2 = getelementptr inbounds i8, ptr %0, i32 8
store ptr %fn.funcptr, ptr %2, align 4 store ptr %fn.funcptr, ptr %2, align 4
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #9
ret void ret void
@@ -125,9 +125,9 @@ entry:
define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 { define linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 {
entry: entry:
%1 = load i32, ptr %0, align 4 %1 = load i32, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8 %4 = getelementptr inbounds i8, ptr %0, i32 8
%5 = load ptr, ptr %4, align 4 %5 = load ptr, ptr %4, align 4
call void %5(i32 %1, ptr %3) #9 call void %5(i32 %1, ptr %3) #9
call void @runtime.deadlock(ptr undef) #9 call void @runtime.deadlock(ptr undef) #9
@@ -165,11 +165,11 @@ entry:
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store ptr %itf.value, ptr %0, align 4 store ptr %itf.value, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4 %1 = getelementptr inbounds i8, ptr %0, i32 4
store ptr @"main$string", ptr %1, align 4 store ptr @"main$string", ptr %1, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8 %2 = getelementptr inbounds i8, ptr %0, i32 8
store i32 4, ptr %2, align 4 store i32 4, ptr %2, align 4
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12 %3 = getelementptr inbounds i8, ptr %0, i32 12
store ptr %itf.typecode, ptr %3, align 4 store ptr %itf.typecode, ptr %3, align 4
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9 call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
ret void ret void
@@ -181,24 +181,24 @@ declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 { define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 {
entry: entry:
%1 = load ptr, ptr %0, align 4 %1 = load ptr, ptr %0, align 4
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4 %2 = getelementptr inbounds i8, ptr %0, i32 4
%3 = load ptr, ptr %2, align 4 %3 = load ptr, ptr %2, align 4
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8 %4 = getelementptr inbounds i8, ptr %0, i32 8
%5 = load i32, ptr %4, align 4 %5 = load i32, ptr %4, align 4
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12 %6 = getelementptr inbounds i8, ptr %0, i32 12
%7 = load ptr, ptr %6, align 4 %7 = load ptr, ptr %6, align 4
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9 call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9
call void @runtime.deadlock(ptr undef) #9 call void @runtime.deadlock(ptr undef) #9
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.regularFunction" } attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.regularFunction" }
attributes #4 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" } attributes #4 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" } attributes #5 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
attributes #6 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper" } attributes #6 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper" }
attributes #7 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" } attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
attributes #8 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" } attributes #8 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
attributes #9 = { nounwind } attributes #9 = { nounwind }
+8 -8
View File
@@ -1,6 +1,6 @@
; ModuleID = 'interface.go' ; ModuleID = 'interface.go'
source_filename = "interface.go" source_filename = "interface.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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._interface = type { ptr, ptr } %runtime._interface = type { ptr, ptr }
@@ -130,11 +130,11 @@ entry:
declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, ptr, ptr) #6 declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr, ptr, ptr) #6
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-methods"="reflect/methods.Error() string" } attributes #3 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-methods"="reflect/methods.Error() string" }
attributes #4 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-methods"="reflect/methods.String() string" } attributes #4 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-methods"="reflect/methods.String() string" }
attributes #5 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" } attributes #5 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
attributes #6 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" } attributes #6 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
attributes #7 = { nounwind } attributes #7 = { nounwind }
+4 -4
View File
@@ -1,6 +1,6 @@
; ModuleID = 'pointer.go' ; ModuleID = 'pointer.go'
source_filename = "pointer.go" source_filename = "pointer.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
@@ -44,7 +44,7 @@ entry:
ret ptr %x ret ptr %x
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+11 -11
View File
@@ -1,6 +1,6 @@
; ModuleID = 'pragma.go' ; ModuleID = 'pragma.go'
source_filename = "pragma.go" source_filename = "pragma.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
@extern_global = external global [0 x i8], align 1 @extern_global = external global [0 x i8], align 1
@@ -93,13 +93,13 @@ entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="extern_func" } attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="extern_func" }
attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="exportedFunctionInSection" } attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="exportedFunctionInSection" }
attributes #7 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-import-module"="modulename" "wasm-import-name"="import1" } attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-import-module"="modulename" "wasm-import-name"="import1" }
attributes #8 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-import-module"="foobar" "wasm-import-name"="imported" } attributes #8 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-import-module"="foobar" "wasm-import-name"="imported" }
attributes #9 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="exported" } attributes #9 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "wasm-export-name"="exported" }
+6 -6
View File
@@ -1,6 +1,6 @@
; ModuleID = 'slice.go' ; ModuleID = 'slice.go'
source_filename = "slice.go" source_filename = "slice.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
; Function Attrs: allockind("alloc,zeroed") allocsize(0) ; Function Attrs: allockind("alloc,zeroed") allocsize(0)
@@ -51,9 +51,9 @@ entry:
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3
store i32 1, ptr %varargs, align 4 store i32 1, ptr %varargs, align 4
%0 = getelementptr inbounds nuw i8, ptr %varargs, i32 4 %0 = getelementptr inbounds i8, ptr %varargs, i32 4
store i32 2, ptr %0, align 4 store i32 2, ptr %0, align 4
%1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8 %1 = getelementptr inbounds i8, ptr %varargs, i32 8
store i32 3, ptr %1, align 4 store i32 3, ptr %1, align 4
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #3 %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #3
%append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0 %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
@@ -322,7 +322,7 @@ unsafe.Slice.throw: ; preds = %entry
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+14 -14
View File
@@ -1,6 +1,6 @@
; ModuleID = 'string.go' ; ModuleID = 'string.go'
source_filename = "string.go" source_filename = "string.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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._string = type { ptr, i32 } %runtime._string = type { ptr, i32 }
@@ -31,13 +31,13 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i32 @main.stringLen(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 { define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {
entry: entry:
ret i32 %s.len ret i32 %s.len
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringIndex(ptr readonly %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #2 { define hidden i8 @main.stringIndex(ptr %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #2 {
entry: entry:
%.not = icmp ult i32 %index, %s.len %.not = icmp ult i32 %index, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
@@ -55,16 +55,16 @@ lookup.throw: ; preds = %entry
declare void @runtime.lookupPanic(ptr) #1 declare void @runtime.lookupPanic(ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareEqual(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringEqual(ptr readonly, i32, ptr readonly, i32, ptr) #1 declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareUnequal(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3 %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3
%1 = xor i1 %0, true %1 = xor i1 %0, true
@@ -72,23 +72,23 @@ entry:
} }
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i1 @main.stringCompareLarger(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 { define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3 %0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3
ret i1 %0 ret i1 %0
} }
declare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1 declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #1
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.stringLookup(ptr readonly %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #2 { define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #2 {
entry: entry:
%0 = zext i8 %x to i32 %0 = zext i8 %x to i32
%.not = icmp ugt i32 %s.len, %0 %.not = icmp ult i32 %0, %s.len
br i1 %.not, label %lookup.next, label %lookup.throw br i1 %.not, label %lookup.next, label %lookup.throw
lookup.next: ; preds = %entry lookup.next: ; preds = %entry
%1 = getelementptr inbounds nuw i8, ptr %s.data, i32 %0 %1 = getelementptr inbounds i8, ptr %s.data, i32 %0
%2 = load i8, ptr %1, align 1 %2 = load i8, ptr %1, align 1
ret i8 %2 ret i8 %2
@@ -97,7 +97,7 @@ lookup.throw: ; preds = %entry
unreachable unreachable
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { nounwind } attributes #3 = { nounwind }
+19 -19
View File
@@ -1,6 +1,6 @@
; ModuleID = 'zeromap.go' ; ModuleID = 'zeromap.go'
source_filename = "zeromap.go" source_filename = "zeromap.go"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-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"
%main.hasPadding = type { i1, i32, i1 } %main.hasPadding = type { i1, i32, i1 }
@@ -27,9 +27,9 @@ entry:
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
store %main.hasPadding %2, ptr %hashmap.key, align 4 store %main.hasPadding %2, ptr %hashmap.key, align 4
%3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1 %3 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
%4 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9 %4 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5
%5 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5 %5 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
@@ -60,9 +60,9 @@ entry:
store i32 5, ptr %hashmap.value, align 4 store i32 5, ptr %hashmap.value, align 4
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
store %main.hasPadding %2, ptr %hashmap.key, align 4 store %main.hasPadding %2, ptr %hashmap.key, align 4
%3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1 %3 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
%4 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9 %4 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5
call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5 call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
@@ -81,16 +81,16 @@ entry:
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0 %s.elt = extractvalue [2 x %main.hasPadding] %s, 0
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4 store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12 %hashmap.key.repack1 = getelementptr inbounds i8, ptr %hashmap.key, i32 12
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1 %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4 store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
%0 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1 %0 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5
%1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9 %1 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5
%2 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 13 %2 = getelementptr inbounds i8, ptr %hashmap.key, i32 13
call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5
%3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 21 %3 = getelementptr inbounds i8, ptr %hashmap.key, i32 21
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
%4 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5 %4 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
@@ -109,16 +109,16 @@ entry:
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0 %s.elt = extractvalue [2 x %main.hasPadding] %s, 0
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4 store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12 %hashmap.key.repack1 = getelementptr inbounds i8, ptr %hashmap.key, i32 12
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1 %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4 store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
%0 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1 %0 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5
%1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9 %1 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5
%2 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 13 %2 = getelementptr inbounds i8, ptr %hashmap.key, i32 13
call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5
%3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 21 %3 = getelementptr inbounds i8, ptr %hashmap.key, i32 21
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5 call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5 call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
@@ -132,9 +132,9 @@ entry:
ret void ret void
} }
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #3 = { noinline nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" } attributes #3 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
attributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } attributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #5 = { nounwind } attributes #5 = { nounwind }
+8
View File
@@ -5,6 +5,8 @@ go 1.22.0
require ( require (
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee
github.com/chromedp/chromedp v0.7.6
github.com/gofrs/flock v0.8.1 github.com/gofrs/flock v0.8.1
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
@@ -22,7 +24,13 @@ require (
) )
require ( require (
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/creack/goselect v0.1.2 // indirect github.com/creack/goselect v0.1.2 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/stretchr/testify v1.8.4 // indirect github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
+21
View File
@@ -2,16 +2,33 @@ github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 h1:2O/WuAt8J5id3k
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw= github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI= github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/chromedp/cdproto v0.0.0-20211126220118-81fa0469ad77/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee h1:+SFdIVfQpG0s0DHYzou0kgfE0n0ZjKPwbiRJsXrZegU=
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
github.com/chromedp/chromedp v0.7.6 h1:2juGaktzjwULlsn+DnvIZXFUckEp5xs+GOBroaea+jA=
github.com/chromedp/chromedp v0.7.6/go.mod h1:ayT4YU/MGAALNfOg9gNrpGSAdnU51PMx+FCeuT1iXzo=
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -25,6 +42,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E= github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28= github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs= github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
@@ -44,6 +63,8 @@ golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// Version of TinyGo. // Version of TinyGo.
// Update this value before release of new version of software. // Update this value before release of new version of software.
const version = "0.40.0" const version = "0.39.0-dev"
// Return TinyGo version, either in the form 0.30.0 or as a development version // Return TinyGo version, either in the form 0.30.0 or as a development version
// (like 0.30.0-dev-abcd012). // (like 0.30.0-dev-abcd012).
+1 -1
View File
@@ -577,7 +577,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
// runtime instead of at compile time. But we need to // runtime instead of at compile time. But we need to
// revert any changes made by the call first. // revert any changes made by the call first.
if r.debug { if r.debug {
fmt.Fprintln(os.Stderr, indent+"!! revert because of error:", callErr.Error()) fmt.Fprintln(os.Stderr, indent+"!! revert because of error:", callErr.Err)
} }
callMem.revert() callMem.revert()
err := r.runAtRuntime(fn, inst, locals, &mem, indent) err := r.runAtRuntime(fn, inst, locals, &mem, indent)
+1 -1
View File
@@ -10,7 +10,7 @@ target triple = "x86_64--linux"
@main.exposedValue2 = local_unnamed_addr global i16 0 @main.exposedValue2 = local_unnamed_addr global i16 0
@main.insertedValue = local_unnamed_addr global { i8, i32, { float, { i64, i16 } } } zeroinitializer @main.insertedValue = local_unnamed_addr global { i8, i32, { float, { i64, i16 } } } zeroinitializer
@main.gepArray = local_unnamed_addr global [8 x i8] zeroinitializer @main.gepArray = local_unnamed_addr global [8 x i8] zeroinitializer
@main.negativeGEP = global ptr getelementptr inbounds nuw (i8, ptr @main.negativeGEP, i64 2) @main.negativeGEP = global ptr getelementptr inbounds (i8, ptr @main.negativeGEP, i64 2)
declare void @runtime.printint64(i64) unnamed_addr declare void @runtime.printint64(i64) unnamed_addr
+1 -1
View File
@@ -5,7 +5,7 @@ target triple = "x86_64--linux"
@ptrToIntResult = local_unnamed_addr global i8 2 @ptrToIntResult = local_unnamed_addr global i8 2
@pointerTagResult = local_unnamed_addr global i64 2 @pointerTagResult = local_unnamed_addr global i64 2
@someArray = internal global { i16, i8, i8 } zeroinitializer @someArray = internal global { i16, i8, i8 } zeroinitializer
@someArrayPointer = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @someArray, i64 2) @someArrayPointer = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @someArray, i64 2)
define void @runtime.initAll() local_unnamed_addr { define void @runtime.initAll() local_unnamed_addr {
ret void ret void
+27 -30
View File
@@ -229,36 +229,33 @@ func needsSyscallPackage(buildTags []string) bool {
// means use the TinyGo version. // means use the TinyGo version.
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
paths := map[string]bool{ paths := map[string]bool{
"": true, "": true,
"crypto/": true, "crypto/": true,
"crypto/rand/": false, "crypto/rand/": false,
"crypto/tls/": false, "crypto/tls/": false,
"crypto/x509/": true, "device/": false,
"crypto/x509/internal/": true, "examples/": false,
"crypto/x509/internal/macos/": false, "internal/": true,
"device/": false, "internal/abi/": false,
"examples/": false, "internal/binary/": false,
"internal/": true, "internal/bytealg/": false,
"internal/abi/": false, "internal/cm/": false,
"internal/binary/": false, "internal/futex/": false,
"internal/bytealg/": false, "internal/fuzz/": false,
"internal/cm/": false, "internal/reflectlite/": false,
"internal/futex/": false, "internal/gclayout": false,
"internal/fuzz/": false, "internal/task/": false,
"internal/reflectlite/": false, "internal/wasi/": false,
"internal/gclayout": false, "machine/": false,
"internal/task/": false, "net/": true,
"internal/wasi/": false, "net/http/": false,
"machine/": false, "os/": true,
"net/": true, "reflect/": false,
"net/http/": false, "runtime/": false,
"os/": true, "sync/": true,
"reflect/": false, "testing/": true,
"runtime/": false, "tinygo/": false,
"sync/": true, "unique/": false,
"testing/": true,
"tinygo/": false,
"unique/": false,
} }
if goMinor >= 19 { if goMinor >= 19 {
+5 -44
View File
@@ -291,8 +291,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
}) })
if testConfig.CompileOnly { if testConfig.CompileOnly {
// Return the compiler error, if there is one. return true, nil
return true, err
} }
importPath := strings.TrimSuffix(result.ImportPath, ".test") importPath := strings.TrimSuffix(result.ImportPath, ".test")
@@ -340,17 +339,8 @@ func dirsToModuleRootAbs(maindir, modroot string) []string {
return dirs return dirs
} }
// validateOutputFormat checks if the output file extension matches the expected format
func validateOutputFormat(outpath, expectedExt string) error {
actualExt := filepath.Ext(outpath)
if actualExt != expectedExt {
return fmt.Errorf("output format %s does not match target format %s", actualExt, expectedExt)
}
return nil
}
// Flash builds and flashes the built binary to the given serial port. // Flash builds and flashes the built binary to the given serial port.
func Flash(pkgName, port, outpath string, options *compileopts.Options) error { func Flash(pkgName, port string, options *compileopts.Options) error {
config, err := builder.NewConfig(options) config, err := builder.NewConfig(options)
if err != nil { if err != nil {
return err return err
@@ -399,24 +389,13 @@ func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
if !options.Work { if !options.Work {
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
} }
// Validate output format before building
if outpath != "" {
if err := validateOutputFormat(outpath, fileExt); err != nil {
return err
}
}
// Build the binary. // Build the binary.
result, err := builder.Build(pkgName, fileExt, tmpdir, config) result, err := builder.Build(pkgName, fileExt, tmpdir, config)
if err != nil { if err != nil {
return err return err
} }
// Save output file if specified (after build, before flashing)
if outpath != "" {
if err := copyFile(result.Binary, outpath); err != nil {
return fmt.Errorf("failed to save output file: %v", err)
}
}
// do we need port reset to put MCU into bootloader mode? // do we need port reset to put MCU into bootloader mode?
if config.Target.PortReset == "true" && flashMethod != "openocd" { if config.Target.PortReset == "true" && flashMethod != "openocd" {
port, err := getDefaultPort(port, config.Target.SerialPort) port, err := getDefaultPort(port, config.Target.SerialPort)
@@ -1318,11 +1297,6 @@ extension at all.`
(https://tinygo.org/docs/reference/microcontrollers/). (https://tinygo.org/docs/reference/microcontrollers/).
Examples: "arduino-nano", "d1mini", "xiao". Examples: "arduino-nano", "d1mini", "xiao".
-o={filename}:
Save the built binary to the specified output file. The file
format must match the target's expected format (e.g., .hex,
.uf2). Both flashing and saving will be performed.
-monitor: -monitor:
Start the serial monitor (see below) immediately after Start the serial monitor (see below) immediately after
flashing. However, some microcontrollers need a split second flashing. However, some microcontrollers need a split second
@@ -1635,7 +1609,6 @@ func main() {
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output") cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
monitor := flag.Bool("monitor", false, "enable serial monitor") monitor := flag.Bool("monitor", false, "enable serial monitor")
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor") baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
gocompatibility := flag.Bool("go-compatibility", true, "enable to check for Go versions compatibility, you can also configure this by setting the TINYGO_GOCOMPATIBILITY environment variable")
// Internal flags, that are only intended for TinyGo development. // Internal flags, that are only intended for TinyGo development.
printIR := flag.Bool("internal-printir", false, "print LLVM IR") printIR := flag.Bool("internal-printir", false, "print LLVM IR")
@@ -1654,7 +1627,7 @@ func main() {
flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list") flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list")
} }
var outpath string var outpath string
if command == "help" || command == "build" || command == "test" || command == "flash" { if command == "help" || command == "build" || command == "test" {
flag.StringVar(&outpath, "o", "", "output filename") flag.StringVar(&outpath, "o", "", "output filename")
} }
@@ -1713,16 +1686,6 @@ func main() {
ocdCommands = strings.Split(*ocdCommandsString, ",") ocdCommands = strings.Split(*ocdCommandsString, ",")
} }
val, ok := os.LookupEnv("TINYGO_GOCOMPATIBILITY")
if ok {
b, err := strconv.ParseBool(val)
if err != nil {
fmt.Fprintf(os.Stderr, "could not parse TINYGO_GOCOMPATIBILITY value %q: %v\n", val, err)
os.Exit(1)
}
*gocompatibility = b
}
options := &compileopts.Options{ options := &compileopts.Options{
GOOS: goenv.Get("GOOS"), GOOS: goenv.Get("GOOS"),
GOARCH: goenv.Get("GOARCH"), GOARCH: goenv.Get("GOARCH"),
@@ -1759,7 +1722,6 @@ func main() {
Timeout: *timeout, Timeout: *timeout,
WITPackage: witPackage, WITPackage: witPackage,
WITWorld: witWorld, WITWorld: witWorld,
GoCompatibility: *gocompatibility,
} }
if *printCommands { if *printCommands {
options.PrintCommands = printCommand options.PrintCommands = printCommand
@@ -1816,7 +1778,7 @@ func main() {
case "flash", "gdb", "lldb": case "flash", "gdb", "lldb":
pkgName := filepath.ToSlash(flag.Arg(0)) pkgName := filepath.ToSlash(flag.Arg(0))
if command == "flash" { if command == "flash" {
err := Flash(pkgName, *port, outpath, options) err := Flash(pkgName, *port, options)
printBuildOutput(err, *flagJSON) printBuildOutput(err, *flagJSON)
} else { } else {
if !options.Debug { if !options.Debug {
@@ -1902,7 +1864,6 @@ func main() {
wd = "" wd = ""
} }
diagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd) diagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd)
os.Exit(1)
} }
if !passed { if !passed {
select { select {
+3 -3
View File
@@ -35,8 +35,8 @@ func Monitor(executable, port string, config *compileopts.Config) error {
// Use the RTT interface, which is documented (in part) here: // Use the RTT interface, which is documented (in part) here:
// https://wiki.segger.com/RTT // https://wiki.segger.com/RTT
// Try to find the "_SEGGER_RTT" symbol (machine.rttSerialInstance) // Try to find the "machine.rttSerialInstance" symbol, which is the RTT
// symbol, which is the RTT control block. // control block.
file, err := elf.Open(executable) file, err := elf.Open(executable)
if err != nil { if err != nil {
return fmt.Errorf("could not open ELF file to determine RTT control block: %w", err) return fmt.Errorf("could not open ELF file to determine RTT control block: %w", err)
@@ -48,7 +48,7 @@ func Monitor(executable, port string, config *compileopts.Config) error {
} }
var address uint64 var address uint64
for _, symbol := range symbols { for _, symbol := range symbols {
if symbol.Name == "_SEGGER_RTT" { if symbol.Name == "machine.rttSerialInstance" {
address = symbol.Value address = symbol.Value
break break
} }
-189
View File
@@ -1,189 +0,0 @@
package macos
import (
"errors"
"time"
)
// Exported symbols copied from Big Go, but stripped of functionality.
// Allows building of crypto/x509 on macOS.
const (
ErrSecCertificateExpired = -67818
ErrSecHostNameMismatch = -67602
ErrSecNotTrusted = -67843
)
var ErrNoTrustSettings = errors.New("no trust settings found")
var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
var SecPolicyOid = StringToCFString("SecPolicyOid")
var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
func CFArrayAppendValue(array CFRef, val CFRef) {}
func CFArrayGetCount(array CFRef) int {
return 0
}
func CFDataGetBytePtr(data CFRef) uintptr {
return 0
}
func CFDataGetLength(data CFRef) int {
return 0
}
func CFDataToSlice(data CFRef) []byte {
return nil
}
func CFEqual(a, b CFRef) bool {
return false
}
func CFErrorGetCode(errRef CFRef) int {
return 0
}
func CFNumberGetValue(num CFRef) (int32, error) {
return 0, errors.New("not implemented")
}
func CFRelease(ref CFRef) {}
func CFStringToString(ref CFRef) string {
return ""
}
func ReleaseCFArray(array CFRef) {}
func SecCertificateCopyData(cert CFRef) ([]byte, error) {
return nil, errors.New("not implemented")
}
func SecTrustCopyCertificateChain(trustObj CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateCount(trustObj CFRef) int {
return 0
}
func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {
return 0, 0, errors.New("not implemented")
}
func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {
return errors.New("not implemented")
}
type CFRef uintptr
func BytesToCFData(b []byte) CFRef {
return 0
}
func CFArrayCreateMutable() CFRef {
return 0
}
func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
return 0
}
func CFDateCreate(seconds float64) CFRef {
return 0
}
func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
return 0, false
}
func CFErrorCopyDescription(errRef CFRef) CFRef {
return 0
}
func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecCertificateCreateWithData(b []byte) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecPolicyCreateSSL(name string) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustEvaluate(trustObj CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
return 0, errors.New("not implemented")
}
func TimeToCFDateRef(t time.Time) CFRef {
return 0
}
type CFString CFRef
func StringToCFString(s string) CFString {
return 0
}
type OSStatus struct {
// Has unexported fields.
}
func (s OSStatus) Error() string
type SecTrustResultType int32
const (
SecTrustResultInvalid SecTrustResultType = iota
SecTrustResultProceed
SecTrustResultConfirm // deprecated
SecTrustResultDeny
SecTrustResultUnspecified
SecTrustResultRecoverableTrustFailure
SecTrustResultFatalTrustFailure
SecTrustResultOtherError
)
type SecTrustSettingsDomain int32
const (
SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
SecTrustSettingsDomainAdmin
SecTrustSettingsDomainSystem
)
type SecTrustSettingsResult int32
const (
SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
SecTrustSettingsResultTrustRoot
SecTrustSettingsResultTrustAsRoot
SecTrustSettingsResultDeny
SecTrustSettingsResultUnspecified
)
+3 -3
View File
@@ -48,10 +48,10 @@ func Asm(asm string)
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, [{result}]", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1, // "value": 1
// "result": uintptr(unsafe.Pointer(&dest)), // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
+23
View File
@@ -1,6 +1,29 @@
.syntax unified .syntax unified
.cfi_sections .debug_frame .cfi_sections .debug_frame
.section .text.HardFault_Handler
.global HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler:
.cfi_startproc
// Put the old stack pointer in the first argument, for easy debugging. This
// is especially useful on Cortex-M0, which supports far fewer debug
// facilities.
mov r0, sp
// Load the default stack pointer from address 0 so that we can call normal
// functions again that expect a working stack. However, it will corrupt the
// old stack so the function below must not attempt to recover from this
// fault.
movs r3, #0
ldr r3, [r3]
mov sp, r3
// Continue handling this error in Go.
bl handleHardFault
.cfi_endproc
.size HardFault_Handler, .-HardFault_Handler
// This is a convenience function for semihosting support. // This is a convenience function for semihosting support.
// At some point, this should be replaced by inline assembly. // At some point, this should be replaced by inline assembly.
.section .text.SemihostingCall .section .text.SemihostingCall
+3 -3
View File
@@ -10,10 +10,10 @@ func Asm(asm string)
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, [{result}]", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1, // "value": 1
// "result": uintptr(unsafe.Pointer(&dest)), // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
+3 -3
View File
@@ -10,10 +10,10 @@ func Asm(asm string)
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, [{result}]", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1, // "value": 1
// "result": uintptr(unsafe.Pointer(&dest)), // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
+3 -3
View File
@@ -10,10 +10,10 @@ func Asm(asm string)
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "st {value}, [{result}]", // "st {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1, // "value": 1
// "result": uintptr(unsafe.Pointer(&dest)), // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
-7
View File
@@ -8,10 +8,3 @@ import "unsafe"
func NoEscape(p unsafe.Pointer) unsafe.Pointer { func NoEscape(p unsafe.Pointer) unsafe.Pointer {
return p return p
} }
func Escape[T any](x T) T {
// This function is either implemented in the compiler, or left undefined
// for some variation of T. The body of this function should not be compiled
// as-is.
panic("internal/abi.Escape: unreachable (implemented in the compiler)")
}
-7
View File
@@ -108,10 +108,6 @@ func (*stackState) unwind()
func (t *Task) Resume() { func (t *Task) Resume() {
// The current task must be saved and restored because this can nest on WASM with JS. // The current task must be saved and restored because this can nest on WASM with JS.
prevTask := currentTask prevTask := currentTask
if prevTask == nil {
// Save the system stack pointer.
saveStackPointer()
}
t.gcData.swap() t.gcData.swap()
currentTask = t currentTask = t
if !t.state.launched { if !t.state.launched {
@@ -127,9 +123,6 @@ func (t *Task) Resume() {
} }
} }
//go:linkname saveStackPointer runtime.saveStackPointer
func saveStackPointer()
//export tinygo_rewind //export tinygo_rewind
func (*state) rewind() func (*state) rewind()
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build scheduler.tasks && (esp32 || esp32s3) //go:build scheduler.tasks && esp32
package task package task
+2 -13
View File
@@ -58,7 +58,6 @@ void tinygo_task_init(void *mainTask, pthread_t *thread, int *numCPU, void *cont
// Using pthread_kill, we can still send the signal to a specific thread. // Using pthread_kill, we can still send the signal to a specific thread.
struct sigaction act = { 0 }; struct sigaction act = { 0 };
act.sa_handler = tinygo_task_gc_pause; act.sa_handler = tinygo_task_gc_pause;
act.sa_flags = SA_RESTART;
sigaction(taskPauseSignal, &act, NULL); sigaction(taskPauseSignal, &act, NULL);
// Obtain the number of CPUs available on program start (for NumCPU). // Obtain the number of CPUs available on program start (for NumCPU).
@@ -101,7 +100,7 @@ static void* start_wrapper(void *arg) {
}; };
// Start a new goroutine in an OS thread. // Start a new goroutine in an OS thread.
int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, uintptr_t *stackTop, uintptr_t stackSize, void *context) { int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, uintptr_t *stackTop, void *context) {
// Sanity check. Should get optimized away. // Sanity check. Should get optimized away.
if (sizeof(pthread_t) != sizeof(void*)) { if (sizeof(pthread_t) != sizeof(void*)) {
__builtin_trap(); __builtin_trap();
@@ -118,23 +117,13 @@ int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, u
#else #else
sem_init(&state.startlock, 0, 0); sem_init(&state.startlock, 0, 0);
#endif #endif
pthread_attr_t attrs; int result = pthread_create(thread, NULL, &start_wrapper, &state);
pthread_attr_init(&attrs);
pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attrs, stackSize);
int result = pthread_create(thread, &attrs, &start_wrapper, &state);
pthread_attr_destroy(&attrs);
if (result != 0) {
return result;
}
// Wait until the thread has been created and read all state_pass variables. // Wait until the thread has been created and read all state_pass variables.
#if __APPLE__ #if __APPLE__
dispatch_semaphore_wait(state.startlock, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(state.startlock, DISPATCH_TIME_FOREVER);
dispatch_release(state.startlock);
#else #else
sem_wait(&state.startlock); sem_wait(&state.startlock);
sem_destroy(&state.startlock);
#endif #endif
return result; return result;
+67 -103
View File
@@ -23,15 +23,16 @@ type state struct {
// is needed to be able to scan the stack. // is needed to be able to scan the stack.
stackTop uintptr stackTop uintptr
// Lowest address of the stack.
// This is populated when the thread is stopped by the GC.
stackBottom uintptr
// Next task in the activeTasks queue. // Next task in the activeTasks queue.
QueueNext *Task QueueNext *Task
// Semaphore to pause/resume the thread atomically. // Semaphore to pause/resume the thread atomically.
pauseSem Semaphore pauseSem Semaphore
// Semaphore used for stack scanning.
// We can't reuse pauseSem here since the thread might have been paused for
// other reasons (for example, because it was waiting on a channel).
gcSem Semaphore
} }
// Goroutine counter, starting at 0 for the main goroutine. // Goroutine counter, starting at 0 for the main goroutine.
@@ -95,9 +96,6 @@ func (t *Task) Resume() {
t.state.pauseSem.Post() t.state.pauseSem.Post()
} }
// otherGoroutines is the total number of live goroutines minus one.
var otherGoroutines uint32
// Start a new OS thread. // Start a new OS thread.
func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) { func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
t := &Task{} t := &Task{}
@@ -111,13 +109,12 @@ func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
// and the stop-the-world GC won't see threads that haven't started yet or // and the stop-the-world GC won't see threads that haven't started yet or
// are not fully started yet. // are not fully started yet.
activeTaskLock.Lock() activeTaskLock.Lock()
errCode := tinygo_task_start(fn, args, t, &t.state.thread, &t.state.stackTop, stackSize) errCode := tinygo_task_start(fn, args, t, &t.state.thread, &t.state.stackTop)
if errCode != 0 { if errCode != 0 {
runtimePanic("could not start thread") runtimePanic("could not start thread")
} }
t.state.QueueNext = activeTasks t.state.QueueNext = activeTasks
activeTasks = t activeTasks = t
otherGoroutines++
activeTaskLock.Unlock() activeTaskLock.Unlock()
} }
@@ -138,7 +135,6 @@ func taskExited(t *Task) {
break break
} }
} }
otherGoroutines--
activeTaskLock.Unlock() activeTaskLock.Unlock()
// Sanity check. // Sanity check.
@@ -147,42 +143,9 @@ func taskExited(t *Task) {
} }
} }
// scanWaitGroup is used to wait on until all threads have finished the current state transition. // Futex to wait on until all tasks have finished scanning the stack.
var scanWaitGroup waitGroup // This is basically a sync.WaitGroup.
var scanDoneFutex Futex
type waitGroup struct {
f Futex
}
func initWaitGroup(n uint32) waitGroup {
var wg waitGroup
wg.f.Store(n)
return wg
}
func (wg *waitGroup) done() {
if wg.f.Add(^uint32(0)) == 0 {
wg.f.WakeAll()
}
}
func (wg *waitGroup) wait() {
for {
val := wg.f.Load()
if val == 0 {
return
}
wg.f.Wait(val)
}
}
// gcState is used to track and notify threads when the GC is stopping/resuming.
var gcState Futex
const (
gcStateResumed = iota
gcStateStopped
)
// GC scan phase. Because we need to stop the world while scanning, this kinda // GC scan phase. Because we need to stop the world while scanning, this kinda
// needs to be done in the tasks package. // needs to be done in the tasks package.
@@ -192,71 +155,65 @@ const (
func GCStopWorldAndScan() { func GCStopWorldAndScan() {
current := Current() current := Current()
// NOTE: This does not need to be atomic. // Don't allow new goroutines to be started while pausing/resuming threads
if gcState.Load() == gcStateResumed { // in the stop-the-world phase.
// Don't allow new goroutines to be started while pausing/resuming threads activeTaskLock.Lock()
// in the stop-the-world phase.
activeTaskLock.Lock()
// Wait for threads to finish resuming. // Pause all other threads.
scanWaitGroup.wait() numOtherThreads := uint32(0)
// Change the gc state to stopped.
// NOTE: This does not need to be atomic.
gcState.Store(gcStateStopped)
// Set the number of threads to wait for.
scanWaitGroup = initWaitGroup(otherGoroutines)
// Pause all other threads.
for t := activeTasks; t != nil; t = t.state.QueueNext {
if t != current {
tinygo_task_send_gc_signal(t.state.thread)
}
}
// Wait for the threads to finish stopping.
scanWaitGroup.wait()
}
// Scan other thread stacks.
for t := activeTasks; t != nil; t = t.state.QueueNext { for t := activeTasks; t != nil; t = t.state.QueueNext {
if t != current { if t != current {
markRoots(t.state.stackBottom, t.state.stackTop) numOtherThreads++
tinygo_task_send_gc_signal(t.state.thread)
} }
} }
// Store the number of threads to wait for in the futex.
// This is the equivalent of doing an initial wg.Add(numOtherThreads).
scanDoneFutex.Store(numOtherThreads)
// Scan the current stack, and all current registers. // Scan the current stack, and all current registers.
scanCurrentStack() scanCurrentStack()
// Wake each paused thread for the first time so it will scan the stack.
for t := activeTasks; t != nil; t = t.state.QueueNext {
if t != current {
t.state.gcSem.Post()
}
}
// Wait until all threads have finished scanning their stack.
// This is the equivalent of wg.Wait()
for {
val := scanDoneFutex.Load()
if val == 0 {
break
}
scanDoneFutex.Wait(val)
}
// Scan all globals (implemented in the runtime). // Scan all globals (implemented in the runtime).
gcScanGlobals() gcScanGlobals()
} }
// After the GC is done scanning, resume all other threads. // After the GC is done scanning, resume all other threads.
//
// This must only be called after a GCStopWorldAndScan call.
func GCResumeWorld() { func GCResumeWorld() {
// NOTE: This does not need to be atomic. current := Current()
if gcState.Load() == gcStateResumed {
// This is already resumed. // Wake each paused thread for the second time, so they will resume normal
return // operation.
for t := activeTasks; t != nil; t = t.state.QueueNext {
if t != current {
t.state.gcSem.Post()
}
} }
// Set the wait group to track resume progress.
scanWaitGroup = initWaitGroup(otherGoroutines)
// Set the state to resumed.
gcState.Store(gcStateResumed)
// Wake all of the stopped threads.
gcState.WakeAll()
// Allow goroutines to start and exit again. // Allow goroutines to start and exit again.
activeTaskLock.Unlock() activeTaskLock.Unlock()
} }
//go:linkname markRoots runtime.markRoots
func markRoots(start, end uintptr)
// Scan globals, implemented in the runtime package. // Scan globals, implemented in the runtime package.
func gcScanGlobals() func gcScanGlobals()
@@ -264,27 +221,34 @@ var stackScanLock PMutex
//export tinygo_task_gc_pause //export tinygo_task_gc_pause
func tingyo_task_gc_pause(sig int32) { func tingyo_task_gc_pause(sig int32) {
// Write the entrty stack pointer to the state. // Wait until we get the signal to start scanning the stack.
Current().state.stackBottom = uintptr(stacksave()) Current().state.gcSem.Wait()
// Notify the GC that we are stopped. // Scan the thread stack.
scanWaitGroup.done() // Only scan a single thread stack at a time, because the GC marking phase
// doesn't support parallelism.
// TODO: it may be possible to call markRoots directly (without saving
// registers) since we are in a signal handler that already saved a bunch of
// registers. This is an optimization left for a future time.
stackScanLock.Lock()
scanCurrentStack()
stackScanLock.Unlock()
// Wait for the GC to resume. // Equivalent of wg.Done(): subtract one from the futex and if the result is
for gcState.Load() == gcStateStopped { // 0 (meaning we were the last in the waitgroup), wake the waiting thread.
gcState.Wait(gcStateStopped) n := uint32(1)
if scanDoneFutex.Add(-n) == 0 {
scanDoneFutex.Wake()
} }
// Notify the GC that we have resumed. // Wait until we get the signal we can resume normally (after the mark phase
scanWaitGroup.done() // has finished).
Current().state.gcSem.Wait()
} }
//go:export tinygo_scanCurrentStack //go:export tinygo_scanCurrentStack
func scanCurrentStack() func scanCurrentStack()
//go:linkname stacksave runtime.stacksave
func stacksave() unsafe.Pointer
// Return the highest address of the current stack. // Return the highest address of the current stack.
func StackTop() uintptr { func StackTop() uintptr {
return Current().state.stackTop return Current().state.stackTop
@@ -302,7 +266,7 @@ func tinygo_task_init(t *Task, thread *threadID, numCPU *int32)
// Here same as for tinygo_task_init. // Here same as for tinygo_task_init.
// //
//go:linkname tinygo_task_start tinygo_task_start //go:linkname tinygo_task_start tinygo_task_start
func tinygo_task_start(fn uintptr, args unsafe.Pointer, t *Task, thread *threadID, stackTop *uintptr, stackSize uintptr) int32 func tinygo_task_start(fn uintptr, args unsafe.Pointer, t *Task, thread *threadID, stackTop *uintptr) int32
// Pause the thread by sending it a signal. // Pause the thread by sending it a signal.
// //
+2 -2
View File
@@ -15,8 +15,8 @@ const (
P09 Pin = 9 P09 Pin = 9
P10 Pin = 10 P10 Pin = 10
P11 Pin = 11 P11 Pin = 11
P12 Pin = 12 // peripherals: I2C0 SDA P12 Pin = 12
P13 Pin = 13 // peripherals: I2C0 SCL P13 Pin = 13
P14 Pin = 14 P14 Pin = 14
P15 Pin = 15 P15 Pin = 15
P16 Pin = 16 P16 Pin = 16
-22
View File
@@ -1,22 +0,0 @@
//go:build gopher_arcade
package machine
// Return the current CPU frequency in hertz.
func CPUFrequency() uint32 {
return 8000000
}
const (
P5 Pin = PB0
P6 Pin = PB1
P7 Pin = PB2
P2 Pin = PB3
P3 Pin = PB4
P1 Pin = PB5
LED = P1
BUTTON_LEFT = P7
BUTTON_RIGHT = P5
SPEAKER = P6
)
-183
View File
@@ -1,183 +0,0 @@
//go:build metro_rp2350
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
GP23 Pin = GPIO23
GP24 Pin = GPIO24
GP25 Pin = GPIO25
GP26 Pin = GPIO26
GP27 Pin = GPIO27
GP28 Pin = GPIO28
GP29 Pin = GPIO29
GP30 Pin = GPIO30
GP31 Pin = GPIO31
GP32 Pin = GPIO32
GP33 Pin = GPIO33
GP34 Pin = GPIO34
GP35 Pin = GPIO35
GP36 Pin = GPIO36
GP37 Pin = GPIO37
GP38 Pin = GPIO38
GP39 Pin = GPIO39
GP40 Pin = GPIO40
GP41 Pin = GPIO41
GP42 Pin = GPIO42
GP43 Pin = GPIO43
GP44 Pin = GPIO44
GP45 Pin = GPIO45
GP46 Pin = GPIO46
// Boot button
BUTTON Pin = GPIO24
// Onboard LED
LED Pin = GPIO23
// Onboard NeoPixel
NEOPIXEL Pin = GPIO25
WS2812 Pin = GPIO25
// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)
// Arduino-header digital pins
const (
RX Pin = GPIO1
TX Pin = GPIO0
D2 Pin = GPIO2
D3 Pin = GPIO3
D4 Pin = GPIO4
D5 Pin = GPIO5
D6 Pin = GPIO6
D7 Pin = GPIO7
D8 Pin = GPIO8
D9 Pin = GPIO9
D10 Pin = GPIO10
D11 Pin = GPIO11
D22 Pin = GPIO22
D23 Pin = GPIO23
)
// Arduino-header analog pins
const (
A0 Pin = GPIO41
A1 Pin = GPIO42
A2 Pin = GPIO43
A3 Pin = GPIO44
A4 Pin = GPIO45
A5 Pin = GPIO46
)
// I2C Default pins on Raspberry Pico.
const (
I2C0_SDA_PIN = GP20
I2C0_SCL_PIN = GP21
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 = GPIO30
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO31 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO28 // Rx
// SPI header pins
MOSI Pin = SPI1_SDO_PIN
MISO Pin = SPI1_SDI_PIN
SCK Pin = SPI1_SCK_PIN
)
// SD card reader pins
const (
SD_SCK = GPIO34
SD_MOSI = GPIO35
SD_MISO = GPIO36
SDIO_DATA1 = GPIO37
SDIO_DATA2 = GPIO38
SD_CS = GPIO39
SD_CARD_DETECT = GPIO40
)
// HSTX pins
const (
CKN Pin = GPIO15
CKP Pin = GPIO14
D0N Pin = GPIO19
D0P Pin = GPIO18
D1N Pin = GPIO17
D1P Pin = GPIO16
D2N Pin = GPIO13
D2P Pin = GPIO12
D26 Pin = GPIO26
D27 Pin = GPIO27
SCL Pin = GPIO21
SDA Pin = GPIO20
)
// USB host header pins
const (
USB_HOST_DATA_PLUS Pin = GPIO32
USB_HOST_DATA_MINUS Pin = GPIO33
USB_HOST_5V_POWER Pin = GPIO29
)
// 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 = "Metro RP2350"
usb_STRING_MANUFACTURER = "Adafruit"
)
var (
usb_VID uint16 = 0x239A
usb_PID uint16 = 0x814E
)
-173
View File
@@ -1,173 +0,0 @@
//go:build pico2_ice
// Most of the info is from
// https://pico2-ice.tinyvision.ai/md_pinout.html although
// (2025-09-07) RP4 appears twice in that pinout - the schematic is
// more clear. Consistent with other RPi boards, we use GPn instead of
// RPn to reference the RPi connected pins.
package machine
// GPIO pins
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
GP23 = GPIO23
GP24 = GPIO24
GP25 = GPIO25
GP26 = GPIO26
GP27 = GPIO27
GP28 = GPIO28
GP29 = GPIO29
GP30 = GPIO30
GP31 = GPIO31
GP32 = GPIO32
GP33 = GPIO33
GP34 = GPIO34
GP35 = GPIO35
GP36 = GPIO36
GP37 = GPIO37
GP38 = GPIO38
GP39 = GPIO39
GP40 = GPIO40
GP41 = GPIO41
GP42 = GPIO42
GP43 = GPIO43
GP44 = GPIO44
GP45 = GPIO45
GP46 = GPIO46
GP47 = GPIO47
// RPi pins shared with ICE. The ICE number is what appears on
// the board silkscreen.
ICE9 = GP28
ICE11 = GP29
ICE14 = GP7
ICE15 = GP6
ICE16 = GP5
ICE17 = GP4
ICE18 = GP27
ICE19 = GP23
ICE20 = GP22
ICE21 = GP26
ICE23 = GP25
ICE25 = GP30
ICE26 = GP24
ICE27 = GP20
// FPGA Clock pin.
ICE35_G0 = GP21
// Silkscreen & Pinout names
ICE_SSN = ICE16
ICE_SO = ICE14
ICE_SI = ICE17
ICE_CK = ICE15
SD = GP2
SC = GP3
FPGA_RSTN = GP31
A3 = GP32
A1 = GP33
A4 = GP34
A2 = GP35
B3 = GP36
B1 = GP37
B4 = GP38
B2 = GP39
N0 = GP40 // On the board these are labeled "~0"
N1 = GP41
N2 = GP42
N3 = GP43
N4 = GP44
N5 = GP45
N6 = GP46
// Functions from Schematic.
ICE_DONE = GP40
USB_BOOT = GP42
// Button
SW1 = GP42
BOOTSEL = GP42
// Tricolor LEDs
LED_RED = GP1
LED_GREEN = GP0
LED_BLUE = GP9
// Onboard LED
LED = LED_GREEN
// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)
// This board does not define default i2c pins.
const (
I2C0_SDA_PIN = NoPin
I2C0_SCL_PIN = NoPin
I2C1_SDA_PIN = NoPin
I2C1_SCL_PIN = NoPin
)
// 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 = "Pico2"
usb_STRING_MANUFACTURER = "Raspberry Pi"
)
var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000A
)
-58
View File
@@ -1,58 +0,0 @@
//go:build xiao_esp32s3
// This file contains the pin mappings for the Seeed XIAO ESP32S3 boards.
//
// Seeed Studio XIAO ESP32S3 is an IoT mini development board based on
// the Espressif ESP32-S3 WiFi/Bluetooth dual-mode chip.
//
// - https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html
// - https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/
package machine
// Digital Pins
const (
D0 = GPIO1
D1 = GPIO2
D2 = GPIO3
D3 = GPIO4
D4 = GPIO5
D5 = GPIO6
D6 = GPIO43
D7 = GPIO44
D8 = GPIO7
D9 = GPIO8
D10 = GPIO9
)
// Analog pins
const (
A0 = GPIO1
A1 = GPIO2
A2 = GPIO3
A3 = GPIO4
)
// UART pins
const (
UART_RX_PIN = GPIO44
UART_TX_PIN = GPIO43
)
// I2C pins
const (
SDA_PIN = GPIO5
SCL_PIN = GPIO6
)
// SPI pins
const (
SPI_SCK_PIN = GPIO7
SPI_SDI_PIN = GPIO9
SPI_SDO_PIN = GPIO8
)
// Onboard LEDs
const (
LED = GPIO21
)
-5
View File
@@ -43,11 +43,6 @@ type BlockDevice interface {
io.ReaderAt io.ReaderAt
// WriteAt writes the given number of bytes to the block device. // WriteAt writes the given number of bytes to the block device.
//
// This interface directly writes data to the underlying block device.
// Different kinds of devices have different requirements: most can only
// write data after the page has been erased, and many can only write data
// with specific alignment (such as 4-byte alignment).
io.WriterAt io.WriterAt
// Size returns the number of bytes in this block device. // Size returns the number of bytes in this block device.
+1 -31
View File
@@ -1,9 +1,6 @@
package machine package machine
import ( import "errors"
"errors"
"unsafe"
)
var ( var (
ErrTimeoutRNG = errors.New("machine: RNG Timeout") ErrTimeoutRNG = errors.New("machine: RNG Timeout")
@@ -65,30 +62,3 @@ func (p Pin) Low() {
type ADC struct { type ADC struct {
Pin Pin Pin Pin
} }
// Convert the pointer to a uintptr, to be used for memory I/O (DMA for
// example). It also means the pointer is "gone" as far as the compiler is
// concerned, and a GC cycle might deallocate the object. To prevent this from
// happening, also call keepAliveNoEscape at a point after the address isn't
// accessed anymore by the hardware.
// The only exception is if the pointer is accessed later in a volatile way
// (volatile read/write), which also forces the value to stay alive until that
// point.
//
// This function is treated specially by the compiler to mark the 'ptr'
// parameter as not escaping.
//
// TODO: this function should eventually be replaced with the proposed ptrtoaddr
// instruction in LLVM. See:
// https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/10
// https://github.com/llvm/llvm-project/pull/139357
func unsafeNoEscape(ptr unsafe.Pointer) uintptr {
return uintptr(ptr)
}
// Make sure the given pointer stays alive until this point. This is similar to
// runtime.KeepAlive, with the difference that it won't let the pointer escape.
// This is typically used together with unsafeNoEscape.
//
// This is a compiler intrinsic.
func keepAliveNoEscape(ptr unsafe.Pointer)
-4
View File
@@ -519,10 +519,6 @@ type Serialer interface {
RTS() bool RTS() bool
} }
func initUSB() {
// nothing to do here
}
// USB Serial/JTAG Controller // USB Serial/JTAG Controller
// See esp32-c3_technical_reference_manual_en.pdf // See esp32-c3_technical_reference_manual_en.pdf
// pg. 736 // pg. 736
-312
View File
@@ -1,312 +0,0 @@
//go:build esp32s3
package machine
import (
"device/esp"
"errors"
"runtime/volatile"
"unsafe"
)
const deviceName = esp.Device
const xtalClock = 40_000000 // 40MHz
const apbClock = 80_000000 // 80MHz
const cryptoPWMClock = 160_000000 // 160MHz
// GetCPUFrequency returns the current CPU frequency of the chip.
func GetCPUFrequency() (uint32, error) {
switch esp.SYSTEM.GetSYSCLK_CONF_SOC_CLK_SEL() {
case 0:
return xtalClock / (esp.SYSTEM.GetSYSCLK_CONF_PRE_DIV_CNT() + 1), nil
case 1:
switch esp.SYSTEM.GetCPU_PER_CONF_CPUPERIOD_SEL() {
case 0:
return 80e6, nil
case 1:
return 160e6, nil
case 2:
// If esp.SYSTEM.GetCPU_PER_CONF_PLL_FREQ_SEL() == 1, this is undefined
return 240e6, nil
}
case 2:
//RC Fast Clock
return (175e5) / (esp.SYSTEM.GetSYSCLK_CONF_PRE_DIV_CNT() + 1), nil
}
return 0, errors.New("machine: Unable to determine current cpu frequency")
}
// SetCPUFrequency sets the frequency of the CPU to one of several targets
func SetCPUFrequency(frequency uint32) error {
// Always assume we are on PLL. Lower frequencies can be set with a different
// clock source, but this will change the behavior of APB clock and Crypto PWM
// clock
//esp.SYSTEM.SetSYSCLK_CONF_SOC_CLK_SEL(1)
switch frequency {
case 80_000000:
esp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(0)
esp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(0) // Reduce PLL freq when possible
return nil
case 160_000000:
esp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(1)
esp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(0)
return nil
case 240_000000:
esp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(1) // Increase PLL freq when needed
esp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(2)
return nil
}
return errors.New("machine: Unsupported CPU frequency selected. Supported: 80, 160, 240 MHz")
}
var (
ErrInvalidSPIBus = errors.New("machine: invalid SPI bus")
)
const (
PinOutput PinMode = iota
PinInput
PinInputPullup
PinInputPulldown
)
// Hardware pin numbers
const (
GPIO0 Pin = 0
GPIO1 Pin = 1
GPIO2 Pin = 2
GPIO3 Pin = 3
GPIO4 Pin = 4
GPIO5 Pin = 5
GPIO6 Pin = 6
GPIO7 Pin = 7
GPIO8 Pin = 8
GPIO9 Pin = 9
GPIO10 Pin = 10
GPIO11 Pin = 11
GPIO12 Pin = 12
GPIO13 Pin = 13
GPIO14 Pin = 14
GPIO15 Pin = 15
GPIO16 Pin = 16
GPIO17 Pin = 17
GPIO18 Pin = 18
GPIO19 Pin = 19
GPIO20 Pin = 20
GPIO21 Pin = 21
GPIO26 Pin = 26
GPIO27 Pin = 27
GPIO28 Pin = 28
GPIO29 Pin = 29
GPIO30 Pin = 30
GPIO31 Pin = 31
GPIO32 Pin = 32
GPIO33 Pin = 33
GPIO34 Pin = 34
GPIO35 Pin = 35
GPIO36 Pin = 36
GPIO37 Pin = 37
GPIO38 Pin = 38
GPIO39 Pin = 39
GPIO40 Pin = 40
GPIO41 Pin = 41
GPIO42 Pin = 42
GPIO43 Pin = 43
GPIO44 Pin = 44
GPIO45 Pin = 45
GPIO46 Pin = 46
GPIO47 Pin = 47
GPIO48 Pin = 48
)
// Configure this pin with the given configuration.
func (p Pin) Configure(config PinConfig) {
// Output function 256 is a special value reserved for use as a regular GPIO
// pin. Peripherals (SPI etc) can set a custom output function by calling
// lowercase configure() instead with a signal name.
p.configure(config, 256)
}
// configure is the same as Configure, but allows for setting a specific input
// or output signal.
// Signals are always routed through the GPIO matrix for simplicity. Output
// signals are configured in FUNCx_OUT_SEL_CFG which selects a particular signal
// to output on a given pin. Input signals are configured in FUNCy_IN_SEL_CFG,
// which sets the pin to use for a particular input signal.
func (p Pin) configure(config PinConfig, signal uint32) {
if p == NoPin {
// This simplifies pin configuration in peripherals such as SPI.
return
}
ioConfig := uint32(0)
// MCU_SEL: Function 1 is always GPIO
ioConfig |= (1 << esp.IO_MUX_GPIO_MCU_SEL_Pos)
// FUN_IE: Make this pin an input pin (always set for GPIO operation)
ioConfig |= esp.IO_MUX_GPIO_FUN_IE
// DRV: Set drive strength to 20 mA as a default. Pins 17 and 18 are special
var drive uint32
if p == GPIO17 || p == GPIO18 {
drive = 1 // 20 mA
} else {
drive = 2 // 20 mA
}
ioConfig |= (drive << esp.IO_MUX_GPIO_FUN_DRV_Pos)
// WPU/WPD: Select pull mode.
if config.Mode == PinInputPullup {
ioConfig |= esp.IO_MUX_GPIO_FUN_WPU
} else if config.Mode == PinInputPulldown {
ioConfig |= esp.IO_MUX_GPIO_FUN_WPD
}
// Set configuration
ioRegister := p.ioMuxReg()
ioRegister.Set(ioConfig)
switch config.Mode {
case PinOutput:
// Set the 'output enable' bit.
if p < 32 {
esp.GPIO.ENABLE_W1TS.Set(1 << p)
} else {
esp.GPIO.ENABLE1_W1TS.Set(1 << (p - 32))
}
// Set the signal to read the output value from. It can be a peripheral
// output signal, or the special value 256 which indicates regular GPIO
// usage.
p.outFunc().Set(signal)
case PinInput, PinInputPullup, PinInputPulldown:
// Clear the 'output enable' bit.
if p < 32 {
esp.GPIO.ENABLE_W1TC.Set(1 << p)
} else {
esp.GPIO.ENABLE1_W1TC.Set(1 << (p - 32))
}
if signal != 256 {
// Signal is a peripheral function (not a simple GPIO). Connect this
// signal to the pin.
// Note that outFunc and inFunc work in the opposite direction.
// outFunc configures a pin to use a given output signal, while
// inFunc specifies a pin to use to read the signal from.
inFunc(signal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(p)<<esp.GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos)
}
}
}
// ioMuxReg returns the IO_MUX_n_REG register used for configuring the io mux for
// this pin
func (p Pin) ioMuxReg() *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.IO_MUX.GPIO0), uintptr(p)*4))
}
// outFunc returns the FUNCx_OUT_SEL_CFG register used for configuring the
// output function selection.
func (p Pin) outFunc() *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_OUT_SEL_CFG), uintptr(p)*4))
}
// inFunc returns the FUNCy_IN_SEL_CFG register used for configuring the input
// function selection.
func inFunc(signal uint32) *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_IN_SEL_CFG), uintptr(signal)*4))
}
// Set the pin to high or low.
// Warning: only use this on an output pin!
func (p Pin) Set(value bool) {
if value {
reg, mask := p.portMaskSet()
reg.Set(mask)
} else {
reg, mask := p.portMaskClear()
reg.Set(mask)
}
}
// Return the register and mask to enable a given GPIO pin. This can be used to
// implement bit-banged drivers.
//
// Warning: only use this on an output pin!
func (p Pin) PortMaskSet() (*uint32, uint32) {
reg, mask := p.portMaskSet()
return &reg.Reg, mask
}
// Return the register and mask to disable a given GPIO pin. This can be used to
// implement bit-banged drivers.
//
// Warning: only use this on an output pin!
func (p Pin) PortMaskClear() (*uint32, uint32) {
reg, mask := p.portMaskClear()
return &reg.Reg, mask
}
func (p Pin) portMaskSet() (*volatile.Register32, uint32) {
if p < 32 {
return &esp.GPIO.OUT_W1TS, 1 << p
} else {
return &esp.GPIO.OUT1_W1TS, 1 << (p - 32)
}
}
func (p Pin) portMaskClear() (*volatile.Register32, uint32) {
if p < 32 {
return &esp.GPIO.OUT_W1TC, 1 << p
} else {
return &esp.GPIO.OUT1_W1TC, 1 << (p - 32)
}
}
// Get returns the current value of a GPIO pin when the pin is configured as an
// input or as an output.
func (p Pin) Get() bool {
if p < 32 {
return esp.GPIO.IN.Get()&(1<<p) != 0
} else {
return esp.GPIO.IN1.Get()&(1<<(p-32)) != 0
}
}
var DefaultUART = UART0
var (
UART0 = &_UART0
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
UART1 = &_UART1
_UART1 = UART{Bus: esp.UART1, Buffer: NewRingBuffer()}
UART2 = &_UART2
_UART2 = UART{Bus: esp.UART2, Buffer: NewRingBuffer()}
)
type UART struct {
Bus *esp.UART_Type
Buffer *RingBuffer
}
func (uart *UART) Configure(config UARTConfig) {
if config.BaudRate == 0 {
config.BaudRate = 115200
}
// Crystal clock source is selected by default
uart.Bus.CLKDIV.Set(xtalClock / config.BaudRate)
}
func (uart *UART) writeByte(b byte) error {
for (uart.Bus.STATUS.Get()>>16)&0xff >= 128 {
// Read UART_TXFIFO_CNT from the status register, which indicates how
// many bytes there are in the transmit buffer. Wait until there are
// less than 128 bytes in this buffer (the default buffer size).
}
uart.Bus.FIFO.Set(uint32(b))
return nil
}
func (uart *UART) flush() {}
// TODO: SPI
-117
View File
@@ -3,9 +3,7 @@
package machine package machine
import ( import (
"device/arm"
"device/nrf" "device/nrf"
"errors"
"internal/binary" "internal/binary"
"runtime/interrupt" "runtime/interrupt"
"unsafe" "unsafe"
@@ -382,10 +380,6 @@ func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
// If the length of p is not long enough it will be padded with 0xFF bytes. // If the length of p is not long enough it will be padded with 0xFF bytes.
// This method assumes that the destination is already erased. // This method assumes that the destination is already erased.
func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
if len(p) == 0 {
return 0, nil // nothing to do (and it would fail in sd_flash_write)
}
if FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() { if FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {
return 0, errFlashCannotWritePastEOF return 0, errFlashCannotWritePastEOF
} }
@@ -393,34 +387,6 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
address := FlashDataStart() + uintptr(off) address := FlashDataStart() + uintptr(off)
padded := flashPad(p, int(f.WriteBlockSize())) padded := flashPad(p, int(f.WriteBlockSize()))
// When the SoftDevice is enabled, access to the flash is restricted and
// must go through the SoftDevice API.
if isSoftDeviceEnabled() {
// Call sd_flash_write, which is SVC_SOC_BASE + 9 in all the
// SoftDevices I've checked.
// Documentation:
// https://docs.nordicsemi.com/bundle/s140_v6.0.0_api/page/group_n_r_f_s_o_c_f_u_n_c_t_i_o_n_s.html
result := arm.SVCall3(0x20+9, address, &p[0], uint32(len(p)))
if result != 0 {
// Could not queue flash operation? Not sure when this can
// happen.
return 0, flashError
}
// Wait until the SoftDevice is finished.
flashStatus = flashStatusBusy
for flashStatus == flashStatusBusy {
handleSoftDeviceEvents()
}
// Check whether the operation was successful.
if flashStatus != flashStatusOk {
flashStatus = flashStatusOk
return 0, flashError
}
return len(p), nil
}
waitWhileFlashBusy() waitWhileFlashBusy()
nrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Wen) nrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Wen)
@@ -462,40 +428,6 @@ func (f flashBlockDevice) EraseBlockSize() int64 {
// supports this. The start and len parameters are in block numbers, use // supports this. The start and len parameters are in block numbers, use
// EraseBlockSize to map addresses to blocks. // EraseBlockSize to map addresses to blocks.
func (f flashBlockDevice) EraseBlocks(start, len int64) error { func (f flashBlockDevice) EraseBlocks(start, len int64) error {
// When the SoftDevice is enabled, access to the flash is restricted and
// must go through the SoftDevice API.
if isSoftDeviceEnabled() {
for i := range uint32(len) {
flashPage := uint32(FlashDataStart())/eraseBlockSizeValue + uint32(start) + i
// Call sd_flash_page_erase, which is SVC_SOC_BASE + 8 in all the
// SoftDevices I've checked.
// Documentation:
// https://docs.nordicsemi.com/bundle/s140_v6.0.0_api/page/group_n_r_f_s_o_c_f_u_n_c_t_i_o_n_s.html#ga9c93dd94a138ad8b5ed3693ea38ffb3e
result := arm.SVCall1(0x20+8, flashPage)
if result != 0 {
// Could not queue flash operation? Not sure when this can
// happen.
return flashError
}
// Wait until the SoftDevice is finished.
flashStatus = flashStatusBusy
for flashStatus == flashStatusBusy {
handleSoftDeviceEvents()
}
// Check whether the operation was successful.
if flashStatus != flashStatusOk {
flashStatus = flashStatusOk
return flashError
}
}
return nil
}
// SoftDevice is not used or enabled. Use NVIC directly.
address := FlashDataStart() + uintptr(start*f.EraseBlockSize()) address := FlashDataStart() + uintptr(start*f.EraseBlockSize())
waitWhileFlashBusy() waitWhileFlashBusy()
@@ -515,52 +447,3 @@ func waitWhileFlashBusy() {
for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready { for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready {
} }
} }
var flashError = errors.New("machine: flash operation failed")
const (
flashStatusOk = iota
flashStatusError
flashStatusBusy
)
var flashStatus uint8 = flashStatusOk
var sdEvent uint32
// Process all queued SoftDevice events. May only be called when the SoftDevice is enabled.
//
// Normally these are handled in the same interrupt where Bluetooth events are
// handled. But in TinyGo, that's complicated. One option would be to put it in
// the tinygo.org/x/bluetooth package, but that would cause a circular
// dependency between the machine and the bluetooth package. Another would be to
// put it here, but let the bluetooth package call handleSoftDeviceEvents, but
// that relies on updating the bluetooth package at the same time. As a
// compromise, these events are handled directly where they are expected (here
// in the machine package). This works in practice since there are only very few
// of such events (at the moment, only flash-related ones which is in the
// machine package anyway).
func handleSoftDeviceEvents() {
for {
var result uintptr
if nrf.Device == "nrf52" || nrf.Device == "nrf52840" || nrf.Device == "nrf52833" {
// sd_evt_get: SOC_SVC_BASE_NOT_AVAILABLE + 31
result = arm.SVCall1(0x2C+31, &sdEvent)
} else {
return // TODO: nrf51 etc
}
if result != 0 {
// Some error occured. The only possible error is
// NRF_ERROR_NOT_FOUND, which means there are no more events.
return
}
// The following events are the same numbers in all SoftDevices I've checked.
switch sdEvent {
case 2: // NRF_EVT_FLASH_OPERATION_SUCCESS
flashStatus = flashStatusOk
case 3: // NRF_EVT_FLASH_OPERATION_ERROR
flashStatus = flashStatusError
}
}
}
-2
View File
@@ -69,5 +69,3 @@ const eraseBlockSizeValue = 4096
func eraseBlockSize() int64 { func eraseBlockSize() int64 {
return eraseBlockSizeValue return eraseBlockSizeValue
} }
const spiMaxBufferSize = 255 // from the datasheet: TXD.MAXCNT and RXD.MAXCNT
-2
View File
@@ -90,5 +90,3 @@ const eraseBlockSizeValue = 4096
func eraseBlockSize() int64 { func eraseBlockSize() int64 {
return eraseBlockSizeValue return eraseBlockSizeValue
} }
const spiMaxBufferSize = 0xffff // from the datasheet: TXD.MAXCNT and RXD.MAXCNT
-6
View File
@@ -108,9 +108,3 @@ const eraseBlockSizeValue = 4096
func eraseBlockSize() int64 { func eraseBlockSize() int64 {
return eraseBlockSizeValue return eraseBlockSizeValue
} }
const spiMaxBufferSize = 0xffff // from the datasheet: TXD.MAXCNT and RXD.MAXCNT
// ADC instance for the VDDH input pin. This pin is typically connected to USB
// input voltage (~5V) or directly to a battery.
var ADC_VDDH = ADC{adcVDDHPin}
+7 -20
View File
@@ -49,7 +49,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
// Configure for a single shot to perform both write and read (as applicable) // Configure for a single shot to perform both write and read (as applicable)
if len(w) != 0 { if len(w) != 0 {
i2c.Bus.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(w))))) i2c.Bus.TXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&w[0]))))
i2c.Bus.TXD.MAXCNT.Set(uint32(len(w))) i2c.Bus.TXD.MAXCNT.Set(uint32(len(w)))
// If no read, immediately signal stop after TX // If no read, immediately signal stop after TX
@@ -58,7 +58,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
} }
} }
if len(r) != 0 { if len(r) != 0 {
i2c.Bus.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(r))))) i2c.Bus.RXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&r[0]))))
i2c.Bus.RXD.MAXCNT.Set(uint32(len(r))) i2c.Bus.RXD.MAXCNT.Set(uint32(len(r)))
// Auto-start Rx after Tx and Stop after Rx // Auto-start Rx after Tx and Stop after Rx
@@ -78,22 +78,17 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
// Allow scheduler to run // Allow scheduler to run
gosched() gosched()
// Handle first occurrence of error by ensuring STOP sent on bus // Handle errors by ensuring STOP sent on bus
if err == nil && i2c.Bus.EVENTS_ERROR.Get() != 0 { if i2c.Bus.EVENTS_ERROR.Get() != 0 {
err = twiCError(i2c.Bus.ERRORSRC.Get())
if i2c.Bus.EVENTS_STOPPED.Get() == 0 { if i2c.Bus.EVENTS_STOPPED.Get() == 0 {
// STOP cannot be sent during SUSPEND // STOP cannot be sent during SUSPEND
i2c.Bus.TASKS_RESUME.Set(1) i2c.Bus.TASKS_RESUME.Set(1)
i2c.Bus.TASKS_STOP.Set(1) i2c.Bus.TASKS_STOP.Set(1)
} }
err = twiCError(i2c.Bus.ERRORSRC.Get())
} }
} }
// Make sure the w and r buffers stay alive until this point, so they won't
// be garbage collected while the buffers are used by the hardware.
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(w)))
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(r)))
return return
} }
@@ -122,7 +117,7 @@ func (i2c *I2C) Listen(addr uint8) error {
// //
// For request events, the caller MUST call `Reply` to avoid hanging the i2c bus indefinitely. // For request events, the caller MUST call `Reply` to avoid hanging the i2c bus indefinitely.
func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error) { func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error) {
i2c.BusT.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(buf))))) i2c.BusT.RXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&buf[0]))))
i2c.BusT.RXD.MAXCNT.Set(uint32(len(buf))) i2c.BusT.RXD.MAXCNT.Set(uint32(len(buf)))
i2c.BusT.TASKS_PREPARERX.Set(nrf.TWIS_TASKS_PREPARERX_TASKS_PREPARERX_Trigger) i2c.BusT.TASKS_PREPARERX.Set(nrf.TWIS_TASKS_PREPARERX_TASKS_PREPARERX_Trigger)
@@ -139,10 +134,6 @@ func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err err
} }
} }
// Make sure buf stays alive until this point, so it won't be garbage
// collected while it is used by the hardware.
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))
count = 0 count = 0
evt = I2CFinish evt = I2CFinish
err = nil err = nil
@@ -172,7 +163,7 @@ func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err err
// Reply supplies the response data the controller. // Reply supplies the response data the controller.
func (i2c *I2C) Reply(buf []byte) error { func (i2c *I2C) Reply(buf []byte) error {
i2c.BusT.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(buf))))) i2c.BusT.TXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&buf[0]))))
i2c.BusT.TXD.MAXCNT.Set(uint32(len(buf))) i2c.BusT.TXD.MAXCNT.Set(uint32(len(buf)))
i2c.BusT.EVENTS_STOPPED.Set(0) i2c.BusT.EVENTS_STOPPED.Set(0)
@@ -189,10 +180,6 @@ func (i2c *I2C) Reply(buf []byte) error {
} }
} }
// Make sure the buffer stays alive until this point, so it won't be garbage
// collected while it is used by the hardware.
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))
i2c.BusT.EVENTS_STOPPED.Set(0) i2c.BusT.EVENTS_STOPPED.Set(0)
return nil return nil
+24 -37
View File
@@ -12,8 +12,6 @@ func CPUFrequency() uint32 {
return 64000000 return 64000000
} }
var adcVDDHPin = Pin(254) // special pin number for VDDH on the nrf52840
// InitADC initializes the registers needed for ADC. // InitADC initializes the registers needed for ADC.
func InitADC() { func InitADC() {
// Enable ADC. // Enable ADC.
@@ -28,7 +26,7 @@ func InitADC() {
// Samples can be 1(default), 2, 4, 8, 16, 32, 64, 128, 256 samples // Samples can be 1(default), 2, 4, 8, 16, 32, 64, 128, 256 samples
func (a *ADC) Configure(config ADCConfig) { func (a *ADC) Configure(config ADCConfig) {
var configVal uint32 = nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESP_Pos | var configVal uint32 = nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESP_Pos |
nrf.SAADC_CH_CONFIG_RESN_Bypass<<nrf.SAADC_CH_CONFIG_RESN_Pos | nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESN_Pos |
nrf.SAADC_CH_CONFIG_REFSEL_Internal<<nrf.SAADC_CH_CONFIG_REFSEL_Pos | nrf.SAADC_CH_CONFIG_REFSEL_Internal<<nrf.SAADC_CH_CONFIG_REFSEL_Pos |
nrf.SAADC_CH_CONFIG_MODE_SE<<nrf.SAADC_CH_CONFIG_MODE_Pos nrf.SAADC_CH_CONFIG_MODE_SE<<nrf.SAADC_CH_CONFIG_MODE_Pos
@@ -118,43 +116,36 @@ func (a *ADC) Configure(config ADCConfig) {
// Get returns the current value of an ADC pin in the range 0..0xffff. // Get returns the current value of an ADC pin in the range 0..0xffff.
func (a *ADC) Get() uint16 { func (a *ADC) Get() uint16 {
var adcPin uint32 var pwmPin uint32
var rawValue volatile.Register16 var rawValue volatile.Register16
switch a.Pin { switch a.Pin {
case 2: case 2:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0
case 3: case 3:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1
case 4: case 4:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2
case 5: case 5:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3
case 28: case 28:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4
case 29: case 29:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5
case 30: case 30:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6
case 31: case 31:
adcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7 pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7
case adcVDDHPin:
if Device == "nrf52840" {
adcPin = 0x0D // VDDHDIV5 on the nrf52840
} else {
return 0
}
default: default:
return 0 return 0
} }
// Set pin to read. // Set pin to read.
nrf.SAADC.CH[0].PSELP.Set(adcPin) nrf.SAADC.CH[0].PSELN.Set(pwmPin)
nrf.SAADC.CH[0].PSELP.Set(pwmPin)
// Destination for sample result. // Destination for sample result.
// Note: rawValue doesn't need to be kept alive for the GC, since the nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&rawValue))))
// volatile read later will force it to stay alive.
nrf.SAADC.RESULT.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(&rawValue))))
nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample
// Start tasks. // Start tasks.
@@ -310,18 +301,20 @@ func (spi *SPI) Transfer(w byte) (byte, error) {
// padded until they fit: if len(w) > len(r) the extra bytes received will be // padded until they fit: if len(w) > len(r) the extra bytes received will be
// dropped and if len(w) < len(r) extra 0 bytes will be sent. // dropped and if len(w) < len(r) extra 0 bytes will be sent.
func (spi *SPI) Tx(w, r []byte) error { func (spi *SPI) Tx(w, r []byte) error {
// Unfortunately the hardware (on the nrf52832) only supports a limited // Unfortunately the hardware (on the nrf52832) only supports up to 255
// amount of bytes in the buffers (depending on the chip), so if either w or // bytes in the buffers, so if either w or r is longer than that the
// r is longer than that the transfer needs to be broken up in pieces. // transfer needs to be broken up in pieces.
// The nrf52840 supports far larger buffers however, which isn't yet
// supported.
for len(r) != 0 || len(w) != 0 { for len(r) != 0 || len(w) != 0 {
// Prepare the SPI transfer: set the DMA pointers and lengths. // Prepare the SPI transfer: set the DMA pointers and lengths.
// read buffer // read buffer
nr := uint32(len(r)) nr := uint32(len(r))
if nr > 0 { if nr > 0 {
if nr > spiMaxBufferSize { if nr > 255 {
nr = spiMaxBufferSize nr = 255
} }
spi.Bus.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(r))))) spi.Bus.RXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&r[0]))))
r = r[nr:] r = r[nr:]
} }
spi.Bus.RXD.MAXCNT.Set(nr) spi.Bus.RXD.MAXCNT.Set(nr)
@@ -329,10 +322,10 @@ func (spi *SPI) Tx(w, r []byte) error {
// write buffer // write buffer
nw := uint32(len(w)) nw := uint32(len(w))
if nw > 0 { if nw > 0 {
if nw > spiMaxBufferSize { if nw > 255 {
nw = spiMaxBufferSize nw = 255
} }
spi.Bus.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(w))))) spi.Bus.TXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&w[0]))))
w = w[nw:] w = w[nw:]
} }
spi.Bus.TXD.MAXCNT.Set(nw) spi.Bus.TXD.MAXCNT.Set(nw)
@@ -342,16 +335,10 @@ func (spi *SPI) Tx(w, r []byte) error {
// finished if the transfer is send-only (a common case). // finished if the transfer is send-only (a common case).
spi.Bus.TASKS_START.Set(1) spi.Bus.TASKS_START.Set(1)
for spi.Bus.EVENTS_END.Get() == 0 { for spi.Bus.EVENTS_END.Get() == 0 {
gosched()
} }
spi.Bus.EVENTS_END.Set(0) spi.Bus.EVENTS_END.Set(0)
} }
// Make sure the w and r buffers stay alive for the GC until this point,
// since they are used by the hardware but not otherwise visible.
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(r)))
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(w)))
return nil return nil
} }
-4
View File
@@ -7,7 +7,3 @@ package machine
func GetRNG() (ret uint32, err error) { func GetRNG() (ret uint32, err error) {
return getRNG() return getRNG()
} }
func isSoftDeviceEnabled() bool {
return false
}
+6 -8
View File
@@ -11,8 +11,9 @@ import (
// avoid a heap allocation in GetRNG. // avoid a heap allocation in GetRNG.
var ( var (
bytesAvailable uint8 softdeviceEnabled uint8
buf [4]uint8 bytesAvailable uint8
buf [4]uint8
errNoSoftDeviceSupport = errors.New("rng: softdevice not supported on this device") errNoSoftDeviceSupport = errors.New("rng: softdevice not supported on this device")
errNotEnoughRandomData = errors.New("rng: not enough random data available") errNotEnoughRandomData = errors.New("rng: not enough random data available")
@@ -23,7 +24,9 @@ var (
func GetRNG() (ret uint32, err error) { func GetRNG() (ret uint32, err error) {
// First check whether the SoftDevice is enabled. // First check whether the SoftDevice is enabled.
// sd_rand_application_bytes_available_get cannot be called when the SoftDevice is not enabled. // sd_rand_application_bytes_available_get cannot be called when the SoftDevice is not enabled.
if !isSoftDeviceEnabled() { arm.SVCall1(0x12, &softdeviceEnabled) // sd_softdevice_is_enabled
if softdeviceEnabled == 0 {
return getRNG() return getRNG()
} }
@@ -54,8 +57,3 @@ func GetRNG() (ret uint32, err error) {
return uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24, nil return uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24, nil
} }
// This function is defined in the runtime, but we need it too.
//
//go:linkname isSoftDeviceEnabled runtime.isSoftDeviceEnabled
func isSoftDeviceEnabled() bool
-4
View File
@@ -58,10 +58,6 @@ func machineInit() {
// Peripheral clocks should now all be running // Peripheral clocks should now all be running
unresetBlockWait(RESETS_RESET_Msk) unresetBlockWait(RESETS_RESET_Msk)
// DBGPAUSE pauses the timer when a debugger is connected. This prevents
// sleep functions from ever returning, so disable it.
timer.setDbgPause(false)
} }
//go:linkname ticks runtime.machineTicks //go:linkname ticks runtime.machineTicks
-25
View File
@@ -124,31 +124,6 @@ const (
fnXIP pinFunc = 0 fnXIP pinFunc = 0
) )
// validPins confirms that the SPI pin selection is a legitimate one
// for the the 2040 chip.
func (spi *SPI) validPins(config SPIConfig) error {
var okSDI, okSDO, okSCK bool
switch spi.Bus {
case rp.SPI0:
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
case rp.SPI1:
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
}
switch {
case !okSDI:
return errSPIInvalidSDI
case !okSDO:
return errSPIInvalidSDO
case !okSCK:
return errSPIInvalidSCK
}
return nil
}
// Configure configures the gpio pin as per mode. // Configure configures the gpio pin as per mode.
func (p Pin) Configure(config PinConfig) { func (p Pin) Configure(config PinConfig) {
if p == NoPin { if p == NoPin {
-27
View File
@@ -2,8 +2,6 @@
package machine package machine
import "device/rp"
// Analog pins on RP2350a. // Analog pins on RP2350a.
const ( const (
ADC0 Pin = GPIO26 ADC0 Pin = GPIO26
@@ -14,28 +12,3 @@ const (
// fifth ADC channel. // fifth ADC channel.
thermADC = 30 thermADC = 30
) )
// validPins confirms that the SPI pin selection is a legitimate one
// for the the 2350a chip.
func (spi *SPI) validPins(config SPIConfig) error {
var okSDI, okSDO, okSCK bool
switch spi.Bus {
case rp.SPI0:
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
case rp.SPI1:
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
}
switch {
case !okSDI:
return errSPIInvalidSDI
case !okSDO:
return errSPIInvalidSDO
case !okSCK:
return errSPIInvalidSCK
}
return nil
}
-27
View File
@@ -2,8 +2,6 @@
package machine package machine
import "device/rp"
// RP2350B has additional pins. // RP2350B has additional pins.
const ( const (
@@ -48,28 +46,3 @@ var (
PWM10 = getPWMGroup(10) PWM10 = getPWMGroup(10)
PWM11 = getPWMGroup(11) PWM11 = getPWMGroup(11)
) )
// validPins confirms that the SPI pin selection is a legitimate one
// for the the 2350b chip.
func (spi *SPI) validPins(config SPIConfig) error {
var okSDI, okSDO, okSCK bool
switch spi.Bus {
case rp.SPI0:
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20 || config.SDI == 32 || config.SDI == 36
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23 || config.SDO == 35 || config.SDO == 39
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22 || config.SCK == 34 || config.SCK == 38
case rp.SPI1:
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28 || config.SDI == 40 || config.SDI == 44
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27 || config.SDO == 31 || config.SDO == 43 || config.SDO == 47
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26 || config.SCK == 30 || config.SCK == 42 || config.SCK == 46
}
switch {
case !okSDI:
return errSPIInvalidSDI
case !okSDO:
return errSPIInvalidSDO
case !okSCK:
return errSPIInvalidSCK
}
return nil
}
+1 -2
View File
@@ -100,8 +100,7 @@ func ReadTemperature() (millicelsius int32) {
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
// 1/0.001721 ≈ 581 return (27000<<16 - (int32(thermChan.getVoltage())-706<<16)*581) >> 16
return int32(((int64(27000) << 16) - ((int64(thermChan.getVoltage()) - (int64(706) << 16)) * 581)) >> 16)
} }
// waitForReady spins waiting for the ADC peripheral to become ready. // waitForReady spins waiting for the ADC peripheral to become ready.
+22 -9
View File
@@ -108,7 +108,7 @@ func (spi *SPI) SetBaudRate(br uint32) error {
var prescale, postdiv uint32 var prescale, postdiv uint32
freq := CPUFrequency() freq := CPUFrequency()
for prescale = 2; prescale < 255; prescale += 2 { for prescale = 2; prescale < 255; prescale += 2 {
if uint64(freq) < uint64((prescale+2)*256)*uint64(br) { if freq < (prescale+2)*256*br {
break break
} }
} }
@@ -165,9 +165,27 @@ func (spi *SPI) Configure(config SPIConfig) error {
config.SDI = SPI1_SDI_PIN config.SDI = SPI1_SDI_PIN
} }
} }
if err := spi.validPins(config); err != nil { var okSDI, okSDO, okSCK bool
return err switch spi.Bus {
case rp.SPI0:
okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20
okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23
okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22
case rp.SPI1:
okSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28
okSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27
okSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26
} }
switch {
case !okSDI:
return errSPIInvalidSDI
case !okSDO:
return errSPIInvalidSDO
case !okSCK:
return errSPIInvalidSCK
}
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = defaultBaud config.Frequency = defaultBaud
} }
@@ -291,7 +309,7 @@ func (spi *SPI) tx(tx []byte) error {
// - set data size to single bytes // - set data size to single bytes
// - set the DREQ so that the DMA will fill the SPI FIFO as needed // - set the DREQ so that the DMA will fill the SPI FIFO as needed
// - start the transfer // - start the transfer
ch.READ_ADDR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(tx))))) ch.READ_ADDR.Set(uint32(uintptr(unsafe.Pointer(&tx[0]))))
ch.WRITE_ADDR.Set(uint32(uintptr(unsafe.Pointer(&spi.Bus.SSPDR)))) ch.WRITE_ADDR.Set(uint32(uintptr(unsafe.Pointer(&spi.Bus.SSPDR))))
ch.TRANS_COUNT.Set(uint32(len(tx))) ch.TRANS_COUNT.Set(uint32(len(tx)))
ch.CTRL_TRIG.Set(rp.DMA_CH0_CTRL_TRIG_INCR_READ | ch.CTRL_TRIG.Set(rp.DMA_CH0_CTRL_TRIG_INCR_READ |
@@ -310,11 +328,6 @@ func (spi *SPI) tx(tx []byte) error {
for ch.CTRL_TRIG.Get()&rp.DMA_CH0_CTRL_TRIG_BUSY != 0 { for ch.CTRL_TRIG.Get()&rp.DMA_CH0_CTRL_TRIG_BUSY != 0 {
} }
// Make sure the read buffer stays alive until this point (in the unlikely
// case the tx slice wasn't read after this function returns and a GC cycle
// happened inbetween).
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(tx)))
// We didn't read any result values, which means the RX FIFO has likely // We didn't read any result values, which means the RX FIFO has likely
// overflown. We have to clean up this mess now. // overflown. We have to clean up this mess now.
-12
View File
@@ -101,15 +101,3 @@ func (tmr *timerType) lightSleep(us uint64) {
// Disable interrupt // Disable interrupt
intr.Disable() intr.Disable()
} }
// setDbgPause sets whether this timer is paused when a debugger is connected.
func (tmr *timerType) setDbgPause(enable bool) {
const bitPos = 1
const bitMask = 0b11
val := uint32(0b00)
if enable {
// Disable timer when debugger is connected to either core.
val = 0b11
}
tmr.dbgPause.ReplaceBits(val, bitMask, bitPos)
}
+2 -6
View File
@@ -104,9 +104,7 @@ func (uart *UART) SetBaudRate(br uint32) {
func (uart *UART) writeByte(c byte) error { func (uart *UART) writeByte(c byte) error {
// wait until buffer is not full // wait until buffer is not full
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) { for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) {
if !interrupt.In() { gosched()
gosched()
}
} }
// write data // write data
@@ -116,9 +114,7 @@ func (uart *UART) writeByte(c byte) error {
func (uart *UART) flush() { func (uart *UART) flush() {
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_BUSY) { for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_BUSY) {
if !interrupt.In() { gosched()
gosched()
}
} }
} }
-2
View File
@@ -16,8 +16,6 @@ import (
) )
// This symbol name is known by the compiler, see monitor.go. // This symbol name is known by the compiler, see monitor.go.
//
//go:linkname rttSerialInstance _SEGGER_RTT
var rttSerialInstance rttSerial var rttSerialInstance rttSerial
var Serial = &rttSerialInstance var Serial = &rttSerialInstance
-1
View File
@@ -6,6 +6,5 @@ package machine
var Serial Serialer var Serial Serialer
func InitSerial() { func InitSerial() {
initUSB()
Serial = USBCDC Serial = USBCDC
} }
-11
View File
@@ -19,17 +19,6 @@ var (
USBCDC Serialer USBCDC Serialer
) )
func initUSB() {
enableUSBCDC()
USBDev.Configure(UARTConfig{})
}
// Using go:linkname here because there's a circular dependency between the
// machine package and the machine/usb/cdc package.
//
//go:linkname enableUSBCDC machine/usb/cdc.EnableUSBCDC
func enableUSBCDC()
type Serialer interface { type Serialer interface {
WriteByte(c byte) error WriteByte(c byte) error
Write(data []byte) (n int, err error) Write(data []byte) (n int, err error)

Some files were not shown because too many files have changed in this diff Show More