Compare commits

..

2 Commits

Author SHA1 Message Date
Ayke van Laethem 7ff626dcee reflect: fully implement Type.AssignableTo
This fully implements AssignableTo, fixing a number of bugs in the
previous implementation. In particular, it now supports AssignableTo for
interface types.
2024-07-31 20:08:46 +02:00
Ayke van Laethem 19e2d12517 compiler: reimplement interface type asserts
This is a big reimplementation that simplifies the compiler a lot.
Instead of storing the method set in metadata and lowering the type
asserts as a whole program pass, this change just puts the list of
methods in the type code (and a separate global for the interface type).
2024-07-31 19:55:18 +02:00
129 changed files with 1526 additions and 2368 deletions
-2
View File
@@ -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:
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+3 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
} }
+1 -1
View File
@@ -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
View File
@@ -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 "":
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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{
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+24 -25
View File
@@ -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 }
+15 -16
View File
@@ -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
View File
@@ -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
-273
View File
@@ -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" }
+12 -12
View File
@@ -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" }
+8 -9
View File
@@ -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 }
+46 -46
View File
@@ -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 }
+11 -12
View File
@@ -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 }
+24 -25
View File
@@ -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
View File
@@ -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 }
+45 -46
View File
@@ -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 }
+12 -11
View File
@@ -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 }
+15 -16
View File
@@ -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" }
+42 -43
View File
@@ -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 }
+15 -16
View File
@@ -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 }
+16 -17
View File
@@ -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 }
+2 -2
View File
@@ -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
View File
@@ -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")
} }
+13 -2
View File
@@ -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
) )
+33 -4
View File
@@ -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
View File
@@ -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
-30
View File
@@ -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
)
-56
View File
@@ -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=
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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{}
-58
View File
@@ -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
+47 -7
View File
@@ -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
View File
@@ -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)
-26
View File
@@ -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
1 acuire acquire
2 addess address
3 adust adjust
4 allcoate allocate
5 alloated allocated
6 archtecture architecture
7 arcive archive
8 beconfigured be configured
9 configration configuration
10 contants constants
11 cricital critical
12 evaulator evaluator
13 freqency frequency
14 frquency frequency
15 implmented implemented
16 interrput interrupt
17 interrut interrupt
18 poitner pointer
19 probbably probably
20 refection reflection
21 satisifying satisfying
22 simulataneously simultaneously
23 suggets suggests
24 undefied undefined
25 unecessary unnecessary
26 unsiged unsigned
+19 -41
View File
@@ -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
}
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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()
+2 -2
View File
@@ -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()
+1 -1
View File
@@ -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)
} }
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
} }
+2 -2
View File
@@ -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:
+2 -2
View File
@@ -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
-1
View File
@@ -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)
+10
View File
@@ -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 {
-25
View File
@@ -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.
-19
View File
@@ -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 {
+1 -1
View File
@@ -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)
} }
} }
+1 -1
View File
@@ -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)
} }
} }
-61
View File
@@ -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())
}
}
+83
View File
@@ -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
}
+225
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -10
View File
@@ -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)))
+12
View File
@@ -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 {
+1 -1
View File
@@ -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
+56
View File
@@ -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)
}
+3
View File
@@ -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) {
+1 -1
View File
@@ -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{}{
+1 -1
View File
@@ -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))
} }
+1 -1
View File
@@ -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))
+1 -1
View File
@@ -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))
} }
+1 -1
View File
@@ -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
View File
@@ -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.
-8
View File
@@ -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))
} }
-1
View File
@@ -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.
-1
View File
@@ -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