mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 19:43:44 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ff626dcee | |||
| 19e2d12517 |
@@ -104,8 +104,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "15"
|
llvm: "15"
|
||||||
# "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21
|
|
||||||
fmt-check: false
|
|
||||||
resource_class: large
|
resource_class: large
|
||||||
test-llvm18-go122:
|
test-llvm18-go122:
|
||||||
docker:
|
docker:
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ jobs:
|
|||||||
gem install --no-document fpm
|
gem install --no-document fpm
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: make lint
|
run: make lint
|
||||||
- name: Run spellcheck
|
|
||||||
run: make spell
|
|
||||||
- name: Build TinyGo release
|
- name: Build TinyGo release
|
||||||
run: |
|
run: |
|
||||||
make release deb -j3 STATIC=1
|
make release deb -j3 STATIC=1
|
||||||
|
|||||||
-15
@@ -28,21 +28,6 @@ build tools to be built. Go is of course necessary to build TinyGo itself.
|
|||||||
The rest of this guide assumes you're running Linux, but it should be equivalent
|
The rest of this guide assumes you're running Linux, but it should be equivalent
|
||||||
on a different system like Mac.
|
on a different system like Mac.
|
||||||
|
|
||||||
## Using GNU Make
|
|
||||||
|
|
||||||
The static build of TinyGo is driven by GNUmakefile, which provides a help target for quick reference:
|
|
||||||
|
|
||||||
% make help
|
|
||||||
clean Remove build directory
|
|
||||||
fmt Reformat source
|
|
||||||
fmt-check Warn if any source needs reformatting
|
|
||||||
gen-device Generate microcontroller-specific sources
|
|
||||||
llvm-source Get LLVM sources
|
|
||||||
llvm-build Build LLVM
|
|
||||||
tinygo Build the TinyGo compiler
|
|
||||||
lint Lint source tree
|
|
||||||
spell Spellcheck source tree
|
|
||||||
|
|
||||||
## Download the source
|
## Download the source
|
||||||
|
|
||||||
The first step is to download the TinyGo sources (use `--recursive` if you clone
|
The first step is to download the TinyGo sources (use `--recursive` if you clone
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@
|
|||||||
- `builder`: keep un-wasm-opt'd .wasm if -work was passed
|
- `builder`: keep un-wasm-opt'd .wasm if -work was passed
|
||||||
- `builder`: make sure wasm-opt command line is printed if asked
|
- `builder`: make sure wasm-opt command line is printed if asked
|
||||||
- `cgo`: implement shift operations in preprocessor macros
|
- `cgo`: implement shift operations in preprocessor macros
|
||||||
- `interp`: checking for methodset existence
|
- `interp`: checking for methodset existance
|
||||||
|
|
||||||
* **standard library**
|
* **standard library**
|
||||||
- `machine`: add `__tinygo_spi_tx` function to simulator
|
- `machine`: add `__tinygo_spi_tx` function to simulator
|
||||||
@@ -217,7 +217,7 @@
|
|||||||
- `reflect`: add SetZero
|
- `reflect`: add SetZero
|
||||||
- `reflect`: fix iterating over maps with interface{} keys
|
- `reflect`: fix iterating over maps with interface{} keys
|
||||||
- `reflect`: implement Value.Grow
|
- `reflect`: implement Value.Grow
|
||||||
- `reflect`: remove unnecessary heap allocations
|
- `reflect`: remove unecessary heap allocations
|
||||||
- `reflect`: use .key() instead of a type assert
|
- `reflect`: use .key() instead of a type assert
|
||||||
- `sync`: add implementation from upstream Go for OnceFunc, OnceValue, and OnceValues
|
- `sync`: add implementation from upstream Go for OnceFunc, OnceValue, and OnceValues
|
||||||
* **targets**
|
* **targets**
|
||||||
|
|||||||
+26
-31
@@ -175,17 +175,17 @@ ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
|||||||
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
clean: ## Remove build directory
|
clean:
|
||||||
@rm -rf build
|
@rm -rf build
|
||||||
|
|
||||||
FMT_PATHS = ./*.go builder cgo/*.go compiler interp loader src transform
|
FMT_PATHS = ./*.go builder cgo/*.go compiler interp loader src transform
|
||||||
fmt: ## Reformat source
|
fmt:
|
||||||
@gofmt -l -w $(FMT_PATHS)
|
@gofmt -l -w $(FMT_PATHS)
|
||||||
fmt-check: ## Warn if any source needs reformatting
|
fmt-check:
|
||||||
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
||||||
|
|
||||||
|
|
||||||
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources
|
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp
|
||||||
ifneq ($(STM32), 0)
|
ifneq ($(STM32), 0)
|
||||||
gen-device: gen-device-stm32
|
gen-device: gen-device-stm32
|
||||||
endif
|
endif
|
||||||
@@ -237,16 +237,18 @@ gen-device-renesas: build/gen-device-svd
|
|||||||
./build/gen-device-svd -source=https://github.com/tinygo-org/renesas-svd lib/renesas-svd/ src/device/renesas/
|
./build/gen-device-svd -source=https://github.com/tinygo-org/renesas-svd lib/renesas-svd/ src/device/renesas/
|
||||||
GO111MODULE=off $(GO) fmt ./src/device/renesas
|
GO111MODULE=off $(GO) fmt ./src/device/renesas
|
||||||
|
|
||||||
|
# Get LLVM sources.
|
||||||
$(LLVM_PROJECTDIR)/llvm:
|
$(LLVM_PROJECTDIR)/llvm:
|
||||||
git clone -b tinygo_xtensa_release_18.1.2 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
|
git clone -b tinygo_xtensa_release_18.1.2 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
|
||||||
llvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources
|
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
||||||
|
|
||||||
# Configure LLVM.
|
# Configure LLVM.
|
||||||
TINYGO_SOURCE_DIR=$(shell pwd)
|
TINYGO_SOURCE_DIR=$(shell pwd)
|
||||||
$(LLVM_BUILDDIR)/build.ninja:
|
$(LLVM_BUILDDIR)/build.ninja:
|
||||||
mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
|
mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
|
||||||
|
|
||||||
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja ## Build LLVM
|
# Build LLVM.
|
||||||
|
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
|
||||||
cd $(LLVM_BUILDDIR) && ninja $(NINJA_BUILD_TARGETS)
|
cd $(LLVM_BUILDDIR) && ninja $(NINJA_BUILD_TARGETS)
|
||||||
|
|
||||||
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
||||||
@@ -289,7 +291,8 @@ ifeq (, $(shell which node))
|
|||||||
endif
|
endif
|
||||||
@if [ $(NODEJS_VERSION) -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version 18+ to run tests."; exit 1; fi
|
@if [ $(NODEJS_VERSION) -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version 18+ to run tests."; exit 1; fi
|
||||||
|
|
||||||
tinygo: ## Build the TinyGo compiler
|
# Build the Go compiler.
|
||||||
|
tinygo:
|
||||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
|
||||||
test: wasi-libc check-nodejs-version
|
test: wasi-libc check-nodejs-version
|
||||||
@@ -853,7 +856,6 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
|
|||||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/stdio
|
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||||
@mkdir -p build/release/tinygo/lib/musl/arch
|
@mkdir -p build/release/tinygo/lib/musl/arch
|
||||||
@mkdir -p build/release/tinygo/lib/musl/crt
|
@mkdir -p build/release/tinygo/lib/musl/crt
|
||||||
@@ -865,6 +867,9 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
|
|||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-cli/
|
@mkdir -p build/release/tinygo/lib/wasi-cli/
|
||||||
|
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0
|
||||||
|
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus
|
||||||
|
@mkdir -p build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4
|
||||||
@echo copying source files
|
@echo copying source files
|
||||||
@cp -p build/tinygo$(EXE) build/release/tinygo/bin
|
@cp -p build/tinygo$(EXE) build/release/tinygo/bin
|
||||||
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
||||||
@@ -889,12 +894,10 @@ endif
|
|||||||
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/locale build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/linux build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/linux build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/multibyte build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
||||||
@@ -904,7 +907,6 @@ endif
|
|||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/stdio/ucrt_* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/stdio
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-headers/crt/ build/release/tinygo/lib/mingw-w64/mingw-w64-headers
|
@cp -rp lib/mingw-w64/mingw-w64-headers/crt/ build/release/tinygo/lib/mingw-w64/mingw-w64-headers
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-headers/defaults/include build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
@cp -rp lib/mingw-w64/mingw-w64-headers/defaults/include build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||||
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
|
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
|
||||||
@@ -930,6 +932,12 @@ endif
|
|||||||
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
||||||
@cp -rp src build/release/tinygo/src
|
@cp -rp src build/release/tinygo/src
|
||||||
@cp -rp targets build/release/tinygo/targets
|
@cp -rp targets build/release/tinygo/targets
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m0 -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0/compiler-rt compiler-rt
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m0plus -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus/compiler-rt compiler-rt
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m4 -o build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4/compiler-rt compiler-rt
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m0 -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0/picolibc picolibc
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m0plus -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus/picolibc picolibc
|
||||||
|
./build/release/tinygo/bin/tinygo build-library -target=cortex-m4 -o build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4/picolibc picolibc
|
||||||
|
|
||||||
release:
|
release:
|
||||||
tar -czf build/release.tar.gz -C build/release tinygo
|
tar -czf build/release.tar.gz -C build/release tinygo
|
||||||
@@ -949,31 +957,18 @@ endif
|
|||||||
|
|
||||||
.PHONY: tools
|
.PHONY: tools
|
||||||
tools:
|
tools:
|
||||||
cd internal/tools && go generate -tags tools ./
|
go generate -C ./internal/tools -tags tools ./
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: tools ## Lint source tree
|
lint:
|
||||||
revive -version
|
go run github.com/mgechev/revive -version
|
||||||
# TODO: lint more directories!
|
# TODO: lint more directories!
|
||||||
# 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/... src/{os,reflect}/*.go | grep -v "should have comment or be unexported" | grep '.' | awk '{print}; END {exit NR>0}'
|
go run github.com/mgechev/revive -config revive.toml compiler/... src/{os,reflect}/*.go | 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
|
|
||||||
.PHONY: spell
|
.PHONY: spell
|
||||||
spell: tools ## Spellcheck source tree
|
spell:
|
||||||
misspell -error --dict misspell.csv -i 'ackward,devided,extint,rela' $$( $(SPELLDIRSCMD) ) *.md
|
# Check for typos in comments. Skip git submodules etc.
|
||||||
|
go run github.com/client9/misspell/cmd/misspell -i 'ackward,devided,extint,inbetween,programmmer,rela' $$( find . -depth 1 -type d | egrep -w -v 'lib|llvm|src/net' )
|
||||||
.PHONY: spellfix
|
|
||||||
spellfix: tools ## Same as spell, but fixes what it finds
|
|
||||||
misspell -w --dict misspell.csv -i 'ackward,devided,extint,rela' $$( $(SPELLDIRSCMD) ) *.md
|
|
||||||
|
|
||||||
# https://www.client9.com/self-documenting-makefiles/
|
|
||||||
.PHONY: help
|
|
||||||
help:
|
|
||||||
@awk -F ':|##' '/^[^\t].+?:.*?##/ {\
|
|
||||||
gsub(/\$$\(LLVM_BUILDDIR\)/, "$(LLVM_BUILDDIR)"); \
|
|
||||||
printf "\033[36m%-30s\033[0m %s\n", $$1, $$NF \
|
|
||||||
}' $(MAKEFILE_LIST)
|
|
||||||
#.DEFAULT_GOAL=help
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ import (
|
|||||||
"github.com/blakesmith/ar"
|
"github.com/blakesmith/ar"
|
||||||
)
|
)
|
||||||
|
|
||||||
// makeArchive creates an archive for static linking from a list of object files
|
// makeArchive creates an arcive for static linking from a list of object files
|
||||||
// given as a parameter. It is equivalent to the following command:
|
// given as a parameter. It is equivalent to the following command:
|
||||||
//
|
//
|
||||||
// ar -rcs <archivePath> <objs...>
|
// ar -rcs <archivePath> <objs...>
|
||||||
|
|||||||
+7
-10
@@ -148,7 +148,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
job := makeDarwinLibSystemJob(config, tmpdir)
|
job := makeDarwinLibSystemJob(config, tmpdir)
|
||||||
libcDependencies = append(libcDependencies, job)
|
libcDependencies = append(libcDependencies, job)
|
||||||
case "musl":
|
case "musl":
|
||||||
job, unlock, err := libMusl.load(config, tmpdir)
|
job, unlock, err := Musl.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(job.result), "crt1.o")))
|
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(job.result), "crt1.o")))
|
||||||
libcDependencies = append(libcDependencies, job)
|
libcDependencies = append(libcDependencies, job)
|
||||||
case "picolibc":
|
case "picolibc":
|
||||||
libcJob, unlock, err := libPicolibc.load(config, tmpdir)
|
libcJob, unlock, err := Picolibc.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
@@ -169,19 +169,18 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
}
|
}
|
||||||
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
||||||
case "wasmbuiltins":
|
case "wasmbuiltins":
|
||||||
libcJob, unlock, err := libWasmBuiltins.load(config, tmpdir)
|
libcJob, unlock, err := WasmBuiltins.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
defer unlock()
|
defer unlock()
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, libcJob)
|
||||||
case "mingw-w64":
|
case "mingw-w64":
|
||||||
job, unlock, err := libMinGW.load(config, tmpdir)
|
_, unlock, err := MinGW.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
defer unlock()
|
unlock()
|
||||||
libcDependencies = append(libcDependencies, job)
|
|
||||||
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
|
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
|
||||||
case "":
|
case "":
|
||||||
// no library specified, so nothing to do
|
// no library specified, so nothing to do
|
||||||
@@ -652,7 +651,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
// Add compiler-rt dependency if needed. Usually this is a simple load from
|
// Add compiler-rt dependency if needed. Usually this is a simple load from
|
||||||
// a cache.
|
// a cache.
|
||||||
if config.Target.RTLib == "compiler-rt" {
|
if config.Target.RTLib == "compiler-rt" {
|
||||||
job, unlock, err := libCompilerRT.load(config, tmpdir)
|
job, unlock, err := CompilerRT.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
@@ -746,8 +745,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
ldflags = append(ldflags, dependency.result)
|
ldflags = append(ldflags, dependency.result)
|
||||||
}
|
}
|
||||||
ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU())
|
ldflags = append(ldflags, "-mllvm", "-mcpu="+config.CPU())
|
||||||
ldflags = append(ldflags, "-mllvm", "-mattr="+config.Features()) // needed for MIPS softfloat
|
|
||||||
ldflags = append(ldflags, "-mllvm", "-wasm-enable-eh")
|
|
||||||
if config.GOOS() == "windows" {
|
if config.GOOS() == "windows" {
|
||||||
// Options for the MinGW wrapper for the lld COFF linker.
|
// Options for the MinGW wrapper for the lld COFF linker.
|
||||||
ldflags = append(ldflags,
|
ldflags = append(ldflags,
|
||||||
@@ -781,7 +778,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
}
|
}
|
||||||
err = link(config.Target.Linker, ldflags...)
|
err = link(config.Target.Linker, ldflags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return &commandError{"failed to link", result.Executable, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
var calculatedStacks []string
|
var calculatedStacks []string
|
||||||
|
|||||||
@@ -57,23 +57,19 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
{GOOS: "linux", GOARCH: "arm", GOARM: "6"},
|
{GOOS: "linux", GOARCH: "arm", GOARM: "6"},
|
||||||
{GOOS: "linux", GOARCH: "arm", GOARM: "7"},
|
{GOOS: "linux", GOARCH: "arm", GOARM: "7"},
|
||||||
{GOOS: "linux", GOARCH: "arm64"},
|
{GOOS: "linux", GOARCH: "arm64"},
|
||||||
{GOOS: "linux", GOARCH: "mips", GOMIPS: "hardfloat"},
|
{GOOS: "linux", GOARCH: "mips"},
|
||||||
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "hardfloat"},
|
{GOOS: "linux", GOARCH: "mipsle"},
|
||||||
{GOOS: "linux", GOARCH: "mips", GOMIPS: "softfloat"},
|
|
||||||
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"},
|
|
||||||
{GOOS: "darwin", GOARCH: "amd64"},
|
{GOOS: "darwin", GOARCH: "amd64"},
|
||||||
{GOOS: "darwin", GOARCH: "arm64"},
|
{GOOS: "darwin", GOARCH: "arm64"},
|
||||||
{GOOS: "windows", GOARCH: "amd64"},
|
{GOOS: "windows", GOARCH: "amd64"},
|
||||||
{GOOS: "windows", GOARCH: "arm64"},
|
{GOOS: "windows", GOARCH: "arm64"},
|
||||||
{GOOS: "wasip1", GOARCH: "wasm"},
|
{GOOS: "wasip1", GOARCH: "wasm"},
|
||||||
|
{GOOS: "wasip2", GOARCH: "wasm"},
|
||||||
} {
|
} {
|
||||||
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
|
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
|
||||||
if options.GOARCH == "arm" {
|
if options.GOARCH == "arm" {
|
||||||
name += ",GOARM=" + options.GOARM
|
name += ",GOARM=" + options.GOARM
|
||||||
}
|
}
|
||||||
if options.GOARCH == "mips" || options.GOARCH == "mipsle" {
|
|
||||||
name += ",GOMIPS=" + options.GOMIPS
|
|
||||||
}
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
testClangAttributes(t, options)
|
testClangAttributes(t, options)
|
||||||
})
|
})
|
||||||
|
|||||||
+7
-41
@@ -3,8 +3,8 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -132,38 +132,6 @@ var genericBuiltins = []string{
|
|||||||
"umodti3.c",
|
"umodti3.c",
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the GENERIC_TF_SOURCES as of LLVM 18.
|
|
||||||
// They are not needed on all platforms (32-bit platforms usually don't need
|
|
||||||
// these) but they seem to compile fine so it's easier to include them.
|
|
||||||
var genericBuiltins128 = []string{
|
|
||||||
"addtf3.c",
|
|
||||||
"comparetf2.c",
|
|
||||||
"divtc3.c",
|
|
||||||
"divtf3.c",
|
|
||||||
"extenddftf2.c",
|
|
||||||
"extendhftf2.c",
|
|
||||||
"extendsftf2.c",
|
|
||||||
"fixtfdi.c",
|
|
||||||
"fixtfsi.c",
|
|
||||||
"fixtfti.c",
|
|
||||||
"fixunstfdi.c",
|
|
||||||
"fixunstfsi.c",
|
|
||||||
"fixunstfti.c",
|
|
||||||
"floatditf.c",
|
|
||||||
"floatsitf.c",
|
|
||||||
"floattitf.c",
|
|
||||||
"floatunditf.c",
|
|
||||||
"floatunsitf.c",
|
|
||||||
"floatuntitf.c",
|
|
||||||
"multc3.c",
|
|
||||||
"multf3.c",
|
|
||||||
"powitf2.c",
|
|
||||||
"subtf3.c",
|
|
||||||
"trunctfdf2.c",
|
|
||||||
"trunctfhf2.c",
|
|
||||||
"trunctfsf2.c",
|
|
||||||
}
|
|
||||||
|
|
||||||
var aeabiBuiltins = []string{
|
var aeabiBuiltins = []string{
|
||||||
"arm/aeabi_cdcmp.S",
|
"arm/aeabi_cdcmp.S",
|
||||||
"arm/aeabi_cdcmpeq_check_nan.c",
|
"arm/aeabi_cdcmpeq_check_nan.c",
|
||||||
@@ -201,12 +169,12 @@ var avrBuiltins = []string{
|
|||||||
"avr/udivmodqi4.S",
|
"avr/udivmodqi4.S",
|
||||||
}
|
}
|
||||||
|
|
||||||
// libCompilerRT is a library with symbols required by programs compiled with
|
// CompilerRT is a library with symbols required by programs compiled with LLVM.
|
||||||
// LLVM. These symbols are for operations that cannot be emitted with a single
|
// These symbols are for operations that cannot be emitted with a single
|
||||||
// instruction or a short sequence of instructions for that target.
|
// instruction or a short sequence of instructions for that target.
|
||||||
//
|
//
|
||||||
// For more information, see: https://compiler-rt.llvm.org/
|
// For more information, see: https://compiler-rt.llvm.org/
|
||||||
var libCompilerRT = Library{
|
var CompilerRT = Library{
|
||||||
name: "compiler-rt",
|
name: "compiler-rt",
|
||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
|
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
|
||||||
@@ -222,13 +190,11 @@ var libCompilerRT = Library{
|
|||||||
},
|
},
|
||||||
librarySources: func(target string) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
||||||
switch compileopts.CanonicalArchName(target) {
|
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||||
case "arm":
|
|
||||||
builtins = append(builtins, aeabiBuiltins...)
|
builtins = append(builtins, aeabiBuiltins...)
|
||||||
case "avr":
|
}
|
||||||
|
if strings.HasPrefix(target, "avr") {
|
||||||
builtins = append(builtins, avrBuiltins...)
|
builtins = append(builtins, avrBuiltins...)
|
||||||
case "x86_64", "aarch64", "riscv64": // any 64-bit arch
|
|
||||||
builtins = append(builtins, genericBuiltins128...)
|
|
||||||
}
|
}
|
||||||
return builtins, nil
|
return builtins, nil
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@ struct AssemblerInvocation {
|
|||||||
EmitDwarfUnwindType EmitDwarfUnwind;
|
EmitDwarfUnwindType EmitDwarfUnwind;
|
||||||
|
|
||||||
// Whether to emit compact-unwind for non-canonical entries.
|
// Whether to emit compact-unwind for non-canonical entries.
|
||||||
// Note: maybe overridden by other constraints.
|
// Note: maybe overriden by other constraints.
|
||||||
unsigned EmitCompactUnwindNonCanonical : 1;
|
unsigned EmitCompactUnwindNonCanonical : 1;
|
||||||
|
|
||||||
/// The name of the relocation model to use.
|
/// The name of the relocation model to use.
|
||||||
|
|||||||
+2
-2
@@ -15,12 +15,12 @@ func (e *MultiError) Error() string {
|
|||||||
|
|
||||||
// newMultiError returns a *MultiError if there is more than one error, or
|
// newMultiError returns a *MultiError if there is more than one error, or
|
||||||
// returns that error directly when there is only one. Passing an empty slice
|
// returns that error directly when there is only one. Passing an empty slice
|
||||||
// will return nil (because there is no error).
|
// will lead to a panic.
|
||||||
// The importPath may be passed if this error is for a single package.
|
// The importPath may be passed if this error is for a single package.
|
||||||
func newMultiError(errs []error, importPath string) error {
|
func newMultiError(errs []error, importPath string) error {
|
||||||
switch len(errs) {
|
switch len(errs) {
|
||||||
case 0:
|
case 0:
|
||||||
return nil
|
panic("attempted to create empty MultiError")
|
||||||
case 1:
|
case 1:
|
||||||
return errs[0]
|
return errs[0]
|
||||||
default:
|
default:
|
||||||
|
|||||||
+24
-13
@@ -35,6 +35,19 @@ type Library struct {
|
|||||||
crt1Source string
|
crt1Source string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the library archive, possibly generating and caching it if needed.
|
||||||
|
// The resulting directory may be stored in the provided tmpdir, which is
|
||||||
|
// expected to be removed after the Load call.
|
||||||
|
func (l *Library) Load(config *compileopts.Config, tmpdir string) (dir string, err error) {
|
||||||
|
job, unlock, err := l.load(config, tmpdir)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer unlock()
|
||||||
|
err = runJobs(job, config.Options.Semaphore)
|
||||||
|
return filepath.Dir(job.result), err
|
||||||
|
}
|
||||||
|
|
||||||
// load returns a compile job to build this library file for the given target
|
// load returns a compile job to build this library file for the given target
|
||||||
// and CPU. It may return a dummy compileJob if the library build is already
|
// and CPU. It may return a dummy compileJob if the library build is already
|
||||||
// cached. The path is stored as job.result but is only valid after the job has
|
// cached. The path is stored as job.result but is only valid after the job has
|
||||||
@@ -149,30 +162,28 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
if config.ABI() != "" {
|
if config.ABI() != "" {
|
||||||
args = append(args, "-mabi="+config.ABI())
|
args = append(args, "-mabi="+config.ABI())
|
||||||
}
|
}
|
||||||
switch compileopts.CanonicalArchName(target) {
|
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||||
case "arm":
|
|
||||||
if strings.Split(target, "-")[2] == "linux" {
|
if strings.Split(target, "-")[2] == "linux" {
|
||||||
args = append(args, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
args = append(args, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
} else {
|
} else {
|
||||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
}
|
}
|
||||||
case "avr":
|
}
|
||||||
|
if strings.HasPrefix(target, "avr") {
|
||||||
// AVR defaults to C float and double both being 32-bit. This deviates
|
// AVR defaults to C float and double both being 32-bit. This deviates
|
||||||
// from what most code (and certainly compiler-rt) expects. So we need
|
// from what most code (and certainly compiler-rt) expects. So we need
|
||||||
// to force the compiler to use 64-bit floating point numbers for
|
// to force the compiler to use 64-bit floating point numbers for
|
||||||
// double.
|
// double.
|
||||||
args = append(args, "-mdouble=64")
|
args = append(args, "-mdouble=64")
|
||||||
case "riscv32":
|
|
||||||
args = append(args, "-march=rv32imac", "-fforce-enable-int128")
|
|
||||||
case "riscv64":
|
|
||||||
args = append(args, "-march=rv64gc")
|
|
||||||
case "mips":
|
|
||||||
args = append(args, "-fno-pic")
|
|
||||||
}
|
}
|
||||||
if config.Target.SoftFloat {
|
if strings.HasPrefix(target, "riscv32-") {
|
||||||
// Use softfloat instead of floating point instructions. This is
|
args = append(args, "-march=rv32imac", "-fforce-enable-int128")
|
||||||
// supported on many architectures.
|
}
|
||||||
args = append(args, "-msoft-float")
|
if strings.HasPrefix(target, "riscv64-") {
|
||||||
|
args = append(args, "-march=rv64gc")
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(target, "mips") {
|
||||||
|
args = append(args, "-fno-pic")
|
||||||
}
|
}
|
||||||
|
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|||||||
+6
-22
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var libMinGW = Library{
|
var MinGW = Library{
|
||||||
name: "mingw-w64",
|
name: "mingw-w64",
|
||||||
makeHeaders: func(target, includeDir string) error {
|
makeHeaders: func(target, includeDir string) error {
|
||||||
// copy _mingw.h
|
// copy _mingw.h
|
||||||
@@ -27,30 +27,14 @@ var libMinGW = Library{
|
|||||||
_, err = io.Copy(outf, inf)
|
_, err = io.Copy(outf, inf)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64") },
|
sourceDir: func() string { return "" }, // unused
|
||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
mingwDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64")
|
// No flags necessary because there are no files to compile.
|
||||||
return []string{
|
return nil
|
||||||
"-nostdlibinc",
|
|
||||||
"-isystem", mingwDir + "/mingw-w64-headers/crt",
|
|
||||||
"-I", mingwDir + "/mingw-w64-headers/defaults/include",
|
|
||||||
"-I" + headerPath,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
librarySources: func(target string) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
// These files are needed so that printf and the like are supported.
|
// We only use the UCRT DLL file. No source files necessary.
|
||||||
sources := []string{
|
return nil, nil
|
||||||
"mingw-w64-crt/stdio/ucrt_fprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_fwprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_printf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_snprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_sprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vfprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vsnprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vsprintf.c",
|
|
||||||
}
|
|
||||||
return sources, nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var libMusl = Library{
|
var Musl = Library{
|
||||||
name: "musl",
|
name: "musl",
|
||||||
makeHeaders: func(target, includeDir string) error {
|
makeHeaders: func(target, includeDir string) error {
|
||||||
bits := filepath.Join(includeDir, "bits")
|
bits := filepath.Join(includeDir, "bits")
|
||||||
@@ -92,8 +92,6 @@ var libMusl = Library{
|
|||||||
"-Wno-ignored-pragmas",
|
"-Wno-ignored-pragmas",
|
||||||
"-Wno-tautological-constant-out-of-range-compare",
|
"-Wno-tautological-constant-out-of-range-compare",
|
||||||
"-Wno-deprecated-non-prototype",
|
"-Wno-deprecated-non-prototype",
|
||||||
"-Wno-format",
|
|
||||||
"-Wno-parentheses",
|
|
||||||
"-Qunused-arguments",
|
"-Qunused-arguments",
|
||||||
// Select include dirs. Don't include standard library includes
|
// Select include dirs. Don't include standard library includes
|
||||||
// (that would introduce host dependencies and other complications),
|
// (that would introduce host dependencies and other complications),
|
||||||
@@ -121,13 +119,11 @@ var libMusl = Library{
|
|||||||
"internal/syscall_ret.c",
|
"internal/syscall_ret.c",
|
||||||
"internal/vdso.c",
|
"internal/vdso.c",
|
||||||
"legacy/*.c",
|
"legacy/*.c",
|
||||||
"locale/*.c",
|
|
||||||
"linux/*.c",
|
"linux/*.c",
|
||||||
"malloc/*.c",
|
"malloc/*.c",
|
||||||
"malloc/mallocng/*.c",
|
"malloc/mallocng/*.c",
|
||||||
"mman/*.c",
|
"mman/*.c",
|
||||||
"math/*.c",
|
"math/*.c",
|
||||||
"multibyte/*.c",
|
|
||||||
"signal/*.c",
|
"signal/*.c",
|
||||||
"stdio/*.c",
|
"stdio/*.c",
|
||||||
"string/*.c",
|
"string/*.c",
|
||||||
|
|||||||
+2
-3
@@ -8,9 +8,9 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// libPicolibc is a C library for bare metal embedded devices. It was originally
|
// Picolibc is a C library for bare metal embedded devices. It was originally
|
||||||
// based on newlib.
|
// based on newlib.
|
||||||
var libPicolibc = Library{
|
var Picolibc = Library{
|
||||||
name: "picolibc",
|
name: "picolibc",
|
||||||
makeHeaders: func(target, includeDir string) error {
|
makeHeaders: func(target, includeDir string) error {
|
||||||
f, err := os.Create(filepath.Join(includeDir, "picolibc.h"))
|
f, err := os.Create(filepath.Join(includeDir, "picolibc.h"))
|
||||||
@@ -29,7 +29,6 @@ var libPicolibc = Library{
|
|||||||
"-D_HAVE_ALIAS_ATTRIBUTE",
|
"-D_HAVE_ALIAS_ATTRIBUTE",
|
||||||
"-DTINY_STDIO",
|
"-DTINY_STDIO",
|
||||||
"-DPOSIX_IO",
|
"-DPOSIX_IO",
|
||||||
"-DFORMAT_DEFAULT_INTEGER", // use __i_vfprintf and __i_vfscanf by default
|
|
||||||
"-D_IEEE_LIBM",
|
"-D_IEEE_LIBM",
|
||||||
"-D__OBSOLETE_MATH_FLOAT=1", // use old math code that doesn't expect a FPU
|
"-D__OBSOLETE_MATH_FLOAT=1", // use old math code that doesn't expect a FPU
|
||||||
"-D__OBSOLETE_MATH_DOUBLE=0",
|
"-D__OBSOLETE_MATH_DOUBLE=0",
|
||||||
|
|||||||
+16
-134
@@ -1,15 +1,10 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/scanner"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// runCCompiler invokes a C compiler with the given arguments.
|
// runCCompiler invokes a C compiler with the given arguments.
|
||||||
@@ -28,135 +23,22 @@ func runCCompiler(flags ...string) error {
|
|||||||
|
|
||||||
// link invokes a linker with the given name and flags.
|
// link invokes a linker with the given name and flags.
|
||||||
func link(linker string, flags ...string) error {
|
func link(linker string, flags ...string) error {
|
||||||
// We only support LLD.
|
if hasBuiltinTools && (linker == "ld.lld" || linker == "wasm-ld") {
|
||||||
if linker != "ld.lld" && linker != "wasm-ld" {
|
// Run command with internal linker.
|
||||||
return fmt.Errorf("unexpected: linker %s should be ld.lld or wasm-ld", linker)
|
cmd := exec.Command(os.Args[0], append([]string{linker}, flags...)...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd *exec.Cmd
|
// Fall back to external command.
|
||||||
if hasBuiltinTools {
|
if _, ok := commands[linker]; ok {
|
||||||
cmd = exec.Command(os.Args[0], append([]string{linker}, flags...)...)
|
return execCommand(linker, flags...)
|
||||||
} else {
|
|
||||||
name, err := LookupCommand(linker)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd = exec.Command(name, flags...)
|
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
|
||||||
|
cmd := exec.Command(linker, flags...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = &buf
|
cmd.Stderr = os.Stderr
|
||||||
err := cmd.Run()
|
cmd.Dir = goenv.Get("TINYGOROOT")
|
||||||
if err != nil {
|
return cmd.Run()
|
||||||
if buf.Len() == 0 {
|
|
||||||
// The linker failed but there was no output.
|
|
||||||
// Therefore, show some output anyway.
|
|
||||||
return fmt.Errorf("failed to run linker: %w", err)
|
|
||||||
}
|
|
||||||
return parseLLDErrors(buf.String())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split LLD errors into individual erros (including errors that continue on the
|
|
||||||
// next line, using a ">>>" prefix). If possible, replace the raw errors with a
|
|
||||||
// more user-friendly version (and one that's more in a Go style).
|
|
||||||
func parseLLDErrors(text string) error {
|
|
||||||
// Split linker output in separate error messages.
|
|
||||||
lines := strings.Split(text, "\n")
|
|
||||||
var errorLines []string // one or more line (belonging to a single error) per line
|
|
||||||
for _, line := range lines {
|
|
||||||
line = strings.TrimRight(line, "\r") // needed for Windows
|
|
||||||
if len(errorLines) != 0 && strings.HasPrefix(line, ">>> ") {
|
|
||||||
errorLines[len(errorLines)-1] += "\n" + line
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
errorLines = append(errorLines, line)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse error messages.
|
|
||||||
var linkErrors []error
|
|
||||||
var flashOverflow, ramOverflow uint64
|
|
||||||
for _, message := range errorLines {
|
|
||||||
parsedError := false
|
|
||||||
|
|
||||||
// Check for undefined symbols.
|
|
||||||
// This can happen in some cases like with CGo and //go:linkname tricker.
|
|
||||||
if matches := regexp.MustCompile(`^ld.lld: error: undefined symbol: (.*)\n`).FindStringSubmatch(message); matches != nil {
|
|
||||||
symbolName := matches[1]
|
|
||||||
for _, line := range strings.Split(message, "\n") {
|
|
||||||
matches := regexp.MustCompile(`referenced by .* \(((.*):([0-9]+))\)`).FindStringSubmatch(line)
|
|
||||||
if matches != nil {
|
|
||||||
parsedError = true
|
|
||||||
line, _ := strconv.Atoi(matches[3])
|
|
||||||
// TODO: detect common mistakes like -gc=none?
|
|
||||||
linkErrors = append(linkErrors, scanner.Error{
|
|
||||||
Pos: token.Position{
|
|
||||||
Filename: matches[2],
|
|
||||||
Line: line,
|
|
||||||
},
|
|
||||||
Msg: "linker could not find symbol " + symbolName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for flash/RAM overflow.
|
|
||||||
if matches := regexp.MustCompile(`^ld.lld: error: section '(.*?)' will not fit in region '(.*?)': overflowed by ([0-9]+) bytes$`).FindStringSubmatch(message); matches != nil {
|
|
||||||
region := matches[2]
|
|
||||||
n, err := strconv.ParseUint(matches[3], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
// Should not happen at all (unless it overflows an uint64 for some reason).
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check which area overflowed.
|
|
||||||
// Some chips use differently named memory areas, but these are by
|
|
||||||
// far the most common.
|
|
||||||
switch region {
|
|
||||||
case "FLASH_TEXT":
|
|
||||||
if n > flashOverflow {
|
|
||||||
flashOverflow = n
|
|
||||||
}
|
|
||||||
parsedError = true
|
|
||||||
case "RAM":
|
|
||||||
if n > ramOverflow {
|
|
||||||
ramOverflow = n
|
|
||||||
}
|
|
||||||
parsedError = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we couldn't parse the linker error: show the error as-is to
|
|
||||||
// the user.
|
|
||||||
if !parsedError {
|
|
||||||
linkErrors = append(linkErrors, LinkerError{message})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if flashOverflow > 0 {
|
|
||||||
linkErrors = append(linkErrors, LinkerError{
|
|
||||||
Msg: fmt.Sprintf("program too large for this chip (flash overflowed by %d bytes)\n\toptimization guide: https://tinygo.org/docs/guides/optimizing-binaries/", flashOverflow),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if ramOverflow > 0 {
|
|
||||||
linkErrors = append(linkErrors, LinkerError{
|
|
||||||
Msg: fmt.Sprintf("program uses too much static RAM on this chip (RAM overflowed by %d bytes)", ramOverflow),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return newMultiError(linkErrors, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// LLD linker error that could not be parsed or doesn't refer to a source
|
|
||||||
// location.
|
|
||||||
type LinkerError struct {
|
|
||||||
Msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e LinkerError) Error() string {
|
|
||||||
return e.Msg
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var libWasmBuiltins = Library{
|
var WasmBuiltins = Library{
|
||||||
name: "wasmbuiltins",
|
name: "wasmbuiltins",
|
||||||
makeHeaders: func(target, includeDir string) error {
|
makeHeaders: func(target, includeDir string) error {
|
||||||
if err := os.Mkdir(includeDir+"/bits", 0o777); err != nil {
|
if err := os.Mkdir(includeDir+"/bits", 0o777); err != nil {
|
||||||
|
|||||||
+5
-23
@@ -60,7 +60,7 @@ func (c *Config) GOOS() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GOARCH returns the GOARCH of the target. This might not always be the actual
|
// GOARCH returns the GOARCH of the target. This might not always be the actual
|
||||||
// architecture: for example, the AVR target is not supported by the Go standard
|
// archtecture: for example, the AVR target is not supported by the Go standard
|
||||||
// library so such targets will usually pretend to be linux/arm.
|
// library so such targets will usually pretend to be linux/arm.
|
||||||
func (c *Config) GOARCH() string {
|
func (c *Config) GOARCH() string {
|
||||||
return c.Target.GOARCH
|
return c.Target.GOARCH
|
||||||
@@ -72,12 +72,6 @@ func (c *Config) GOARM() string {
|
|||||||
return c.Options.GOARM
|
return c.Options.GOARM
|
||||||
}
|
}
|
||||||
|
|
||||||
// GOMIPS will return the GOMIPS environment variable given to the compiler when
|
|
||||||
// building a program.
|
|
||||||
func (c *Config) GOMIPS() string {
|
|
||||||
return c.Options.GOMIPS
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildTags returns the complete list of build tags used during this build.
|
// BuildTags returns the complete list of build tags used during this build.
|
||||||
func (c *Config) BuildTags() []string {
|
func (c *Config) BuildTags() []string {
|
||||||
tags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race)
|
tags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race)
|
||||||
@@ -213,13 +207,10 @@ func (c *Config) RP2040BootPatch() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a canonicalized architecture name, so we don't have to deal with arm*
|
// MuslArchitecture returns the architecture name as used in musl libc. It is
|
||||||
// vs thumb* vs arm64.
|
// usually the same as the first part of the LLVM triple, but not always.
|
||||||
func CanonicalArchName(triple string) string {
|
func MuslArchitecture(triple string) string {
|
||||||
arch := strings.Split(triple, "-")[0]
|
arch := strings.Split(triple, "-")[0]
|
||||||
if arch == "arm64" {
|
|
||||||
return "aarch64"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
|
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
|
||||||
return "arm"
|
return "arm"
|
||||||
}
|
}
|
||||||
@@ -229,12 +220,6 @@ func CanonicalArchName(triple string) string {
|
|||||||
return arch
|
return arch
|
||||||
}
|
}
|
||||||
|
|
||||||
// MuslArchitecture returns the architecture name as used in musl libc. It is
|
|
||||||
// usually the same as the first part of the LLVM triple, but not always.
|
|
||||||
func MuslArchitecture(triple string) string {
|
|
||||||
return CanonicalArchName(triple)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LibcPath returns the path to the libc directory. The libc path will be either
|
// LibcPath returns the path to the libc directory. The libc path will be either
|
||||||
// a precompiled libc shipped with a TinyGo build, or a libc path in the cache
|
// a precompiled libc shipped with a TinyGo build, or a libc path in the cache
|
||||||
// directory (which might not yet be built).
|
// directory (which might not yet be built).
|
||||||
@@ -246,9 +231,6 @@ func (c *Config) LibcPath(name string) (path string, precompiled bool) {
|
|||||||
if c.ABI() != "" {
|
if c.ABI() != "" {
|
||||||
archname += "-" + c.ABI()
|
archname += "-" + c.ABI()
|
||||||
}
|
}
|
||||||
if c.Target.SoftFloat {
|
|
||||||
archname += "-softfloat"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to load a precompiled library.
|
// Try to load a precompiled library.
|
||||||
precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name)
|
precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name)
|
||||||
@@ -461,7 +443,7 @@ func (c *Config) BinaryFormat(ext string) string {
|
|||||||
|
|
||||||
// Programmer returns the flash method and OpenOCD interface name given a
|
// Programmer returns the flash method and OpenOCD interface name given a
|
||||||
// particular configuration. It may either be all configured in the target JSON
|
// particular configuration. It may either be all configured in the target JSON
|
||||||
// file or be modified using the -programmer command-line option.
|
// file or be modified using the -programmmer command-line option.
|
||||||
func (c *Config) Programmer() (method, openocdInterface string) {
|
func (c *Config) Programmer() (method, openocdInterface string) {
|
||||||
switch c.Options.Programmer {
|
switch c.Options.Programmer {
|
||||||
case "":
|
case "":
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ type Options struct {
|
|||||||
GOOS string // environment variable
|
GOOS string // environment variable
|
||||||
GOARCH string // environment variable
|
GOARCH string // environment variable
|
||||||
GOARM string // environment variable (only used with GOARCH=arm)
|
GOARM string // environment variable (only used with GOARCH=arm)
|
||||||
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
|
|
||||||
Directory string // working dir, leave it unset to use the current working dir
|
Directory string // working dir, leave it unset to use the current working dir
|
||||||
Target string
|
Target string
|
||||||
Opt string
|
Opt string
|
||||||
|
|||||||
+92
-98
@@ -30,7 +30,6 @@ type TargetSpec struct {
|
|||||||
Features string `json:"features,omitempty"`
|
Features string `json:"features,omitempty"`
|
||||||
GOOS string `json:"goos,omitempty"`
|
GOOS string `json:"goos,omitempty"`
|
||||||
GOARCH string `json:"goarch,omitempty"`
|
GOARCH string `json:"goarch,omitempty"`
|
||||||
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
|
|
||||||
BuildTags []string `json:"build-tags,omitempty"`
|
BuildTags []string `json:"build-tags,omitempty"`
|
||||||
GC string `json:"gc,omitempty"`
|
GC string `json:"gc,omitempty"`
|
||||||
Scheduler string `json:"scheduler,omitempty"`
|
Scheduler string `json:"scheduler,omitempty"`
|
||||||
@@ -87,10 +86,6 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
|
|||||||
if src.Uint() != 0 {
|
if src.Uint() != 0 {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
case reflect.Bool:
|
|
||||||
if src.Bool() {
|
|
||||||
dst.Set(src)
|
|
||||||
}
|
|
||||||
case reflect.Ptr: // for pointers, copy if not nil
|
case reflect.Ptr: // for pointers, copy if not nil
|
||||||
if !src.IsNil() {
|
if !src.IsNil() {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
@@ -177,7 +172,63 @@ func (spec *TargetSpec) resolveInherits() error {
|
|||||||
// Load a target specification.
|
// Load a target specification.
|
||||||
func LoadTarget(options *Options) (*TargetSpec, error) {
|
func LoadTarget(options *Options) (*TargetSpec, error) {
|
||||||
if options.Target == "" {
|
if options.Target == "" {
|
||||||
return defaultTarget(options)
|
// Configure based on GOOS/GOARCH environment variables (falling back to
|
||||||
|
// runtime.GOOS/runtime.GOARCH), and generate a LLVM target based on it.
|
||||||
|
var llvmarch string
|
||||||
|
switch options.GOARCH {
|
||||||
|
case "386":
|
||||||
|
llvmarch = "i386"
|
||||||
|
case "amd64":
|
||||||
|
llvmarch = "x86_64"
|
||||||
|
case "arm64":
|
||||||
|
llvmarch = "aarch64"
|
||||||
|
case "arm":
|
||||||
|
switch options.GOARM {
|
||||||
|
case "5":
|
||||||
|
llvmarch = "armv5"
|
||||||
|
case "6":
|
||||||
|
llvmarch = "armv6"
|
||||||
|
case "7":
|
||||||
|
llvmarch = "armv7"
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid GOARM=%s, must be 5, 6, or 7", options.GOARM)
|
||||||
|
}
|
||||||
|
case "mips":
|
||||||
|
llvmarch = "mips"
|
||||||
|
case "mipsle":
|
||||||
|
llvmarch = "mipsel"
|
||||||
|
case "wasm":
|
||||||
|
llvmarch = "wasm32"
|
||||||
|
default:
|
||||||
|
llvmarch = options.GOARCH
|
||||||
|
}
|
||||||
|
llvmvendor := "unknown"
|
||||||
|
llvmos := options.GOOS
|
||||||
|
switch llvmos {
|
||||||
|
case "darwin":
|
||||||
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer
|
||||||
|
// to iOS!
|
||||||
|
llvmos = "macosx10.12.0"
|
||||||
|
if llvmarch == "aarch64" {
|
||||||
|
// Looks like Apple prefers to call this architecture ARM64
|
||||||
|
// instead of AArch64.
|
||||||
|
llvmarch = "arm64"
|
||||||
|
llvmos = "macosx11.0.0"
|
||||||
|
}
|
||||||
|
llvmvendor = "apple"
|
||||||
|
case "wasip1":
|
||||||
|
llvmos = "wasi"
|
||||||
|
}
|
||||||
|
// Target triples (which actually have four components, but are called
|
||||||
|
// triples for historical reasons) have the form:
|
||||||
|
// arch-vendor-os-environment
|
||||||
|
target := llvmarch + "-" + llvmvendor + "-" + llvmos
|
||||||
|
if options.GOOS == "windows" {
|
||||||
|
target += "-gnu"
|
||||||
|
} else if options.GOARCH == "arm" {
|
||||||
|
target += "-gnueabihf"
|
||||||
|
}
|
||||||
|
return defaultTarget(options.GOOS, options.GOARCH, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See whether there is a target specification for this target (e.g.
|
// See whether there is a target specification for this target (e.g.
|
||||||
@@ -238,13 +289,14 @@ func GetTargetSpecs() (map[string]*TargetSpec, error) {
|
|||||||
return maps, nil
|
return maps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a target from environment variables (which default to
|
func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||||
// runtime.GOOS/runtime.GOARCH).
|
// No target spec available. Use the default one, useful on most systems
|
||||||
func defaultTarget(options *Options) (*TargetSpec, error) {
|
// with a regular OS.
|
||||||
spec := TargetSpec{
|
spec := TargetSpec{
|
||||||
GOOS: options.GOOS,
|
Triple: triple,
|
||||||
GOARCH: options.GOARCH,
|
GOOS: goos,
|
||||||
BuildTags: []string{options.GOOS, options.GOARCH},
|
GOARCH: goarch,
|
||||||
|
BuildTags: []string{goos, goarch},
|
||||||
GC: "precise",
|
GC: "precise",
|
||||||
Scheduler: "tasks",
|
Scheduler: "tasks",
|
||||||
Linker: "cc",
|
Linker: "cc",
|
||||||
@@ -252,67 +304,38 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
GDB: []string{"gdb"},
|
GDB: []string{"gdb"},
|
||||||
PortReset: "false",
|
PortReset: "false",
|
||||||
}
|
}
|
||||||
|
switch goarch {
|
||||||
// Configure target based on GOARCH.
|
|
||||||
var llvmarch string
|
|
||||||
switch options.GOARCH {
|
|
||||||
case "386":
|
case "386":
|
||||||
llvmarch = "i386"
|
|
||||||
spec.CPU = "pentium4"
|
spec.CPU = "pentium4"
|
||||||
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "amd64":
|
case "amd64":
|
||||||
llvmarch = "x86_64"
|
|
||||||
spec.CPU = "x86-64"
|
spec.CPU = "x86-64"
|
||||||
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "arm":
|
case "arm":
|
||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
switch options.GOARM {
|
switch strings.Split(triple, "-")[0] {
|
||||||
case "5":
|
case "armv5":
|
||||||
llvmarch = "armv5"
|
|
||||||
spec.Features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
case "6":
|
case "armv6":
|
||||||
llvmarch = "armv6"
|
|
||||||
spec.Features = "+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
case "7":
|
case "armv7":
|
||||||
llvmarch = "armv7"
|
|
||||||
spec.Features = "+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
spec.Features = "+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid GOARM=%s, must be 5, 6, or 7", options.GOARM)
|
|
||||||
}
|
}
|
||||||
case "arm64":
|
case "arm64":
|
||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
llvmarch = "aarch64"
|
if goos == "darwin" {
|
||||||
if options.GOOS == "darwin" {
|
|
||||||
spec.Features = "+fp-armv8,+neon"
|
spec.Features = "+fp-armv8,+neon"
|
||||||
// Looks like Apple prefers to call this architecture ARM64
|
} else if goos == "windows" {
|
||||||
// instead of AArch64.
|
|
||||||
llvmarch = "arm64"
|
|
||||||
} else if options.GOOS == "windows" {
|
|
||||||
spec.Features = "+fp-armv8,+neon,-fmv"
|
spec.Features = "+fp-armv8,+neon,-fmv"
|
||||||
} else { // linux
|
} else { // linux
|
||||||
spec.Features = "+fp-armv8,+neon,-fmv,-outline-atomics"
|
spec.Features = "+fp-armv8,+neon,-fmv,-outline-atomics"
|
||||||
}
|
}
|
||||||
case "mips", "mipsle":
|
case "mips", "mipsle":
|
||||||
spec.CPU = "mips32r2"
|
spec.CPU = "mips32r2"
|
||||||
|
spec.Features = "+fpxx,+mips32r2,+nooddspreg,-noabicalls"
|
||||||
spec.CFlags = append(spec.CFlags, "-fno-pic")
|
spec.CFlags = append(spec.CFlags, "-fno-pic")
|
||||||
if options.GOOS == "mips" {
|
|
||||||
llvmarch = "mips" // big endian
|
|
||||||
} else {
|
|
||||||
llvmarch = "mipsel" // little endian
|
|
||||||
}
|
|
||||||
switch options.GOMIPS {
|
|
||||||
case "hardfloat":
|
|
||||||
spec.Features = "+fpxx,+mips32r2,+nooddspreg,-noabicalls"
|
|
||||||
case "softfloat":
|
|
||||||
spec.SoftFloat = true
|
|
||||||
spec.Features = "+mips32r2,+soft-float,-noabicalls"
|
|
||||||
spec.CFlags = append(spec.CFlags, "-msoft-float")
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
|
|
||||||
}
|
|
||||||
case "wasm":
|
case "wasm":
|
||||||
llvmarch = "wasm32"
|
|
||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
spec.Features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext"
|
spec.Features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext"
|
||||||
spec.BuildTags = append(spec.BuildTags, "tinygo.wasm")
|
spec.BuildTags = append(spec.BuildTags, "tinygo.wasm")
|
||||||
@@ -321,37 +344,24 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
"-mnontrapping-fptoint",
|
"-mnontrapping-fptoint",
|
||||||
"-msign-ext",
|
"-msign-ext",
|
||||||
)
|
)
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
|
|
||||||
}
|
}
|
||||||
|
if goos == "darwin" {
|
||||||
// Configure target based on GOOS.
|
|
||||||
llvmos := options.GOOS
|
|
||||||
llvmvendor := "unknown"
|
|
||||||
switch options.GOOS {
|
|
||||||
case "darwin":
|
|
||||||
platformVersion := "10.12.0"
|
|
||||||
if options.GOARCH == "arm64" {
|
|
||||||
platformVersion = "11.0.0" // first macosx platform with arm64 support
|
|
||||||
}
|
|
||||||
llvmvendor = "apple"
|
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "darwin-libSystem"
|
spec.Libc = "darwin-libSystem"
|
||||||
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
|
arch := strings.Split(triple, "-")[0]
|
||||||
// iOS!
|
platformVersion := strings.TrimPrefix(strings.Split(triple, "-")[2], "macosx")
|
||||||
llvmos = "macosx" + platformVersion
|
|
||||||
spec.LDFlags = append(spec.LDFlags,
|
spec.LDFlags = append(spec.LDFlags,
|
||||||
"-flavor", "darwin",
|
"-flavor", "darwin",
|
||||||
"-dead_strip",
|
"-dead_strip",
|
||||||
"-arch", llvmarch,
|
"-arch", arch,
|
||||||
"-platform_version", "macos", platformVersion, platformVersion,
|
"-platform_version", "macos", platformVersion, platformVersion,
|
||||||
)
|
)
|
||||||
case "linux":
|
} else if goos == "linux" {
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
spec.Libc = "musl"
|
spec.Libc = "musl"
|
||||||
spec.LDFlags = append(spec.LDFlags, "--gc-sections")
|
spec.LDFlags = append(spec.LDFlags, "--gc-sections")
|
||||||
if options.GOARCH == "arm64" {
|
if goarch == "arm64" {
|
||||||
// Disable outline atomics. For details, see:
|
// Disable outline atomics. For details, see:
|
||||||
// https://cpufun.substack.com/p/atomics-in-aarch64
|
// https://cpufun.substack.com/p/atomics-in-aarch64
|
||||||
// A better way would be to fully support outline atomics, which
|
// A better way would be to fully support outline atomics, which
|
||||||
@@ -365,7 +375,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
// proper threading.
|
// proper threading.
|
||||||
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
|
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
|
||||||
}
|
}
|
||||||
case "windows":
|
} else if goos == "windows" {
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "mingw-w64"
|
spec.Libc = "mingw-w64"
|
||||||
// Note: using a medium code model, low image base and no ASLR
|
// Note: using a medium code model, low image base and no ASLR
|
||||||
@@ -374,7 +384,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
// normally present in Go (without explicitly opting in).
|
// normally present in Go (without explicitly opting in).
|
||||||
// For more discussion:
|
// For more discussion:
|
||||||
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
|
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
|
||||||
switch options.GOARCH {
|
switch goarch {
|
||||||
case "amd64":
|
case "amd64":
|
||||||
spec.LDFlags = append(spec.LDFlags,
|
spec.LDFlags = append(spec.LDFlags,
|
||||||
"-m", "i386pep",
|
"-m", "i386pep",
|
||||||
@@ -391,7 +401,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
"--no-insert-timestamp",
|
"--no-insert-timestamp",
|
||||||
"--no-dynamicbase",
|
"--no-dynamicbase",
|
||||||
)
|
)
|
||||||
case "wasip1":
|
} else if goos == "wasip1" {
|
||||||
spec.GC = "" // use default GC
|
spec.GC = "" // use default GC
|
||||||
spec.Scheduler = "asyncify"
|
spec.Scheduler = "asyncify"
|
||||||
spec.Linker = "wasm-ld"
|
spec.Linker = "wasm-ld"
|
||||||
@@ -407,43 +417,28 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
"src/runtime/asm_tinygowasm.S",
|
"src/runtime/asm_tinygowasm.S",
|
||||||
"src/internal/task/task_asyncify_wasm.S",
|
"src/internal/task/task_asyncify_wasm.S",
|
||||||
)
|
)
|
||||||
llvmos = "wasi"
|
} else {
|
||||||
default:
|
spec.LDFlags = append(spec.LDFlags, "-no-pie", "-Wl,--gc-sections") // WARNING: clang < 5.0 requires -nopie
|
||||||
return nil, fmt.Errorf("unknown GOOS=%s", options.GOOS)
|
|
||||||
}
|
}
|
||||||
|
if goarch != "wasm" {
|
||||||
// Target triples (which actually have four components, but are called
|
|
||||||
// triples for historical reasons) have the form:
|
|
||||||
// arch-vendor-os-environment
|
|
||||||
spec.Triple = llvmarch + "-" + llvmvendor + "-" + llvmos
|
|
||||||
if options.GOOS == "windows" {
|
|
||||||
spec.Triple += "-gnu"
|
|
||||||
} else if options.GOARCH == "arm" {
|
|
||||||
spec.Triple += "-gnueabihf"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add extra assembly files (needed for the scheduler etc).
|
|
||||||
if options.GOARCH != "wasm" {
|
|
||||||
suffix := ""
|
suffix := ""
|
||||||
if options.GOOS == "windows" && options.GOARCH == "amd64" {
|
if goos == "windows" && goarch == "amd64" {
|
||||||
// Windows uses a different calling convention on amd64 from other
|
// Windows uses a different calling convention on amd64 from other
|
||||||
// operating systems so we need separate assembly files.
|
// operating systems so we need separate assembly files.
|
||||||
suffix = "_windows"
|
suffix = "_windows"
|
||||||
}
|
}
|
||||||
asmGoarch := options.GOARCH
|
asmGoarch := goarch
|
||||||
if options.GOARCH == "mips" || options.GOARCH == "mipsle" {
|
if goarch == "mips" || goarch == "mipsle" {
|
||||||
asmGoarch = "mipsx"
|
asmGoarch = "mipsx"
|
||||||
}
|
}
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/asm_"+asmGoarch+suffix+".S")
|
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/asm_"+asmGoarch+suffix+".S")
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_stack_"+asmGoarch+suffix+".S")
|
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_stack_"+asmGoarch+suffix+".S")
|
||||||
}
|
}
|
||||||
|
if goarch != runtime.GOARCH {
|
||||||
// Configure the emulator.
|
|
||||||
if options.GOARCH != runtime.GOARCH {
|
|
||||||
// Some educated guesses as to how to invoke helper programs.
|
// Some educated guesses as to how to invoke helper programs.
|
||||||
spec.GDB = []string{"gdb-multiarch"}
|
spec.GDB = []string{"gdb-multiarch"}
|
||||||
if options.GOOS == "linux" {
|
if goos == "linux" {
|
||||||
switch options.GOARCH {
|
switch goarch {
|
||||||
case "386":
|
case "386":
|
||||||
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
|
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
|
||||||
if runtime.GOARCH != "amd64" {
|
if runtime.GOARCH != "amd64" {
|
||||||
@@ -462,12 +457,11 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if options.GOOS != runtime.GOOS {
|
if goos != runtime.GOOS {
|
||||||
if options.GOOS == "windows" {
|
if goos == "windows" {
|
||||||
spec.Emulator = "wine {}"
|
spec.Emulator = "wine {}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &spec, nil
|
return &spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ func (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value,
|
|||||||
// However, in practice, it is also necessary to check that the length is
|
// However, in practice, it is also necessary to check that the length is
|
||||||
// not too big that a GEP wouldn't be possible without wrapping the pointer.
|
// not too big that a GEP wouldn't be possible without wrapping the pointer.
|
||||||
// These two checks (non-negative and not too big) can be merged into one
|
// These two checks (non-negative and not too big) can be merged into one
|
||||||
// using an unsigned greater than.
|
// using an unsiged greater than.
|
||||||
|
|
||||||
// Make sure the len value is at least as big as a uintptr.
|
// Make sure the len value is at least as big as a uintptr.
|
||||||
len = b.extendInteger(len, lenType, b.uintptrType)
|
len = b.extendInteger(len, lenType, b.uintptrType)
|
||||||
|
|||||||
+8
-23
@@ -70,25 +70,21 @@ func (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name str
|
|||||||
// createCall creates a call to the given function with the arguments possibly
|
// createCall creates a call to the given function with the arguments possibly
|
||||||
// expanded.
|
// expanded.
|
||||||
func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||||
return b.CreateCall(fnType, fn, b.expandFormalParams(args), name)
|
expanded := make([]llvm.Value, 0, len(args))
|
||||||
|
for _, arg := range args {
|
||||||
|
fragments := b.expandFormalParam(arg)
|
||||||
|
expanded = append(expanded, fragments...)
|
||||||
|
}
|
||||||
|
return b.CreateCall(fnType, fn, expanded, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createInvoke is like createCall but continues execution at the landing pad if
|
// createInvoke is like createCall but continues execution at the landing pad if
|
||||||
// the call resulted in a panic.
|
// the call resulted in a panic.
|
||||||
func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
|
||||||
switch b.deferFrameType() {
|
if b.hasDeferFrame() {
|
||||||
case recoverInlineAsm:
|
|
||||||
b.createInvokeCheckpoint()
|
b.createInvokeCheckpoint()
|
||||||
return b.createCall(fnType, fn, args, name)
|
|
||||||
case recoverWasmEH:
|
|
||||||
continueBB := b.insertBasicBlock("invoke.cont")
|
|
||||||
call := b.CreateInvoke(fnType, fn, b.expandFormalParams(args), continueBB, b.landingpad, name)
|
|
||||||
b.SetInsertPointAtEnd(continueBB)
|
|
||||||
b.blockExits[b.currentBlock] = continueBB
|
|
||||||
return call
|
|
||||||
default:
|
|
||||||
return b.createCall(fnType, fn, args, name)
|
|
||||||
}
|
}
|
||||||
|
return b.createCall(fnType, fn, args, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand an argument type to a list that can be used in a function call
|
// Expand an argument type to a list that can be used in a function call
|
||||||
@@ -127,17 +123,6 @@ func (b *builder) expandFormalParamOffsets(t llvm.Type) []uint64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// expandFormalParams expands every param in the params slice like
|
|
||||||
// expandFormalParam.
|
|
||||||
func (b *builder) expandFormalParams(params []llvm.Value) []llvm.Value {
|
|
||||||
expanded := make([]llvm.Value, 0, len(params))
|
|
||||||
for _, arg := range params {
|
|
||||||
fragments := b.expandFormalParam(arg)
|
|
||||||
expanded = append(expanded, fragments...)
|
|
||||||
}
|
|
||||||
return expanded
|
|
||||||
}
|
|
||||||
|
|
||||||
// expandFormalParam splits a formal param value into pieces, so it can be
|
// expandFormalParam splits a formal param value into pieces, so it can be
|
||||||
// passed directly as part of a function call. For example, it splits up small
|
// passed directly as part of a function call. For example, it splits up small
|
||||||
// structs into individual fields. It is the equivalent of expandFormalParamType
|
// structs into individual fields. It is the equivalent of expandFormalParamType
|
||||||
|
|||||||
+11
-14
@@ -242,7 +242,7 @@ func NewTargetMachine(config *Config) (llvm.TargetMachine, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sizes returns a types.Sizes appropriate for the given target machine. It
|
// Sizes returns a types.Sizes appropriate for the given target machine. It
|
||||||
// includes the correct int size and alignment as is necessary for the Go
|
// includes the correct int size and aligment as is necessary for the Go
|
||||||
// typechecker.
|
// typechecker.
|
||||||
func Sizes(machine llvm.TargetMachine) types.Sizes {
|
func Sizes(machine llvm.TargetMachine) types.Sizes {
|
||||||
targetData := machine.CreateTargetData()
|
targetData := machine.CreateTargetData()
|
||||||
@@ -355,10 +355,7 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *compilerContext) getRuntimeType(name string) types.Type {
|
func (c *compilerContext) getRuntimeType(name string) types.Type {
|
||||||
if typ, ok := c.runtimePkg.Scope().Lookup(name).(*types.TypeName); ok {
|
return c.runtimePkg.Scope().Lookup(name).(*types.TypeName).Type()
|
||||||
return typ.Type()
|
|
||||||
}
|
|
||||||
panic("runtime type not found: " + name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLLVMRuntimeType obtains a named type from the runtime package and returns
|
// getLLVMRuntimeType obtains a named type from the runtime package and returns
|
||||||
@@ -1353,7 +1350,7 @@ func (b *builder) createFunction() {
|
|||||||
b.CreateBr(b.afterDefersBlock[i])
|
b.CreateBr(b.afterDefersBlock[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.deferFrameType() != recoverNone {
|
if b.hasDeferFrame() {
|
||||||
// Create the landing pad block, where execution continues after a
|
// Create the landing pad block, where execution continues after a
|
||||||
// panic.
|
// panic.
|
||||||
b.createLandingPad()
|
b.createLandingPad()
|
||||||
@@ -1490,11 +1487,8 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
|
|||||||
b.createRuntimeInvoke("_panic", []llvm.Value{value}, "")
|
b.createRuntimeInvoke("_panic", []llvm.Value{value}, "")
|
||||||
b.CreateUnreachable()
|
b.CreateUnreachable()
|
||||||
case *ssa.Return:
|
case *ssa.Return:
|
||||||
switch b.deferFrameType() {
|
if b.hasDeferFrame() {
|
||||||
case recoverInlineAsm:
|
b.createRuntimeCall("destroyDeferFrame", []llvm.Value{b.deferFrame}, "")
|
||||||
b.createRuntimeCall("destroyDeferFrameInlineAsm", []llvm.Value{b.deferFrame}, "")
|
|
||||||
case recoverWasmEH:
|
|
||||||
b.createRuntimeCall("destroyDeferFrameWasmEH", []llvm.Value{b.deferFrame}, "")
|
|
||||||
}
|
}
|
||||||
if len(instr.Results) == 0 {
|
if len(instr.Results) == 0 {
|
||||||
b.CreateRetVoid()
|
b.CreateRetVoid()
|
||||||
@@ -1747,7 +1741,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
return b.CreateExtractValue(cplx, 0, "real"), nil
|
return b.CreateExtractValue(cplx, 0, "real"), nil
|
||||||
case "recover":
|
case "recover":
|
||||||
useParentFrame := uint64(0)
|
useParentFrame := uint64(0)
|
||||||
if b.fn.Recover != nil {
|
if b.hasDeferFrame() {
|
||||||
// recover() should return the panic value of the parent function,
|
// recover() should return the panic value of the parent function,
|
||||||
// not of the current function.
|
// not of the current function.
|
||||||
useParentFrame = 1
|
useParentFrame = 1
|
||||||
@@ -1857,8 +1851,11 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
|
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
|
||||||
return b.createRawSyscallNoError(instr)
|
return b.createRawSyscallNoError(instr)
|
||||||
case name == "runtime.supportsRecover":
|
case name == "runtime.supportsRecover":
|
||||||
supportsRecover := uint64(b.supportsRecover())
|
supportsRecover := uint64(0)
|
||||||
return llvm.ConstInt(b.ctx.Int8Type(), supportsRecover, false), nil
|
if b.supportsRecover() {
|
||||||
|
supportsRecover = 1
|
||||||
|
}
|
||||||
|
return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
|
||||||
case name == "runtime.panicStrategy":
|
case name == "runtime.panicStrategy":
|
||||||
// These constants are defined in src/runtime/panic.go.
|
// These constants are defined in src/runtime/panic.go.
|
||||||
panicStrategy := map[string]uint64{
|
panicStrategy := map[string]uint64{
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ func TestCompiler(t *testing.T) {
|
|||||||
{"interface.go", "", ""},
|
{"interface.go", "", ""},
|
||||||
{"func.go", "", ""},
|
{"func.go", "", ""},
|
||||||
{"defer.go", "cortex-m-qemu", ""},
|
{"defer.go", "cortex-m-qemu", ""},
|
||||||
{"defer.go", "wasm", "none"},
|
|
||||||
{"pragma.go", "", ""},
|
{"pragma.go", "", ""},
|
||||||
{"goroutine.go", "wasm", "asyncify"},
|
{"goroutine.go", "wasm", "asyncify"},
|
||||||
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
||||||
|
|||||||
+34
-137
@@ -16,54 +16,34 @@ package compiler
|
|||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type recoverType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Note: this matches recoverSupport in src/runtime/panic.go
|
|
||||||
recoverNone recoverType = iota
|
|
||||||
recoverInlineAsm
|
|
||||||
recoverWasmEH // WebAssembly exception handling
|
|
||||||
)
|
|
||||||
|
|
||||||
// supportsRecover returns whether the compiler supports the recover() builtin
|
// supportsRecover returns whether the compiler supports the recover() builtin
|
||||||
// for the current architecture.
|
// for the current architecture.
|
||||||
func (c *compilerContext) supportsRecover() recoverType {
|
func (b *builder) supportsRecover() bool {
|
||||||
switch c.archFamily() {
|
switch b.archFamily() {
|
||||||
case "wasm32":
|
case "wasm32":
|
||||||
if !strings.Contains(c.Features, "+exception-handling") {
|
// Probably needs to be implemented using the exception handling
|
||||||
// No support for the exception handling proposal.
|
// proposal of WebAssembly:
|
||||||
return recoverNone
|
// https://github.com/WebAssembly/exception-handling
|
||||||
}
|
return false
|
||||||
if c.Scheduler == "asyncify" {
|
|
||||||
// Asyncify does not support WebAssembly exception handling.
|
|
||||||
// It exits with the following message:
|
|
||||||
// unexpected expression type
|
|
||||||
// UNREACHABLE executed at $TINYGOROOT/lib/binaryen/src/passes/Asyncify.cpp:1142!
|
|
||||||
// See: https://github.com/WebAssembly/binaryen/issues/4470
|
|
||||||
return recoverNone
|
|
||||||
}
|
|
||||||
// Use WebAssembly exception handling.
|
|
||||||
return recoverWasmEH
|
|
||||||
case "riscv64", "xtensa":
|
case "riscv64", "xtensa":
|
||||||
// TODO: add support for these architectures
|
// TODO: add support for these architectures
|
||||||
return recoverNone
|
return false
|
||||||
default:
|
default:
|
||||||
return recoverInlineAsm
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deferFrameType returns the defer type for this function. It is always
|
// hasDeferFrame returns whether the current function needs to catch panics and
|
||||||
// recoverNone for functions without defer.
|
// run defers.
|
||||||
func (b *builder) deferFrameType() recoverType {
|
func (b *builder) hasDeferFrame() bool {
|
||||||
if b.fn.Recover == nil {
|
if b.fn.Recover == nil {
|
||||||
return recoverNone
|
return false
|
||||||
}
|
}
|
||||||
return b.supportsRecover()
|
return b.supportsRecover()
|
||||||
}
|
}
|
||||||
@@ -83,40 +63,21 @@ func (b *builder) deferInitFunc() {
|
|||||||
b.deferPtr = b.CreateAlloca(b.dataPtrType, "deferPtr")
|
b.deferPtr = b.CreateAlloca(b.dataPtrType, "deferPtr")
|
||||||
b.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr)
|
b.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr)
|
||||||
|
|
||||||
switch b.deferFrameType() {
|
if b.hasDeferFrame() {
|
||||||
case recoverInlineAsm:
|
|
||||||
// Set up the defer frame with the current stack pointer.
|
// Set up the defer frame with the current stack pointer.
|
||||||
// This assumes that the stack pointer doesn't move outside of the
|
// This assumes that the stack pointer doesn't move outside of the
|
||||||
// function prologue/epilogue (an invariant maintained by TinyGo but
|
// function prologue/epilogue (an invariant maintained by TinyGo but
|
||||||
// possibly broken by the C alloca function).
|
// possibly broken by the C alloca function).
|
||||||
// The frame pointer is _not_ saved, because it is marked as clobbered
|
// The frame pointer is _not_ saved, because it is marked as clobbered
|
||||||
// in the setjmp-like inline assembly.
|
// in the setjmp-like inline assembly.
|
||||||
deferFrameType := b.getLLVMRuntimeType("deferFrameInlineAsm")
|
deferFrameType := b.getLLVMRuntimeType("deferFrame")
|
||||||
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
|
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
|
||||||
stackPointer := b.readStackPointer()
|
stackPointer := b.readStackPointer()
|
||||||
b.createRuntimeCall("setupDeferFrameInlineAsm", []llvm.Value{b.deferFrame, stackPointer}, "")
|
b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "")
|
||||||
|
|
||||||
// Create the landing pad block, which is where control transfers after
|
// Create the landing pad block, which is where control transfers after
|
||||||
// a panic.
|
// a panic.
|
||||||
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "lpad")
|
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "lpad")
|
||||||
case recoverWasmEH:
|
|
||||||
// Set a personality function, which is required by LLVM but not
|
|
||||||
// actually called. __gxx_wasm_personality_v0 is the only one that is
|
|
||||||
// acceptable to the WebAssembly backend it seems.
|
|
||||||
personality := b.mod.NamedFunction("__gxx_wasm_personality_v0")
|
|
||||||
if personality.IsNil() {
|
|
||||||
fnType := llvm.FunctionType(b.ctx.Int32Type(), nil, true)
|
|
||||||
personality = llvm.AddFunction(b.mod, "__gxx_wasm_personality_v0", fnType)
|
|
||||||
}
|
|
||||||
b.llvmFn.SetPersonality(personality)
|
|
||||||
|
|
||||||
// Set up the defer frame.
|
|
||||||
deferFrameType := b.getLLVMRuntimeType("deferFrameWasmEH")
|
|
||||||
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
|
|
||||||
b.createRuntimeCall("setupDeferFrameWasmEH", []llvm.Value{b.deferFrame}, "")
|
|
||||||
|
|
||||||
// Create the landing pad where the 'throw' instruction will jump to.
|
|
||||||
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "catch.dispatch")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,43 +95,6 @@ func (b *builder) createLandingPad() {
|
|||||||
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.supportsRecover() == recoverWasmEH {
|
|
||||||
// Insert exception handling instructions.
|
|
||||||
// This emulates C++ exceptions, as if every function is wrapped like
|
|
||||||
// this:
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// function body
|
|
||||||
// } catch (...) {
|
|
||||||
// run all defers
|
|
||||||
// }
|
|
||||||
// if deferFrame.Panicking {
|
|
||||||
// // re-raise the same panic message
|
|
||||||
// panic(previousPanic)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// This means that if there is a C++ exception in the program, it will
|
|
||||||
// get eaten by the Go code. This is fixable if needed (by checking
|
|
||||||
// whether it's actually a TinyGo exception and re-raising the same
|
|
||||||
// exception if it isn't after running deferred functions).
|
|
||||||
// For more information about C++ exception support in WebAssembly:
|
|
||||||
// https://github.com/WebAssembly/tool-conventions/blob/main/EHScheme.md
|
|
||||||
|
|
||||||
// basic block: catch.dispatch
|
|
||||||
catchStartBB := b.insertBasicBlock("catch.start")
|
|
||||||
catchswitch := b.CreateCatchSwitch(llvm.Value{}, llvm.BasicBlock{}, 1, "")
|
|
||||||
catchswitch.AddHandler(catchStartBB)
|
|
||||||
|
|
||||||
// basic block: catch.start
|
|
||||||
b.SetInsertPointAtEnd(catchStartBB)
|
|
||||||
catchpad := b.CreateCatchPad(catchswitch, []llvm.Value{llvm.ConstNull(b.dataPtrType)}, "")
|
|
||||||
rundefersBB := b.insertBasicBlock("rundefers")
|
|
||||||
b.CreateCatchRet(catchpad, rundefersBB)
|
|
||||||
|
|
||||||
// basic block: rundefers
|
|
||||||
b.SetInsertPointAtEnd(rundefersBB)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.createRunDefers()
|
b.createRunDefers()
|
||||||
|
|
||||||
// Continue at the 'recover' block, which returns to the parent in an
|
// Continue at the 'recover' block, which returns to the parent in an
|
||||||
@@ -508,25 +432,11 @@ func (b *builder) createRunDefers() {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Create loop, in the order:
|
// Create loop, in the order: loophead, loop, callback0, callback1, ..., unreachable, end.
|
||||||
// - loophead
|
|
||||||
// - loop
|
|
||||||
// - callback0
|
|
||||||
// - callback1
|
|
||||||
// - callback*
|
|
||||||
// - unreachable
|
|
||||||
// - catch.dispatch (if wasm EH)
|
|
||||||
// - catch.start (if wasm EH)
|
|
||||||
// - end
|
|
||||||
var catchDispatch, catchStart llvm.BasicBlock
|
|
||||||
end := b.insertBasicBlock("rundefers.end")
|
end := b.insertBasicBlock("rundefers.end")
|
||||||
unreachable := b.ctx.InsertBasicBlock(end, "rundefers.default")
|
unreachable := b.ctx.InsertBasicBlock(end, "rundefers.default")
|
||||||
loop := b.ctx.InsertBasicBlock(unreachable, "rundefers.loop")
|
loop := b.ctx.InsertBasicBlock(unreachable, "rundefers.loop")
|
||||||
loophead := b.ctx.InsertBasicBlock(loop, "rundefers.loophead")
|
loophead := b.ctx.InsertBasicBlock(loop, "rundefers.loophead")
|
||||||
if b.supportsRecover() == recoverWasmEH {
|
|
||||||
catchDispatch = b.ctx.InsertBasicBlock(end, "rundefers.catch.dispatch")
|
|
||||||
catchStart = b.ctx.InsertBasicBlock(end, "rundefers.catch.start")
|
|
||||||
}
|
|
||||||
b.CreateBr(loophead)
|
b.CreateBr(loophead)
|
||||||
|
|
||||||
// Create loop head:
|
// Create loop head:
|
||||||
@@ -561,9 +471,6 @@ func (b *builder) createRunDefers() {
|
|||||||
block := b.insertBasicBlock("rundefers.callback" + strconv.Itoa(i))
|
block := b.insertBasicBlock("rundefers.callback" + strconv.Itoa(i))
|
||||||
sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block)
|
sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block)
|
||||||
b.SetInsertPointAtEnd(block)
|
b.SetInsertPointAtEnd(block)
|
||||||
var fnType llvm.Type
|
|
||||||
var llvmFn llvm.Value
|
|
||||||
var forwardParams []llvm.Value
|
|
||||||
switch callback := callback.(type) {
|
switch callback := callback.(type) {
|
||||||
case *ssa.CallCommon:
|
case *ssa.CallCommon:
|
||||||
// Call on an value or interface value.
|
// Call on an value or interface value.
|
||||||
@@ -584,6 +491,7 @@ func (b *builder) createRunDefers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract the params from the struct (including receiver).
|
// Extract the params from the struct (including receiver).
|
||||||
|
forwardParams := []llvm.Value{}
|
||||||
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
||||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||||
for i := 2; i < len(valueTypes); i++ {
|
for i := 2; i < len(valueTypes); i++ {
|
||||||
@@ -592,6 +500,9 @@ func (b *builder) createRunDefers() {
|
|||||||
forwardParams = append(forwardParams, forwardParam)
|
forwardParams = append(forwardParams, forwardParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fnPtr llvm.Value
|
||||||
|
var fnType llvm.Type
|
||||||
|
|
||||||
if !callback.IsInvoke() {
|
if !callback.IsInvoke() {
|
||||||
// Isolate the func value.
|
// Isolate the func value.
|
||||||
funcValue := forwardParams[0]
|
funcValue := forwardParams[0]
|
||||||
@@ -599,7 +510,7 @@ func (b *builder) createRunDefers() {
|
|||||||
|
|
||||||
//Get function pointer and context
|
//Get function pointer and context
|
||||||
var context llvm.Value
|
var context llvm.Value
|
||||||
llvmFn, context = b.decodeFuncValue(funcValue)
|
fnPtr, context = b.decodeFuncValue(funcValue)
|
||||||
fnType = b.getLLVMFunctionType(callback.Signature())
|
fnType = b.getLLVMFunctionType(callback.Signature())
|
||||||
|
|
||||||
//Pass context
|
//Pass context
|
||||||
@@ -608,8 +519,8 @@ func (b *builder) createRunDefers() {
|
|||||||
// Move typecode from the start to the end of the list of
|
// Move typecode from the start to the end of the list of
|
||||||
// parameters.
|
// parameters.
|
||||||
forwardParams = append(forwardParams[1:], forwardParams[0])
|
forwardParams = append(forwardParams[1:], forwardParams[0])
|
||||||
llvmFn = b.getInvokeFunction(callback)
|
fnPtr = b.getInvokeFunction(callback)
|
||||||
fnType = llvmFn.GlobalValueType()
|
fnType = fnPtr.GlobalValueType()
|
||||||
|
|
||||||
// Add the context parameter. An interface call cannot also be a
|
// Add the context parameter. An interface call cannot also be a
|
||||||
// closure but we have to supply the parameter anyway for platforms
|
// closure but we have to supply the parameter anyway for platforms
|
||||||
@@ -617,6 +528,8 @@ func (b *builder) createRunDefers() {
|
|||||||
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
|
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.createCall(fnType, fnPtr, forwardParams, "")
|
||||||
|
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
// Direct call.
|
// Direct call.
|
||||||
|
|
||||||
@@ -628,6 +541,7 @@ func (b *builder) createRunDefers() {
|
|||||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||||
|
|
||||||
// Extract the params from the struct.
|
// Extract the params from the struct.
|
||||||
|
forwardParams := []llvm.Value{}
|
||||||
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
||||||
for i := range getParams(callback.Signature) {
|
for i := range getParams(callback.Signature) {
|
||||||
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
|
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
|
||||||
@@ -643,7 +557,9 @@ func (b *builder) createRunDefers() {
|
|||||||
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
|
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
|
||||||
}
|
}
|
||||||
|
|
||||||
fnType, llvmFn = b.getFunction(callback)
|
// Call real function.
|
||||||
|
fnType, fn := b.getFunction(callback)
|
||||||
|
b.createInvoke(fnType, fn, forwardParams, "")
|
||||||
|
|
||||||
case *ssa.MakeClosure:
|
case *ssa.MakeClosure:
|
||||||
// Get the real defer struct type and cast to it.
|
// Get the real defer struct type and cast to it.
|
||||||
@@ -657,6 +573,7 @@ func (b *builder) createRunDefers() {
|
|||||||
deferredCallType := b.ctx.StructType(valueTypes, false)
|
deferredCallType := b.ctx.StructType(valueTypes, false)
|
||||||
|
|
||||||
// Extract the params from the struct.
|
// Extract the params from the struct.
|
||||||
|
forwardParams := []llvm.Value{}
|
||||||
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
||||||
for i := 2; i < len(valueTypes); i++ {
|
for i := 2; i < len(valueTypes); i++ {
|
||||||
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
|
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
|
||||||
@@ -665,7 +582,8 @@ func (b *builder) createRunDefers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call deferred function.
|
// Call deferred function.
|
||||||
fnType, llvmFn = b.getFunction(fn)
|
fnType, llvmFn := b.getFunction(fn)
|
||||||
|
b.createCall(fnType, llvmFn, forwardParams, "")
|
||||||
case *ssa.Builtin:
|
case *ssa.Builtin:
|
||||||
db := b.deferBuiltinFuncs[callback]
|
db := b.deferBuiltinFuncs[callback]
|
||||||
|
|
||||||
@@ -693,20 +611,12 @@ func (b *builder) createRunDefers() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
b.diagnostics = append(b.diagnostics, err)
|
b.diagnostics = append(b.diagnostics, err)
|
||||||
}
|
}
|
||||||
b.CreateBr(loophead)
|
|
||||||
continue
|
|
||||||
default:
|
default:
|
||||||
panic("unknown deferred function type")
|
panic("unknown deferred function type")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the deferred function.
|
// Branch back to the start of the loop.
|
||||||
if b.supportsRecover() == recoverWasmEH {
|
b.CreateBr(loophead)
|
||||||
b.CreateInvoke(fnType, llvmFn, b.expandFormalParams(forwardParams), loophead, catchDispatch, "")
|
|
||||||
} else {
|
|
||||||
b.createInvoke(fnType, llvmFn, forwardParams, "")
|
|
||||||
// Branch back to the start of the loop.
|
|
||||||
b.CreateBr(loophead)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create default unreachable block:
|
// Create default unreachable block:
|
||||||
@@ -716,19 +626,6 @@ func (b *builder) createRunDefers() {
|
|||||||
b.SetInsertPointAtEnd(unreachable)
|
b.SetInsertPointAtEnd(unreachable)
|
||||||
b.CreateUnreachable()
|
b.CreateUnreachable()
|
||||||
|
|
||||||
// Ignore any exception that might have occured while running the deferred
|
|
||||||
// functions. The compiler will insert a check whether the function is still
|
|
||||||
// panicking before return, so no panic gets lost.
|
|
||||||
if b.supportsRecover() == recoverWasmEH {
|
|
||||||
b.SetInsertPointAtEnd(catchDispatch)
|
|
||||||
catchswitch := b.CreateCatchSwitch(llvm.Value{}, llvm.BasicBlock{}, 1, "")
|
|
||||||
catchswitch.AddHandler(catchStart)
|
|
||||||
|
|
||||||
b.SetInsertPointAtEnd(catchStart)
|
|
||||||
catchpad := b.CreateCatchPad(catchswitch, []llvm.Value{llvm.ConstNull(b.dataPtrType)}, "")
|
|
||||||
b.CreateCatchRet(catchpad, loophead)
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of loop.
|
// End of loop.
|
||||||
b.SetInsertPointAtEnd(end)
|
b.SetInsertPointAtEnd(end)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ func (b *builder) trackValue(value llvm.Value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// trackPointer creates a call to runtime.trackPointer, bitcasting the pointer
|
// trackPointer creates a call to runtime.trackPointer, bitcasting the poitner
|
||||||
// first if needed. The input value must be of LLVM pointer type.
|
// first if needed. The input value must be of LLVM pointer type.
|
||||||
func (b *builder) trackPointer(value llvm.Value) {
|
func (b *builder) trackPointer(value llvm.Value) {
|
||||||
b.createRuntimeCall("trackPointer", []llvm.Value{value, b.stackChainAlloca}, "")
|
b.createRuntimeCall("trackPointer", []llvm.Value{value, b.stackChainAlloca}, "")
|
||||||
|
|||||||
+91
-28
@@ -10,6 +10,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ func (b *builder) createMakeInterface(val llvm.Value, typ types.Type, pos token.
|
|||||||
|
|
||||||
// extractValueFromInterface extract the value from an interface value
|
// extractValueFromInterface extract the value from an interface value
|
||||||
// (runtime._interface) under the assumption that it is of the type given in
|
// (runtime._interface) under the assumption that it is of the type given in
|
||||||
// llvmType. The behavior is undefined if the interface is nil or llvmType
|
// llvmType. The behavior is undefied if the interface is nil or llvmType
|
||||||
// doesn't match the underlying type of the interface.
|
// doesn't match the underlying type of the interface.
|
||||||
func (b *builder) extractValueFromInterface(itf llvm.Value, llvmType llvm.Type) llvm.Value {
|
func (b *builder) extractValueFromInterface(itf llvm.Value, llvmType llvm.Type) llvm.Value {
|
||||||
valuePtr := b.CreateExtractValue(itf, 1, "typeassert.value.ptr")
|
valuePtr := b.CreateExtractValue(itf, 1, "typeassert.value.ptr")
|
||||||
@@ -180,6 +181,15 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
typeFieldTypes := []*types.Var{
|
typeFieldTypes := []*types.Var{
|
||||||
types.NewVar(token.NoPos, nil, "kind", types.Typ[types.Int8]),
|
types.NewVar(token.NoPos, nil, "kind", types.Typ[types.Int8]),
|
||||||
}
|
}
|
||||||
|
var methods []*types.Func
|
||||||
|
for i := 0; i < ms.Len(); i++ {
|
||||||
|
methods = append(methods, ms.At(i).Obj().(*types.Func))
|
||||||
|
}
|
||||||
|
methodSetType := types.NewStruct([]*types.Var{
|
||||||
|
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", types.NewArray(types.Typ[types.UnsafePointer], int64(len(methods)))),
|
||||||
|
}, nil)
|
||||||
|
methodSetValue := c.getMethodSetValue(methods)
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
@@ -196,6 +206,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
|
||||||
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),
|
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),
|
||||||
)
|
)
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
@@ -214,6 +225,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
)
|
)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
@@ -238,12 +250,13 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
types.NewVar(token.NoPos, nil, "size", types.Typ[types.Uint32]),
|
types.NewVar(token.NoPos, nil, "size", types.Typ[types.Uint32]),
|
||||||
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
)
|
)
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
)
|
)
|
||||||
// TODO: methods
|
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
@@ -294,6 +307,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
||||||
c.getTypeCode(typ.Underlying()), // underlying
|
c.getTypeCode(typ.Underlying()), // underlying
|
||||||
pkgPathPtr, // pkgpath pointer
|
pkgPathPtr, // pkgpath pointer
|
||||||
|
methodSetValue, // methods
|
||||||
c.ctx.ConstString(pkgname+"."+name+"\x00", false), // name
|
c.ctx.ConstString(pkgname+"."+name+"\x00", false), // name
|
||||||
}
|
}
|
||||||
metabyte |= 1 << 5 // "named" flag
|
metabyte |= 1 << 5 // "named" flag
|
||||||
@@ -323,6 +337,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods
|
llvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods
|
||||||
c.getTypeCode(typ.Elem()),
|
c.getTypeCode(typ.Elem()),
|
||||||
|
methodSetValue, // methods
|
||||||
}
|
}
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
@@ -404,9 +419,12 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
typeFields = append(typeFields, llvm.ConstArray(structFieldType, fields))
|
typeFields = append(typeFields, llvm.ConstArray(structFieldType, fields))
|
||||||
|
typeFields = append(typeFields, methodSetValue)
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
typeFields = []llvm.Value{
|
||||||
// TODO: methods
|
c.getTypeCode(types.NewPointer(typ)),
|
||||||
|
methodSetValue,
|
||||||
|
}
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
||||||
// TODO: params, return values, etc
|
// TODO: params, return values, etc
|
||||||
@@ -685,7 +703,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
|
|||||||
assertedType := b.getLLVMType(expr.AssertedType)
|
assertedType := b.getLLVMType(expr.AssertedType)
|
||||||
|
|
||||||
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")
|
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")
|
||||||
commaOk := llvm.Value{}
|
var commaOk llvm.Value
|
||||||
|
|
||||||
if intf, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
|
if intf, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
|
||||||
if intf.Empty() {
|
if intf.Empty() {
|
||||||
@@ -693,17 +711,16 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
|
|||||||
// This type assertion always succeeds, so we can just set commaOk to true.
|
// This type assertion always succeeds, so we can just set commaOk to true.
|
||||||
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
|
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
|
||||||
} else {
|
} else {
|
||||||
// Type assert on interface type with methods.
|
// Type assert using interface type with methods.
|
||||||
// This is a call to an interface type assert function.
|
// This is implemented using a runtime call, which checks that the
|
||||||
// The interface lowering pass will define this function by filling it
|
// type implements each method of the interface.
|
||||||
// with a type switch over all concrete types that implement this
|
// For comparison, here is how the Go compiler does this (which is
|
||||||
// interface, and returning whether it's one of the matched types.
|
// very similar):
|
||||||
// This is very different from how interface asserts are implemented in
|
|
||||||
// the main Go compiler, where the runtime checks whether the type
|
|
||||||
// implements each method of the interface. See:
|
|
||||||
// https://research.swtch.com/interfaces
|
// https://research.swtch.com/interfaces
|
||||||
fn := b.getInterfaceImplementsFunc(expr.AssertedType)
|
commaOk = b.createRuntimeCall("typeImplementsMethodSet", []llvm.Value{
|
||||||
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
|
actualTypeNum,
|
||||||
|
b.getInterfaceMethodSet(intf),
|
||||||
|
}, "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
name, _ := getTypeCodeName(expr.AssertedType)
|
name, _ := getTypeCodeName(expr.AssertedType)
|
||||||
@@ -780,20 +797,66 @@ func (c *compilerContext) getMethodsString(itf *types.Interface) string {
|
|||||||
return strings.Join(methods, "; ")
|
return strings.Join(methods, "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getInterfaceImplementsFunc returns a declared function that works as a type
|
// Get the global that contains an interface method set, creating it if needed.
|
||||||
// switch. The interface lowering pass will define this function.
|
func (c *compilerContext) getInterfaceMethodSet(t *types.Interface) llvm.Value {
|
||||||
func (c *compilerContext) getInterfaceImplementsFunc(assertedType types.Type) llvm.Value {
|
s, _ := getTypeCodeName(t)
|
||||||
s, _ := getTypeCodeName(assertedType.Underlying())
|
methodSetName := s + "$itfmethods"
|
||||||
fnName := s + ".$typeassert"
|
methodSet := c.mod.NamedFunction(methodSetName)
|
||||||
llvmFn := c.mod.NamedFunction(fnName)
|
if methodSet.IsNil() {
|
||||||
if llvmFn.IsNil() {
|
var methods []*types.Func
|
||||||
llvmFnType := llvm.FunctionType(c.ctx.Int1Type(), []llvm.Type{c.dataPtrType}, false)
|
for i := 0; i < t.NumMethods(); i++ {
|
||||||
llvmFn = llvm.AddFunction(c.mod, fnName, llvmFnType)
|
methods = append(methods, t.Method(i))
|
||||||
c.addStandardDeclaredAttributes(llvmFn)
|
}
|
||||||
methods := c.getMethodsString(assertedType.Underlying().(*types.Interface))
|
if len(methods) == 0 {
|
||||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("tinygo-methods", methods))
|
// This *should* be unreachable: the caller checks whether the
|
||||||
|
// interface is empty before creating a method set.
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
methodSetValue := c.getMethodSetValue(methods)
|
||||||
|
methodSet = llvm.AddGlobal(c.mod, methodSetValue.Type(), methodSetName)
|
||||||
|
methodSet.SetInitializer(methodSetValue)
|
||||||
|
methodSet.SetGlobalConstant(true)
|
||||||
|
methodSet.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
|
methodSet.SetAlignment(c.targetData.ABITypeAlignment(methodSetValue.Type()))
|
||||||
|
methodSet.SetUnnamedAddr(true)
|
||||||
}
|
}
|
||||||
return llvmFn
|
|
||||||
|
return methodSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the method set value that is used in a number of type structs.
|
||||||
|
func (c *compilerContext) getMethodSetValue(methods []*types.Func) llvm.Value {
|
||||||
|
// Create a sorted list of method names.
|
||||||
|
var methodRefNames []string
|
||||||
|
for _, method := range methods {
|
||||||
|
name := method.Name()
|
||||||
|
if !token.IsExported(name) {
|
||||||
|
name = method.Pkg().Path() + "." + name
|
||||||
|
}
|
||||||
|
s, _ := getTypeCodeName(method.Type())
|
||||||
|
methodRefNames = append(methodRefNames, "reflect/types.signature:"+name+":"+s)
|
||||||
|
}
|
||||||
|
sort.Strings(methodRefNames)
|
||||||
|
|
||||||
|
// Turn this slice of strings in a slice of global variables.
|
||||||
|
var methodRefValues []llvm.Value
|
||||||
|
for _, name := range methodRefNames {
|
||||||
|
value := c.mod.NamedGlobal(name)
|
||||||
|
if value.IsNil() {
|
||||||
|
value = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), name)
|
||||||
|
value.SetInitializer(llvm.ConstNull(c.ctx.Int8Type()))
|
||||||
|
value.SetGlobalConstant(true)
|
||||||
|
value.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
|
value.SetAlignment(1)
|
||||||
|
}
|
||||||
|
methodRefValues = append(methodRefValues, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ctx.ConstStruct([]llvm.Value{
|
||||||
|
llvm.ConstInt(c.uintptrType, uint64(len(methodRefValues)), false),
|
||||||
|
llvm.ConstArray(c.dataPtrType, methodRefValues),
|
||||||
|
}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getInvokeFunction returns the thunk to call the given interface method. The
|
// getInvokeFunction returns the thunk to call the given interface method. The
|
||||||
|
|||||||
+12
-3
@@ -7,7 +7,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
@@ -419,11 +418,21 @@ func (c *compilerContext) getPointerBitmap(typ llvm.Type, pos token.Pos) *big.In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// archFamily returns the architecture from the LLVM triple but with some
|
// archFamily returns the archtecture from the LLVM triple but with some
|
||||||
// architecture names ("armv6", "thumbv7m", etc) merged into a single
|
// architecture names ("armv6", "thumbv7m", etc) merged into a single
|
||||||
// architecture name ("arm").
|
// architecture name ("arm").
|
||||||
func (c *compilerContext) archFamily() string {
|
func (c *compilerContext) archFamily() string {
|
||||||
return compileopts.CanonicalArchName(c.Triple)
|
arch := strings.Split(c.Triple, "-")[0]
|
||||||
|
if strings.HasPrefix(arch, "arm64") {
|
||||||
|
return "aarch64"
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
|
||||||
|
return "arm"
|
||||||
|
}
|
||||||
|
if arch == "mipsel" {
|
||||||
|
return "mips"
|
||||||
|
}
|
||||||
|
return arch
|
||||||
}
|
}
|
||||||
|
|
||||||
// isThumb returns whether we're in ARM or in Thumb mode. It panics if the
|
// isThumb returns whether we're in ARM or in Thumb mode. It panics if the
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ func AppendToGlobal(mod llvm.Module, globalName string, values ...llvm.Value) {
|
|||||||
used.SetLinkage(llvm.AppendingLinkage)
|
used.SetLinkage(llvm.AppendingLinkage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns the LLVM major version.
|
// Return the LLVM major version.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
majorStr := strings.Split(llvm.Version, ".")[0]
|
majorStr := strings.Split(llvm.Version, ".")[0]
|
||||||
major, err := strconv.Atoi(majorStr)
|
major, err := strconv.Atoi(majorStr)
|
||||||
|
|||||||
+1
-1
@@ -326,7 +326,7 @@ func (b *builder) zeroUndefBytes(llvmType llvm.Type, ptr llvm.Value) error {
|
|||||||
if i < numFields-1 {
|
if i < numFields-1 {
|
||||||
nextOffset = b.targetData.ElementOffset(llvmStructType, i+1)
|
nextOffset = b.targetData.ElementOffset(llvmStructType, i+1)
|
||||||
} else {
|
} else {
|
||||||
// Last field? Next offset is the total size of the allocate struct.
|
// Last field? Next offset is the total size of the allcoate struct.
|
||||||
nextOffset = b.targetData.TypeAllocSize(llvmStructType)
|
nextOffset = b.targetData.TypeAllocSize(llvmStructType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-4
@@ -174,7 +174,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
|||||||
// that the only thing we'll do is read the pointer.
|
// that the only thing we'll do is read the pointer.
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
||||||
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
|
|
||||||
case "__mulsi3", "__divmodsi4", "__udivmodsi4":
|
case "__mulsi3", "__divmodsi4", "__udivmodsi4":
|
||||||
if strings.Split(c.Triple, "-")[0] == "avr" {
|
if strings.Split(c.Triple, "-")[0] == "avr" {
|
||||||
// These functions are compiler-rt/libgcc functions that are
|
// These functions are compiler-rt/libgcc functions that are
|
||||||
@@ -471,9 +470,7 @@ func (c *compilerContext) addStandardDefinedAttributes(llvmFn llvm.Value) {
|
|||||||
// This behavior matches Clang when compiling C source files.
|
// This behavior matches Clang when compiling C source files.
|
||||||
// It reduces binary size on Linux a little bit on non-x86_64 targets by
|
// It reduces binary size on Linux a little bit on non-x86_64 targets by
|
||||||
// eliminating exception tables for these functions.
|
// eliminating exception tables for these functions.
|
||||||
if c.supportsRecover() != recoverWasmEH {
|
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
|
||||||
llvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nounwind"), 0))
|
|
||||||
}
|
|
||||||
if strings.Split(c.Triple, "-")[0] == "x86_64" {
|
if strings.Split(c.Triple, "-")[0] == "x86_64" {
|
||||||
// Required by the ABI.
|
// Required by the ABI.
|
||||||
// The uwtable has two possible values: sync (1) or async (2). We use
|
// The uwtable has two possible values: sync (1) or async (2). We use
|
||||||
|
|||||||
+1
-1
@@ -145,7 +145,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
// Also useful:
|
// Also useful:
|
||||||
// https://web.archive.org/web/20220529105937/https://www.linux-mips.org/wiki/Syscall
|
// https://web.archive.org/web/20220529105937/https://www.linux-mips.org/wiki/Syscall
|
||||||
// The syscall number goes in r2, the result also in r2.
|
// The syscall number goes in r2, the result also in r2.
|
||||||
// Register r7 is both an input parameter and an output parameter: if it
|
// Register r7 is both an input paramter and an output parameter: if it
|
||||||
// is non-zero, the system call failed and r2 is the error code.
|
// is non-zero, the system call failed and r2 is the error code.
|
||||||
// The code below implements the O32 syscall ABI, not the N32 ABI. It
|
// The code below implements the O32 syscall ABI, not the N32 ABI. It
|
||||||
// could implement both at the same time if needed (like what appears to
|
// could implement both at the same time if needed (like what appears to
|
||||||
|
|||||||
Vendored
+24
-25
@@ -13,31 +13,30 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = add i32 %x, %y
|
%0 = add i32 %x, %y
|
||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i32 %x, %y
|
%0 = icmp eq i32 %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i32 %y, 0
|
%0 = icmp eq i32 %y, 0
|
||||||
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
||||||
@@ -55,10 +54,10 @@ divbyzero.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.divideByZeroPanic(ptr) #2
|
declare void @runtime.divideByZeroPanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i32 %y, 0
|
%0 = icmp eq i32 %y, 0
|
||||||
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
||||||
@@ -73,7 +72,7 @@ divbyzero.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i32 %y, 0
|
%0 = icmp eq i32 %y, 0
|
||||||
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
||||||
@@ -92,7 +91,7 @@ divbyzero.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i32 %y, 0
|
%0 = icmp eq i32 %y, 0
|
||||||
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
br i1 %0, label %divbyzero.throw, label %divbyzero.next
|
||||||
@@ -107,61 +106,61 @@ divbyzero.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp oeq float %x, %y
|
%0 = fcmp oeq float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp une float %x, %y
|
%0 = fcmp une float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp olt float %x, %y
|
%0 = fcmp olt float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp ole float %x, %y
|
%0 = fcmp ole float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp ogt float %x, %y
|
%0 = fcmp ogt float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp oge float %x, %y
|
%0 = fcmp oge float %x, %y
|
||||||
ret i1 %0
|
ret i1 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
|
define hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret float %x.r
|
ret float %x.r
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #1 {
|
define hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret float %x.i
|
ret float %x.i
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
|
define hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fadd float %x.r, %y.r
|
%0 = fadd float %x.r, %y.r
|
||||||
%1 = fadd float %x.i, %y.i
|
%1 = fadd float %x.i, %y.i
|
||||||
@@ -171,7 +170,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
|
define hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fsub float %x.r, %y.r
|
%0 = fsub float %x.r, %y.r
|
||||||
%1 = fsub float %x.i, %y.i
|
%1 = fsub float %x.i, %y.i
|
||||||
@@ -181,7 +180,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #1 {
|
define hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fmul float %x.r, %y.r
|
%0 = fmul float %x.r, %y.r
|
||||||
%1 = fmul float %x.i, %y.i
|
%1 = fmul float %x.i, %y.i
|
||||||
@@ -195,19 +194,19 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.foo(ptr %context) unnamed_addr #1 {
|
define hidden void @main.foo(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef)
|
call void @"main.foo$1"(%main.kv.0 zeroinitializer, ptr undef)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr #1 {
|
define internal void @"main.foo$1"(%main.kv.0 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+15
-16
@@ -9,17 +9,16 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanIntSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
||||||
%chan.value = alloca i32, align 4
|
%chan.value = alloca i32, align 4
|
||||||
@@ -33,15 +32,15 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
|
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3
|
||||||
|
|
||||||
declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #3
|
declare void @runtime.chanSend(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
|
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
||||||
%chan.value = alloca i32, align 4
|
%chan.value = alloca i32, align 4
|
||||||
@@ -53,10 +52,10 @@ entry:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #3
|
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(32), ptr, ptr dereferenceable_or_null(24), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
||||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
|
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
|
||||||
@@ -66,7 +65,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
%chan.blockedList = alloca %runtime.channelBlockedList, align 8
|
||||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
|
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %chan.blockedList)
|
||||||
@@ -76,7 +75,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #1 {
|
define hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(32) %ch1, ptr dereferenceable_or_null(32) %ch2, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
|
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
|
||||||
%select.send.value = alloca i32, align 4
|
%select.send.value = alloca i32, align 4
|
||||||
@@ -106,10 +105,10 @@ select.body: ; preds = %select.next
|
|||||||
br label %select.done
|
br label %select.done
|
||||||
}
|
}
|
||||||
|
|
||||||
declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #3
|
declare { i32, i1 } @runtime.tryChanSelect(ptr, ptr, i32, i32, ptr) #1
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
||||||
attributes #4 = { nounwind }
|
attributes #4 = { nounwind }
|
||||||
|
|||||||
+11
-11
@@ -3,7 +3,7 @@ source_filename = "defer.go"
|
|||||||
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
|
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
|
||||||
target triple = "thumbv7m-unknown-unknown-eabi"
|
target triple = "thumbv7m-unknown-unknown-eabi"
|
||||||
|
|
||||||
%runtime.deferFrameInlineAsm = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface }
|
%runtime.deferFrame = type { ptr, ptr, [0 x ptr], ptr, i1, %runtime._interface }
|
||||||
%runtime._interface = type { ptr, ptr }
|
%runtime._interface = type { ptr, ptr }
|
||||||
%runtime._defer = type { i32, ptr }
|
%runtime._defer = type { i32, ptr }
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ entry:
|
|||||||
%defer.alloca = alloca { i32, ptr }, align 4
|
%defer.alloca = alloca { i32, ptr }, align 4
|
||||||
%deferPtr = alloca ptr, align 4
|
%deferPtr = alloca ptr, align 4
|
||||||
store ptr null, ptr %deferPtr, align 4
|
store ptr null, ptr %deferPtr, align 4
|
||||||
%deferframe.buf = alloca %runtime.deferFrameInlineAsm, align 4
|
%deferframe.buf = alloca %runtime.deferFrame, align 4
|
||||||
%0 = call ptr @llvm.stacksave.p0()
|
%0 = call ptr @llvm.stacksave.p0()
|
||||||
call void @runtime.setupDeferFrameInlineAsm(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 { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
%defer.alloca.repack15 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
||||||
store ptr null, ptr %defer.alloca.repack15, align 4
|
store ptr null, ptr %defer.alloca.repack15, align 4
|
||||||
@@ -40,7 +40,7 @@ entry:
|
|||||||
br label %rundefers.block
|
br label %rundefers.block
|
||||||
|
|
||||||
rundefers.after: ; preds = %rundefers.end
|
rundefers.after: ; preds = %rundefers.end
|
||||||
call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
|
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
rundefers.block: ; preds = %1
|
rundefers.block: ; preds = %1
|
||||||
@@ -76,7 +76,7 @@ rundefers.end: ; preds = %rundefers.loophead
|
|||||||
br label %rundefers.after
|
br label %rundefers.after
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end3
|
recover: ; preds = %rundefers.end3
|
||||||
call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
|
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
|
lpad: ; preds = %rundefers.callback012, %rundefers.callback0, %entry
|
||||||
@@ -115,9 +115,9 @@ rundefers.end3: ; preds = %rundefers.loophead6
|
|||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn
|
; Function Attrs: nocallback nofree nosync nounwind willreturn
|
||||||
declare ptr @llvm.stacksave.p0() #3
|
declare ptr @llvm.stacksave.p0() #3
|
||||||
|
|
||||||
declare void @runtime.setupDeferFrameInlineAsm(ptr dereferenceable_or_null(24), ptr, ptr) #2
|
declare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #2
|
||||||
|
|
||||||
declare void @runtime.destroyDeferFrameInlineAsm(ptr dereferenceable_or_null(24), ptr) #2
|
declare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #2
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
|
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
|
||||||
@@ -135,9 +135,9 @@ entry:
|
|||||||
%defer.alloca = alloca { i32, ptr }, align 4
|
%defer.alloca = alloca { i32, ptr }, align 4
|
||||||
%deferPtr = alloca ptr, align 4
|
%deferPtr = alloca ptr, align 4
|
||||||
store ptr null, ptr %deferPtr, align 4
|
store ptr null, ptr %deferPtr, align 4
|
||||||
%deferframe.buf = alloca %runtime.deferFrameInlineAsm, align 4
|
%deferframe.buf = alloca %runtime.deferFrame, align 4
|
||||||
%0 = call ptr @llvm.stacksave.p0()
|
%0 = call ptr @llvm.stacksave.p0()
|
||||||
call void @runtime.setupDeferFrameInlineAsm(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 { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
%defer.alloca.repack22 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
||||||
store ptr null, ptr %defer.alloca.repack22, align 4
|
store ptr null, ptr %defer.alloca.repack22, align 4
|
||||||
@@ -155,7 +155,7 @@ entry:
|
|||||||
br label %rundefers.block
|
br label %rundefers.block
|
||||||
|
|
||||||
rundefers.after: ; preds = %rundefers.end
|
rundefers.after: ; preds = %rundefers.end
|
||||||
call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
|
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
rundefers.block: ; preds = %1
|
rundefers.block: ; preds = %1
|
||||||
@@ -201,7 +201,7 @@ rundefers.end: ; preds = %rundefers.loophead
|
|||||||
br label %rundefers.after
|
br label %rundefers.after
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end7
|
recover: ; preds = %rundefers.end7
|
||||||
call void @runtime.destroyDeferFrameInlineAsm(ptr nonnull %deferframe.buf, ptr undef) #4
|
call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
lpad: ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry
|
lpad: ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry
|
||||||
|
|||||||
Vendored
-273
@@ -1,273 +0,0 @@
|
|||||||
; ModuleID = 'defer.go'
|
|
||||||
source_filename = "defer.go"
|
|
||||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
|
|
||||||
target triple = "wasm32-unknown-wasi"
|
|
||||||
|
|
||||||
%runtime.deferFrameWasmEH = type { ptr, i1, %runtime._interface }
|
|
||||||
%runtime._interface = type { ptr, ptr }
|
|
||||||
%runtime._defer = type { i32, ptr }
|
|
||||||
|
|
||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
|
||||||
|
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @main.external(ptr) #2
|
|
||||||
|
|
||||||
define hidden void @main.deferSimple(ptr %context) unnamed_addr #2 personality ptr @__gxx_wasm_personality_v0 {
|
|
||||||
entry:
|
|
||||||
%defer.alloca = alloca { i32, ptr }, align 8
|
|
||||||
%deferPtr = alloca ptr, align 4
|
|
||||||
store ptr null, ptr %deferPtr, align 4
|
|
||||||
%deferframe.buf = alloca %runtime.deferFrameWasmEH, align 8
|
|
||||||
call void @runtime.setupDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
%stackalloc = alloca i8, align 1
|
|
||||||
call void @runtime.trackPointer(ptr nonnull %defer.alloca, ptr nonnull %stackalloc, ptr undef)
|
|
||||||
store i32 0, ptr %defer.alloca, align 4
|
|
||||||
%defer.alloca.repack13 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
|
||||||
store ptr null, ptr %defer.alloca.repack13, align 4
|
|
||||||
store ptr %defer.alloca, ptr %deferPtr, align 4
|
|
||||||
invoke void @main.external(ptr undef)
|
|
||||||
to label %invoke.cont unwind label %catch.dispatch
|
|
||||||
|
|
||||||
invoke.cont: ; preds = %entry
|
|
||||||
br label %rundefers.block
|
|
||||||
|
|
||||||
rundefers.after: ; preds = %rundefers.end
|
|
||||||
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
ret void
|
|
||||||
|
|
||||||
rundefers.block: ; preds = %invoke.cont
|
|
||||||
br label %rundefers.loophead
|
|
||||||
|
|
||||||
rundefers.loophead: ; preds = %rundefers.catch.start, %rundefers.callback0, %rundefers.block
|
|
||||||
%0 = load ptr, ptr %deferPtr, align 4
|
|
||||||
%stackIsNil = icmp eq ptr %0, null
|
|
||||||
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
|
|
||||||
|
|
||||||
rundefers.loop: ; preds = %rundefers.loophead
|
|
||||||
%stack.next.gep = getelementptr inbounds %runtime._defer, ptr %0, i32 0, i32 1
|
|
||||||
%stack.next = load ptr, ptr %stack.next.gep, align 4
|
|
||||||
store ptr %stack.next, ptr %deferPtr, align 4
|
|
||||||
%callback = load i32, ptr %0, align 4
|
|
||||||
switch i32 %callback, label %rundefers.default [
|
|
||||||
i32 0, label %rundefers.callback0
|
|
||||||
]
|
|
||||||
|
|
||||||
rundefers.callback0: ; preds = %rundefers.loop
|
|
||||||
invoke void @"main.deferSimple$1"(ptr undef)
|
|
||||||
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
|
|
||||||
|
|
||||||
rundefers.default: ; preds = %rundefers.loop
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
rundefers.catch.dispatch: ; preds = %rundefers.callback0
|
|
||||||
%1 = catchswitch within none [label %rundefers.catch.start] unwind to caller
|
|
||||||
|
|
||||||
rundefers.catch.start: ; preds = %rundefers.catch.dispatch
|
|
||||||
%2 = catchpad within %1 [ptr null]
|
|
||||||
catchret from %2 to label %rundefers.loophead
|
|
||||||
|
|
||||||
rundefers.end: ; preds = %rundefers.loophead
|
|
||||||
br label %rundefers.after
|
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end1
|
|
||||||
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
ret void
|
|
||||||
|
|
||||||
catch.dispatch: ; preds = %entry
|
|
||||||
%3 = catchswitch within none [label %catch.start] unwind to caller
|
|
||||||
|
|
||||||
catch.start: ; preds = %catch.dispatch
|
|
||||||
%4 = catchpad within %3 [ptr null]
|
|
||||||
catchret from %4 to label %rundefers
|
|
||||||
|
|
||||||
rundefers: ; preds = %catch.start
|
|
||||||
br label %rundefers.loophead4
|
|
||||||
|
|
||||||
rundefers.loophead4: ; preds = %rundefers.catch.start6, %rundefers.callback012, %rundefers
|
|
||||||
%5 = load ptr, ptr %deferPtr, align 4
|
|
||||||
%stackIsNil7 = icmp eq ptr %5, null
|
|
||||||
br i1 %stackIsNil7, label %rundefers.end1, label %rundefers.loop3
|
|
||||||
|
|
||||||
rundefers.loop3: ; preds = %rundefers.loophead4
|
|
||||||
%stack.next.gep8 = getelementptr inbounds %runtime._defer, ptr %5, i32 0, i32 1
|
|
||||||
%stack.next9 = load ptr, ptr %stack.next.gep8, align 4
|
|
||||||
store ptr %stack.next9, ptr %deferPtr, align 4
|
|
||||||
%callback11 = load i32, ptr %5, align 4
|
|
||||||
switch i32 %callback11, label %rundefers.default2 [
|
|
||||||
i32 0, label %rundefers.callback012
|
|
||||||
]
|
|
||||||
|
|
||||||
rundefers.callback012: ; preds = %rundefers.loop3
|
|
||||||
invoke void @"main.deferSimple$1"(ptr undef)
|
|
||||||
to label %rundefers.loophead4 unwind label %rundefers.catch.dispatch5
|
|
||||||
|
|
||||||
rundefers.default2: ; preds = %rundefers.loop3
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
rundefers.catch.dispatch5: ; preds = %rundefers.callback012
|
|
||||||
%6 = catchswitch within none [label %rundefers.catch.start6] unwind to caller
|
|
||||||
|
|
||||||
rundefers.catch.start6: ; preds = %rundefers.catch.dispatch5
|
|
||||||
%7 = catchpad within %6 [ptr null]
|
|
||||||
catchret from %7 to label %rundefers.loophead4
|
|
||||||
|
|
||||||
rundefers.end1: ; preds = %rundefers.loophead4
|
|
||||||
br label %recover
|
|
||||||
}
|
|
||||||
|
|
||||||
declare i32 @__gxx_wasm_personality_v0(...)
|
|
||||||
|
|
||||||
declare void @runtime.setupDeferFrameWasmEH(ptr dereferenceable_or_null(16), ptr) #2
|
|
||||||
|
|
||||||
declare void @runtime.destroyDeferFrameWasmEH(ptr dereferenceable_or_null(16), ptr) #2
|
|
||||||
|
|
||||||
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #2 {
|
|
||||||
entry:
|
|
||||||
call void @runtime.printint32(i32 3, ptr undef)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @runtime.printint32(i32, ptr) #2
|
|
||||||
|
|
||||||
define hidden void @main.deferMultiple(ptr %context) unnamed_addr #2 personality ptr @__gxx_wasm_personality_v0 {
|
|
||||||
entry:
|
|
||||||
%defer.alloca2 = alloca { i32, ptr }, align 8
|
|
||||||
%defer.alloca = alloca { i32, ptr }, align 8
|
|
||||||
%deferPtr = alloca ptr, align 4
|
|
||||||
store ptr null, ptr %deferPtr, align 4
|
|
||||||
%deferframe.buf = alloca %runtime.deferFrameWasmEH, align 8
|
|
||||||
call void @runtime.setupDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
%stackalloc = alloca i8, align 1
|
|
||||||
call void @runtime.trackPointer(ptr nonnull %defer.alloca, ptr nonnull %stackalloc, ptr undef)
|
|
||||||
store i32 0, ptr %defer.alloca, align 4
|
|
||||||
%defer.alloca.repack16 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
|
||||||
store ptr null, ptr %defer.alloca.repack16, align 4
|
|
||||||
store ptr %defer.alloca, ptr %deferPtr, align 4
|
|
||||||
call void @runtime.trackPointer(ptr nonnull %defer.alloca2, ptr nonnull %stackalloc, ptr undef)
|
|
||||||
store i32 1, ptr %defer.alloca2, align 4
|
|
||||||
%defer.alloca2.repack17 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca2, i32 0, i32 1
|
|
||||||
store ptr %defer.alloca, ptr %defer.alloca2.repack17, align 4
|
|
||||||
store ptr %defer.alloca2, ptr %deferPtr, align 4
|
|
||||||
invoke void @main.external(ptr undef)
|
|
||||||
to label %invoke.cont unwind label %catch.dispatch
|
|
||||||
|
|
||||||
invoke.cont: ; preds = %entry
|
|
||||||
br label %rundefers.block
|
|
||||||
|
|
||||||
rundefers.after: ; preds = %rundefers.end
|
|
||||||
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
ret void
|
|
||||||
|
|
||||||
rundefers.block: ; preds = %invoke.cont
|
|
||||||
br label %rundefers.loophead
|
|
||||||
|
|
||||||
rundefers.loophead: ; preds = %rundefers.catch.start, %rundefers.callback1, %rundefers.callback0, %rundefers.block
|
|
||||||
%0 = load ptr, ptr %deferPtr, align 4
|
|
||||||
%stackIsNil = icmp eq ptr %0, null
|
|
||||||
br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop
|
|
||||||
|
|
||||||
rundefers.loop: ; preds = %rundefers.loophead
|
|
||||||
%stack.next.gep = getelementptr inbounds %runtime._defer, ptr %0, i32 0, i32 1
|
|
||||||
%stack.next = load ptr, ptr %stack.next.gep, align 4
|
|
||||||
store ptr %stack.next, ptr %deferPtr, align 4
|
|
||||||
%callback = load i32, ptr %0, align 4
|
|
||||||
switch i32 %callback, label %rundefers.default [
|
|
||||||
i32 0, label %rundefers.callback0
|
|
||||||
i32 1, label %rundefers.callback1
|
|
||||||
]
|
|
||||||
|
|
||||||
rundefers.callback0: ; preds = %rundefers.loop
|
|
||||||
invoke void @"main.deferMultiple$1"(ptr undef)
|
|
||||||
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
|
|
||||||
|
|
||||||
rundefers.callback1: ; preds = %rundefers.loop
|
|
||||||
invoke void @"main.deferMultiple$2"(ptr undef)
|
|
||||||
to label %rundefers.loophead unwind label %rundefers.catch.dispatch
|
|
||||||
|
|
||||||
rundefers.default: ; preds = %rundefers.loop
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
rundefers.catch.dispatch: ; preds = %rundefers.callback1, %rundefers.callback0
|
|
||||||
%1 = catchswitch within none [label %rundefers.catch.start] unwind to caller
|
|
||||||
|
|
||||||
rundefers.catch.start: ; preds = %rundefers.catch.dispatch
|
|
||||||
%2 = catchpad within %1 [ptr null]
|
|
||||||
catchret from %2 to label %rundefers.loophead
|
|
||||||
|
|
||||||
rundefers.end: ; preds = %rundefers.loophead
|
|
||||||
br label %rundefers.after
|
|
||||||
|
|
||||||
recover: ; preds = %rundefers.end3
|
|
||||||
call void @runtime.destroyDeferFrameWasmEH(ptr nonnull %deferframe.buf, ptr undef)
|
|
||||||
ret void
|
|
||||||
|
|
||||||
catch.dispatch: ; preds = %entry
|
|
||||||
%3 = catchswitch within none [label %catch.start] unwind to caller
|
|
||||||
|
|
||||||
catch.start: ; preds = %catch.dispatch
|
|
||||||
%4 = catchpad within %3 [ptr null]
|
|
||||||
catchret from %4 to label %rundefers
|
|
||||||
|
|
||||||
rundefers: ; preds = %catch.start
|
|
||||||
br label %rundefers.loophead6
|
|
||||||
|
|
||||||
rundefers.loophead6: ; preds = %rundefers.catch.start8, %rundefers.callback115, %rundefers.callback014, %rundefers
|
|
||||||
%5 = load ptr, ptr %deferPtr, align 4
|
|
||||||
%stackIsNil9 = icmp eq ptr %5, null
|
|
||||||
br i1 %stackIsNil9, label %rundefers.end3, label %rundefers.loop5
|
|
||||||
|
|
||||||
rundefers.loop5: ; preds = %rundefers.loophead6
|
|
||||||
%stack.next.gep10 = getelementptr inbounds %runtime._defer, ptr %5, i32 0, i32 1
|
|
||||||
%stack.next11 = load ptr, ptr %stack.next.gep10, align 4
|
|
||||||
store ptr %stack.next11, ptr %deferPtr, align 4
|
|
||||||
%callback13 = load i32, ptr %5, align 4
|
|
||||||
switch i32 %callback13, label %rundefers.default4 [
|
|
||||||
i32 0, label %rundefers.callback014
|
|
||||||
i32 1, label %rundefers.callback115
|
|
||||||
]
|
|
||||||
|
|
||||||
rundefers.callback014: ; preds = %rundefers.loop5
|
|
||||||
invoke void @"main.deferMultiple$1"(ptr undef)
|
|
||||||
to label %rundefers.loophead6 unwind label %rundefers.catch.dispatch7
|
|
||||||
|
|
||||||
rundefers.callback115: ; preds = %rundefers.loop5
|
|
||||||
invoke void @"main.deferMultiple$2"(ptr undef)
|
|
||||||
to label %rundefers.loophead6 unwind label %rundefers.catch.dispatch7
|
|
||||||
|
|
||||||
rundefers.default4: ; preds = %rundefers.loop5
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
rundefers.catch.dispatch7: ; preds = %rundefers.callback115, %rundefers.callback014
|
|
||||||
%6 = catchswitch within none [label %rundefers.catch.start8] unwind to caller
|
|
||||||
|
|
||||||
rundefers.catch.start8: ; preds = %rundefers.catch.dispatch7
|
|
||||||
%7 = catchpad within %6 [ptr null]
|
|
||||||
catchret from %7 to label %rundefers.loophead6
|
|
||||||
|
|
||||||
rundefers.end3: ; preds = %rundefers.loophead6
|
|
||||||
br label %recover
|
|
||||||
}
|
|
||||||
|
|
||||||
define internal void @"main.deferMultiple$1"(ptr %context) unnamed_addr #2 {
|
|
||||||
entry:
|
|
||||||
call void @runtime.printint32(i32 3, ptr undef)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define internal void @"main.deferMultiple$2"(ptr %context) unnamed_addr #2 {
|
|
||||||
entry:
|
|
||||||
call void @runtime.printint32(i32 5, ptr undef)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
Vendored
+12
-12
@@ -6,17 +6,16 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%positive = fcmp oge float %v, 0.000000e+00
|
%positive = fcmp oge float %v, 0.000000e+00
|
||||||
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
||||||
@@ -28,25 +27,25 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.maxu32f(ptr %context) unnamed_addr #1 {
|
define hidden float @main.maxu32f(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret float 0x41F0000000000000
|
ret float 0x41F0000000000000
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret i32 -1
|
ret i32 -1
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #1 {
|
define hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
|
ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = uitofp i32 %v to float
|
%0 = uitofp i32 %v to float
|
||||||
%withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
|
%withinmax = fcmp ole float %0, 0x41EFFFFFC0000000
|
||||||
@@ -56,7 +55,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #1 {
|
define hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%positive = fcmp oge float %v, 0.000000e+00
|
%positive = fcmp oge float %v, 0.000000e+00
|
||||||
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
%withinmax = fcmp ole float %v, 0x41EFFFFFC0000000
|
||||||
@@ -69,7 +68,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #1 {
|
define hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%positive = fcmp oge float %v, 0.000000e+00
|
%positive = fcmp oge float %v, 0.000000e+00
|
||||||
%withinmax = fcmp ole float %v, 2.550000e+02
|
%withinmax = fcmp ole float %v, 2.550000e+02
|
||||||
@@ -81,7 +80,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #1 {
|
define hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%abovemin = fcmp oge float %v, -1.280000e+02
|
%abovemin = fcmp oge float %v, -1.280000e+02
|
||||||
%belowmax = fcmp ole float %v, 1.270000e+02
|
%belowmax = fcmp ole float %v, 1.270000e+02
|
||||||
@@ -94,5 +93,6 @@ entry:
|
|||||||
ret i8 %0
|
ret i8 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
|
|||||||
Vendored
+8
-9
@@ -6,17 +6,16 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #1 {
|
define hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq ptr %callback.funcptr, null
|
%0 = icmp eq ptr %callback.funcptr, null
|
||||||
br i1 %0, label %fpcall.throw, label %fpcall.next
|
br i1 %0, label %fpcall.throw, label %fpcall.next
|
||||||
@@ -30,22 +29,22 @@ fpcall.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.nilPanic(ptr) #2
|
declare void @runtime.nilPanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.bar(ptr %context) unnamed_addr #1 {
|
define hidden void @main.bar(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)
|
call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #1 {
|
define hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+46
-46
@@ -22,99 +22,98 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
|
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
|
||||||
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
|
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
|
||||||
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 80, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
|
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 80, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
|
||||||
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:complex128" }, align 4
|
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, i16, ptr, { i32, [0 x ptr] } } { i8 -43, i16 0, ptr @"reflect/types.type:basic:complex128", { i32, [0 x ptr] } zeroinitializer }, align 4
|
||||||
|
|
||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.newScalar(ptr %context) unnamed_addr #1 {
|
define hidden void @main.newScalar(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new, ptr @main.scalar1, align 4
|
store ptr %new, ptr @main.scalar1, align 4
|
||||||
%new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new1, ptr @main.scalar2, align 4
|
store ptr %new1, ptr @main.scalar2, align 4
|
||||||
%new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new2, ptr @main.scalar3, align 4
|
store ptr %new2, ptr @main.scalar3, align 4
|
||||||
%new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new3, ptr @main.scalar4, align 4
|
store ptr %new3, ptr @main.scalar4, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.newArray(ptr %context) unnamed_addr #1 {
|
define hidden void @main.newArray(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new, ptr @main.array1, align 4
|
store ptr %new, ptr @main.array1, align 4
|
||||||
%new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new1, ptr @main.array2, align 4
|
store ptr %new1, ptr @main.array2, align 4
|
||||||
%new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
|
%new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new2, ptr @main.array3, align 4
|
store ptr %new2, ptr @main.array3, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.newStruct(ptr %context) unnamed_addr #1 {
|
define hidden void @main.newStruct(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new, ptr @main.struct1, align 4
|
store ptr %new, ptr @main.struct1, align 4
|
||||||
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new1, ptr @main.struct2, align 4
|
store ptr %new1, ptr @main.struct2, align 4
|
||||||
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #2
|
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new2, ptr @main.struct3, align 4
|
store ptr %new2, ptr @main.struct3, align 4
|
||||||
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #2
|
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new3, ptr @main.struct4, align 4
|
store ptr %new3, ptr @main.struct4, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #2
|
%new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %new
|
ret ptr %new
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.makeSlice(ptr %context) unnamed_addr #1 {
|
define hidden void @main.makeSlice(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #2
|
%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)
|
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 ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 1), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 1), align 4
|
||||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4
|
||||||
%makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #2
|
%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)
|
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 ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 1), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 1), align 4
|
||||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4
|
||||||
%makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #2
|
%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)
|
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 ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 1), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 1), align 4
|
||||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 4
|
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 4
|
||||||
@@ -122,20 +121,21 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #1 {
|
define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #2
|
%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)
|
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 { double, double }, ptr %0, i32 0, i32 1
|
%.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1
|
||||||
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)
|
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:complex128", ptr nonnull %stackalloc, ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret %runtime._interface %1
|
ret %runtime._interface %1
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { nounwind }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+11
-12
@@ -8,25 +8,24 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, 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)
|
call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %s.data
|
ret ptr %s.data
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.unsafeString(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #1 {
|
define hidden %runtime._string @main.unsafeString(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = icmp slt i16 %len, 0
|
%0 = icmp slt i16 %len, 0
|
||||||
@@ -40,7 +39,7 @@ unsafe.String.next: ; preds = %entry
|
|||||||
%5 = zext i16 %len to i32
|
%5 = zext i16 %len to i32
|
||||||
%6 = insertvalue %runtime._string undef, ptr %ptr, 0
|
%6 = insertvalue %runtime._string undef, ptr %ptr, 0
|
||||||
%7 = insertvalue %runtime._string %6, i32 %5, 1
|
%7 = insertvalue %runtime._string %6, i32 %5, 1
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret %runtime._string %7
|
ret %runtime._string %7
|
||||||
|
|
||||||
unsafe.String.throw: ; preds = %entry
|
unsafe.String.throw: ; preds = %entry
|
||||||
@@ -48,17 +47,17 @@ unsafe.String.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.unsafeSlicePanic(ptr) #2
|
declare void @runtime.unsafeSlicePanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.unsafeStringData(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1 {
|
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)
|
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,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+24
-25
@@ -8,30 +8,29 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.min1(i32 %a, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.min1(i32 %a, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret i32 %a
|
ret i32 %a
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.min3(i32 %a, i32 %b, i32 %c, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.min3(i32 %a, i32 %b, i32 %c, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
||||||
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
|
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
|
||||||
@@ -39,7 +38,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.min4(i32 %a, i32 %b, i32 %c, i32 %d, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.min4(i32 %a, i32 %b, i32 %c, i32 %d, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
|
||||||
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
|
%1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)
|
||||||
@@ -48,21 +47,21 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.minUint8(i8 %a, i8 %b, ptr %context) unnamed_addr #1 {
|
define hidden i8 @main.minUint8(i8 %a, i8 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i8 @llvm.umin.i8(i8 %a, i8 %b)
|
%0 = call i8 @llvm.umin.i8(i8 %a, i8 %b)
|
||||||
ret i8 %0
|
ret i8 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.umin.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.umin.i32(i32 %a, i32 %b)
|
||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #1 {
|
define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp olt float %a, %b
|
%0 = fcmp olt float %a, %b
|
||||||
%1 = select i1 %0, float %a, float %b
|
%1 = select i1 %0, float %a, float %b
|
||||||
@@ -70,7 +69,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #1 {
|
define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp olt double %a, %b
|
%0 = fcmp olt double %a, %b
|
||||||
%1 = select i1 %0, double %a, double %b
|
%1 = select i1 %0, double %a, double %b
|
||||||
@@ -78,7 +77,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.minString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #1 {
|
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
|
||||||
@@ -88,28 +87,28 @@ entry:
|
|||||||
%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 = extractvalue %runtime._string %5, 0
|
%6 = extractvalue %runtime._string %5, 0
|
||||||
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef)
|
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, i32, ptr, i32, ptr) #2
|
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 #1 {
|
define hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.smax.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.smax.i32(i32 %a, i32 %b)
|
||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
|
%0 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
|
||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #1 {
|
define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp ogt float %a, %b
|
%0 = fcmp ogt float %a, %b
|
||||||
%1 = select i1 %0, float %a, float %b
|
%1 = select i1 %0, float %a, float %b
|
||||||
@@ -117,7 +116,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.maxString(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr %context) unnamed_addr #1 {
|
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
|
||||||
@@ -127,12 +126,12 @@ entry:
|
|||||||
%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 = extractvalue %runtime._string %5, 0
|
%6 = extractvalue %runtime._string %5, 0
|
||||||
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._string %5
|
ret %runtime._string %5
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
|
define hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = shl i32 %s.len, 2
|
%0 = shl i32 %s.len, 2
|
||||||
call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false)
|
call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false)
|
||||||
@@ -143,19 +142,19 @@ entry:
|
|||||||
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3
|
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
|
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #1 {
|
define hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @runtime.hashmapClear(ptr %m, ptr undef) #5
|
call void @runtime.hashmapClear(ptr %m, ptr undef) #5
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #2
|
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
declare i32 @llvm.smin.i32(i32, i32) #4
|
declare i32 @llvm.smin.i32(i32, i32) #4
|
||||||
@@ -172,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,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
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 }
|
||||||
|
|||||||
+32
-33
@@ -10,25 +10,24 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @main.regularFunction(i32, ptr) #2
|
declare void @main.regularFunction(i32, ptr) #1
|
||||||
|
|
||||||
declare void @runtime.deadlock(ptr) #2
|
declare void @runtime.deadlock(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
||||||
@@ -39,17 +38,17 @@ entry:
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"internal/task.start"(i32, ptr, i32, ptr) #2
|
declare void @"internal/task.start"(i32, ptr, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
|
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@@ -64,16 +63,16 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
|
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
|
||||||
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
|
||||||
store i32 3, ptr %n, align 4
|
store i32 3, ptr %n, align 4
|
||||||
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
|
||||||
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #9
|
||||||
%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)
|
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 { i32, ptr }, ptr %0, i32 0, i32 1
|
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
|
||||||
store ptr %n, ptr %1, align 4
|
store ptr %n, ptr %1, align 4
|
||||||
@@ -84,7 +83,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #1 {
|
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
store i32 7, ptr %context, align 4
|
store i32 7, ptr %context, align 4
|
||||||
ret void
|
ret void
|
||||||
@@ -101,14 +100,14 @@ entry:
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.printint32(i32, ptr) #2
|
declare void @runtime.printint32(i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
|
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%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)
|
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 { i32, ptr, ptr }, ptr %0, i32 0, i32 1
|
%1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
store ptr %fn.context, ptr %1, align 4
|
store ptr %fn.context, ptr %1, align 4
|
||||||
@@ -132,35 +131,35 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
|
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
|
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
|
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(32) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @runtime.chanClose(ptr %ch, ptr undef) #9
|
call void @runtime.chanClose(ptr %ch, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #2
|
declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%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)
|
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 { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1
|
%1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1
|
||||||
store ptr @"main$string", ptr %1, align 4
|
store ptr @"main$string", ptr %1, align 4
|
||||||
@@ -189,13 +188,13 @@ entry:
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.regularFunction" }
|
attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.regularFunction" }
|
||||||
attributes #4 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
attributes #4 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
||||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
attributes #5 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
||||||
attributes #6 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper" }
|
attributes #6 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper" }
|
||||||
attributes #7 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
||||||
attributes #8 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
attributes #8 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
||||||
attributes #9 = { nounwind }
|
attributes #9 = { nounwind }
|
||||||
|
|||||||
Vendored
+45
-46
@@ -7,68 +7,71 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
%runtime._string = type { ptr, i32 }
|
%runtime._string = type { ptr, i32 }
|
||||||
|
|
||||||
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
||||||
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:int" }, align 4
|
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr, { i32, [0 x ptr] } } { i8 -43, i16 0, ptr @"reflect/types.type:basic:int", { i32, [0 x ptr] } zeroinitializer }, align 4
|
||||||
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:named:error" }, align 4
|
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr, { i32, [0 x ptr] } } { i8 -43, i16 0, ptr @"reflect/types.type:named:error", { i32, [0 x ptr] } zeroinitializer }, align 4
|
||||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 116, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [7 x i8] c".error\00" }, align 4
|
@"reflect/types.signature:Error:func:{}{basic:string}" = linkonce_odr constant i8 0, align 1
|
||||||
|
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, { i32, [1 x ptr] }, [7 x i8] } { i8 116, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:Error:func:{}{basic:string}"] }, [7 x i8] c".error\00" }, align 4
|
||||||
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||||
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 84, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, { i32, [1 x ptr] } } { i8 84, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:Error:func:{}{basic:string}"] } }, align 4
|
||||||
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr, { i32, [0 x ptr] } } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", { i32, [0 x ptr] } zeroinitializer }, align 4
|
||||||
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr, { i32, [0 x ptr] } } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}", { i32, [0 x ptr] } zeroinitializer }, align 4
|
||||||
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 84, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }, align 4
|
@"reflect/types.signature:String:func:{}{basic:string}" = linkonce_odr constant i8 0, align 1
|
||||||
|
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, { i32, [1 x ptr] } } { i8 84, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:String:func:{}{basic:string}"] } }, align 4
|
||||||
@"reflect/types.typeid:basic:int" = external constant i8
|
@"reflect/types.typeid:basic:int" = external constant i8
|
||||||
|
@"interface:{Error:func:{}{basic:string}}$itfmethods" = linkonce_odr unnamed_addr constant { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:Error:func:{}{basic:string}"] }, align 4
|
||||||
|
@"interface:{String:func:{}{basic:string}}$itfmethods" = linkonce_odr unnamed_addr constant { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:String:func:{}{basic:string}"] }, align 4
|
||||||
|
|
||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:int", ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:basic:int", ptr nonnull %stackalloc, ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._interface { ptr @"reflect/types.type:basic:int", ptr null }
|
ret %runtime._interface { ptr @"reflect/types.type:basic:int", ptr null }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:basic:int", ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:basic:int", ptr nonnull %stackalloc, ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._interface { ptr @"reflect/types.type:pointer:basic:int", ptr null }
|
ret %runtime._interface { ptr @"reflect/types.type:pointer:basic:int", ptr null }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:named:error", ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:named:error", ptr nonnull %stackalloc, ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._interface { ptr @"reflect/types.type:pointer:named:error", ptr null }
|
ret %runtime._interface { ptr @"reflect/types.type:pointer:named:error", ptr null }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr nonnull %stackalloc, ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._interface { ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr null }
|
ret %runtime._interface { ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", ptr null }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.isInt(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.isInt(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%typecode = call i1 @runtime.typeAssert(ptr %itf.typecode, ptr nonnull @"reflect/types.typeid:basic:int", ptr undef) #7
|
%typecode = call i1 @runtime.typeAssert(ptr %itf.typecode, ptr nonnull @"reflect/types.typeid:basic:int", ptr undef) #5
|
||||||
br i1 %typecode, label %typeassert.ok, label %typeassert.next
|
br i1 %typecode, label %typeassert.ok, label %typeassert.next
|
||||||
|
|
||||||
typeassert.next: ; preds = %typeassert.ok, %entry
|
typeassert.next: ; preds = %typeassert.ok, %entry
|
||||||
@@ -78,12 +81,12 @@ typeassert.ok: ; preds = %entry
|
|||||||
br label %typeassert.next
|
br label %typeassert.next
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #2
|
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.isError(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.isError(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7
|
%0 = call i1 @runtime.typeImplementsMethodSet(ptr %itf.typecode, ptr nonnull @"interface:{Error:func:{}{basic:string}}$itfmethods", ptr undef) #5
|
||||||
br i1 %0, label %typeassert.ok, label %typeassert.next
|
br i1 %0, label %typeassert.ok, label %typeassert.next
|
||||||
|
|
||||||
typeassert.next: ; preds = %typeassert.ok, %entry
|
typeassert.next: ; preds = %typeassert.ok, %entry
|
||||||
@@ -93,12 +96,12 @@ typeassert.ok: ; preds = %entry
|
|||||||
br label %typeassert.next
|
br label %typeassert.next
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i1 @"interface:{Error:func:{}{basic:string}}.$typeassert"(ptr) #3
|
declare i1 @runtime.typeImplementsMethodSet(ptr, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.isStringer(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden i1 @main.isStringer(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr %itf.typecode) #7
|
%0 = call i1 @runtime.typeImplementsMethodSet(ptr %itf.typecode, ptr nonnull @"interface:{String:func:{}{basic:string}}$itfmethods", ptr undef) #5
|
||||||
br i1 %0, label %typeassert.ok, label %typeassert.next
|
br i1 %0, label %typeassert.ok, label %typeassert.next
|
||||||
|
|
||||||
typeassert.next: ; preds = %typeassert.ok, %entry
|
typeassert.next: ; preds = %typeassert.ok, %entry
|
||||||
@@ -108,34 +111,30 @@ typeassert.ok: ; preds = %entry
|
|||||||
br label %typeassert.next
|
br label %typeassert.next
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i1 @"interface:{String:func:{}{basic:string}}.$typeassert"(ptr) #4
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.callFooMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden i8 @main.callFooMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr %itf.value, i32 3, ptr %itf.typecode, ptr undef) #7
|
%0 = call i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr %itf.value, i32 3, ptr %itf.typecode, ptr undef) #5
|
||||||
ret i8 %0
|
ret i8 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr, i32, ptr, ptr) #5
|
declare i8 @"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke"(ptr, i32, ptr, ptr) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.callErrorMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden %runtime._string @main.callErrorMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, ptr %itf.typecode, ptr undef) #7
|
%0 = call %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"(ptr %itf.value, ptr %itf.typecode, ptr undef) #5
|
||||||
%1 = extractvalue %runtime._string %0, 0
|
%1 = extractvalue %runtime._string %0, 0
|
||||||
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret %runtime._string %0
|
ret %runtime._string %0
|
||||||
}
|
}
|
||||||
|
|
||||||
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) #4
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.Error() string" }
|
attributes #3 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
|
||||||
attributes #4 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-methods"="reflect/methods.String() string" }
|
attributes #4 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
|
||||||
attributes #5 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
|
attributes #5 = { nounwind }
|
||||||
attributes #6 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
|
|
||||||
attributes #7 = { nounwind }
|
|
||||||
|
|||||||
Vendored
+12
-11
@@ -6,44 +6,45 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #1 {
|
define hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret [0 x i32] zeroinitializer
|
ret [0 x i32] zeroinitializer
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %x
|
ret ptr %x
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %x
|
ret ptr %x
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %x
|
ret ptr %x
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+15
-16
@@ -14,28 +14,27 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define void @extern_func() #2 {
|
define void @extern_func() #3 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #1 {
|
define hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @somepkg.someFunction2(ptr) #3
|
declare void @somepkg.someFunction2(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: inlinehint nounwind
|
; Function Attrs: inlinehint nounwind
|
||||||
define hidden void @main.inlineFunc(ptr %context) unnamed_addr #4 {
|
define hidden void @main.inlineFunc(ptr %context) unnamed_addr #4 {
|
||||||
@@ -71,15 +70,15 @@ entry:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @main.undefinedFunctionNotInSection(ptr) #3
|
declare void @main.undefinedFunctionNotInSection(ptr) #1
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #3 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
|
||||||
attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #4 = { inlinehint nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #5 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
|
attributes #6 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
|
||||||
attributes #7 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="modulename" "wasm-import-name"="import1" }
|
attributes #7 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="modulename" "wasm-import-name"="import1" }
|
||||||
attributes #8 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="foobar" "wasm-import-name"="imported" }
|
attributes #8 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-import-module"="foobar" "wasm-import-name"="imported" }
|
||||||
attributes #9 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exported" }
|
attributes #9 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exported" }
|
||||||
|
|||||||
Vendored
+42
-43
@@ -6,29 +6,28 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret i32 %ints.len
|
ret i32 %ints.len
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret i32 %ints.cap
|
ret i32 %ints.cap
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%.not = icmp ult i32 %index, %ints.len
|
%.not = icmp ult i32 %index, %ints.len
|
||||||
br i1 %.not, label %lookup.next, label %lookup.throw
|
br i1 %.not, label %lookup.next, label %lookup.throw
|
||||||
@@ -43,14 +42,14 @@ lookup.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.lookupPanic(ptr) #2
|
declare void @runtime.lookupPanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%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)
|
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 [3 x i32], ptr %varargs, i32 0, i32 1
|
%0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1
|
||||||
store i32 2, ptr %0, align 4
|
store i32 2, ptr %0, align 4
|
||||||
@@ -63,14 +62,14 @@ entry:
|
|||||||
%2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
%2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
||||||
%3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
|
%3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
|
||||||
%4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
|
%4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
|
||||||
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %4
|
ret { ptr, i32, i32 } %4
|
||||||
}
|
}
|
||||||
|
|
||||||
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #2
|
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #3
|
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #3
|
||||||
@@ -80,21 +79,21 @@ entry:
|
|||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
|
||||||
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
|
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3
|
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3
|
||||||
ret i32 %copy.n
|
ret i32 %copy.n
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
|
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%slice.maxcap = icmp slt i32 %len, 0
|
%slice.maxcap = icmp slt i32 %len, 0
|
||||||
@@ -105,7 +104,7 @@ slice.next: ; preds = %entry
|
|||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
@@ -113,10 +112,10 @@ slice.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.slicePanic(ptr) #2
|
declare void @runtime.slicePanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%slice.maxcap = icmp slt i32 %len, 0
|
%slice.maxcap = icmp slt i32 %len, 0
|
||||||
@@ -128,7 +127,7 @@ slice.next: ; preds = %entry
|
|||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
@@ -137,7 +136,7 @@ slice.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%slice.maxcap = icmp ugt i32 %len, 1431655765
|
%slice.maxcap = icmp ugt i32 %len, 1431655765
|
||||||
@@ -149,7 +148,7 @@ slice.next: ; preds = %entry
|
|||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
@@ -158,7 +157,7 @@ slice.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%slice.maxcap = icmp ugt i32 %len, 1073741823
|
%slice.maxcap = icmp ugt i32 %len, 1073741823
|
||||||
@@ -170,7 +169,7 @@ slice.next: ; preds = %entry
|
|||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
@@ -179,26 +178,26 @@ slice.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = getelementptr i8, ptr %p, i32 %len
|
%0 = getelementptr i8, ptr %p, i32 %len
|
||||||
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %0
|
ret ptr %0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = trunc i64 %len to i32
|
%0 = trunc i64 %len to i32
|
||||||
%1 = getelementptr i8, ptr %p, i32 %0
|
%1 = getelementptr i8, ptr %p, i32 %0
|
||||||
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret ptr %1
|
ret ptr %1
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp ult i32 %s.len, 4
|
%0 = icmp ult i32 %s.len, 4
|
||||||
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
||||||
@@ -211,14 +210,14 @@ slicetoarray.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.sliceToArrayPointerPanic(ptr) #2
|
declare void @runtime.sliceToArrayPointerPanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #1 {
|
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
||||||
|
|
||||||
slicetoarray.next: ; preds = %entry
|
slicetoarray.next: ; preds = %entry
|
||||||
@@ -229,7 +228,7 @@ slicetoarray.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = icmp ugt i32 %len, 1073741823
|
%0 = icmp ugt i32 %len, 1073741823
|
||||||
@@ -243,7 +242,7 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
|
%6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %7
|
ret { ptr, i32, i32 } %7
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
@@ -251,10 +250,10 @@ unsafe.Slice.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.unsafeSlicePanic(ptr) #2
|
declare void @runtime.unsafeSlicePanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = icmp eq ptr %ptr, null
|
%0 = icmp eq ptr %ptr, null
|
||||||
@@ -267,7 +266,7 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
|
%5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
|
||||||
%6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
|
%6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %6
|
ret { ptr, i32, i32 } %6
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
@@ -276,7 +275,7 @@ unsafe.Slice.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = icmp ugt i64 %len, 1073741823
|
%0 = icmp ugt i64 %len, 1073741823
|
||||||
@@ -291,7 +290,7 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
||||||
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %8
|
ret { ptr, i32, i32 } %8
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
@@ -300,7 +299,7 @@ unsafe.Slice.throw: ; preds = %entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #1 {
|
define hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = icmp ugt i64 %len, 1073741823
|
%0 = icmp ugt i64 %len, 1073741823
|
||||||
@@ -315,7 +314,7 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
||||||
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef)
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
ret { ptr, i32, i32 } %8
|
ret { ptr, i32, i32 } %8
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
@@ -323,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,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+15
-16
@@ -10,35 +10,34 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._string @main.someString(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret %runtime._string { ptr @"main$string", i32 3 }
|
ret %runtime._string { ptr @"main$string", i32 3 }
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #1 {
|
define hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret %runtime._string zeroinitializer
|
ret %runtime._string zeroinitializer
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.stringLen(ptr %s.data, i32 %s.len, ptr %context) unnamed_addr #1 {
|
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 %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #1 {
|
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
|
||||||
@@ -53,19 +52,19 @@ lookup.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.lookupPanic(ptr) #2
|
declare void @runtime.lookupPanic(ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.stringCompareEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
|
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, i32, ptr, i32, ptr) #2
|
declare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.stringCompareUnequal(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
|
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
|
||||||
@@ -73,16 +72,16 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i1 @main.stringCompareLarger(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr %context) unnamed_addr #1 {
|
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, i32, ptr, i32, ptr) #2
|
declare i1 @runtime.stringLess(ptr, i32, ptr, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i8 @main.stringLookup(ptr %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #1 {
|
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 ult i32 %0, %s.len
|
%.not = icmp ult i32 %0, %s.len
|
||||||
@@ -98,7 +97,7 @@ lookup.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nounwind }
|
||||||
|
|||||||
Vendored
+16
-17
@@ -8,17 +8,16 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
define hidden void @main.init(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden i32 @main.testZeroGet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.testZeroGet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca %main.hasPadding, align 8
|
%hashmap.key = alloca %main.hasPadding, align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
@@ -40,17 +39,17 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3
|
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #4
|
||||||
|
|
||||||
declare void @runtime.memzero(ptr, i32, ptr) #4
|
declare void @runtime.memzero(ptr, i32, ptr) #1
|
||||||
|
|
||||||
declare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(40), ptr, ptr, i32, ptr) #4
|
declare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(40), ptr, ptr, i32, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
|
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #4
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
|
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca %main.hasPadding, align 8
|
%hashmap.key = alloca %main.hasPadding, align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
@@ -71,10 +70,10 @@ entry:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(40), ptr, ptr, ptr) #4
|
declare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(40), ptr, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
@@ -101,7 +100,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #2 {
|
define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||||
%hashmap.value = alloca i32, align 4
|
%hashmap.value = alloca i32, align 4
|
||||||
@@ -128,14 +127,14 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.main(ptr %context) unnamed_addr #1 {
|
define hidden void @main.main(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { noinline nounwind "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
attributes #3 = { noinline nounwind "target-features"="+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #4 = { "target-features"="+bulk-memory,+exception-handling,+mutable-globals,+nontrapping-fptoint,+sign-ext" }
|
attributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
||||||
attributes #5 = { nounwind }
|
attributes #5 = { nounwind }
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func CreateDiagnostics(err error) ProgramDiagnostic {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Right now, the compiler will only show errors for the first package that
|
// Right now, the compiler will only show errors for the first pacakge that
|
||||||
// fails to build. This is likely to change in the future.
|
// fails to build. This is likely to change in the future.
|
||||||
return ProgramDiagnostic{
|
return ProgramDiagnostic{
|
||||||
createPackageDiagnostic(err),
|
createPackageDiagnostic(err),
|
||||||
@@ -147,7 +147,7 @@ func createDiagnostics(err error) []Diagnostic {
|
|||||||
// last package
|
// last package
|
||||||
fmt.Fprintln(buf, "\timports", pkgPath+": "+err.Err.Error())
|
fmt.Fprintln(buf, "\timports", pkgPath+": "+err.Err.Error())
|
||||||
} else {
|
} else {
|
||||||
// not the last package
|
// not the last pacakge
|
||||||
fmt.Fprintln(buf, "\timports", pkgPath)
|
fmt.Fprintln(buf, "\timports", pkgPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-38
@@ -7,6 +7,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/diagnostics"
|
"github.com/tinygo-org/tinygo/diagnostics"
|
||||||
@@ -14,55 +15,38 @@ import (
|
|||||||
|
|
||||||
// Test the error messages of the TinyGo compiler.
|
// Test the error messages of the TinyGo compiler.
|
||||||
func TestErrors(t *testing.T) {
|
func TestErrors(t *testing.T) {
|
||||||
// TODO: nicely formatted error messages for:
|
for _, name := range []string{
|
||||||
// - duplicate symbols in ld.lld (currently only prints bitcode file)
|
"cgo",
|
||||||
type errorTest struct {
|
"compiler",
|
||||||
name string
|
"interp",
|
||||||
target string
|
"loader-importcycle",
|
||||||
}
|
"loader-invaliddep",
|
||||||
for _, tc := range []errorTest{
|
"loader-invalidpackage",
|
||||||
{name: "cgo"},
|
"loader-nopackage",
|
||||||
{name: "compiler"},
|
"optimizer",
|
||||||
{name: "interp"},
|
"syntax",
|
||||||
{name: "linker-flashoverflow", target: "cortex-m-qemu"},
|
"types",
|
||||||
{name: "linker-ramoverflow", target: "cortex-m-qemu"},
|
|
||||||
{name: "linker-undefined", target: "darwin/arm64"},
|
|
||||||
{name: "linker-undefined", target: "linux/amd64"},
|
|
||||||
//{name: "linker-undefined", target: "windows/amd64"}, // TODO: no source location
|
|
||||||
{name: "linker-undefined", target: "cortex-m-qemu"},
|
|
||||||
//{name: "linker-undefined", target: "wasip1"}, // TODO: no source location
|
|
||||||
{name: "loader-importcycle"},
|
|
||||||
{name: "loader-invaliddep"},
|
|
||||||
{name: "loader-invalidpackage"},
|
|
||||||
{name: "loader-nopackage"},
|
|
||||||
{name: "optimizer"},
|
|
||||||
{name: "syntax"},
|
|
||||||
{name: "types"},
|
|
||||||
} {
|
} {
|
||||||
name := tc.name
|
|
||||||
if tc.target != "" {
|
|
||||||
name += "#" + tc.target
|
|
||||||
}
|
|
||||||
target := tc.target
|
|
||||||
if target == "" {
|
|
||||||
target = "wasip1"
|
|
||||||
}
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
options := optionsFromTarget(target, sema)
|
testErrorMessages(t, "./testdata/errors/"+name+".go")
|
||||||
testErrorMessages(t, "./testdata/errors/"+tc.name+".go", &options)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testErrorMessages(t *testing.T, filename string, options *compileopts.Options) {
|
func testErrorMessages(t *testing.T, filename string) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Parse expected error messages.
|
// Parse expected error messages.
|
||||||
expected := readErrorMessages(t, filename)
|
expected := readErrorMessages(t, filename)
|
||||||
|
|
||||||
// Try to build a binary (this should fail with an error).
|
// Try to build a binary (this should fail with an error).
|
||||||
tmpdir := t.TempDir()
|
tmpdir := t.TempDir()
|
||||||
err := Build(filename, tmpdir+"/out", options)
|
err := Build(filename, tmpdir+"/out", &compileopts.Options{
|
||||||
|
Target: "wasip1",
|
||||||
|
Semaphore: sema,
|
||||||
|
InterpTimeout: 180 * time.Second,
|
||||||
|
Debug: true,
|
||||||
|
VerifyIR: true,
|
||||||
|
Opt: "z",
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected to get a compiler error")
|
t.Fatal("expected to get a compiler error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,30 +7,41 @@ require (
|
|||||||
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/cdproto v0.0.0-20220113222801-0725d94bb6ee
|
||||||
github.com/chromedp/chromedp v0.7.6
|
github.com/chromedp/chromedp v0.7.6
|
||||||
|
github.com/client9/misspell v0.3.4
|
||||||
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
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||||
github.com/mattn/go-colorable v0.1.13
|
github.com/mattn/go-colorable v0.1.13
|
||||||
github.com/mattn/go-tty v0.0.4
|
github.com/mattn/go-tty v0.0.4
|
||||||
|
github.com/mgechev/revive v1.3.7
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
||||||
go.bug.st/serial v1.6.0
|
go.bug.st/serial v1.6.0
|
||||||
golang.org/x/net v0.26.0
|
golang.org/x/net v0.26.0
|
||||||
golang.org/x/sys v0.21.0
|
golang.org/x/sys v0.21.0
|
||||||
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
|
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0
|
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||||
|
github.com/chavacava/garif v0.1.0 // indirect
|
||||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
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/fatih/color v1.16.0 // indirect
|
||||||
|
github.com/fatih/structtag v1.2.0 // indirect
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/gobwas/ws v1.1.0 // indirect
|
github.com/gobwas/ws v1.1.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // 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/mattn/go-runewidth v0.0.9 // indirect
|
||||||
|
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
golang.org/x/text v0.16.0 // indirect
|
golang.org/x/text v0.16.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c h1:4T0Vj1UkGgcpkRrmn7SbokebnlfxJcMZPgWtOYACAAA=
|
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c h1:4T0Vj1UkGgcpkRrmn7SbokebnlfxJcMZPgWtOYACAAA=
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c/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/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
||||||
|
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
||||||
github.com/chromedp/cdproto v0.0.0-20211126220118-81fa0469ad77/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
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 h1:+SFdIVfQpG0s0DHYzou0kgfE0n0ZjKPwbiRJsXrZegU=
|
||||||
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
||||||
@@ -9,10 +13,17 @@ github.com/chromedp/chromedp v0.7.6 h1:2juGaktzjwULlsn+DnvIZXFUckEp5xs+GOBroaea+
|
|||||||
github.com/chromedp/chromedp v0.7.6/go.mod h1:ayT4YU/MGAALNfOg9gNrpGSAdnU51PMx+FCeuT1iXzo=
|
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 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||||
|
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 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/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
|
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||||
|
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
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/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 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
@@ -40,24 +51,41 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
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-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9/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/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=
|
||||||
|
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
|
||||||
|
github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE=
|
||||||
|
github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
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/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
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=
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||||
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
|
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
||||||
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.7.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=
|
||||||
@@ -75,7 +103,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
|||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0 h1:aN9rSxvVWmipB13yVAFOmRj3LX4Kkfiq/fSl5EAilDA=
|
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8 h1:bLsZXRUBavt++CJlMN7sppNziqu3LyamESLhFJcpqFQ=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20240804145059-aaff3eb751f0/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+1
-11
@@ -30,11 +30,8 @@ var Keys = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
switch Get("GOARCH") {
|
if Get("GOARCH") == "arm" {
|
||||||
case "arm":
|
|
||||||
Keys = append(Keys, "GOARM")
|
Keys = append(Keys, "GOARM")
|
||||||
case "mips", "mipsle":
|
|
||||||
Keys = append(Keys, "GOMIPS")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,13 +128,6 @@ func Get(name string) string {
|
|||||||
// difference between ARMv6 and ARMv7. ARMv6 binaries are much smaller,
|
// difference between ARMv6 and ARMv7. ARMv6 binaries are much smaller,
|
||||||
// especially when floating point instructions are involved.
|
// especially when floating point instructions are involved.
|
||||||
return "6"
|
return "6"
|
||||||
case "GOMIPS":
|
|
||||||
gomips := os.Getenv("GOMIPS")
|
|
||||||
if gomips == "" {
|
|
||||||
// Default to hardfloat (this matches the Go toolchain).
|
|
||||||
gomips = "hardfloat"
|
|
||||||
}
|
|
||||||
return gomips
|
|
||||||
case "GOROOT":
|
case "GOROOT":
|
||||||
readGoEnvVars()
|
readGoEnvVars()
|
||||||
return goEnvVars.GOROOT
|
return goEnvVars.GOROOT
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
// TODO: remove this (by merging it into the top-level go.mod)
|
|
||||||
// once the top level go.mod specifies a go new enough to make our version of misspell happy.
|
|
||||||
|
|
||||||
module tools
|
|
||||||
|
|
||||||
go 1.21
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/golangci/misspell v0.6.0
|
|
||||||
github.com/mgechev/revive v1.3.9
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
|
||||||
github.com/chavacava/garif v0.1.0 // indirect
|
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
|
||||||
github.com/fatih/structtag v1.2.0 // indirect
|
|
||||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
|
||||||
golang.org/x/sys v0.22.0 // indirect
|
|
||||||
golang.org/x/text v0.14.0 // indirect
|
|
||||||
golang.org/x/tools v0.23.0 // indirect
|
|
||||||
)
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
|
||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
|
||||||
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
|
||||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
|
||||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
|
||||||
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
|
|
||||||
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
|
|
||||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
|
||||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
|
|
||||||
github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=
|
|
||||||
github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
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/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
|
||||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
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.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
|
||||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
@@ -5,9 +5,9 @@
|
|||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/golangci/misspell"
|
_ "github.com/client9/misspell"
|
||||||
_ "github.com/mgechev/revive"
|
_ "github.com/mgechev/revive"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go install github.com/golangci/misspell/cmd/misspell
|
//go:generate go install github.com/client9/misspell/cmd/misspell
|
||||||
//go:generate go install github.com/mgechev/revive
|
//go:generate go install github.com/mgechev/revive
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ All in all, this design provides several benefits:
|
|||||||
it should be a whole lot faster for loops as it doesn't have to call into
|
it should be a whole lot faster for loops as it doesn't have to call into
|
||||||
LLVM (via CGo) for every operation.
|
LLVM (via CGo) for every operation.
|
||||||
|
|
||||||
As mentioned, this partial evaluator comes in three parts: a compiler, an
|
As mentioned, this partial evaulator comes in three parts: a compiler, an
|
||||||
interpreter, and a memory manager.
|
interpreter, and a memory manager.
|
||||||
|
|
||||||
## Compiler
|
## Compiler
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {
|
|||||||
return &r
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose deallocates all allocated LLVM resources.
|
// Dispose deallocates all alloated LLVM resources.
|
||||||
func (r *runner) dispose() {
|
func (r *runner) dispose() {
|
||||||
r.targetData.Dispose()
|
r.targetData.Dispose()
|
||||||
r.targetData = llvm.TargetData{}
|
r.targetData = llvm.TargetData{}
|
||||||
|
|||||||
@@ -421,64 +421,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
// Special function that will trigger an error.
|
// Special function that will trigger an error.
|
||||||
// This is used to test error reporting.
|
// This is used to test error reporting.
|
||||||
return nil, mem, r.errorAt(inst, errors.New("test error"))
|
return nil, mem, r.errorAt(inst, errors.New("test error"))
|
||||||
case strings.HasSuffix(callFn.name, ".$typeassert"):
|
|
||||||
if r.debug {
|
|
||||||
fmt.Fprintln(os.Stderr, indent+"interface assert:", operands[1:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load various values for the interface implements check below.
|
|
||||||
typecodePtr, err := operands[1].asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
// typecodePtr always point to the numMethod field in the type
|
|
||||||
// description struct. The methodSet, when present, comes right
|
|
||||||
// before the numMethod field (the compiler doesn't generate
|
|
||||||
// method sets for concrete types without methods).
|
|
||||||
// Considering that the compiler doesn't emit interface type
|
|
||||||
// asserts for interfaces with no methods (as the always succeed)
|
|
||||||
// then if the offset is zero, this assert must always fail.
|
|
||||||
if typecodePtr.offset() == 0 {
|
|
||||||
locals[inst.localIndex] = literalValue{uint8(0)}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
typecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
methodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
methodSet := mem.get(methodSetPtr.index()).llvmGlobal.Initializer()
|
|
||||||
numMethods := int(r.builder.CreateExtractValue(methodSet, 0, "").ZExtValue())
|
|
||||||
llvmFn := inst.llvmInst.CalledValue()
|
|
||||||
methodSetAttr := llvmFn.GetStringAttributeAtIndex(-1, "tinygo-methods")
|
|
||||||
methodSetString := methodSetAttr.GetStringValue()
|
|
||||||
|
|
||||||
// Make a set of all the methods on the concrete type, for
|
|
||||||
// easier checking in the next step.
|
|
||||||
concreteTypeMethods := map[string]struct{}{}
|
|
||||||
for i := 0; i < numMethods; i++ {
|
|
||||||
methodInfo := r.builder.CreateExtractValue(methodSet, 1, "")
|
|
||||||
name := r.builder.CreateExtractValue(methodInfo, i, "").Name()
|
|
||||||
concreteTypeMethods[name] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether all interface methods are also in the list
|
|
||||||
// of defined methods calculated above. This is the interface
|
|
||||||
// assert itself.
|
|
||||||
assertOk := uint8(1) // i1 true
|
|
||||||
for _, name := range strings.Split(methodSetString, "; ") {
|
|
||||||
if _, ok := concreteTypeMethods[name]; !ok {
|
|
||||||
// There is a method on the interface that is not
|
|
||||||
// implemented by the type. The assertion will fail.
|
|
||||||
assertOk = 0 // i1 false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If assertOk is still 1, the assertion succeeded.
|
|
||||||
locals[inst.localIndex] = literalValue{assertOk}
|
|
||||||
case strings.HasSuffix(callFn.name, "$invoke"):
|
case strings.HasSuffix(callFn.name, "$invoke"):
|
||||||
// This thunk is the interface method dispatcher: it is called
|
// This thunk is the interface method dispatcher: it is called
|
||||||
// with all regular parameters and a type code. It will then
|
// with all regular parameters and a type code. It will then
|
||||||
|
|||||||
@@ -936,7 +936,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
|
|
||||||
// Configure stdout/stderr. The stdout may go to a buffer, not a real
|
// Configure stdout/stderr. The stdout may go to a buffer, not a real
|
||||||
// stdout.
|
// stdout.
|
||||||
cmd.Stdout = newOutputWriter(stdout, result.Executable)
|
cmd.Stdout = stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if config.EmulatorName() == "simavr" {
|
if config.EmulatorName() == "simavr" {
|
||||||
cmd.Stdout = nil // don't print initial load commands
|
cmd.Stdout = nil // don't print initial load commands
|
||||||
@@ -1437,7 +1437,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" {
|
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
||||||
flag.StringVar(&outpath, "o", "", "output filename")
|
flag.StringVar(&outpath, "o", "", "output filename")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1467,8 +1467,7 @@ func main() {
|
|||||||
case "clang", "ld.lld", "wasm-ld":
|
case "clang", "ld.lld", "wasm-ld":
|
||||||
err := builder.RunTool(command, os.Args[2:]...)
|
err := builder.RunTool(command, os.Args[2:]...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The tool should have printed an error message already.
|
fmt.Fprintln(os.Stderr, err)
|
||||||
// Don't print another error message here.
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@@ -1499,7 +1498,6 @@ func main() {
|
|||||||
GOOS: goenv.Get("GOOS"),
|
GOOS: goenv.Get("GOOS"),
|
||||||
GOARCH: goenv.Get("GOARCH"),
|
GOARCH: goenv.Get("GOARCH"),
|
||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
GOMIPS: goenv.Get("GOMIPS"),
|
|
||||||
Target: *target,
|
Target: *target,
|
||||||
StackSize: stackSize,
|
StackSize: stackSize,
|
||||||
Opt: *opt,
|
Opt: *opt,
|
||||||
@@ -1572,6 +1570,50 @@ func main() {
|
|||||||
|
|
||||||
err := Build(pkgName, outpath, options)
|
err := Build(pkgName, outpath, options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
|
case "build-library":
|
||||||
|
// Note: this command is only meant to be used while making a release!
|
||||||
|
if outpath == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
||||||
|
usage(command)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if *target == "" {
|
||||||
|
fmt.Fprintln(os.Stderr, "No target (-target).")
|
||||||
|
}
|
||||||
|
if flag.NArg() != 1 {
|
||||||
|
fmt.Fprintf(os.Stderr, "Build-library only accepts exactly one library name as argument, %d given\n", flag.NArg())
|
||||||
|
usage(command)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
var lib *builder.Library
|
||||||
|
switch name := flag.Arg(0); name {
|
||||||
|
case "compiler-rt":
|
||||||
|
lib = &builder.CompilerRT
|
||||||
|
case "picolibc":
|
||||||
|
lib = &builder.Picolibc
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
tmpdir, err := os.MkdirTemp("", "tinygo*")
|
||||||
|
if err != nil {
|
||||||
|
handleCompilerError(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpdir)
|
||||||
|
spec, err := compileopts.LoadTarget(options)
|
||||||
|
if err != nil {
|
||||||
|
handleCompilerError(err)
|
||||||
|
}
|
||||||
|
config := &compileopts.Config{
|
||||||
|
Options: options,
|
||||||
|
Target: spec,
|
||||||
|
}
|
||||||
|
path, err := lib.Load(config, tmpdir)
|
||||||
|
handleCompilerError(err)
|
||||||
|
err = copyFile(path, outpath)
|
||||||
|
if err != nil {
|
||||||
|
handleCompilerError(err)
|
||||||
|
}
|
||||||
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" {
|
||||||
@@ -1738,7 +1780,6 @@ func main() {
|
|||||||
GOOS string `json:"goos"`
|
GOOS string `json:"goos"`
|
||||||
GOARCH string `json:"goarch"`
|
GOARCH string `json:"goarch"`
|
||||||
GOARM string `json:"goarm"`
|
GOARM string `json:"goarm"`
|
||||||
GOMIPS string `json:"gomips"`
|
|
||||||
BuildTags []string `json:"build_tags"`
|
BuildTags []string `json:"build_tags"`
|
||||||
GC string `json:"garbage_collector"`
|
GC string `json:"garbage_collector"`
|
||||||
Scheduler string `json:"scheduler"`
|
Scheduler string `json:"scheduler"`
|
||||||
@@ -1749,7 +1790,6 @@ func main() {
|
|||||||
GOOS: config.GOOS(),
|
GOOS: config.GOOS(),
|
||||||
GOARCH: config.GOARCH(),
|
GOARCH: config.GOARCH(),
|
||||||
GOARM: config.GOARM(),
|
GOARM: config.GOARM(),
|
||||||
GOMIPS: config.GOMIPS(),
|
|
||||||
BuildTags: config.BuildTags(),
|
BuildTags: config.BuildTags(),
|
||||||
GC: config.GC(),
|
GC: config.GC(),
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
|
|||||||
+6
-18
@@ -8,6 +8,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -36,7 +37,7 @@ var supportedLinuxArches = map[string]string{
|
|||||||
"X86Linux": "linux/386",
|
"X86Linux": "linux/386",
|
||||||
"ARMLinux": "linux/arm/6",
|
"ARMLinux": "linux/arm/6",
|
||||||
"ARM64Linux": "linux/arm64",
|
"ARM64Linux": "linux/arm64",
|
||||||
"MIPSLinux": "linux/mipsle/hardfloat",
|
"MIPSLinux": "linux/mipsle",
|
||||||
"WASIp1": "wasip1/wasm",
|
"WASIp1": "wasip1/wasm",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,18 +287,10 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
runTest("rand.go", options, t, nil, nil)
|
runTest("rand.go", options, t, nil, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if !isWASI {
|
if !isWebAssembly {
|
||||||
// On WebAssembly, recover() needs the exception handling proposal which
|
// The recover() builtin isn't supported yet on WebAssembly and Windows.
|
||||||
// isn't (as of 2024) implemented in wasmtime so this test is skipped on
|
|
||||||
// WASI.
|
|
||||||
t.Run("recover.go", func(t *testing.T) {
|
t.Run("recover.go", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
options := options
|
|
||||||
if isWebAssembly {
|
|
||||||
// Hack: Asyncify doesn't support exception handling
|
|
||||||
// instructions.
|
|
||||||
options.Scheduler = "none"
|
|
||||||
}
|
|
||||||
runTest("recover.go", options, t, nil, nil)
|
runTest("recover.go", options, t, nil, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -333,7 +326,6 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
|||||||
GOOS: goenv.Get("GOOS"),
|
GOOS: goenv.Get("GOOS"),
|
||||||
GOARCH: goenv.Get("GOARCH"),
|
GOARCH: goenv.Get("GOARCH"),
|
||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
GOMIPS: goenv.Get("GOMIPS"),
|
|
||||||
Target: target,
|
Target: target,
|
||||||
Semaphore: sema,
|
Semaphore: sema,
|
||||||
InterpTimeout: 180 * time.Second,
|
InterpTimeout: 180 * time.Second,
|
||||||
@@ -357,11 +349,8 @@ func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
|
|||||||
VerifyIR: true,
|
VerifyIR: true,
|
||||||
Opt: "z",
|
Opt: "z",
|
||||||
}
|
}
|
||||||
switch options.GOARCH {
|
if options.GOARCH == "arm" {
|
||||||
case "arm":
|
|
||||||
options.GOARM = parts[2]
|
options.GOARM = parts[2]
|
||||||
case "mips", "mipsle":
|
|
||||||
options.GOMIPS = parts[2]
|
|
||||||
}
|
}
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
@@ -707,8 +696,7 @@ func TestMain(m *testing.M) {
|
|||||||
// Invoke a specific tool.
|
// Invoke a specific tool.
|
||||||
err := builder.RunTool(os.Args[1], os.Args[2:]...)
|
err := builder.RunTool(os.Args[1], os.Args[2:]...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The tool should have printed an error message already.
|
fmt.Fprintln(os.Stderr, err)
|
||||||
// Don't print another error message here.
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
acuire,acquire
|
|
||||||
addess,address
|
|
||||||
adust,adjust
|
|
||||||
allcoate,allocate
|
|
||||||
alloated,allocated
|
|
||||||
archtecture,architecture
|
|
||||||
arcive,archive
|
|
||||||
beconfigured,be configured
|
|
||||||
configration,configuration
|
|
||||||
contants,constants
|
|
||||||
cricital,critical
|
|
||||||
evaulator,evaluator
|
|
||||||
freqency,frequency
|
|
||||||
frquency,frequency
|
|
||||||
implmented,implemented
|
|
||||||
interrput,interrupt
|
|
||||||
interrut,interrupt
|
|
||||||
poitner,pointer
|
|
||||||
probbably,probably
|
|
||||||
refection,reflection
|
|
||||||
satisifying,satisfying
|
|
||||||
simulataneously,simultaneously
|
|
||||||
suggets,suggests
|
|
||||||
undefied,undefined
|
|
||||||
unecessary,unnecessary
|
|
||||||
unsiged,unsigned
|
|
||||||
|
+19
-41
@@ -197,14 +197,31 @@ func Monitor(executable, port string, config *compileopts.Config) error {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
buf := make([]byte, 100*1024)
|
buf := make([]byte, 100*1024)
|
||||||
writer := newOutputWriter(os.Stdout, executable)
|
var line []byte
|
||||||
for {
|
for {
|
||||||
n, err := serialConn.Read(buf)
|
n, err := serialConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCh <- fmt.Errorf("read error: %w", err)
|
errCh <- fmt.Errorf("read error: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writer.Write(buf[:n])
|
start := 0
|
||||||
|
for i, c := range buf[:n] {
|
||||||
|
if c == '\n' {
|
||||||
|
os.Stdout.Write(buf[start : i+1])
|
||||||
|
start = i + 1
|
||||||
|
address := extractPanicAddress(line)
|
||||||
|
if address != 0 {
|
||||||
|
loc, err := addressToLine(executable, address)
|
||||||
|
if err == nil && loc.IsValid() {
|
||||||
|
fmt.Printf("[tinygo: panic at %s]\n", loc.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line = line[:0]
|
||||||
|
} else {
|
||||||
|
line = append(line, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Stdout.Write(buf[start:n])
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -383,42 +400,3 @@ func readDWARF(executable string) (*dwarf.Data, error) {
|
|||||||
return nil, errors.New("unknown binary format")
|
return nil, errors.New("unknown binary format")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type outputWriter struct {
|
|
||||||
out io.Writer
|
|
||||||
executable string
|
|
||||||
line []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// newOutputWriter returns an io.Writer that will intercept panic addresses and
|
|
||||||
// will try to insert a source location in the output if the source location can
|
|
||||||
// be found in the executable.
|
|
||||||
func newOutputWriter(out io.Writer, executable string) *outputWriter {
|
|
||||||
return &outputWriter{
|
|
||||||
out: out,
|
|
||||||
executable: executable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *outputWriter) Write(p []byte) (n int, err error) {
|
|
||||||
start := 0
|
|
||||||
for i, c := range p {
|
|
||||||
if c == '\n' {
|
|
||||||
w.out.Write(p[start : i+1])
|
|
||||||
start = i + 1
|
|
||||||
address := extractPanicAddress(w.line)
|
|
||||||
if address != 0 {
|
|
||||||
loc, err := addressToLine(w.executable, address)
|
|
||||||
if err == nil && loc.Filename != "" {
|
|
||||||
fmt.Printf("[tinygo: panic at %s]\n", loc.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.line = w.line[:0]
|
|
||||||
} else {
|
|
||||||
w.line = append(w.line, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.out.Write(p[start:])
|
|
||||||
n = len(p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// This implementation of crypto/rand uses the arc4random_buf function
|
// This implementation of crypto/rand uses the arc4random_buf function
|
||||||
// (available on both MacOS and WASI) to generate random numbers.
|
// (available on both MacOS and WASI) to generate random numbers.
|
||||||
//
|
//
|
||||||
// Note: arc4random_buf (unlike what the name suggests) does not use the insecure
|
// Note: arc4random_buf (unlike what the name suggets) does not use the insecure
|
||||||
// RC4 cipher. Instead, it uses a high-quality cipher, varying by the libc
|
// RC4 cipher. Instead, it uses a high-quality cipher, varying by the libc
|
||||||
// implementation.
|
// implementation.
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ type Dialer struct {
|
|||||||
//
|
//
|
||||||
// The returned Conn, if any, will always be of type *Conn.
|
// The returned Conn, if any, will always be of type *Conn.
|
||||||
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return nil, errors.New("tls:DialContext not implemented")
|
return nil, errors.New("tls:DialContext not implmented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadX509KeyPair reads and parses a public/private key pair from a pair
|
// LoadX509KeyPair reads and parses a public/private key pair from a pair
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ func (pwm PWM) Configure(config PWMConfig) error {
|
|||||||
// Set the PWM mode to fast PWM (mode = 3).
|
// Set the PWM mode to fast PWM (mode = 3).
|
||||||
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
|
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
|
||||||
// monotonic timer is using the same time as PWM:0
|
// monotonic timer is using the same time as PWM:0
|
||||||
// we must adjust internal settings of monotonic timer when PWM:0 settings changed
|
// we must adust internal settings of monotonic timer when PWM:0 settings changed
|
||||||
adjustMonotonicTimer()
|
adjustMonotonicTimer()
|
||||||
} else {
|
} else {
|
||||||
avr.TCCR2B.Set(prescaler)
|
avr.TCCR2B.Set(prescaler)
|
||||||
@@ -718,7 +718,7 @@ func (pwm PWM) Set(channel uint8, value uint32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// monotonic timer is using the same time as PWM:0
|
// monotonic timer is using the same time as PWM:0
|
||||||
// we must adjust internal settings of monotonic timer when PWM:0 settings changed
|
// we must adust internal settings of monotonic timer when PWM:0 settings changed
|
||||||
adjustMonotonicTimer()
|
adjustMonotonicTimer()
|
||||||
case 1:
|
case 1:
|
||||||
mask := interrupt.Disable()
|
mask := interrupt.Disable()
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (pwm PWM) Configure(config PWMConfig) error {
|
|||||||
// Set the PWM mode to fast PWM (mode = 3).
|
// Set the PWM mode to fast PWM (mode = 3).
|
||||||
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
|
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
|
||||||
// monotonic timer is using the same time as PWM:0
|
// monotonic timer is using the same time as PWM:0
|
||||||
// we must adjust internal settings of monotonic timer when PWM:0 settings changed
|
// we must adust internal settings of monotonic timer when PWM:0 settings changed
|
||||||
adjustMonotonicTimer()
|
adjustMonotonicTimer()
|
||||||
} else {
|
} else {
|
||||||
avr.TCCR2B.Set(prescaler)
|
avr.TCCR2B.Set(prescaler)
|
||||||
@@ -385,7 +385,7 @@ func (pwm PWM) Set(channel uint8, value uint32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// monotonic timer is using the same time as PWM:0
|
// monotonic timer is using the same time as PWM:0
|
||||||
// we must adjust internal settings of monotonic timer when PWM:0 settings changed
|
// we must adust internal settings of monotonic timer when PWM:0 settings changed
|
||||||
adjustMonotonicTimer()
|
adjustMonotonicTimer()
|
||||||
case 1:
|
case 1:
|
||||||
mask := interrupt.Disable()
|
mask := interrupt.Disable()
|
||||||
|
|||||||
@@ -480,7 +480,7 @@ func (uart *UART) enableTransmitter() {
|
|||||||
uart.Bus.SetCONF0_TXFIFO_RST(0)
|
uart.Bus.SetCONF0_TXFIFO_RST(0)
|
||||||
// TXINFO empty threshold is when txfifo_empty_int interrupt produced after the amount of data in Tx-FIFO is less than this register value.
|
// TXINFO empty threshold is when txfifo_empty_int interrupt produced after the amount of data in Tx-FIFO is less than this register value.
|
||||||
uart.Bus.SetCONF1_TXFIFO_EMPTY_THRHD(uart_empty_thresh_default)
|
uart.Bus.SetCONF1_TXFIFO_EMPTY_THRHD(uart_empty_thresh_default)
|
||||||
// we are not using interrupt on TX since write we are waiting for FIFO to have space.
|
// we are not using interrut on TX since write we are waiting for FIFO to have space.
|
||||||
// uart.Bus.INT_ENA.SetBits(esp.UART_INT_ENA_TXFIFO_EMPTY_INT_ENA)
|
// uart.Bus.INT_ENA.SetBits(esp.UART_INT_ENA_TXFIFO_EMPTY_INT_ENA)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ func (p Pin) getGPIO() (norm *nxp.GPIO_Type, fast *nxp.GPIO_Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPad returns both the pad and mux configuration registers for a given Pin.
|
// getPad returns both the pad and mux configration registers for a given Pin.
|
||||||
func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {
|
func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {
|
||||||
switch p.getPort() {
|
switch p.getPort() {
|
||||||
case portA:
|
case portA:
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ var (
|
|||||||
// here: https://github.com/vmilea/pico_i2c_slave
|
// here: https://github.com/vmilea/pico_i2c_slave
|
||||||
|
|
||||||
// Features: Taken from datasheet.
|
// Features: Taken from datasheet.
|
||||||
// Default controller mode, with target mode available (not simultaneously).
|
// Default controller mode, with target mode available (not simulataneously).
|
||||||
// Default target address of RP2040: 0x055
|
// Default target address of RP2040: 0x055
|
||||||
// Supports 10-bit addressing in controller mode
|
// Supports 10-bit addressing in controller mode
|
||||||
// 16-element transmit buffer
|
// 16-element transmit buffer
|
||||||
@@ -36,7 +36,7 @@ var (
|
|||||||
// GPIO config
|
// GPIO config
|
||||||
// Each controller must connect its clock SCL and data SDA to one pair of GPIOs.
|
// Each controller must connect its clock SCL and data SDA to one pair of GPIOs.
|
||||||
// The I2C standard requires that drivers drivea signal low, or when not driven the signal will be pulled high.
|
// The I2C standard requires that drivers drivea signal low, or when not driven the signal will be pulled high.
|
||||||
// This applies to SCL and SDA. The GPIO pads should be configured for:
|
// This applies to SCL and SDA. The GPIO pads should beconfigured for:
|
||||||
// Pull-up enabled
|
// Pull-up enabled
|
||||||
// Slew rate limited
|
// Slew rate limited
|
||||||
// Schmitt trigger enabled
|
// Schmitt trigger enabled
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
|
|||||||
// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)
|
// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)
|
||||||
pclk1 := CPUFrequency() / 2
|
pclk1 := CPUFrequency() / 2
|
||||||
|
|
||||||
// set frequency range to PCLK1 clock speed in MHz
|
// set freqency range to PCLK1 clock speed in MHz
|
||||||
// aka setting the value 36 means to use 36 MHz clock
|
// aka setting the value 36 means to use 36 MHz clock
|
||||||
return pclk1 / 1000000
|
return pclk1 / 1000000
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,10 +256,10 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set frequency dependent on PCLK prescaler. Since these are rather weird
|
// set frequency dependent on PCLK prescaler. Since these are rather weird
|
||||||
// speeds due to the CPU frequency, pick a range up to that frequency for
|
// speeds due to the CPU freqency, pick a range up to that frquency for
|
||||||
// clients to use more human-understandable numbers, e.g. nearest 100KHz
|
// clients to use more human-understandable numbers, e.g. nearest 100KHz
|
||||||
|
|
||||||
// These are based on APB2 clock frequency (84MHz on the discovery board)
|
// These are based on APB2 clock frquency (84MHz on the discovery board)
|
||||||
// TODO: also include the MCU/APB clock setting in the equation
|
// TODO: also include the MCU/APB clock setting in the equation
|
||||||
switch {
|
switch {
|
||||||
case localFrequency < 328125:
|
case localFrequency < 328125:
|
||||||
|
|||||||
@@ -327,10 +327,10 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|||||||
localFrequency := config.Frequency
|
localFrequency := config.Frequency
|
||||||
|
|
||||||
// set frequency dependent on PCLK prescaler. Since these are rather weird
|
// set frequency dependent on PCLK prescaler. Since these are rather weird
|
||||||
// speeds due to the CPU frequency, pick a range up to that frequency for
|
// speeds due to the CPU freqency, pick a range up to that frquency for
|
||||||
// clients to use more human-understandable numbers, e.g. nearest 100KHz
|
// clients to use more human-understandable numbers, e.g. nearest 100KHz
|
||||||
|
|
||||||
// These are based on 80MHz peripheral clock frequency
|
// These are based on 80MHz peripheral clock frquency
|
||||||
switch {
|
switch {
|
||||||
case localFrequency < 312500:
|
case localFrequency < 312500:
|
||||||
conf = stm32.SPI_CR1_BR_Div256
|
conf = stm32.SPI_CR1_BR_Div256
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ func (p *Process) Release() error {
|
|||||||
return p.release()
|
return p.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindProcess looks for a running process by its pid.
|
|
||||||
// Keep compatibility with golang and always succeed and return new proc with pid on Linux.
|
// Keep compatibility with golang and always succeed and return new proc with pid on Linux.
|
||||||
func FindProcess(pid int) (*Process, error) {
|
func FindProcess(pid int) (*Process, error) {
|
||||||
return findProcess(pid)
|
return findProcess(pid)
|
||||||
|
|||||||
@@ -290,6 +290,16 @@ func (f *File) Sync() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truncate is a stub, not yet implemented
|
||||||
|
func (f *File) Truncate(size int64) (err error) {
|
||||||
|
if f.handle == nil {
|
||||||
|
err = ErrClosed
|
||||||
|
} else {
|
||||||
|
err = ErrNotImplemented
|
||||||
|
}
|
||||||
|
return &PathError{Op: "truncate", Path: f.name, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
// LinkError records an error during a link or symlink or rename system call and
|
// LinkError records an error during a link or symlink or rename system call and
|
||||||
// the paths that caused it.
|
// the paths that caused it.
|
||||||
type LinkError struct {
|
type LinkError struct {
|
||||||
|
|||||||
@@ -55,19 +55,6 @@ func NewFile(fd uintptr, name string) *File {
|
|||||||
return &File{&file{handle: unixFileHandle(fd), name: name}}
|
return &File{&file{handle: unixFileHandle(fd), name: name}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
|
||||||
// If the file is a symbolic link, it changes the size of the link's target.
|
|
||||||
// If there is an error, it will be of type *PathError.
|
|
||||||
func Truncate(name string, size int64) error {
|
|
||||||
e := ignoringEINTR(func() error {
|
|
||||||
return syscall.Truncate(name, size)
|
|
||||||
})
|
|
||||||
if e != nil {
|
|
||||||
return &PathError{Op: "truncate", Path: name, Err: e}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pipe() (r *File, w *File, err error) {
|
func Pipe() (r *File, w *File, err error) {
|
||||||
var p [2]int
|
var p [2]int
|
||||||
err = handleSyscallError(syscall.Pipe2(p[:], syscall.O_CLOEXEC))
|
err = handleSyscallError(syscall.Pipe2(p[:], syscall.O_CLOEXEC))
|
||||||
@@ -138,18 +125,6 @@ func Readlink(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the file.
|
|
||||||
// It does not change the I/O offset.
|
|
||||||
// If there is an error, it will be of type *PathError.
|
|
||||||
// Alternatively just use 'raw' syscall by file name
|
|
||||||
func (f *File) Truncate(size int64) (err error) {
|
|
||||||
if f.handle == nil {
|
|
||||||
return ErrClosed
|
|
||||||
}
|
|
||||||
|
|
||||||
return Truncate(f.name, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
|
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
|
||||||
// It returns the number of bytes read and any error encountered, possibly io.EOF.
|
// It returns the number of bytes read and any error encountered, possibly io.EOF.
|
||||||
// At end of file, Pread returns 0, io.EOF.
|
// At end of file, Pread returns 0, io.EOF.
|
||||||
|
|||||||
@@ -59,16 +59,6 @@ func Pipe() (r *File, w *File, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *unixFileHandle) Truncate(size int64) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
|
||||||
// If the file is a symbolic link, it changes the size of the link's target.
|
|
||||||
func Truncate(name string, size int64) error {
|
|
||||||
return &PathError{Op: "truncate", Path: name, Err: ErrNotImplemented}
|
|
||||||
}
|
|
||||||
|
|
||||||
func tempDir() string {
|
func tempDir() string {
|
||||||
n := uint32(syscall.MAX_PATH)
|
n := uint32(syscall.MAX_PATH)
|
||||||
for {
|
for {
|
||||||
@@ -116,15 +106,6 @@ func (f unixFileHandle) Sync() error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
|
||||||
// If the file is a symbolic link, it changes the size of the link's target.
|
|
||||||
func (f *File) Truncate(size int64) error {
|
|
||||||
if f.handle == nil {
|
|
||||||
return &PathError{Op: "truncate", Path: f.name, Err: ErrClosed}
|
|
||||||
}
|
|
||||||
return Truncate(f.name, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows.
|
// isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows.
|
||||||
// True is returned if name is 'NUL' whatever the case.
|
// True is returned if name is 'NUL' whatever the case.
|
||||||
func isWindowsNulName(name string) bool {
|
func isWindowsNulName(name string) bool {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func TestStatBadDir(t *testing.T) {
|
|||||||
badDir := filepath.Join(dir, "not-exist/really-not-exist")
|
badDir := filepath.Join(dir, "not-exist/really-not-exist")
|
||||||
_, err := Stat(badDir)
|
_, err := Stat(badDir)
|
||||||
if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
|
if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
|
||||||
t.Errorf("Mkdir error = %#v; want PathError for path %q satisfying IsNotExist", err, badDir)
|
t.Errorf("Mkdir error = %#v; want PathError for path %q satisifying IsNotExist", err, badDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func TestMkdirTempBadDir(t *testing.T) {
|
|||||||
badDir := filepath.Join(dir, "not-exist")
|
badDir := filepath.Join(dir, "not-exist")
|
||||||
_, err = MkdirTemp(badDir, "foo")
|
_, err = MkdirTemp(badDir, "foo")
|
||||||
if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
|
if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
|
||||||
t.Errorf("TempDir error = %#v; want PathError for path %q satisfying IsNotExist", err, badDir)
|
t.Errorf("TempDir error = %#v; want PathError for path %q satisifying IsNotExist", err, badDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
//go:build darwin || (linux && !baremetal && !js && !wasi)
|
|
||||||
|
|
||||||
// Copyright 2024 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package os_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTruncate(t *testing.T) {
|
|
||||||
// Truncate is not supported on Windows or wasi at the moment
|
|
||||||
if runtime.GOOS == "windows" || runtime.GOOS == "wasip1" || runtime.GOOS == "wasip2" {
|
|
||||||
t.Logf("skipping test on %s", runtime.GOOS)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
|
||||||
file := filepath.Join(tmpDir, "truncate_test")
|
|
||||||
|
|
||||||
fd, err := Create(file)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("create %q: got %v, want nil", file, err)
|
|
||||||
}
|
|
||||||
defer fd.Close()
|
|
||||||
|
|
||||||
// truncate up to 0x100
|
|
||||||
if err := fd.Truncate(0x100); err != nil {
|
|
||||||
t.Fatalf("truncate %q: got %v, want nil", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if size is 0x100
|
|
||||||
fi, err := Stat(file)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("stat %q: got %v, want nil", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.Size() != 0x100 {
|
|
||||||
t.Fatalf("size of %q is %d; want 0x100", file, fi.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
// truncate down to 0x80
|
|
||||||
if err := fd.Truncate(0x80); err != nil {
|
|
||||||
t.Fatalf("truncate %q: got %v, want nil", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if size is 0x80
|
|
||||||
fi, err = Stat(file)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("stat %q: got %v, want nil", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.Size() != 0x80 {
|
|
||||||
t.Fatalf("size of %q is %d; want 0x80", file, fi.Size())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package reflect
|
||||||
|
|
||||||
|
// This file defines functions that logically belong in the runtime but that
|
||||||
|
// depend on the internals of the reflect package and are therefore better
|
||||||
|
// implemented directly in the reflect package.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Return whether the concrete type implements the asserted method set.
|
||||||
|
// This function is called both from the compiler and from the reflect package.
|
||||||
|
//
|
||||||
|
//go:linkname typeImplementsMethodSet runtime.typeImplementsMethodSet
|
||||||
|
func typeImplementsMethodSet(concreteType, assertedMethodSet unsafe.Pointer) bool {
|
||||||
|
if concreteType == nil {
|
||||||
|
// This can happen when doing a type assert on a nil interface value.
|
||||||
|
// According to the Go language specification, a type assert on a nil
|
||||||
|
// interface always fails.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||||
|
itfNumMethod := *(*uintptr)(assertedMethodSet)
|
||||||
|
if itfNumMethod == 0 {
|
||||||
|
// While the compiler shouldn't emit such type asserts, the reflect
|
||||||
|
// package may do so.
|
||||||
|
// This is actually needed for correctness: for example a value of type
|
||||||
|
// int may be assigned to a variable of type interface{}.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull the method set out of the concrete type.
|
||||||
|
var methods *methodSet
|
||||||
|
metaByte := *(*uint8)(concreteType)
|
||||||
|
if metaByte&flagNamed != 0 {
|
||||||
|
concreteType := (*namedType)(concreteType)
|
||||||
|
methods = &concreteType.methods
|
||||||
|
} else if metaByte&kindMask == uint8(Struct) {
|
||||||
|
concreteType := (*structType)(concreteType)
|
||||||
|
methods = &concreteType.methods
|
||||||
|
} else if metaByte&kindMask == uint8(Pointer) {
|
||||||
|
concreteType := (*ptrType)(concreteType)
|
||||||
|
methods = &concreteType.methods
|
||||||
|
} else {
|
||||||
|
// Other types don't have a method set.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
concreteTypePtr := unsafe.Pointer(&methods.methods)
|
||||||
|
concreteTypeEnd := unsafe.Add(concreteTypePtr, uintptr(methods.length)*ptrSize)
|
||||||
|
|
||||||
|
// Iterate over each method in the interface method set, and check whether
|
||||||
|
// the method exists in the method set of the concrete type.
|
||||||
|
// Both method sets are sorted in the same way, so we can use a simple loop
|
||||||
|
// to check for a match.
|
||||||
|
assertedTypePtr := unsafe.Add(assertedMethodSet, ptrSize)
|
||||||
|
assertedTypeEnd := unsafe.Add(assertedTypePtr, itfNumMethod*ptrSize)
|
||||||
|
for assertedTypePtr != assertedTypeEnd {
|
||||||
|
assertedMethod := *(*unsafe.Pointer)(assertedTypePtr)
|
||||||
|
|
||||||
|
// Search for the same method in the concrete type.
|
||||||
|
for {
|
||||||
|
if concreteTypePtr == concreteTypeEnd {
|
||||||
|
// Reached the end of the concrete type method set.
|
||||||
|
// The method wasn't found, so the type assert failed.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
concreteMethod := *(*unsafe.Pointer)(concreteTypePtr)
|
||||||
|
concreteTypePtr = unsafe.Add(concreteTypePtr, ptrSize)
|
||||||
|
if concreteMethod == assertedMethod {
|
||||||
|
// Found the method in the concrete type. Continue with the
|
||||||
|
// next in the interface method set.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The method was found. Continue with the next.
|
||||||
|
assertedTypePtr = unsafe.Add(assertedTypePtr, ptrSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// All methods in the interface were found.
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package reflect_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"io"
|
||||||
|
. "reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//func TestImplicitMapConversion(t *testing.T) {
|
||||||
|
// // Test implicit conversions in MapIndex and SetMapIndex.
|
||||||
|
// {
|
||||||
|
// // direct
|
||||||
|
// m := make(map[int]int)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// mv.SetMapIndex(ValueOf(1), ValueOf(2))
|
||||||
|
// x, ok := m[1]
|
||||||
|
// if x != 2 {
|
||||||
|
// t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
|
||||||
|
// }
|
||||||
|
// if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
|
||||||
|
// t.Errorf("#1 MapIndex(1) = %d", n)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert interface key
|
||||||
|
// m := make(map[any]int)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// mv.SetMapIndex(ValueOf(1), ValueOf(2))
|
||||||
|
// x, ok := m[1]
|
||||||
|
// if x != 2 {
|
||||||
|
// t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
|
||||||
|
// }
|
||||||
|
// if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
|
||||||
|
// t.Errorf("#2 MapIndex(1) = %d", n)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert interface value
|
||||||
|
// m := make(map[int]any)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// mv.SetMapIndex(ValueOf(1), ValueOf(2))
|
||||||
|
// x, ok := m[1]
|
||||||
|
// if x != 2 {
|
||||||
|
// t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
|
||||||
|
// }
|
||||||
|
// if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
|
||||||
|
// t.Errorf("#3 MapIndex(1) = %d", n)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert both interface key and interface value
|
||||||
|
// m := make(map[any]any)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// mv.SetMapIndex(ValueOf(1), ValueOf(2))
|
||||||
|
// x, ok := m[1]
|
||||||
|
// if x != 2 {
|
||||||
|
// t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
|
||||||
|
// }
|
||||||
|
// if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
|
||||||
|
// t.Errorf("#4 MapIndex(1) = %d", n)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert both, with non-empty interfaces
|
||||||
|
// m := make(map[io.Reader]io.Writer)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// b1 := new(bytes.Buffer)
|
||||||
|
// b2 := new(bytes.Buffer)
|
||||||
|
// mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
|
||||||
|
// x, ok := m[b1]
|
||||||
|
// if x != b2 {
|
||||||
|
// t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
|
||||||
|
// }
|
||||||
|
// if p := mv.MapIndex(ValueOf(b1)).Elem().UnsafePointer(); p != unsafe.Pointer(b2) {
|
||||||
|
// t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert channel direction
|
||||||
|
// m := make(map[<-chan int]chan int)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// c1 := make(chan int)
|
||||||
|
// c2 := make(chan int)
|
||||||
|
// mv.SetMapIndex(ValueOf(c1), ValueOf(c2))
|
||||||
|
// x, ok := m[c1]
|
||||||
|
// if x != c2 {
|
||||||
|
// t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
|
||||||
|
// }
|
||||||
|
// if p := mv.MapIndex(ValueOf(c1)).UnsafePointer(); p != ValueOf(c2).UnsafePointer() {
|
||||||
|
// t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// // convert identical underlying types
|
||||||
|
// type MyBuffer bytes.Buffer
|
||||||
|
// m := make(map[*MyBuffer]*bytes.Buffer)
|
||||||
|
// mv := ValueOf(m)
|
||||||
|
// b1 := new(MyBuffer)
|
||||||
|
// b2 := new(bytes.Buffer)
|
||||||
|
// mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
|
||||||
|
// x, ok := m[b1]
|
||||||
|
// if x != b2 {
|
||||||
|
// t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
|
||||||
|
// }
|
||||||
|
// if p := mv.MapIndex(ValueOf(b1)).UnsafePointer(); p != unsafe.Pointer(b2) {
|
||||||
|
// t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func TestImplicitSetConversion(t *testing.T) {
|
||||||
|
// // Assume TestImplicitMapConversion covered the basics.
|
||||||
|
// // Just make sure conversions are being applied at all.
|
||||||
|
// var r io.Reader
|
||||||
|
// b := new(bytes.Buffer)
|
||||||
|
// rv := ValueOf(&r).Elem()
|
||||||
|
// rv.Set(ValueOf(b))
|
||||||
|
// if r != b {
|
||||||
|
// t.Errorf("after Set: r=%T(%v)", r, r)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func TestImplicitSendConversion(t *testing.T) {
|
||||||
|
// c := make(chan io.Reader, 10)
|
||||||
|
// b := new(bytes.Buffer)
|
||||||
|
// ValueOf(c).Send(ValueOf(b))
|
||||||
|
// if bb := <-c; bb != b {
|
||||||
|
// t.Errorf("Received %p != %p", bb, b)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func TestImplicitCallConversion(t *testing.T) {
|
||||||
|
// // Arguments must be assignable to parameter types.
|
||||||
|
// fv := ValueOf(io.WriteString)
|
||||||
|
// b := new(strings.Builder)
|
||||||
|
// fv.Call([]Value{ValueOf(b), ValueOf("hello world")})
|
||||||
|
// if b.String() != "hello world" {
|
||||||
|
// t.Errorf("After call: string=%q want %q", b.String(), "hello world")
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func TestImplicitAppendConversion(t *testing.T) {
|
||||||
|
// // Arguments must be assignable to the slice's element type.
|
||||||
|
// s := []io.Reader{}
|
||||||
|
// sv := ValueOf(&s).Elem()
|
||||||
|
// b := new(bytes.Buffer)
|
||||||
|
// sv.Set(Append(sv, ValueOf(b)))
|
||||||
|
// if len(s) != 1 || s[0] != b {
|
||||||
|
// t.Errorf("after append: s=%v want [%p]", s, b)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
var implementsTests = []struct {
|
||||||
|
x any
|
||||||
|
t any
|
||||||
|
b bool
|
||||||
|
}{
|
||||||
|
{new(*bytes.Buffer), new(io.Reader), true},
|
||||||
|
{new(bytes.Buffer), new(io.Reader), false},
|
||||||
|
{new(*bytes.Buffer), new(io.ReaderAt), false},
|
||||||
|
{new(*ast.Ident), new(ast.Expr), true},
|
||||||
|
{new(*notAnExpr), new(ast.Expr), false},
|
||||||
|
{new(*ast.Ident), new(notASTExpr), false},
|
||||||
|
{new(notASTExpr), new(ast.Expr), false},
|
||||||
|
{new(ast.Expr), new(notASTExpr), false},
|
||||||
|
{new(*notAnExpr), new(notASTExpr), true},
|
||||||
|
}
|
||||||
|
|
||||||
|
type notAnExpr struct{}
|
||||||
|
|
||||||
|
func (notAnExpr) Pos() token.Pos { return token.NoPos }
|
||||||
|
func (notAnExpr) End() token.Pos { return token.NoPos }
|
||||||
|
func (notAnExpr) exprNode() {}
|
||||||
|
|
||||||
|
type notASTExpr interface {
|
||||||
|
Pos() token.Pos
|
||||||
|
End() token.Pos
|
||||||
|
exprNode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImplements(t *testing.T) {
|
||||||
|
for _, tt := range implementsTests {
|
||||||
|
xv := TypeOf(tt.x).Elem()
|
||||||
|
xt := TypeOf(tt.t).Elem()
|
||||||
|
if b := xv.Implements(xt); b != tt.b {
|
||||||
|
t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var assignableTests = []struct {
|
||||||
|
x any
|
||||||
|
t any
|
||||||
|
b bool
|
||||||
|
}{
|
||||||
|
{new(chan int), new(<-chan int), true},
|
||||||
|
{new(<-chan int), new(chan int), false},
|
||||||
|
{new(*int), new(IntPtr), true},
|
||||||
|
{new(IntPtr), new(*int), true},
|
||||||
|
{new(IntPtr), new(IntPtr1), false},
|
||||||
|
{new(Ch), new(<-chan any), true},
|
||||||
|
// test runs implementsTests too
|
||||||
|
}
|
||||||
|
|
||||||
|
type IntPtr *int
|
||||||
|
type IntPtr1 *int
|
||||||
|
type Ch <-chan any
|
||||||
|
|
||||||
|
func TestAssignableTo(t *testing.T) {
|
||||||
|
for _, tt := range append(assignableTests, implementsTests...) {
|
||||||
|
xv := TypeOf(tt.x).Elem()
|
||||||
|
xt := TypeOf(tt.t).Elem()
|
||||||
|
if b := xv.AssignableTo(xt); b != tt.b {
|
||||||
|
t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
-15
@@ -23,6 +23,7 @@
|
|||||||
// meta uint8
|
// meta uint8
|
||||||
// nmethods uint16
|
// nmethods uint16
|
||||||
// elementType *typeStruct
|
// elementType *typeStruct
|
||||||
|
// methods methodSet
|
||||||
// - array types (see arrayType)
|
// - array types (see arrayType)
|
||||||
// meta uint8
|
// meta uint8
|
||||||
// nmethods uint16 (0)
|
// nmethods uint16 (0)
|
||||||
@@ -44,7 +45,8 @@
|
|||||||
// pkgpath *byte // package path; null terminated
|
// pkgpath *byte // package path; null terminated
|
||||||
// numField uint16
|
// numField uint16
|
||||||
// fields [...]structField // the remaining fields are all of type structField
|
// fields [...]structField // the remaining fields are all of type structField
|
||||||
// - interface types (this is missing the interface methods):
|
// methods methodSet
|
||||||
|
// - interface types:
|
||||||
// meta uint8
|
// meta uint8
|
||||||
// ptrTo *typeStruct
|
// ptrTo *typeStruct
|
||||||
// - signature types (this is missing input and output parameters):
|
// - signature types (this is missing input and output parameters):
|
||||||
@@ -56,6 +58,7 @@
|
|||||||
// ptrTo *typeStruct
|
// ptrTo *typeStruct
|
||||||
// elem *typeStruct // underlying type
|
// elem *typeStruct // underlying type
|
||||||
// pkgpath *byte // pkgpath; null terminated
|
// pkgpath *byte // pkgpath; null terminated
|
||||||
|
// methods methodSet
|
||||||
// name [1]byte // actual name; null terminated
|
// name [1]byte // actual name; null terminated
|
||||||
//
|
//
|
||||||
// The type struct is essentially a union of all the above types. Which it is,
|
// The type struct is essentially a union of all the above types. Which it is,
|
||||||
@@ -404,7 +407,7 @@ const (
|
|||||||
|
|
||||||
// The base type struct. All type structs start with this.
|
// The base type struct. All type structs start with this.
|
||||||
type rawType struct {
|
type rawType struct {
|
||||||
meta uint8 // metadata byte, contains kind and flags (see constants above)
|
meta uint8 // metadata byte, contains kind and flags (see contants above)
|
||||||
}
|
}
|
||||||
|
|
||||||
// All types that have an element type: named, chan, slice, array, map (but not
|
// All types that have an element type: named, chan, slice, array, map (but not
|
||||||
@@ -420,6 +423,7 @@ type ptrType struct {
|
|||||||
rawType
|
rawType
|
||||||
numMethod uint16
|
numMethod uint16
|
||||||
elem *rawType
|
elem *rawType
|
||||||
|
methods methodSet
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayType struct {
|
type arrayType struct {
|
||||||
@@ -445,6 +449,7 @@ type namedType struct {
|
|||||||
ptrTo *rawType
|
ptrTo *rawType
|
||||||
elem *rawType
|
elem *rawType
|
||||||
pkg *byte
|
pkg *byte
|
||||||
|
methods methodSet
|
||||||
name [1]byte
|
name [1]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,6 +468,7 @@ type structType struct {
|
|||||||
size uint32
|
size uint32
|
||||||
numField uint16
|
numField uint16
|
||||||
fields [1]structField // the remaining fields are all of type structField
|
fields [1]structField // the remaining fields are all of type structField
|
||||||
|
methods methodSet
|
||||||
}
|
}
|
||||||
|
|
||||||
type structField struct {
|
type structField struct {
|
||||||
@@ -470,6 +476,18 @@ type structField struct {
|
|||||||
data unsafe.Pointer // various bits of information, packed in a byte array
|
data unsafe.Pointer // various bits of information, packed in a byte array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type interfaceType struct {
|
||||||
|
rawType
|
||||||
|
ptrTo *rawType
|
||||||
|
methods methodSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method set, as emitted by the compiler.
|
||||||
|
type methodSet struct {
|
||||||
|
length uintptr
|
||||||
|
methods [0]*byte // variable number of methods
|
||||||
|
}
|
||||||
|
|
||||||
// Equivalent to (go/types.Type).Underlying(): if this is a named type return
|
// Equivalent to (go/types.Type).Underlying(): if this is a named type return
|
||||||
// the underlying type, else just return the type itself.
|
// the underlying type, else just return the type itself.
|
||||||
func (t *rawType) underlying() *rawType {
|
func (t *rawType) underlying() *rawType {
|
||||||
@@ -774,7 +792,7 @@ func (t *rawType) rawFieldByNameFunc(match func(string) bool) (rawStructField, [
|
|||||||
if match(name) {
|
if match(name) {
|
||||||
found = append(found, result{
|
found = append(found, result{
|
||||||
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
|
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
|
||||||
append(ll.index[:len(ll.index):len(ll.index)], int(i)),
|
append(ll.index, int(i)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +805,7 @@ func (t *rawType) rawFieldByNameFunc(match func(string) bool) (rawStructField, [
|
|||||||
|
|
||||||
nextlevel = append(nextlevel, fieldWalker{
|
nextlevel = append(nextlevel, fieldWalker{
|
||||||
t: embedded,
|
t: embedded,
|
||||||
index: append(ll.index[:len(ll.index):len(ll.index)], int(i)),
|
index: append(ll.index, int(i)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,17 +972,52 @@ func (t *rawType) FieldAlign() int {
|
|||||||
// AssignableTo returns whether a value of type t can be assigned to a variable
|
// AssignableTo returns whether a value of type t can be assigned to a variable
|
||||||
// of type u.
|
// of type u.
|
||||||
func (t *rawType) AssignableTo(u Type) bool {
|
func (t *rawType) AssignableTo(u Type) bool {
|
||||||
if t == u.(*rawType) {
|
// Quotes come from the language spec:
|
||||||
return true
|
// https://go.dev/ref/spec#Assignability
|
||||||
}
|
// > A value x of type V is assignable to a variable of type T ("x is
|
||||||
|
// > assignable to T") if one of the following conditions applies:
|
||||||
if u.Kind() == Interface && u.NumMethod() == 0 {
|
// [...]
|
||||||
|
// (Replace T with t, and x with u).
|
||||||
|
u_raw := u.(*rawType)
|
||||||
|
if t == u_raw {
|
||||||
|
// > V and T are identical.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.Kind() == Interface {
|
if u.Kind() == Interface {
|
||||||
panic("reflect: unimplemented: AssignableTo with interface")
|
// > T is an interface type, but not a type parameter, and x implements
|
||||||
|
// > T.
|
||||||
|
u_itf := (*interfaceType)(unsafe.Pointer(u_raw.underlying()))
|
||||||
|
res := typeImplementsMethodSet(unsafe.Pointer(t), unsafe.Pointer(&u_itf.methods))
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_named := t.isNamed()
|
||||||
|
u_named := u_raw.isNamed()
|
||||||
|
if t_named && u_named {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.underlying() == u_raw.underlying() {
|
||||||
|
// > V and T have identical underlying types but are not type parameters
|
||||||
|
// > and at least one of V or T is not a named type.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Kind() == Chan && u_raw.Kind() == Chan {
|
||||||
|
// > V and T are channel types with identical element types, V is a
|
||||||
|
// > bidirectional channel, and at least one of V or T is not a named
|
||||||
|
// > type.
|
||||||
|
t_chan := (*elemType)(unsafe.Pointer(t.underlying()))
|
||||||
|
u_chan := (*elemType)(unsafe.Pointer(u_raw.underlying()))
|
||||||
|
if t_chan.elem != u_chan.elem {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t_chan.ChanDir() != BothDir {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,7 +1025,8 @@ func (t *rawType) Implements(u Type) bool {
|
|||||||
if u.Kind() != Interface {
|
if u.Kind() != Interface {
|
||||||
panic("reflect: non-interface type passed to Type.Implements")
|
panic("reflect: non-interface type passed to Type.Implements")
|
||||||
}
|
}
|
||||||
return t.AssignableTo(u)
|
u_itf := (*interfaceType)(unsafe.Pointer(u.(*rawType).underlying()))
|
||||||
|
return typeImplementsMethodSet(unsafe.Pointer(t), unsafe.Pointer(&u_itf.methods))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparable returns whether values of this type can be compared to each other.
|
// Comparable returns whether values of this type can be compared to each other.
|
||||||
@@ -1046,7 +1100,9 @@ func readStringZ(data unsafe.Pointer) string {
|
|||||||
|
|
||||||
func (t *rawType) name() string {
|
func (t *rawType) name() string {
|
||||||
ntype := (*namedType)(unsafe.Pointer(t))
|
ntype := (*namedType)(unsafe.Pointer(t))
|
||||||
return readStringZ(unsafe.Pointer(&ntype.name[0]))
|
ptr := unsafe.Pointer(&ntype.name[0])
|
||||||
|
ptr = unsafe.Add(ptr, uintptr(ntype.methods.length)*unsafe.Sizeof(unsafe.Pointer(nil)))
|
||||||
|
return readStringZ(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *rawType) Name() string {
|
func (t *rawType) Name() string {
|
||||||
@@ -1060,10 +1116,8 @@ func (t *rawType) Name() string {
|
|||||||
panic("corrupt name data")
|
panic("corrupt name data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if kind := t.Kind(); kind < UnsafePointer {
|
if t.Kind() <= UnsafePointer {
|
||||||
return t.Kind().String()
|
return t.Kind().String()
|
||||||
} else if kind == UnsafePointer {
|
|
||||||
return "Pointer"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
+26
-15
@@ -646,10 +646,10 @@ func (v Value) Slice3(i, j, k int) Value {
|
|||||||
panic("unimplemented: (reflect.Value).Slice3()")
|
panic("unimplemented: (reflect.Value).Slice3()")
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname maplen runtime.hashmapLen
|
//go:linkname maplen runtime.hashmapLenUnsafePointer
|
||||||
func maplen(p unsafe.Pointer) int
|
func maplen(p unsafe.Pointer) int
|
||||||
|
|
||||||
//go:linkname chanlen runtime.chanLen
|
//go:linkname chanlen runtime.chanLenUnsafePointer
|
||||||
func chanlen(p unsafe.Pointer) int
|
func chanlen(p unsafe.Pointer) int
|
||||||
|
|
||||||
// Len returns the length of this value for slices, strings, arrays, channels,
|
// Len returns the length of this value for slices, strings, arrays, channels,
|
||||||
@@ -671,7 +671,7 @@ func (v Value) Len() int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname chancap runtime.chanCap
|
//go:linkname chancap runtime.chanCapUnsafePointer
|
||||||
func chancap(p unsafe.Pointer) int
|
func chancap(p unsafe.Pointer) int
|
||||||
|
|
||||||
// Cap returns the capacity of this value for arrays, channels and slices.
|
// Cap returns the capacity of this value for arrays, channels and slices.
|
||||||
@@ -965,13 +965,13 @@ func (v Value) MapKeys() []Value {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname hashmapStringGet runtime.hashmapStringGet
|
//go:linkname hashmapStringGet runtime.hashmapStringGetUnsafePointer
|
||||||
func hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueSize uintptr) bool
|
func hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueSize uintptr) bool
|
||||||
|
|
||||||
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGet
|
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGetUnsafePointer
|
||||||
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
||||||
|
|
||||||
//go:linkname hashmapInterfaceGet runtime.hashmapInterfaceGet
|
//go:linkname hashmapInterfaceGet runtime.hashmapInterfaceGetUnsafePointer
|
||||||
func hashmapInterfaceGet(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool
|
func hashmapInterfaceGet(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool
|
||||||
|
|
||||||
func (v Value) MapIndex(key Value) Value {
|
func (v Value) MapIndex(key Value) Value {
|
||||||
@@ -1018,7 +1018,7 @@ func (v Value) MapIndex(key Value) Value {
|
|||||||
//go:linkname hashmapNewIterator runtime.hashmapNewIterator
|
//go:linkname hashmapNewIterator runtime.hashmapNewIterator
|
||||||
func hashmapNewIterator() unsafe.Pointer
|
func hashmapNewIterator() unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname hashmapNext runtime.hashmapNext
|
//go:linkname hashmapNext runtime.hashmapNextUnsafePointer
|
||||||
func hashmapNext(m unsafe.Pointer, it unsafe.Pointer, key, value unsafe.Pointer) bool
|
func hashmapNext(m unsafe.Pointer, it unsafe.Pointer, key, value unsafe.Pointer) bool
|
||||||
|
|
||||||
func (v Value) MapRange() *MapIter {
|
func (v Value) MapRange() *MapIter {
|
||||||
@@ -1712,7 +1712,18 @@ func extendSlice(v Value, n int) sliceHeader {
|
|||||||
old = *(*sliceHeader)(v.value)
|
old = *(*sliceHeader)(v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
nbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), v.typecode.elem().Size())
|
var nbuf unsafe.Pointer
|
||||||
|
var nlen, ncap uintptr
|
||||||
|
|
||||||
|
if old.len+uintptr(n) > old.cap {
|
||||||
|
// we need to grow the slice
|
||||||
|
nbuf, nlen, ncap = sliceGrow(old.data, old.len, old.cap, old.cap+uintptr(n), v.typecode.elem().Size())
|
||||||
|
} else {
|
||||||
|
// we can reuse the slice we have
|
||||||
|
nbuf = old.data
|
||||||
|
nlen = old.len
|
||||||
|
ncap = old.cap
|
||||||
|
}
|
||||||
|
|
||||||
return sliceHeader{
|
return sliceHeader{
|
||||||
data: nbuf,
|
data: nbuf,
|
||||||
@@ -1786,22 +1797,22 @@ func (v Value) Grow(n int) {
|
|||||||
slice.cap = newslice.cap
|
slice.cap = newslice.cap
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname hashmapStringSet runtime.hashmapStringSet
|
//go:linkname hashmapStringSet runtime.hashmapStringSetUnsafePointer
|
||||||
func hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)
|
func hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname hashmapBinarySet runtime.hashmapBinarySet
|
//go:linkname hashmapBinarySet runtime.hashmapBinarySetUnsafePointer
|
||||||
func hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)
|
func hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname hashmapInterfaceSet runtime.hashmapInterfaceSet
|
//go:linkname hashmapInterfaceSet runtime.hashmapInterfaceSetUnsafePointer
|
||||||
func hashmapInterfaceSet(m unsafe.Pointer, key interface{}, value unsafe.Pointer)
|
func hashmapInterfaceSet(m unsafe.Pointer, key interface{}, value unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname hashmapStringDelete runtime.hashmapStringDelete
|
//go:linkname hashmapStringDelete runtime.hashmapStringDeleteUnsafePointer
|
||||||
func hashmapStringDelete(m unsafe.Pointer, key string)
|
func hashmapStringDelete(m unsafe.Pointer, key string)
|
||||||
|
|
||||||
//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDelete
|
//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDeleteUnsafePointer
|
||||||
func hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)
|
func hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname hashmapInterfaceDelete runtime.hashmapInterfaceDelete
|
//go:linkname hashmapInterfaceDelete runtime.hashmapInterfaceDeleteUnsafePointer
|
||||||
func hashmapInterfaceDelete(m unsafe.Pointer, key interface{})
|
func hashmapInterfaceDelete(m unsafe.Pointer, key interface{})
|
||||||
|
|
||||||
func (v Value) SetMapIndex(key, elem Value) {
|
func (v Value) SetMapIndex(key, elem Value) {
|
||||||
@@ -1930,7 +1941,7 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value {
|
|||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname hashmapMake runtime.hashmapMake
|
//go:linkname hashmapMake runtime.hashmapMakeUnsafePointer
|
||||||
func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe.Pointer
|
func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe.Pointer
|
||||||
|
|
||||||
// MakeMapWithSize creates a new map with the specified type and initial space
|
// MakeMapWithSize creates a new map with the specified type and initial space
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ func TestTinyMap(t *testing.T) {
|
|||||||
// make sure we can get it out
|
// make sure we can get it out
|
||||||
v2 := refut.MapIndex(ValueOf(unmarshalerText{"x", "y"}))
|
v2 := refut.MapIndex(ValueOf(unmarshalerText{"x", "y"}))
|
||||||
if !v2.IsValid() || !v2.Bool() {
|
if !v2.IsValid() || !v2.Bool() {
|
||||||
t.Errorf("Failed to look up map struct key with reflection")
|
t.Errorf("Failed to look up map struct key with refection")
|
||||||
}
|
}
|
||||||
|
|
||||||
// put in a key with reflection
|
// put in a key with reflection
|
||||||
@@ -592,15 +592,6 @@ func TestTinyNumMethods(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAssignableTo(t *testing.T) {
|
|
||||||
var a any
|
|
||||||
refa := ValueOf(&a).Elem()
|
|
||||||
refa.Set(ValueOf(4))
|
|
||||||
if got, want := refa.Interface().(int), 4; got != want {
|
|
||||||
t.Errorf("AssignableTo / Set failed, got %v, want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvert(t *testing.T) {
|
func TestConvert(t *testing.T) {
|
||||||
v := ValueOf(int64(3))
|
v := ValueOf(int64(3))
|
||||||
c := v.Convert(TypeOf(byte(0)))
|
c := v.Convert(TypeOf(byte(0)))
|
||||||
|
|||||||
@@ -148,6 +148,12 @@ func chanLen(c *channel) int {
|
|||||||
return int(c.bufUsed)
|
return int(c.bufUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrapper for use in reflect
|
||||||
|
func chanLenUnsafePointer(p unsafe.Pointer) int {
|
||||||
|
c := (*channel)(p)
|
||||||
|
return chanLen(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Return the capacity of this chan, called from the cap builtin.
|
// Return the capacity of this chan, called from the cap builtin.
|
||||||
// A nil chan is defined as having capacity 0.
|
// A nil chan is defined as having capacity 0.
|
||||||
//
|
//
|
||||||
@@ -159,6 +165,12 @@ func chanCap(c *channel) int {
|
|||||||
return int(c.bufSize)
|
return int(c.bufSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrapper for use in reflect
|
||||||
|
func chanCapUnsafePointer(p unsafe.Pointer) int {
|
||||||
|
c := (*channel)(p)
|
||||||
|
return chanCap(c)
|
||||||
|
}
|
||||||
|
|
||||||
// resumeRX resumes the next receiver and returns the destination pointer.
|
// resumeRX resumes the next receiver and returns the destination pointer.
|
||||||
// If the ok value is true, then the caller is expected to store a value into this pointer.
|
// If the ok value is true, then the caller is expected to store a value into this pointer.
|
||||||
func (ch *channel) resumeRX(ok bool) unsafe.Pointer {
|
func (ch *channel) resumeRX(ok bool) unsafe.Pointer {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type stackChainObject struct {
|
|||||||
//
|
//
|
||||||
// Therefore, we only need to scan the system stack.
|
// Therefore, we only need to scan the system stack.
|
||||||
// It is relatively easy to scan the system stack while we're on it: we can
|
// It is relatively easy to scan the system stack while we're on it: we can
|
||||||
// simply read __stack_pointer and __global_base and scan the area in between.
|
// simply read __stack_pointer and __global_base and scan the area inbetween.
|
||||||
// Unfortunately, it's hard to get the system stack pointer while we're on a
|
// Unfortunately, it's hard to get the system stack pointer while we're on a
|
||||||
// goroutine stack. But when we're on a goroutine stack, the system stack is in
|
// goroutine stack. But when we're on a goroutine stack, the system stack is in
|
||||||
// the scheduler which means there shouldn't be anything on the system stack
|
// the scheduler which means there shouldn't be anything on the system stack
|
||||||
|
|||||||
@@ -87,6 +87,10 @@ func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) *hashm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapMakeUnsafePointer(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe.Pointer {
|
||||||
|
return (unsafe.Pointer)(hashmapMake(keySize, valueSize, sizeHint, alg))
|
||||||
|
}
|
||||||
|
|
||||||
// Remove all entries from the map, without actually deallocating the space for
|
// Remove all entries from the map, without actually deallocating the space for
|
||||||
// it. This is used for the clear builtin, and can be used to reuse a map (to
|
// it. This is used for the clear builtin, and can be used to reuse a map (to
|
||||||
// avoid extra heap allocations).
|
// avoid extra heap allocations).
|
||||||
@@ -174,6 +178,10 @@ func hashmapLen(m *hashmap) int {
|
|||||||
return int(m.count)
|
return int(m.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapLenUnsafePointer(m unsafe.Pointer) int {
|
||||||
|
return hashmapLen((*hashmap)(m))
|
||||||
|
}
|
||||||
|
|
||||||
//go:inline
|
//go:inline
|
||||||
func hashmapBucketSize(m *hashmap) uintptr {
|
func hashmapBucketSize(m *hashmap) uintptr {
|
||||||
return unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
|
return unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
|
||||||
@@ -260,6 +268,10 @@ func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
|
|||||||
*emptySlotTophash = tophash
|
*emptySlotTophash = tophash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapSetUnsafePointer(m unsafe.Pointer, key unsafe.Pointer, value unsafe.Pointer, hash uint32) {
|
||||||
|
hashmapSet((*hashmap)(m), key, value, hash)
|
||||||
|
}
|
||||||
|
|
||||||
// hashmapInsertIntoNewBucket creates a new bucket, inserts the given key and
|
// hashmapInsertIntoNewBucket creates a new bucket, inserts the given key and
|
||||||
// value into the bucket, and returns a pointer to this bucket.
|
// value into the bucket, and returns a pointer to this bucket.
|
||||||
func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket {
|
func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket {
|
||||||
@@ -340,6 +352,10 @@ func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash u
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapGetUnsafePointer(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr, hash uint32) bool {
|
||||||
|
return hashmapGet((*hashmap)(m), key, value, valueSize, hash)
|
||||||
|
}
|
||||||
|
|
||||||
// Delete a given key from the map. No-op when the key does not exist in the
|
// Delete a given key from the map. No-op when the key does not exist in the
|
||||||
// map.
|
// map.
|
||||||
//
|
//
|
||||||
@@ -440,6 +456,10 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapNextUnsafePointer(m unsafe.Pointer, it unsafe.Pointer, key, value unsafe.Pointer) bool {
|
||||||
|
return hashmapNext((*hashmap)(m), (*hashmapIterator)(it), key, value)
|
||||||
|
}
|
||||||
|
|
||||||
// Hashmap with plain binary data keys (not containing strings etc.).
|
// Hashmap with plain binary data keys (not containing strings etc.).
|
||||||
func hashmapBinarySet(m *hashmap, key, value unsafe.Pointer) {
|
func hashmapBinarySet(m *hashmap, key, value unsafe.Pointer) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
@@ -449,6 +469,10 @@ func hashmapBinarySet(m *hashmap, key, value unsafe.Pointer) {
|
|||||||
hashmapSet(m, key, value, hash)
|
hashmapSet(m, key, value, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapBinarySetUnsafePointer(m unsafe.Pointer, key, value unsafe.Pointer) {
|
||||||
|
hashmapBinarySet((*hashmap)(m), key, value)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr) bool {
|
func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
memzero(value, uintptr(valueSize))
|
memzero(value, uintptr(valueSize))
|
||||||
@@ -458,6 +482,10 @@ func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr)
|
|||||||
return hashmapGet(m, key, value, valueSize, hash)
|
return hashmapGet(m, key, value, valueSize, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapBinaryGetUnsafePointer(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
|
return hashmapBinaryGet((*hashmap)(m), key, value, valueSize)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
|
func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
@@ -466,6 +494,10 @@ func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
|
|||||||
hashmapDelete(m, key, hash)
|
hashmapDelete(m, key, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapBinaryDeleteUnsafePointer(m unsafe.Pointer, key unsafe.Pointer) {
|
||||||
|
hashmapBinaryDelete((*hashmap)(m), key)
|
||||||
|
}
|
||||||
|
|
||||||
// Hashmap with string keys (a common case).
|
// Hashmap with string keys (a common case).
|
||||||
|
|
||||||
func hashmapStringEqual(x, y unsafe.Pointer, n uintptr) bool {
|
func hashmapStringEqual(x, y unsafe.Pointer, n uintptr) bool {
|
||||||
@@ -490,6 +522,10 @@ func hashmapStringSet(m *hashmap, key string, value unsafe.Pointer) {
|
|||||||
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapStringSetUnsafePointer(m unsafe.Pointer, key string, value unsafe.Pointer) {
|
||||||
|
hashmapStringSet((*hashmap)(m), key, value)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapStringGet(m *hashmap, key string, value unsafe.Pointer, valueSize uintptr) bool {
|
func hashmapStringGet(m *hashmap, key string, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
memzero(value, uintptr(valueSize))
|
memzero(value, uintptr(valueSize))
|
||||||
@@ -499,6 +535,10 @@ func hashmapStringGet(m *hashmap, key string, value unsafe.Pointer, valueSize ui
|
|||||||
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapStringGetUnsafePointer(m unsafe.Pointer, key string, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
|
return hashmapStringGet((*hashmap)(m), key, value, valueSize)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapStringDelete(m *hashmap, key string) {
|
func hashmapStringDelete(m *hashmap, key string) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
@@ -507,6 +547,10 @@ func hashmapStringDelete(m *hashmap, key string) {
|
|||||||
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapStringDeleteUnsafePointer(m unsafe.Pointer, key string) {
|
||||||
|
hashmapStringDelete((*hashmap)(m), key)
|
||||||
|
}
|
||||||
|
|
||||||
// Hashmap with interface keys (for everything else).
|
// Hashmap with interface keys (for everything else).
|
||||||
|
|
||||||
// This is a method that is intentionally unexported in the reflect package. It
|
// This is a method that is intentionally unexported in the reflect package. It
|
||||||
@@ -610,6 +654,10 @@ func hashmapInterfaceSet(m *hashmap, key interface{}, value unsafe.Pointer) {
|
|||||||
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceSetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer) {
|
||||||
|
hashmapInterfaceSet((*hashmap)(m), key, value)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
memzero(value, uintptr(valueSize))
|
memzero(value, uintptr(valueSize))
|
||||||
@@ -619,6 +667,10 @@ func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valu
|
|||||||
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceGetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
|
return hashmapInterfaceGet((*hashmap)(m), key, value, valueSize)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
@@ -626,3 +678,7 @@ func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
|||||||
hash := hashmapInterfaceHash(key, m.seed)
|
hash := hashmapInterfaceHash(key, m.seed)
|
||||||
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceDeleteUnsafePointer(m unsafe.Pointer, key interface{}) {
|
||||||
|
hashmapInterfaceDelete((*hashmap)(m), key)
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ func reflectValueEqual(x, y reflect.Value) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implemented in the reflect package.
|
||||||
|
func typeImplementsMethodSet(actualTypeNum, assertedMethodSet unsafe.Pointer) bool
|
||||||
|
|
||||||
// interfaceTypeAssert is called when a type assert without comma-ok still
|
// interfaceTypeAssert is called when a type assert without comma-ok still
|
||||||
// returns false.
|
// returns false.
|
||||||
func interfaceTypeAssert(ok bool) {
|
func interfaceTypeAssert(ok bool) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
// SREG is at I/O address 0x3f.
|
// SREG is at I/O address 0x3f.
|
||||||
device.AsmFull("out 0x3f, {state}", map[string]interface{}{
|
device.AsmFull("out 0x3f, {state}", map[string]interface{}{
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
arm.EnableInterrupts(uintptr(state))
|
arm.EnableInterrupts(uintptr(state))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ func handleException(mcause uintptr) {
|
|||||||
println("*** Exception: mcause:", mcause)
|
println("*** Exception: mcause:", mcause)
|
||||||
switch uint32(mcause & 0x1f) {
|
switch uint32(mcause & 0x1f) {
|
||||||
case 1:
|
case 1:
|
||||||
println("*** virtual address:", riscv.MTVAL.Get())
|
println("*** virtual addess:", riscv.MTVAL.Get())
|
||||||
case 2:
|
case 2:
|
||||||
println("*** opcode:", riscv.MTVAL.Get())
|
println("*** opcode:", riscv.MTVAL.Get())
|
||||||
case 5:
|
case 5:
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
// Restore interrupts to the previous state.
|
// Restore interrupts to the previous state.
|
||||||
gba.INTERRUPT.PAUSE.Set(uint16(state))
|
gba.INTERRUPT.PAUSE.Set(uint16(state))
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {}
|
func Restore(state State) {}
|
||||||
|
|
||||||
// In returns whether the system is currently in an interrupt.
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
riscv.EnableInterrupts(uintptr(state))
|
riscv.EnableInterrupts(uintptr(state))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func Disable() (state State) {
|
|||||||
// Restore restores interrupts to what they were before. Give the previous state
|
// Restore restores interrupts to what they were before. Give the previous state
|
||||||
// returned by Disable as a parameter. If interrupts were disabled before
|
// returned by Disable as a parameter. If interrupts were disabled before
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// critical sections.
|
// cricital sections.
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
device.AsmFull("wsr {state}, PS", map[string]interface{}{
|
device.AsmFull("wsr {state}, PS", map[string]interface{}{
|
||||||
"state": state,
|
"state": state,
|
||||||
|
|||||||
+29
-99
@@ -15,20 +15,11 @@ func trap()
|
|||||||
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
|
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
|
||||||
//
|
//
|
||||||
//export tinygo_longjmp
|
//export tinygo_longjmp
|
||||||
func tinygo_longjmp(frame *deferFrameInlineAsm)
|
func tinygo_longjmp(frame *deferFrame)
|
||||||
|
|
||||||
// Compiler intrinsic.
|
// Compiler intrinsic.
|
||||||
// Returns whether recover is supported on the current architecture.
|
// Returns whether recover is supported on the current architecture.
|
||||||
func supportsRecover() recoverType
|
func supportsRecover() bool
|
||||||
|
|
||||||
type recoverType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Note: these contants match recoverSupport in compiler/defer.go
|
|
||||||
recoverNone recoverType = iota
|
|
||||||
recoverInlineAsm
|
|
||||||
recoverWasmEH
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
panicStrategyPrint = 1
|
panicStrategyPrint = 1
|
||||||
@@ -40,55 +31,33 @@ const (
|
|||||||
// using the -panic= compiler flag.
|
// using the -panic= compiler flag.
|
||||||
func panicStrategy() uint8
|
func panicStrategy() uint8
|
||||||
|
|
||||||
// LLVM compiler intrinsic: this inserts a wasm 'throw' instruction.
|
// DeferFrame is a stack allocated object that stores information for the
|
||||||
//
|
// current "defer frame", which is used in functions that use the `defer`
|
||||||
//export llvm.wasm.throw
|
|
||||||
func wasm_throw(uint32, unsafe.Pointer)
|
|
||||||
|
|
||||||
// DeferFrameInlineAsm is a stack allocated object that stores information for
|
|
||||||
// the current "defer frame", which is used in functions that use the `defer`
|
|
||||||
// keyword.
|
// keyword.
|
||||||
// The compiler knows about the JumpPC struct offset, so it should not be moved
|
// The compiler knows about the JumpPC struct offset, so it should not be moved
|
||||||
// without also updating compiler/defer.go.
|
// without also updating compiler/defer.go.
|
||||||
type deferFrameInlineAsm struct {
|
type deferFrame struct {
|
||||||
JumpSP unsafe.Pointer // stack pointer to return to
|
JumpSP unsafe.Pointer // stack pointer to return to
|
||||||
JumpPC unsafe.Pointer // pc to return to
|
JumpPC unsafe.Pointer // pc to return to
|
||||||
ExtraRegs [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture)
|
ExtraRegs [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture)
|
||||||
Previous *deferFrameInlineAsm // previous recover buffer pointer
|
Previous *deferFrame // previous recover buffer pointer
|
||||||
Panicking bool // true iff this defer frame is panicking
|
Panicking bool // true iff this defer frame is panicking
|
||||||
PanicValue interface{} // panic value, might be nil for panic(nil) for example
|
PanicValue interface{} // panic value, might be nil for panic(nil) for example
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeferFrameWasmEH is like deferFrameInlineAsm but for WebAssembly exception
|
|
||||||
// handling.
|
|
||||||
type deferFrameWasmEH struct {
|
|
||||||
Previous *deferFrameWasmEH // previous recover buffer pointer
|
|
||||||
Panicking bool // true iff this defer frame is panicking
|
|
||||||
PanicValue interface{} // panic value, might be nil for panic(nil) for example
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builtin function panic(msg), used as a compiler intrinsic.
|
// Builtin function panic(msg), used as a compiler intrinsic.
|
||||||
func _panic(message interface{}) {
|
func _panic(message interface{}) {
|
||||||
if panicStrategy() == panicStrategyTrap {
|
if panicStrategy() == panicStrategyTrap {
|
||||||
trap()
|
trap()
|
||||||
}
|
}
|
||||||
switch supportsRecover() {
|
if supportsRecover() {
|
||||||
case recoverInlineAsm:
|
frame := (*deferFrame)(task.Current().DeferFrame)
|
||||||
frame := (*deferFrameInlineAsm)(task.Current().DeferFrame)
|
|
||||||
if frame != nil {
|
if frame != nil {
|
||||||
frame.PanicValue = message
|
frame.PanicValue = message
|
||||||
frame.Panicking = true
|
frame.Panicking = true
|
||||||
tinygo_longjmp(frame)
|
tinygo_longjmp(frame)
|
||||||
// unreachable
|
// unreachable
|
||||||
}
|
}
|
||||||
case recoverWasmEH:
|
|
||||||
frame := (*deferFrameWasmEH)(task.Current().DeferFrame)
|
|
||||||
if frame != nil {
|
|
||||||
frame.PanicValue = message
|
|
||||||
frame.Panicking = true
|
|
||||||
wasm_throw(0, nil)
|
|
||||||
// unreachable
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printstring("panic: ")
|
printstring("panic: ")
|
||||||
printitf(message)
|
printitf(message)
|
||||||
@@ -125,43 +94,21 @@ func runtimePanicAt(addr unsafe.Pointer, msg string) {
|
|||||||
//
|
//
|
||||||
//go:inline
|
//go:inline
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func setupDeferFrameInlineAsm(frame *deferFrameInlineAsm, jumpSP unsafe.Pointer) {
|
func setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {
|
||||||
currentTask := task.Current()
|
currentTask := task.Current()
|
||||||
frame.Previous = (*deferFrameInlineAsm)(currentTask.DeferFrame)
|
frame.Previous = (*deferFrame)(currentTask.DeferFrame)
|
||||||
frame.JumpSP = jumpSP
|
frame.JumpSP = jumpSP
|
||||||
frame.Panicking = false
|
frame.Panicking = false
|
||||||
currentTask.DeferFrame = unsafe.Pointer(frame)
|
currentTask.DeferFrame = unsafe.Pointer(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:inline
|
|
||||||
//go:nobounds
|
|
||||||
func setupDeferFrameWasmEH(frame *deferFrameWasmEH) {
|
|
||||||
currentTask := task.Current()
|
|
||||||
frame.Previous = (*deferFrameWasmEH)(currentTask.DeferFrame)
|
|
||||||
frame.Panicking = false
|
|
||||||
currentTask.DeferFrame = unsafe.Pointer(frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called right before the return instruction. It pops the defer frame from the
|
// Called right before the return instruction. It pops the defer frame from the
|
||||||
// linked list of defer frames. It also re-raises a panic if the goroutine is
|
// linked list of defer frames. It also re-raises a panic if the goroutine is
|
||||||
// still panicking.
|
// still panicking.
|
||||||
//
|
//
|
||||||
//go:inline
|
//go:inline
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func destroyDeferFrameInlineAsm(frame *deferFrameInlineAsm) {
|
func destroyDeferFrame(frame *deferFrame) {
|
||||||
task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
|
|
||||||
if frame.Panicking {
|
|
||||||
// We're still panicking!
|
|
||||||
// Re-raise the panic now.
|
|
||||||
_panic(frame.PanicValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like destroyDeferFrameInlineAsm but for wasm.
|
|
||||||
//
|
|
||||||
//go:inline
|
|
||||||
//go:nobounds
|
|
||||||
func destroyDeferFrameWasmEH(frame *deferFrameWasmEH) {
|
|
||||||
task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
|
task.Current().DeferFrame = unsafe.Pointer(frame.Previous)
|
||||||
if frame.Panicking {
|
if frame.Panicking {
|
||||||
// We're still panicking!
|
// We're still panicking!
|
||||||
@@ -175,44 +122,27 @@ func destroyDeferFrameWasmEH(frame *deferFrameWasmEH) {
|
|||||||
// useParentFrame is set when the caller of runtime._recover has a defer frame
|
// useParentFrame is set when the caller of runtime._recover has a defer frame
|
||||||
// itself. In that case, recover() shouldn't check that frame but one frame up.
|
// itself. In that case, recover() shouldn't check that frame but one frame up.
|
||||||
func _recover(useParentFrame bool) interface{} {
|
func _recover(useParentFrame bool) interface{} {
|
||||||
// TODO: somehow check that recover() is called directly by a deferred
|
if !supportsRecover() {
|
||||||
// function in a panicking goroutine. Maybe this can be done by comparing
|
|
||||||
// the frame pointer?
|
|
||||||
switch supportsRecover() {
|
|
||||||
case recoverInlineAsm:
|
|
||||||
frame := (*deferFrameInlineAsm)(task.Current().DeferFrame)
|
|
||||||
if useParentFrame {
|
|
||||||
// Don't recover panic from the current frame (which can't be
|
|
||||||
// panicking already), but instead from the previous frame.
|
|
||||||
frame = frame.Previous
|
|
||||||
}
|
|
||||||
if frame != nil && frame.Panicking {
|
|
||||||
// Only the first call to recover returns the panic value. It also
|
|
||||||
// stops the panicking sequence, hence setting panicking to false.
|
|
||||||
frame.Panicking = false
|
|
||||||
return frame.PanicValue
|
|
||||||
}
|
|
||||||
// Not panicking, so return a nil interface.
|
|
||||||
return nil
|
|
||||||
case recoverWasmEH:
|
|
||||||
frame := (*deferFrameWasmEH)(task.Current().DeferFrame)
|
|
||||||
if useParentFrame {
|
|
||||||
// Don't recover panic from the current frame (which can't be
|
|
||||||
// panicking already), but instead from the previous frame.
|
|
||||||
frame = frame.Previous
|
|
||||||
}
|
|
||||||
if frame != nil && frame.Panicking {
|
|
||||||
// Only the first call to recover returns the panic value. It also
|
|
||||||
// stops the panicking sequence, hence setting panicking to false.
|
|
||||||
frame.Panicking = false
|
|
||||||
return frame.PanicValue
|
|
||||||
}
|
|
||||||
// Not panicking, so return a nil interface.
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
// Compiling without stack unwinding support, so make this a no-op.
|
// Compiling without stack unwinding support, so make this a no-op.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// TODO: somehow check that recover() is called directly by a deferred
|
||||||
|
// function in a panicking goroutine. Maybe this can be done by comparing
|
||||||
|
// the frame pointer?
|
||||||
|
frame := (*deferFrame)(task.Current().DeferFrame)
|
||||||
|
if useParentFrame {
|
||||||
|
// Don't recover panic from the current frame (which can't be panicking
|
||||||
|
// already), but instead from the previous frame.
|
||||||
|
frame = frame.Previous
|
||||||
|
}
|
||||||
|
if frame != nil && frame.Panicking {
|
||||||
|
// Only the first call to recover returns the panic value. It also stops
|
||||||
|
// the panicking sequence, hence setting panicking to false.
|
||||||
|
frame.Panicking = false
|
||||||
|
return frame.PanicValue
|
||||||
|
}
|
||||||
|
// Not panicking, so return a nil interface.
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panic when trying to dereference a nil pointer.
|
// Panic when trying to dereference a nil pointer.
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (e
|
|||||||
//go:wasmimport wasi_snapshot_preview1 proc_exit
|
//go:wasmimport wasi_snapshot_preview1 proc_exit
|
||||||
func proc_exit(exitcode uint32)
|
func proc_exit(exitcode uint32)
|
||||||
|
|
||||||
// Flush stdio on exit.
|
|
||||||
//
|
|
||||||
//export __stdio_exit
|
|
||||||
func __stdio_exit()
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
putcharBufferSize = 120
|
putcharBufferSize = 120
|
||||||
stdout = 1
|
stdout = 1
|
||||||
@@ -77,9 +72,6 @@ func abort() {
|
|||||||
|
|
||||||
//go:linkname syscall_Exit syscall.Exit
|
//go:linkname syscall_Exit syscall.Exit
|
||||||
func syscall_Exit(code int) {
|
func syscall_Exit(code int) {
|
||||||
// TODO: should we call __stdio_exit here?
|
|
||||||
// It's a low-level exit (syscall.Exit) so doing any libc stuff seems
|
|
||||||
// unexpected, but then where else should stdio buffers be flushed?
|
|
||||||
proc_exit(uint32(code))
|
proc_exit(uint32(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ func _start() {
|
|||||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||||
run()
|
run()
|
||||||
__stdio_exit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the command line arguments from WASI.
|
// Read the command line arguments from WASI.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ func _start() {
|
|||||||
|
|
||||||
wasmNested = true
|
wasmNested = true
|
||||||
run()
|
run()
|
||||||
__stdio_exit()
|
|
||||||
wasmNested = false
|
wasmNested = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user