Compare commits

..

1 Commits

Author SHA1 Message Date
Pat Whittingslow 6ecac82c63 Add agents.md guideline for using ASD-STE100 in documentation 2026-07-30 18:50:05 -03:00
57 changed files with 159 additions and 1750 deletions
+2 -2
View File
@@ -40,7 +40,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Restore LLVM source cache - name: Restore LLVM source cache
uses: actions/cache/restore@v5 uses: actions/cache/restore@v5
@@ -131,7 +131,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Build TinyGo (LLVM ${{ matrix.version }}) - name: Build TinyGo (LLVM ${{ matrix.version }})
run: go install -tags=llvm${{ matrix.version }} run: go install -tags=llvm${{ matrix.version }}
+5 -17
View File
@@ -23,7 +23,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Run go mod tidy - name: Run go mod tidy
run: go mod tidy run: go mod tidy
@@ -36,7 +36,7 @@ jobs:
# statically linked binary. # statically linked binary.
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: golang:1.27-alpine image: golang:1.27rc2-alpine
outputs: outputs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
@@ -160,7 +160,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Install wasmtime - name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1 uses: bytecodealliance/actions/wasmtime/setup@v1
@@ -196,10 +196,6 @@ jobs:
cat /proc/cpuinfo cat /proc/cpuinfo
sudo apt-get update sudo apt-get update
sudo apt-get install --no-install-recommends \ sudo apt-get install --no-install-recommends \
libgcrypt20 \
libpixman-1-0 \
libsdl2-2.0-0 \
libslirp0 \
qemu-system-arm \ qemu-system-arm \
qemu-system-riscv32 \ qemu-system-riscv32 \
qemu-user \ qemu-user \
@@ -208,7 +204,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v6
@@ -220,14 +216,6 @@ jobs:
version: "29.0.1" version: "29.0.1"
- name: Setup `wasm-tools` - name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1 uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Install Espressif QEMU
run: |
release=esp-develop-9.2.2-20260417
archive=qemu-xtensa-softmmu-${release//-/_}-x86_64-linux-gnu.tar.xz
curl -fL --retry 3 -o "$RUNNER_TEMP/$archive" \
"https://github.com/espressif/qemu/releases/download/$release/$archive"
tar -xJf "$RUNNER_TEMP/$archive" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/qemu/bin" >> "$GITHUB_PATH"
- name: Restore LLVM source cache - name: Restore LLVM source cache
uses: actions/cache/restore@v5 uses: actions/cache/restore@v5
id: cache-llvm-source id: cache-llvm-source
@@ -335,7 +323,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Restore LLVM source cache - name: Restore LLVM source cache
uses: actions/cache/restore@v5 uses: actions/cache/restore@v5
+4 -4
View File
@@ -34,7 +34,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Restore cached LLVM source - name: Restore cached LLVM source
uses: actions/cache/restore@v5 uses: actions/cache/restore@v5
@@ -129,7 +129,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v8 uses: actions/download-artifact@v8
@@ -150,7 +150,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v8 uses: actions/download-artifact@v8
@@ -176,7 +176,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v6 uses: actions/setup-go@v6
with: with:
go-version: '1.27.0' go-version: '1.27.0-rc.2'
cache: true cache: true
- name: Download TinyGo build - name: Download TinyGo build
uses: actions/download-artifact@v8 uses: actions/download-artifact@v8
+2 -2
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo # tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.27 AS tinygo-llvm FROM golang:1.27rc2 AS tinygo-llvm
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-17 ninja-build && \ apt-get install -y apt-utils make cmake clang-17 ninja-build && \
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
# tinygo-compiler copies the compiler build over to a base Go container (without # tinygo-compiler copies the compiler build over to a base Go container (without
# all the build tools etc). # all the build tools etc).
FROM golang:1.27 AS tinygo-compiler FROM golang:1.27rc2 AS tinygo-compiler
# Copy tinygo build. # Copy tinygo build.
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
+2 -23
View File
@@ -473,15 +473,9 @@ TEST_PACKAGES_NONWASM = \
# (just like wasm). # (just like wasm).
# * picolibc math functions apparently are less precise, the math package # * picolibc math functions apparently are less precise, the math package
# fails on baremetal. # fails on baremetal.
# * Since Go 1.27 the crypto tests below go through cryptotest.TestHash, which
# calls cryptotest.BoundarySlices. These targets report GOOS=linux, so they
# build boundary.go (//go:build linux || darwin) rather than
# boundary_compat.go, and that needs a working syscall.Mmap/syscall.Mprotect
# which we don't have. See #5593.
TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST)) TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))
TEST_PACKAGES_NONBAREMETAL = \ TEST_PACKAGES_NONBAREMETAL = \
$(TEST_PACKAGES_NONWASM) \ $(TEST_PACKAGES_NONWASM) \
$(TEST_PACKAGES_NOBOUNDARYSLICES) \
math \ math \
$(nil) $(nil)
@@ -490,19 +484,6 @@ TEST_PACKAGES_NOWASI = \
crypto/ecdsa \ crypto/ecdsa \
$(nil) $(nil)
# wasip1 reports GOOS=wasip1 and so gets the boundary_compat.go fallback, but
# wasip2 reports GOOS=linux and hits the same BoundarySlices problem as
# baremetal. On wasip2 syscall.Mmap returns ENOSYS and t.Fatalf cannot Goexit,
# so the test falls through and panics with "slice out of range".
TEST_PACKAGES_FAST_WASIP2 = $(filter-out $(TEST_PACKAGES_NOBOUNDARYSLICES), $(TEST_PACKAGES_FAST_WASI))
TEST_PACKAGES_NOBOUNDARYSLICES = \
crypto/md5 \
crypto/sha1 \
crypto/sha256 \
crypto/sha512 \
$(nil)
# Report platforms on which each standard library package is known to pass tests # Report platforms on which each standard library package is known to pass tests
report-stdlib-tests-pass: report-stdlib-tests-pass:
$(eval jointmp := $(shell echo /tmp/join.$$$$)) $(eval jointmp := $(shell echo /tmp/join.$$$$))
@@ -529,7 +510,7 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
TEST_IOFS := false TEST_IOFS := false
endif endif
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic|TestAsValidation|TestUnmarshalNestingLimitSlice|TestUnmarshalNestingLimitStruct' TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic|TestAsValidation'
TEST_ADDITIONAL_FLAGS ?= TEST_ADDITIONAL_FLAGS ?=
# Test known-working standard library packages. # Test known-working standard library packages.
@@ -538,8 +519,6 @@ TEST_ADDITIONAL_FLAGS ?=
tinygo-test: tinygo-test:
@# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented. @# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented.
@# TestParseAndBytesRoundTrip/P256/Generic: needs Goexit to run defers on wasm. @# TestParseAndBytesRoundTrip/P256/Generic: needs Goexit to run defers on wasm.
@# TestUnmarshalNestingLimit{Slice,Struct}: encoding/asn1 nesting limit added in
@# https://github.com/golang/go/commit/6a6d115f9a7422b2fa081ba6f567eefb4a099462
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(filter-out encoding/xml,$(TEST_PACKAGES_HOST)) $(TEST_PACKAGES_SLOW) $(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(filter-out encoding/xml,$(TEST_PACKAGES_HOST)) $(TEST_PACKAGES_SLOW)
ifeq ($(TEST_ENCODING_XML),true) ifeq ($(TEST_ENCODING_XML),true)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) -stack-size=16MB encoding/xml $(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) -stack-size=16MB encoding/xml
@@ -570,7 +549,7 @@ tinygo-test-wasip1-fast:
tinygo-test-wasip2-slow: tinygo-test-wasip2-slow:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW) $(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW)
tinygo-test-wasip2-fast: tinygo-test-wasip2-fast:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASIP2) ./tests/runtime_wasi $(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi
tinygo-test-wasip2-sum-slow: tinygo-test-wasip2-sum-slow:
TINYGO=$(TINYGO) \ TINYGO=$(TINYGO) \
+1
View File
@@ -0,0 +1 @@
Use ASD-STE100 Simplified Technical English for content outside of the code like comments, PR description, PR title, github comments.
+2 -9
View File
@@ -24,7 +24,6 @@ import (
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/gofrs/flock" "github.com/gofrs/flock"
"github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/compileopts"
@@ -270,7 +269,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
// Create the *ssa.Program. This does not yet build the entire SSA of the // Create the *ssa.Program. This does not yet build the entire SSA of the
// program so it's pretty fast and doesn't need to be parallelized. // program so it's pretty fast and doesn't need to be parallelized.
program := lprogram.LoadSSA() program := lprogram.LoadSSA()
buildProgram := sync.OnceFunc(program.Build)
// Add jobs to compile each package. // Add jobs to compile each package.
// Packages that have a cache hit will not be compiled again. // Packages that have a cache hit will not be compiled again.
@@ -400,13 +398,8 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
return nil return nil
} }
// SSA package builds may run concurrently, but the resulting // Compile AST to IR. The compiler.CompilePackage function will
// functions cannot be inspected until all builds have finished: // build the SSA as needed.
// generic instances and wrappers can be shared across packages.
// Build the whole program once before compiling any package.
buildProgram()
// Compile AST to IR.
mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA()) mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
defer mod.Context().Dispose() defer mod.Context().Dispose()
defer mod.Dispose() defer mod.Dispose()
+3 -6
View File
@@ -111,6 +111,9 @@ func makeESPFirmwareImage(infile, outfile, format string) error {
// Compute the size of the RAM portion of the image (everything the ROM // Compute the size of the RAM portion of the image (everything the ROM
// bootloader loads, up to and including the appended SHA256 hash). // bootloader loads, up to and including the appended SHA256 hash).
ramImageSize := 0 ramImageSize := 0
if makeImage {
ramImageSize += 4096
}
ramImageSize += 24 // image header (8) + trailer fields (16) ramImageSize += 24 // image header (8) + trailer fields (16)
for _, seg := range segments { for _, seg := range segments {
ramImageSize += 8 + len(seg.data) // segment header + data (4-aligned) ramImageSize += 8 + len(seg.data) // segment header + data (4-aligned)
@@ -281,9 +284,6 @@ func makeESPFirmwareImage(infile, outfile, format string) error {
dromSize := 0 dromSize := 0
if len(dromSegs) > 0 { if len(dromSegs) > 0 {
targetImageOffset := int(dromFlashAddr - flashBase) targetImageOffset := int(dromFlashAddr - flashBase)
if makeImage {
targetImageOffset = int(dromFlashAddr)
}
if outf.Len() > targetImageOffset { if outf.Len() > targetImageOffset {
return fmt.Errorf("ESP32: RAM segments too large (%d bytes), overlap DROM at flash 0x%x", outf.Len(), dromFlashAddr) return fmt.Errorf("ESP32: RAM segments too large (%d bytes), overlap DROM at flash 0x%x", outf.Len(), dromFlashAddr)
} }
@@ -304,9 +304,6 @@ func makeESPFirmwareImage(infile, outfile, format string) error {
} }
iromFlashAddr := dromFlashAddr + uint32(dromPages)*pageSize iromFlashAddr := dromFlashAddr + uint32(dromPages)*pageSize
targetImageOffset := int(iromFlashAddr - flashBase) targetImageOffset := int(iromFlashAddr - flashBase)
if makeImage {
targetImageOffset = int(iromFlashAddr)
}
if outf.Len() > targetImageOffset { if outf.Len() > targetImageOffset {
return fmt.Errorf("ESP32: DROM too large, overlaps IROM at flash 0x%x", iromFlashAddr) return fmt.Errorf("ESP32: DROM too large, overlaps IROM at flash 0x%x", iromFlashAddr)
} }
+3 -3
View File
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test. // This is a small number of very diverse targets that we want to test.
tests := []sizeTest{ tests := []sizeTest{
// microcontrollers // microcontrollers
{"hifive1b", "examples/echo", 4321, 323, 0, 2268}, {"hifive1b", "examples/echo", 4313, 323, 0, 2260},
{"microbit", "examples/serial", 2842, 382, 8, 2264}, {"microbit", "examples/serial", 2838, 382, 8, 2256},
{"wioterminal", "examples/pininterrupt", 8039, 1665, 132, 7496}, {"wioterminal", "examples/pininterrupt", 8027, 1665, 132, 7488},
// TODO: also check wasm. Right now this is difficult, because // TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the // wasm binaries are run through wasm-opt and therefore the
+3 -3
View File
@@ -296,9 +296,6 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
} }
// CompilePackage compiles a single package to a LLVM module. // CompilePackage compiles a single package to a LLVM module.
//
// The SSA package must already be built. When packages are compiled
// concurrently, the entire SSA program must be built before compilation starts.
func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) { func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
c := newCompilerContext(moduleName, machine, config, dumpSSA) c := newCompilerContext(moduleName, machine, config, dumpSSA)
defer c.dispose() defer c.dispose()
@@ -309,6 +306,9 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg
c.program = ssaPkg.Prog c.program = ssaPkg.Prog
// Convert AST to SSA.
ssaPkg.Build()
// Assign names to function-local named types before compiling the // Assign names to function-local named types before compiling the
// package, so that types declared in different functions (or in // package, so that types declared in different functions (or in
// different instantiations of a generic function) do not collide. // different instantiations of a generic function) do not collide.
+5 -6
View File
@@ -115,7 +115,7 @@ func TestCompiler(t *testing.T) {
// Update test if needed. Do not check the result. // Update test if needed. Do not check the result.
if *flagUpdate { if *flagUpdate {
err := os.WriteFile(outPath, []byte(normalizeIR(mod.String())), 0666) err := os.WriteFile(outPath, []byte(mod.String()), 0666)
if err != nil { if err != nil {
t.Error("failed to write updated output file:", err) t.Error("failed to write updated output file:", err)
} }
@@ -174,8 +174,9 @@ func TestOptimizedLargeAggregateABI(t *testing.T) {
} }
} }
// normalizeIR canonicalizes LLVM-version-specific IR spellings for comparison // normalizeIR canonicalizes LLVM IR so a single golden file keeps matching
// and when regenerating golden files. // across LLVM versions. Golden files are written against LLVM <21; newer LLVM
// prints some attributes differently.
func normalizeIR(s string) string { func normalizeIR(s string) string {
// Golden files are written using the pre-LLVM21 'nocapture' spelling, // Golden files are written using the pre-LLVM21 'nocapture' spelling,
// which LLVM printed before any co-occurring attribute such as // which LLVM printed before any co-occurring attribute such as
@@ -413,7 +414,5 @@ func testCompilePackage(t *testing.T, options *compileopts.Options, file string)
// Compile AST to IR. // Compile AST to IR.
program := lprogram.LoadSSA() program := lprogram.LoadSSA()
pkg := lprogram.MainPkg() pkg := lprogram.MainPkg()
ssaPkg := program.Package(pkg.Pkg) return CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
ssaPkg.Build()
return CompilePackage(file, pkg, ssaPkg, machine, compilerConfig, false)
} }
+16 -16
View File
@@ -19,33 +19,33 @@ define hidden void @main.chanIntSend(ptr dereferenceable_or_null(36) %ch, ptr %c
entry: entry:
%chan.op = alloca %runtime.channelOp, align 8 %chan.op = alloca %runtime.channelOp, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
store i32 3, ptr %chan.value, align 4 store i32 3, ptr %chan.value, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3 call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
ret void ret void
} }
; 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(ptr nocapture) #2 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0 declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
; 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(ptr nocapture) #2 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 { define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.op = alloca %runtime.channelOp, align 8 %chan.op = alloca %runtime.channelOp, align 8
%chan.value = alloca i32, align 4 %chan.value = alloca i32, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3 %0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
ret void ret void
} }
@@ -55,9 +55,9 @@ declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferen
define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 { define hidden void @main.chanZeroSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.op = alloca %runtime.channelOp, align 8 %chan.op = alloca %runtime.channelOp, align 8
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3 call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
ret void ret void
} }
@@ -65,9 +65,9 @@ entry:
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 { define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
entry: entry:
%chan.op = alloca %runtime.channelOp, align 8 %chan.op = alloca %runtime.channelOp, align 8
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3 %0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
ret void ret void
} }
@@ -77,7 +77,7 @@ 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
store i32 1, ptr %select.send.value, align 4 store i32 1, ptr %select.send.value, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %select.states.alloca) call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
store ptr %ch1, ptr %select.states.alloca, align 4 store ptr %ch1, ptr %select.states.alloca, align 4
%select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4 %select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4
store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4 store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
@@ -86,7 +86,7 @@ entry:
%.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12 %.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12
store ptr null, ptr %.repack3, align 4 store ptr null, ptr %.repack3, align 4
%select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #3 %select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #3
call void @llvm.lifetime.end.p0(ptr nonnull %select.states.alloca) call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
%1 = extractvalue { i32, i1 } %select.result, 0 %1 = extractvalue { i32, i1 } %select.result, 0
%2 = icmp eq i32 %1, 0 %2 = icmp eq i32 %1, 0
br i1 %2, label %select.done, label %select.next br i1 %2, label %select.done, label %select.next
+5 -5
View File
@@ -15,7 +15,7 @@ target triple = "wasm32-unknown-wasi"
@"reflect/types.type:basic:string" = linkonce_odr constant { i8, ptr } { i8 81, ptr @"reflect/types.type:pointer:basic:string" }, align 4 @"reflect/types.type:basic:string" = linkonce_odr constant { i8, ptr } { i8 81, ptr @"reflect/types.type:pointer:basic:string" }, align 4
@"reflect/types.type:pointer:basic:string" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:string" }, align 4 @"reflect/types.type:pointer:basic:string" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:string" }, align 4
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0 declare void @runtime.trackPointer(ptr readonly captures(none), ptr, ptr) #0
; 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 #1 {
@@ -31,7 +31,7 @@ entry:
} }
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2 declare void @llvm.memcpy.p0.p0.i32(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i32, i1 immarg) #2
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @"(main.largeReceiver).readLargeValue"(ptr readonly dereferenceable_or_null(1025) %receiver, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 { define hidden i8 @"(main.largeReceiver).readLargeValue"(ptr readonly dereferenceable_or_null(1025) %receiver, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
@@ -344,7 +344,7 @@ if.then: ; preds = %typeassert.next
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0 declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #7 declare void @llvm.memset.p0.i32(ptr writeonly captures(none), i8, i32, i1 immarg) #7
; Function Attrs: nounwind ; Function Attrs: nounwind
define hidden i8 @main.useLargeMap(ptr readonly dereferenceable_or_null(1025) %key, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 { define hidden i8 @main.useLargeMap(ptr readonly dereferenceable_or_null(1025) %key, ptr readonly dereferenceable_or_null(1025) %value, ptr %context) unnamed_addr #1 {
@@ -423,12 +423,12 @@ if.then: ; preds = %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(ptr nocapture) #8 declare void @llvm.lifetime.start.p0(ptr captures(none)) #8
declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0 declare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
; 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(ptr nocapture) #8 declare void @llvm.lifetime.end.p0(ptr captures(none)) #8
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0 declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
+18 -18
View File
@@ -21,23 +21,23 @@ entry:
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0 %0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1 %1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2 %2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
store %main.hasPadding %2, ptr %hashmap.key, align 4 store %main.hasPadding %2, ptr %hashmap.key, align 4
%3 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4 %3 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
%4 = load i32, ptr %hashmap.value, align 4 %4 = load i32, ptr %hashmap.value, align 4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
ret i32 %4 ret i32 %4
} }
; 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(ptr nocapture) #3 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3
declare i1 @runtime.hashmapGenericGet(ptr dereferenceable_or_null(48), ptr nocapture, ptr nocapture, i32, ptr) #0 declare i1 @runtime.hashmapGenericGet(ptr dereferenceable_or_null(48), ptr nocapture, ptr nocapture, i32, ptr) #0
; 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(ptr nocapture) #3 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
; Function Attrs: noinline nounwind ; Function Attrs: noinline nounwind
define hidden void @main.testZeroSet(ptr dereferenceable_or_null(48) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 { define hidden void @main.testZeroSet(ptr dereferenceable_or_null(48) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #2 {
@@ -47,13 +47,13 @@ entry:
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0 %0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1 %1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2 %2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
store i32 5, ptr %hashmap.value, align 4 store i32 5, ptr %hashmap.value, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
store %main.hasPadding %2, ptr %hashmap.key, align 4 store %main.hasPadding %2, ptr %hashmap.key, align 4
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4 call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
ret void ret void
} }
@@ -64,17 +64,17 @@ define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(48) %m, [2
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
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0 %s.elt = extractvalue [2 x %main.hasPadding] %s, 0
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4 store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12 %hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1 %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4 store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
%0 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4 %0 = call i1 @runtime.hashmapGenericGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
%1 = load i32, ptr %hashmap.value, align 4 %1 = load i32, ptr %hashmap.value, align 4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
ret i32 %1 ret i32 %1
} }
@@ -83,17 +83,17 @@ define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(48) %m, [2
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
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
store i32 5, ptr %hashmap.value, align 4 store i32 5, ptr %hashmap.value, align 4
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0 %s.elt = extractvalue [2 x %main.hasPadding] %s, 0
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4 store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12 %hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1 %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4 store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4 call void @runtime.hashmapGenericSet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #4
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key) call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value) call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
ret void ret void
} }
-1
View File
@@ -22,7 +22,6 @@ func TestInterp(t *testing.T) {
"store", "store",
"alloc", "alloc",
"slicedata", "slicedata",
"aggregate",
} { } {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
+5 -3
View File
@@ -928,9 +928,11 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me
llvmFn := operands[len(operands)-1] llvmFn := operands[len(operands)-1]
args := operands[:len(operands)-1] args := operands[:len(operands)-1]
for _, op := range operands { for _, op := range operands {
err := mem.markExternalStore(op) if op.Type().TypeKind() == llvm.PointerTypeKind {
if err != nil { err := mem.markExternalStore(op)
return r.errorAt(inst, err) if err != nil {
return r.errorAt(inst, err)
}
} }
} }
result = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args, inst.name) result = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args, inst.name)
-27
View File
@@ -1,27 +0,0 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
declare void @externalAggregate({ ptr })
@main.value = global i32 1
@main.result = global i32 0
define void @runtime.initAll() unnamed_addr {
entry:
call void @main.init(ptr undef)
ret void
}
define internal void @main.init(ptr %context) unnamed_addr {
entry:
; The pointer is hidden inside an aggregate argument.
%arg = insertvalue { ptr } undef, ptr @main.value, 0
; This call runs at runtime and may modify @main.value.
call void @externalAggregate({ ptr } %arg)
; Therefore this load must also remain at runtime.
%value = load i32, ptr @main.value
store i32 %value, ptr @main.result
ret void
}
-15
View File
@@ -1,15 +0,0 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
@main.value = global i32 1
@main.result = local_unnamed_addr global i32 0
declare void @externalAggregate({ ptr }) local_unnamed_addr
define void @runtime.initAll() unnamed_addr {
entry:
call void @externalAggregate({ ptr } { ptr @main.value })
%value = load i32, ptr @main.value, align 4
store i32 %value, ptr @main.result, align 4
ret void
}
+1 -8
View File
@@ -177,15 +177,8 @@ func Build(pkgName, outpath string, config *compileopts.Config) error {
// Pick a default output path based on the main directory. // Pick a default output path based on the main directory.
outpath = filepath.Base(result.MainDir) + config.DefaultBinaryExtension() outpath = filepath.Base(result.MainDir) + config.DefaultBinaryExtension()
} }
} else if fi, statErr := os.Stat(outpath); statErr == nil && fi.IsDir() {
var name string
if strings.HasSuffix(pkgName, ".go") {
name = filepath.Base(pkgName[:len(pkgName)-3]) + config.DefaultBinaryExtension()
} else {
name = filepath.Base(result.MainDir) + config.DefaultBinaryExtension()
}
outpath = filepath.Join(outpath, name)
} }
if err := os.Rename(result.Binary, outpath); err != nil { if err := os.Rename(result.Binary, outpath); err != nil {
// Moving failed. Do a file copy. // Moving failed. Do a file copy.
inf, err := os.Open(result.Binary) inf, err := os.Open(result.Binary)
-30
View File
@@ -261,21 +261,6 @@ func TestTimerStopResetRace(t *testing.T) {
runTest("timer_stop_reset_race.go", optionsFromTarget("", sema), t, nil, nil) runTest("timer_stop_reset_race.go", optionsFromTarget("", sema), t, nil, nil)
} }
func TestESP32QEMU(t *testing.T) {
t.Parallel()
options := optionsFromTarget("esp32-qemu", sema)
emuCheck(t, options)
machines, err := exec.Command("qemu-system-xtensa", "-machine", "help").Output()
if err != nil {
t.Fatal("failed to list qemu-system-xtensa machines:", err)
}
if !regexp.MustCompile(`(?m)^esp32\s`).Match(machines) {
t.Skip("qemu-system-xtensa does not support the ESP32 machine")
}
runTest("print.go", options, t, nil, nil)
}
func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
emuCheck(t, options) emuCheck(t, options)
@@ -554,9 +539,6 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
if config.EmulatorName() == "simavr" { if config.EmulatorName() == "simavr" {
actual = cleanSimAVRTestOutput(actual) actual = cleanSimAVRTestOutput(actual)
} }
if config.EmulatorName() == "qemu-system-xtensa" {
actual = cleanESP32QEMUOutput(actual)
}
if name == "testing.go" { if name == "testing.go" {
// Strip actual time. // Strip actual time.
re := regexp.MustCompile(`\([0-9]\.[0-9][0-9]s\)`) re := regexp.MustCompile(`\([0-9]\.[0-9][0-9]s\)`)
@@ -582,18 +564,6 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
} }
} }
func cleanESP32QEMUOutput(output []byte) []byte {
entryLine := bytes.Index(output, []byte("\nentry "))
if entryLine < 0 {
return output
}
entryLineEnd := bytes.IndexByte(output[entryLine+1:], '\n')
if entryLineEnd < 0 {
return output
}
return output[entryLine+1+entryLineEnd+1:]
}
func cleanSimAVRTestOutput(output []byte) []byte { func cleanSimAVRTestOutput(output []byte) []byte {
output = bytes.ReplaceAll(output, []byte{0x1b, '[', '3', '2', 'm'}, nil) output = bytes.ReplaceAll(output, []byte{0x1b, '[', '3', '2', 'm'}, nil)
output = bytes.ReplaceAll(output, []byte{0x1b, '[', '0', 'm'}, nil) output = bytes.ReplaceAll(output, []byte{0x1b, '[', '0', 'm'}, nil)
-23
View File
@@ -2208,9 +2208,6 @@ func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe
//go:linkname hashmapMakeReflect runtime.hashmapMakeReflect //go:linkname hashmapMakeReflect runtime.hashmapMakeReflect
func hashmapMakeReflect(keySize, valueSize, sizeHint uintptr, keyType unsafe.Pointer) unsafe.Pointer func hashmapMakeReflect(keySize, valueSize, sizeHint uintptr, keyType unsafe.Pointer) unsafe.Pointer
//go:linkname chanMake runtime.chanMake
func chanMake(elementSize uintptr, bufSize uintptr) 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
// for approximately n elements. // for approximately n elements.
func MakeMapWithSize(typ Type, n int) Value { func MakeMapWithSize(typ Type, n int) Value {
@@ -2257,26 +2254,6 @@ func MakeMap(typ Type) Value {
return MakeMapWithSize(typ, 8) return MakeMapWithSize(typ, 8)
} }
// MakeChan creates a new channel with the specified type and buffer size.
func MakeChan(typ Type, size int) Value {
if typ.Kind() != Chan {
panic(&ValueError{Method: "MakeChan", Kind: typ.Kind()})
}
if size < 0 {
panic("reflect.MakeChan: negative buffer size")
}
if typ.(*RawType).ChanDir() != BothDir {
panic("reflect.MakeChan: unidirectional channel type")
}
elem := typ.Elem().(*RawType)
ch := chanMake(elem.Size(), uintptr(size))
return Value{
typecode: typ.(*RawType),
value: ch,
flags: valueFlagExported,
}
}
func (v Value) Call(in []Value) []Value { func (v Value) Call(in []Value) []Value {
panic("unimplemented: (reflect.Value).Call()") panic("unimplemented: (reflect.Value).Call()")
} }
+14 -16
View File
@@ -68,12 +68,14 @@ tinygo_swapTask:
// After the recursive spill returns, the physical register file still // After the recursive spill returns, the physical register file still
// has WindowStart bits set for the spill helper frames. // has WindowStart bits set for the spill helper frames.
// These are dropped below, once the stack switch is done. // We will clear WindowStart completely (to 0) right before the retw.n
// below, after the stack switch is done. This prevents stale overflow
// when the new goroutine's calls rotate back into these panes.
// Mask interrupts until WindowStart matches the new stack, or one lands in // Restore interrupts.
// the gap and clobbers the a0-a3 that retw.n reloads. l32i a4, sp, 4 // reload saved PS
// Xtensa ISA Reference Manual, RETW, section 8.3.253, p.565. wsr.ps a4
l32i a4, sp, 4 // reload saved PS, restored below rsync
// At this point, the following is true: // At this point, the following is true:
// WindowStart == 1 << WindowBase // WindowStart == 1 << WindowBase
@@ -95,20 +97,16 @@ tinygo_swapTask:
// register also stores the parent register window. // register also stores the parent register window.
l32i.n a0, sp, 0 l32i.n a0, sp, 0
// Drop every WindowStart bit but this window's: stale bits overflow garbage, // Clear ALL WindowStart bits. With all windows spilled to the stack,
// and an all-zero WindowStart marks the running frame dead. // we must ensure no stale WS bits remain: the retw.n below will trigger
// Xtensa ISA Reference Manual, WINDOWSTART (SR 73), Table 5-148. // underflow4 to load the new goroutine's registers from the new stack
rsr a6, WINDOWBASE // (which sets the appropriate WS bit via rfwu). Any stale WS bits
movi a5, 1 // (from spill helpers or the old goroutine) would cause spurious
ssl a6 // overflows of garbage register values into memory.
sll a5, a5 // a5 = 1 << WindowBase movi a5, 0
wsr a5, WINDOWSTART wsr a5, WINDOWSTART
rsync rsync
// Window state now matches the new stack, so unmask interrupts.
wsr.ps a4
rsync
// Return into the new stack. This instruction will trigger a window // Return into the new stack. This instruction will trigger a window
// underflow, reloading the saved registers from the stack. // underflow, reloading the saved registers from the stack.
retw.n retw.n
+1 -15
View File
@@ -51,7 +51,7 @@ func (dev *USBDevice) Configure(config UARTConfig) {
sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos) sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos)
// attach // attach
dev.Attach() sam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)
// enable interrupt for end of reset // enable interrupt for end of reset
sam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST) sam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST)
@@ -68,20 +68,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
dev.initcomplete = true dev.initcomplete = true
} }
// Attach connects the device to the USB bus, allowing the host to detect and
// enumerate it. It can be used together with Detach to delay enumeration
// until the USB configuration (device identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
sam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)
}
// Detach disconnects the device from the USB bus. To the host this appears
// as if the device was unplugged. A subsequent Attach makes the host
// enumerate the device again.
func (dev *USBDevice) Detach() {
sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_DETACH)
}
func handlePadCalibration() { func handlePadCalibration() {
// Load Pad Calibration data from non-volatile memory // Load Pad Calibration data from non-volatile memory
// This requires registers that are not included in the SVD file. // This requires registers that are not included in the SVD file.
+1 -15
View File
@@ -51,7 +51,7 @@ func (dev *USBDevice) Configure(config UARTConfig) {
sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos) sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos)
// attach // attach
dev.Attach() sam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)
// enable interrupt for end of reset // enable interrupt for end of reset
sam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST) sam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST)
@@ -71,20 +71,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
dev.initcomplete = true dev.initcomplete = true
} }
// Attach connects the device to the USB bus, allowing the host to detect and
// enumerate it. It can be used together with Detach to delay enumeration
// until the USB configuration (device identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
sam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)
}
// Detach disconnects the device from the USB bus. To the host this appears
// as if the device was unplugged. A subsequent Attach makes the host
// enumerate the device again.
func (dev *USBDevice) Detach() {
sam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_DETACH)
}
func handlePadCalibration() { func handlePadCalibration() {
// Load Pad Calibration data from non-volatile memory // Load Pad Calibration data from non-volatile memory
// This requires registers that are not included in the SVD file. // This requires registers that are not included in the SVD file.
-59
View File
@@ -112,11 +112,6 @@ func (p Pin) configure(config PinConfig, signal uint32) {
// Configure the pad with the given IO mux configuration. // Configure the pad with the given IO mux configuration.
p.mux().Set(muxConfig) p.mux().Set(muxConfig)
// Internal pull resistors for pins with RTC function ignore
// the IO_MUX_GPIO0_FUN_WPU and IO_MUX_GPIO0_FUN_WPD bits set
// above and are instead controlled by the RTC_IO registers.
p.configureRTCPull(config.Mode)
switch config.Mode { switch config.Mode {
case PinOutput: case PinOutput:
// Set the 'output enable' bit. // Set the 'output enable' bit.
@@ -298,60 +293,6 @@ func (p Pin) mux() *volatile.Register32 {
} }
} }
// configureRTCPull applies the pullup/pulldown setting to a pin.
// This mirrors ESP-IDF:
// https://github.com/espressif/esp-idf/blob/08e0d30/components/esp_driver_gpio/src/gpio.c#L283
// https://github.com/espressif/esp-idf/blob/08e0d30/components/esp_hal_gpio/esp32/rtc_io_periph.c#L57
// https://github.com/espressif/esp-idf/blob/08e0d30/components/esp_hal_gpio/esp32/include/hal/rtc_io_ll.h#L175
func (p Pin) configureRTCPull(mode PinMode) {
var rue, rde uint32
switch mode {
case PinInputPullup:
rue = 1
case PinInputPulldown:
rde = 1
}
switch p {
case 0:
esp.RTC_IO.SetTOUCH_PAD1_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD1_RDE(rde)
case 2:
esp.RTC_IO.SetTOUCH_PAD2_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD2_RDE(rde)
case 4:
esp.RTC_IO.SetTOUCH_PAD0_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD0_RDE(rde)
case 12:
esp.RTC_IO.SetTOUCH_PAD5_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD5_RDE(rde)
case 13:
esp.RTC_IO.SetTOUCH_PAD4_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD4_RDE(rde)
case 14:
esp.RTC_IO.SetTOUCH_PAD6_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD6_RDE(rde)
case 15:
esp.RTC_IO.SetTOUCH_PAD3_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD3_RDE(rde)
case 25:
esp.RTC_IO.SetPAD_DAC1_PDAC1_RUE(rue)
esp.RTC_IO.SetPAD_DAC1_PDAC1_RDE(rde)
case 26:
esp.RTC_IO.SetPAD_DAC2_PDAC2_RUE(rue)
esp.RTC_IO.SetPAD_DAC2_PDAC2_RDE(rde)
case 27:
esp.RTC_IO.SetTOUCH_PAD7_RUE(rue)
esp.RTC_IO.SetTOUCH_PAD7_RDE(rde)
case 32:
esp.RTC_IO.SetXTAL_32K_PAD_X32P_RUE(rue)
esp.RTC_IO.SetXTAL_32K_PAD_X32P_RDE(rde)
case 33:
esp.RTC_IO.SetXTAL_32K_PAD_X32N_RUE(rue)
esp.RTC_IO.SetXTAL_32K_PAD_X32N_RDE(rde)
}
}
const maxPin = 40 const maxPin = 40
// cpuInterruptFromPin selects an edge-triggered CPU interrupt line for GPIO. // cpuInterruptFromPin selects an edge-triggered CPU interrupt line for GPIO.
+3 -1
View File
@@ -242,6 +242,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
timeoutNS := int64(timeoutMS) * 1000000 timeoutNS := int64(timeoutMS) * 1000000
needAddress := true needAddress := true
needRestart := false needRestart := false
readLast := false
var readTo []byte var readTo []byte
for cmdIdx, reg := 0, &i2c.Bus.COMD0; cmdIdx < len(cmd); { for cmdIdx, reg := 0, &i2c.Bus.COMD0; cmdIdx < len(cmd); {
c := &cmd[cmdIdx] c := &cmd[cmdIdx]
@@ -309,6 +310,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
} }
if split { if split {
readLast = true
reg.Set(i2cCMD_READLAST | 1) reg.Set(i2cCMD_READLAST | 1)
reg = nextAddress(reg) reg = nextAddress(reg)
readTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte readTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte
@@ -340,7 +342,7 @@ func (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {
} }
} }
switch { switch {
case mask&esp.I2C_INT_STATUS_ACK_ERR_INT_ST_Msk != 0: case mask&esp.I2C_INT_STATUS_ACK_ERR_INT_ST_Msk != 0 && !readLast:
return errI2CAckExpected return errI2CAckExpected
case mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0: case mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0:
// timeout leaves the bus in an undefined state, reset // timeout leaves the bus in an undefined state, reset
-5
View File
@@ -67,11 +67,6 @@ func (dev *USBDevice) SetStallEPOut(ep uint32) {}
func (dev *USBDevice) ClearStallEPIn(ep uint32) {} func (dev *USBDevice) ClearStallEPIn(ep uint32) {}
func (dev *USBDevice) ClearStallEPOut(ep uint32) {} func (dev *USBDevice) ClearStallEPOut(ep uint32) {}
// Attach and Detach are no-ops: the USB Serial/JTAG controller has no
// software-controlled soft-connect, it is always attached to the bus.
func (dev *USBDevice) Attach() {}
func (dev *USBDevice) Detach() {}
// initUSB is intentionally empty — the interp phase evaluates init() // initUSB is intentionally empty — the interp phase evaluates init()
// functions at compile time and cannot access hardware registers. // functions at compile time and cannot access hardware registers.
// Actual hardware setup is deferred to the first Configure() call. // Actual hardware setup is deferred to the first Configure() call.
-5
View File
@@ -66,11 +66,6 @@ func (dev *USBDevice) SetStallEPOut(ep uint32) {}
func (dev *USBDevice) ClearStallEPIn(ep uint32) {} func (dev *USBDevice) ClearStallEPIn(ep uint32) {}
func (dev *USBDevice) ClearStallEPOut(ep uint32) {} func (dev *USBDevice) ClearStallEPOut(ep uint32) {}
// Attach and Detach are no-ops: the USB Serial/JTAG controller has no
// software-controlled soft-connect, it is always attached to the bus.
func (dev *USBDevice) Attach() {}
func (dev *USBDevice) Detach() {}
// initUSB is intentionally empty — the interp phase evaluates init() // initUSB is intentionally empty — the interp phase evaluates init()
// functions at compile time and cannot access hardware registers. // functions at compile time and cannot access hardware registers.
// Actual hardware setup is deferred to the first Configure() call. // Actual hardware setup is deferred to the first Configure() call.
-5
View File
@@ -67,11 +67,6 @@ func (dev *USBDevice) SetStallEPOut(ep uint32) {}
func (dev *USBDevice) ClearStallEPIn(ep uint32) {} func (dev *USBDevice) ClearStallEPIn(ep uint32) {}
func (dev *USBDevice) ClearStallEPOut(ep uint32) {} func (dev *USBDevice) ClearStallEPOut(ep uint32) {}
// Attach and Detach are no-ops: the USB Serial/JTAG controller has no
// software-controlled soft-connect, it is always attached to the bus.
func (dev *USBDevice) Attach() {}
func (dev *USBDevice) Detach() {}
// initUSB is intentionally empty — the interp phase evaluates init() // initUSB is intentionally empty — the interp phase evaluates init()
// functions at compile time and cannot access hardware registers. // functions at compile time and cannot access hardware registers.
// Actual hardware setup is deferred to the first Configure() call. // Actual hardware setup is deferred to the first Configure() call.
+1 -25
View File
@@ -22,11 +22,6 @@ var (
epinen uint32 epinen uint32
epouten uint32 epouten uint32
easyDMABusy volatile.Register8 easyDMABusy volatile.Register8
// usbDetached keeps the device detached from the bus after Detach: the
// USB IRQ handler re-enables the DP pull-up on every power-ready event,
// which would otherwise silently undo a Detach.
usbDetached bool
) )
// enterCriticalSection is used to protect access to easyDMA - only one thing // enterCriticalSection is used to protect access to easyDMA - only one thing
@@ -94,23 +89,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
dev.initcomplete = true dev.initcomplete = true
} }
// Attach connects the device to the USB bus by enabling the DP pull-up,
// allowing the host to detect and enumerate it. It can be used together with
// Detach to delay enumeration until the USB configuration (device
// identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
usbDetached = false
nrf.USBD.USBPULLUP.Set(1)
}
// Detach disconnects the device from the USB bus by disabling the DP pull-up.
// To the host this appears as if the device was unplugged. A subsequent
// Attach makes the host enumerate the device again.
func (dev *USBDevice) Detach() {
usbDetached = true
nrf.USBD.USBPULLUP.Set(0)
}
func handleUSBIRQ(interrupt.Interrupt) { func handleUSBIRQ(interrupt.Interrupt) {
if nrf.USBD.EVENTS_SOF.Get() == 1 { if nrf.USBD.EVENTS_SOF.Get() == 1 {
nrf.USBD.EVENTS_SOF.Set(0) nrf.USBD.EVENTS_SOF.Set(0)
@@ -125,9 +103,7 @@ func handleUSBIRQ(interrupt.Interrupt) {
// Configure control endpoint // Configure control endpoint
initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)
if !usbDetached { nrf.USBD.USBPULLUP.Set(1)
nrf.USBD.USBPULLUP.Set(1)
}
usbConfiguration = 0 usbConfiguration = 0
} }
-15
View File
@@ -43,24 +43,9 @@ func (dev *USBDevice) Configure(config UARTConfig) {
rp.USBCTRL_REGS_INTE_SETUP_REQ) rp.USBCTRL_REGS_INTE_SETUP_REQ)
// Present full speed device by enabling pull up on DP // Present full speed device by enabling pull up on DP
dev.Attach()
}
// Attach connects the device to the USB bus by enabling the DP pull-up,
// allowing the host to detect and enumerate it. It can be used together with
// Detach to delay enumeration until the USB configuration (device
// identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
rp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN) rp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN)
} }
// Detach disconnects the device from the USB bus by disabling the DP pull-up.
// To the host this appears as if the device was unplugged. A subsequent
// Attach makes the host enumerate the device again.
func (dev *USBDevice) Detach() {
rp.USBCTRL_REGS.SIE_CTRL.ClearBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN)
}
func handleUSBIRQ(intr interrupt.Interrupt) { func handleUSBIRQ(intr interrupt.Interrupt) {
status := rp.USBCTRL_REGS.INTS.Get() status := rp.USBCTRL_REGS.INTS.Get()
+1 -16
View File
@@ -43,27 +43,12 @@ func (dev *USBDevice) Configure(config UARTConfig) {
rp.USB_INTE_SETUP_REQ) rp.USB_INTE_SETUP_REQ)
// Present full speed device by enabling pull up on DP // Present full speed device by enabling pull up on DP
dev.Attach() rp.USB.SIE_CTRL.SetBits(rp.USB_SIE_CTRL_PULLUP_EN)
// 12.7.2 Disable phy isolation // 12.7.2 Disable phy isolation
rp.USB.SetMAIN_CTRL_PHY_ISO(0x0) rp.USB.SetMAIN_CTRL_PHY_ISO(0x0)
} }
// Attach connects the device to the USB bus by enabling the DP pull-up,
// allowing the host to detect and enumerate it. It can be used together with
// Detach to delay enumeration until the USB configuration (device
// identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
rp.USB.SIE_CTRL.SetBits(rp.USB_SIE_CTRL_PULLUP_EN)
}
// Detach disconnects the device from the USB bus by disabling the DP pull-up.
// To the host this appears as if the device was unplugged. A subsequent
// Attach makes the host enumerate the device again.
func (dev *USBDevice) Detach() {
rp.USB.SIE_CTRL.ClearBits(rp.USB_SIE_CTRL_PULLUP_EN)
}
func handleUSBIRQ(intr interrupt.Interrupt) { func handleUSBIRQ(intr interrupt.Interrupt) {
status := rp.USB.INTS.Get() status := rp.USB.INTS.Get()
+2 -17
View File
@@ -254,7 +254,7 @@ func (dev *USBDevice) Configure(config UARTConfig) {
otgPower.PCGCCTL.Set(0) otgPower.PCGCCTL.Set(0)
// Soft-disconnect now (after CSRST reset DCTL to its default connected state). // Soft-disconnect now (after CSRST reset DCTL to its default connected state).
dev.Detach() otgDevice.DCTL.SetBits(dctlSDIS)
// ---- 7. Configure data FIFOs -------------------------------------------- // ---- 7. Configure data FIFOs --------------------------------------------
@@ -311,26 +311,11 @@ func (dev *USBDevice) Configure(config UARTConfig) {
// ---- 12. Connect to host (clear soft-disconnect) ----------------------- // ---- 12. Connect to host (clear soft-disconnect) -----------------------
dev.Attach() otgDevice.DCTL.ClearBits(dctlSDIS)
dev.initcomplete = true dev.initcomplete = true
} }
// Attach connects the device to the USB bus by releasing soft disconnect,
// allowing the host to detect and enumerate it. It can be used together with
// Detach to delay enumeration until the USB configuration (device
// identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
otgDevice.DCTL.ClearBits(dctlSDIS)
}
// Detach disconnects the device from the USB bus by asserting soft
// disconnect. To the host this appears as if the device was unplugged. A
// subsequent Attach makes the host enumerate the device again.
func (dev *USBDevice) Detach() {
otgDevice.DCTL.SetBits(dctlSDIS)
}
// handleUSBIRQ is the OTG FS interrupt handler, dispatching on GINTSTS bits. // handleUSBIRQ is the OTG FS interrupt handler, dispatching on GINTSTS bits.
func handleUSBIRQ(intr interrupt.Interrupt) { func handleUSBIRQ(intr interrupt.Interrupt) {
status := stm32.OTG_FS_GLOBAL.GINTSTS.Get() & status := stm32.OTG_FS_GLOBAL.GINTSTS.Get() &
+1 -16
View File
@@ -206,7 +206,7 @@ func (dev *USBDevice) Configure(config UARTConfig) {
// Stay soft-disconnected until configuration is complete; CSRST left // Stay soft-disconnected until configuration is complete; CSRST left
// DCTL at its default "connected" state. // DCTL at its default "connected" state.
dev.Detach() usbOTG.DCTL.SetBits(DCTL_SDIS)
// 5. Force device mode now that the core is out of reset. The mode // 5. Force device mode now that the core is out of reset. The mode
// change takes effect only after up to 25 ms (RM0433); poll GINTSTS.CMOD // change takes effect only after up to 25 ms (RM0433); poll GINTSTS.CMOD
@@ -265,24 +265,9 @@ func (dev *USBDevice) Configure(config UARTConfig) {
dev.initcomplete = true dev.initcomplete = true
// Release soft-disconnect: pulls D+ high, making device visible to host. // Release soft-disconnect: pulls D+ high, making device visible to host.
dev.Attach()
}
// Attach connects the device to the USB bus by releasing soft disconnect,
// allowing the host to detect and enumerate it. It can be used together with
// Detach to delay enumeration until the USB configuration (device
// identifiers, classes, ...) is complete.
func (dev *USBDevice) Attach() {
usbOTG.DCTL.ClearBits(DCTL_SDIS) usbOTG.DCTL.ClearBits(DCTL_SDIS)
} }
// Detach disconnects the device from the USB bus by asserting soft
// disconnect. To the host this appears as if the device was unplugged. A
// subsequent Attach makes the host enumerate the device again.
func (dev *USBDevice) Detach() {
usbOTG.DCTL.SetBits(DCTL_SDIS)
}
func initEndpoint(ep, config uint32) { func initEndpoint(ep, config uint32) {
if ep == 0 { if ep == 0 {
// Control endpoint // Control endpoint
-11
View File
@@ -163,17 +163,6 @@ func (f *File) Truncate(size int64) (err error) {
return Truncate(f.name, size) return Truncate(f.name, size)
} }
// Chown changes the numeric uid and gid of the named file.
// A uid or gid of -1 means to not change that value.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
if f.handle == nil {
return ErrClosed
}
return Chown(f.name, uid, gid)
}
func (f *File) chmod(mode FileMode) error { func (f *File) chmod(mode FileMode) error {
if f.handle == nil { if f.handle == nil {
return ErrClosed return ErrClosed
-6
View File
@@ -1,6 +0,0 @@
package os
import "syscall"
// Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() }
+5
View File
@@ -6,6 +6,11 @@
package os package os
import "syscall"
// Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() }
func (fs *fileStat) Name() string { return fs.name } func (fs *fileStat) Name() string { return fs.name }
func (fs *fileStat) IsDir() bool { return fs.Mode().IsDir() } func (fs *fileStat) IsDir() bool { return fs.Mode().IsDir() }
-5
View File
@@ -201,11 +201,6 @@ func MakeMapWithSize(typ Type, n int) Value {
return Value{reflectlite.MakeMapWithSize(toRawType(typ), n)} return Value{reflectlite.MakeMapWithSize(toRawType(typ), n)}
} }
// MakeChan creates a new channel with the specified type and buffer size.
func MakeChan(typ Type, buffer int) Value {
return Value{reflectlite.MakeChan(toRawType(typ), buffer)}
}
func (v Value) Call(in []Value) []Value { func (v Value) Call(in []Value) []Value {
panic("unimplemented: (reflect.Value).Call()") panic("unimplemented: (reflect.Value).Call()")
} }
-80
View File
@@ -994,86 +994,6 @@ func TestTypeAssertPanic(t *testing.T) {
}) })
} }
func TestTinyMakeChan(t *testing.T) {
// Value.Send and Value.Recv are not implemented yet, so the channel is
// exercised through Interface(): that proves MakeChan returns a working
// channel rather than merely a value of the right kind.
t.Run("buffered", func(t *testing.T) {
v := MakeChan(TypeOf(make(chan int)), 2)
if got, want := v.Kind(), Chan; got != want {
t.Errorf("Kind()=%v, want %v", got, want)
}
if got, want := v.Cap(), 2; got != want {
t.Errorf("Cap()=%v, want %v", got, want)
}
if got, want := v.Len(), 0; got != want {
t.Errorf("Len()=%v, want %v", got, want)
}
ch, ok := v.Interface().(chan int)
if !ok {
t.Fatalf("Interface() is %T, want chan int", v.Interface())
}
ch <- 1
ch <- 2
if got, want := v.Len(), 2; got != want {
t.Errorf("Len()=%v after two sends, want %v", got, want)
}
if got, want := <-ch, 1; got != want {
t.Errorf("<-ch=%v, want %v", got, want)
}
if got, want := <-ch, 2; got != want {
t.Errorf("<-ch=%v, want %v", got, want)
}
})
t.Run("unbuffered", func(t *testing.T) {
v := MakeChan(TypeOf(make(chan string)), 0)
if got, want := v.Cap(), 0; got != want {
t.Errorf("Cap()=%v, want %v", got, want)
}
ch, ok := v.Interface().(chan string)
if !ok {
t.Fatalf("Interface() is %T, want chan string", v.Interface())
}
go func() { ch <- "hello" }()
if got, want := <-ch, "hello"; got != want {
t.Errorf("<-ch=%q, want %q", got, want)
}
})
// The three cases below rely on recovering from a panic, which wasm
// cannot do yet without exceptions. Log and return rather than Skip:
// t.Skip needs the same machinery it is standing in for.
//
// Checked on GOARCH rather than GOOS because the limitation is wasm's, not
// any one platform's: this covers wasip1, wasip2 and js/wasm alike.
// TODO: drop this once tinygo-org/tinygo#5550 lands.
if runtime.GOARCH == "wasm" {
t.Log("not running the panic cases: panic/recover on wasm needs #5550")
return
}
t.Run("not a channel", func(t *testing.T) {
defer func() { recover() }()
MakeChan(TypeOf(0), 0)
t.Fatalf("MakeChan did not panic on a non-channel type")
})
t.Run("negative buffer", func(t *testing.T) {
defer func() { recover() }()
MakeChan(TypeOf(make(chan int)), -1)
t.Fatalf("MakeChan did not panic on a negative buffer size")
})
t.Run("directional", func(t *testing.T) {
defer func() { recover() }()
var recvOnly <-chan int
MakeChan(TypeOf(recvOnly), 0)
t.Fatalf("MakeChan did not panic on a unidirectional channel type")
})
}
// Functions needed by all_test.go // Functions needed by all_test.go
func IsRO(v Value) bool { func IsRO(v Value) bool {
+1 -10
View File
@@ -56,7 +56,6 @@ var (
endBlock gcBlock // the block just past the end of the available space endBlock gcBlock // the block just past the end of the available space
gcTotalAlloc uint64 // total number of bytes allocated gcTotalAlloc uint64 // total number of bytes allocated
gcMallocs uint64 // total number of allocations gcMallocs uint64 // total number of allocations
gcNumGC uint32 // total number of completed collection cycles
gcLock task.PMutex // lock to avoid race conditions on multicore systems gcLock task.PMutex // lock to avoid race conditions on multicore systems
) )
@@ -511,7 +510,7 @@ func realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
lastBlock := firstBlock.findHead() lastBlock := firstBlock.findHead()
// Calculate the size of the original allocation body. // Calculate the size of the original allocation body.
oldSize := uintptr(lastBlock-firstBlock)*bytesPerBlock + (bytesPerBlock - unsafe.Sizeof(objHeader{})) oldSize := uintptr(lastBlock-firstBlock)*blocksPerStateByte + (bytesPerBlock - unsafe.Sizeof(objHeader{}))
if size <= oldSize { if size <= oldSize {
// The requested size is less than the old size. // The requested size is less than the old size.
@@ -611,11 +610,6 @@ func runGC() (freeBytes uintptr) {
dumpHeap() dumpHeap()
} }
// The cycle is complete. Counted here rather than in GC() so that
// collections triggered by an allocation are counted too. Every caller
// holds gcLock, the same lock ReadMemStats reads it under.
gcNumGC++
return return
} }
@@ -856,9 +850,6 @@ func ReadMemStats(m *MemStats) {
// Record the total allocated bytes. // Record the total allocated bytes.
m.TotalAlloc = gcTotalAlloc m.TotalAlloc = gcTotalAlloc
// Record the number of completed collection cycles.
m.NumGC = gcNumGC
gcLock.Unlock() gcLock.Unlock()
} }
-1
View File
@@ -129,7 +129,6 @@ func ReadMemStats(m *MemStats) {
m.Mallocs = 0 // not provided by bdwgc m.Mallocs = 0 // not provided by bdwgc
m.Frees = 0 // not provided by bdwgc m.Frees = 0 // not provided by bdwgc
m.Sys = uint64(gcMemStats.obtained_from_os_bytes) m.Sys = uint64(gcMemStats.obtained_from_os_bytes)
m.NumGC = uint32(gcMemStats.gc_no)
gcLock.Unlock() gcLock.Unlock()
} }
+1 -8
View File
@@ -47,14 +47,8 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
gcTotalAlloc += uint64(size) gcTotalAlloc += uint64(size)
gcMallocs++ gcMallocs++
heapptr += size heapptr += size
if heapptr < addr { for heapptr >= heapEnd {
// The allocation size overflowed the heap pointer.
runtimePanic("out of memory")
}
for heapptr > heapEnd {
// Try to increase the heap and check again. // Try to increase the heap and check again.
// Use > instead of >= because an allocation that exactly
// ends at heapEnd is still within heap boundaries.
if growHeap() { if growHeap() {
continue continue
} }
@@ -109,7 +103,6 @@ func ReadMemStats(m *MemStats) {
m.HeapAlloc = gcTotalAlloc m.HeapAlloc = gcTotalAlloc
m.HeapObjects = gcMallocs m.HeapObjects = gcMallocs
m.Alloc = m.HeapAlloc m.Alloc = m.HeapAlloc
m.NumGC = 0 // this GC never collects, so no cycle ever completes
gcLock.Unlock() gcLock.Unlock()
} }
+7 -6
View File
@@ -43,12 +43,6 @@ func gcMarkReachable() {
gcPauseCore(i) gcPauseCore(i)
} }
// Busy-wait until all the other cores are ready.
for gcScanState.Load() != numCPU {
spinLoopWait()
}
gcScanState.Store(0)
// Scan the stack(s) of the current core. // Scan the stack(s) of the current core.
scanCurrentStack() scanCurrentStack()
if !task.OnSystemStack() { if !task.OnSystemStack() {
@@ -59,6 +53,13 @@ func gcMarkReachable() {
// Scan globals. // Scan globals.
findGlobals(markRoots) findGlobals(markRoots)
// Busy-wait until all the other cores are ready. They certainly should be,
// after the scanning we did above.
for gcScanState.Load() != numCPU {
spinLoopWait()
}
gcScanState.Store(0)
// Signal each core in turn that they can scan the stack. // Signal each core in turn that they can scan the stack.
for i := uint32(0); i < numCPU; i++ { for i := uint32(0); i < numCPU; i++ {
if i == core { if i == core {
+2 -2
View File
@@ -807,13 +807,13 @@ func hashmapInterfaceHash(itf interface{}, seed uintptr) uint32 {
case reflectlite.Array: case reflectlite.Array:
var hash uint32 var hash uint32
for i := 0; i < x.Len(); i++ { for i := 0; i < x.Len(); i++ {
hash = (hash * 31) ^ hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed) hash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)
} }
return hash return hash
case reflectlite.Struct: case reflectlite.Struct:
var hash uint32 var hash uint32
for i := 0; i < x.NumField(); i++ { for i := 0; i < x.NumField(); i++ {
hash = (hash * 31) ^ hashmapInterfaceHash(valueInterfaceUnsafe(x.Field(i)), seed) hash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Field(i)), seed)
} }
return hash return hash
default: default:
-5
View File
@@ -82,9 +82,4 @@ type MemStats struct {
// GCSys is bytes of memory in garbage collection metadata. // GCSys is bytes of memory in garbage collection metadata.
GCSys uint64 GCSys uint64
// NumGC is the number of completed GC cycles.
//
// The leaking collector never collects, so it always reports 0.
NumGC uint32
} }
+6
View File
@@ -78,6 +78,12 @@ var _ebss [0]byte
//go:extern _vector_table //go:extern _vector_table
var _vector_table [0]uintptr var _vector_table [0]uintptr
func abort() {
for {
device.Asm("waiti 0")
}
}
// interruptInit installs the Xtensa vector table by writing its address // interruptInit installs the Xtensa vector table by writing its address
// to the VECBASE special register and ensures all CPU interrupts are // to the VECBASE special register and ensures all CPU interrupts are
// initially disabled. // initially disabled.
-11
View File
@@ -1,11 +0,0 @@
//go:build esp32 && !qemu
package runtime
import "device"
func abort() {
for {
device.Asm("waiti 0")
}
}
-28
View File
@@ -1,28 +0,0 @@
//go:build esp32 && qemu
package runtime
import "device"
func exit(code int) {
qemuExit(code)
}
func abort() {
qemuExit(1)
}
func qemuExit(code int) {
// QEMU semihosting expects a2 = SYS_exit (1) and a3 = the exit code.
// AsmFull cannot declare these clobbers, so no Go code may run afterward.
device.AsmFull(
"mov a3, {code}\n"+
"movi a2, 1\n"+
"simcall",
map[string]interface{}{"code": code},
)
// This loop ensures the clobbered registers are never used again.
for {
device.Asm("waiti 0")
}
}
+4
View File
@@ -55,6 +55,10 @@ func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks) * 25 return int64(ticks) * 25
} }
func exit(code int) {
abort()
}
func putchar(c byte) { func putchar(c byte) {
machine.Serial.WriteByte(c) machine.Serial.WriteByte(c)
} }
-7
View File
@@ -1,7 +0,0 @@
//go:build (esp32 && !qemu) || esp32c3 || esp32c6
package runtime
func exit(code int) {
abort()
}
-39
View File
@@ -1,39 +0,0 @@
//go:build baremetal || js || wasip1 || wasip2 || wasm_unknown || nintendoswitch
// Copyright 2009 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 syscall
// Statfs_t and Fsid have been copied from the Go source tree
// (syscall/ztypes_linux_amd64.go).
type Statfs_t struct {
Type int64
Bsize int64
Blocks uint64
Bfree uint64
Bavail uint64
Files uint64
Ffree uint64
Fsid Fsid
Namelen int64
Frsize int64
Flags int64
Spare [4]int64
}
type Fsid struct {
X__val [2]int32
}
// This is a stub, it is not functional.
func Statfs(path string, buf *Statfs_t) (err error) {
return ENOSYS
}
// This is a stub, it is not functional.
func Fstatfs(fd int, buf *Statfs_t) (err error) {
return ENOSYS
}
-5
View File
@@ -1,5 +0,0 @@
{
"inherits": ["esp32-generic"],
"build-tags": ["qemu"],
"emulator": "qemu-system-xtensa -machine esp32 -nographic -semihosting -drive file={img},if=mtd,format=raw"
}
+1
View File
@@ -25,5 +25,6 @@
], ],
"binary-format": "esp32", "binary-format": "esp32",
"flash-method": "esp32flash", "flash-method": "esp32flash",
"emulator": "qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw",
"gdb": ["xtensa-esp32-elf-gdb"] "gdb": ["xtensa-esp32-elf-gdb"]
} }
+3 -55
View File
@@ -299,26 +299,13 @@ _handle_kernel_exc:
.global _handle_level1 .global _handle_level1
_handle_level1: _handle_level1:
// EXCCAUSE 5 (AllocaCause) is a MOVSP window-spill request, not a fault, so // --- allocate 96-byte exception frame on the interrupted stack ---
// it is checked before any state is touched: a0 is still in EXCSAVE1.
// Xtensa ISA Reference Manual, Table 4-64 "Exception Causes".
rsr a0, EXCCAUSE
bnei a0, 5, 1f
j _xt_alloca_exc
1:
rsr a0, EXCSAVE1 // restore a0 clobbered by the EXCCAUSE read
// --- allocate the exception frame on the interrupted stack ---
// Layout (offsets from a1 after adjustment): // Layout (offsets from a1 after adjustment):
// 0: a0 4: a1(orig) 8: a2 12: a3 16: a4 20: a5 // 0: a0 4: a1(orig) 8: a2 12: a3 16: a4 20: a5
// 24: a6 28: a7 32: a8 36: a9 40: a10 44: a11 // 24: a6 28: a7 32: a8 36: a9 40: a10 44: a11
// 48: a12 52: a13 56: a14 60: a15 // 48: a12 52: a13 56: a14 60: a15
// 64: SAR 68: EPC1 72: PS 76: WINDOWBASE 80: WINDOWSTART // 64: SAR 68: EPC1 72: PS
// addi a0, a1, -96 // a0 = new frame pointer
// 128, not the 84 the layout needs: the low 16 bytes are the interruptee's
// windowed-ABI base save area, as in ESP-IDF's XT_STK_FRMSZ (+0x20).
// https://github.com/espressif/esp-idf/blob/master/components/xtensa/include/xtensa_context.h
addi a0, a1, -128 // a0 = new frame pointer
s32i a1, a0, 4 // save original a1 (SP) s32i a1, a0, 4 // save original a1 (SP)
mov a1, a0 // a1 = frame pointer mov a1, a0 // a1 = frame pointer
@@ -352,14 +339,6 @@ _handle_level1:
// level-1 interrupts. // level-1 interrupts.
rsr a2, PS rsr a2, PS
s32i a2, a1, 72 // save PS (with EXCM=1 set by hardware) s32i a2, a1, 72 // save PS (with EXCM=1 set by hardware)
// Captured here, not in the C handler: getting there costs a callx4 and the
// printfs rotate and spill windows, so they would report their own state.
rsr a3, WINDOWBASE
s32i a3, a1, 76
rsr a3, WINDOWSTART
s32i a3, a1, 80
movi a3, ~0x1F // mask: clear INTLEVEL (bits 0-3) + EXCM (bit 4) movi a3, ~0x1F // mask: clear INTLEVEL (bits 0-3) + EXCM (bit 4)
and a2, a2, a3 and a2, a2, a3
movi a3, 1 // INTLEVEL = 1 movi a3, 1 // INTLEVEL = 1
@@ -433,37 +412,6 @@ _handle_level1:
rfe rfe
// Alloca (MOVSP) exception: rotate back to the MOVSP window, fix PS.OWB, then
// fall into the matching window underflow handler, which spills and rfwu's back.
// Ported from ESP-IDF _xt_alloca_exc:
// https://github.com/espressif/esp-idf/blob/master/components/xtensa/xtensa_vectors.S
.balign 4
.global _xt_alloca_exc
_xt_alloca_exc:
rsr a0, WINDOWBASE // grab WINDOWBASE before rotw changes it
rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch
rsr a2, PS
extui a3, a2, 8, 4 // a3 = PS.OWB (shift 8, 4 bits)
xor a3, a3, a4 // bits that changed from old to current WB
rsr a4, EXCSAVE1 // restore the interruptee's a0 (now in a4)
slli a3, a3, 8
xor a2, a2, a3 // flip those bits in PS.OWB
wsr a2, PS // PS.OWB now matches the new WINDOWBASE
rsync
// Dispatch on the call size in bits 31:30 of the interruptee's a0; plain `j`
// because _bbci.l's 8-bit range cannot reach the underflow vectors.
// Xtensa ISA Reference Manual, RETW, section 8.3.253, p.565 (a0 encoding).
_bbsi.l a4, 31, 1f
j _window_underflow4
1:
rotw -1 // interruptee's a0 moves to a8
_bbsi.l a8, 30, 2f
j _window_underflow8
2:
rotw -1
j _window_underflow12
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Default weak espradio_user_exception: infinite loop halt. // Default weak espradio_user_exception: infinite loop halt.
// Overridden by the strong definition in espradio's isr.c when linked. // Overridden by the strong definition in espradio's isr.c when linked.
+1
View File
@@ -25,5 +25,6 @@
], ],
"binary-format": "esp32s3", "binary-format": "esp32s3",
"flash-method": "esp32jtag", "flash-method": "esp32jtag",
"emulator": "qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw",
"gdb": ["xtensa-esp32-elf-gdb"] "gdb": ["xtensa-esp32-elf-gdb"]
} }
+3 -1011
View File
File diff suppressed because it is too large Load Diff
+24 -29
View File
@@ -76,7 +76,7 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:] actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]
if *update { if *update {
err := os.WriteFile(pathPrefix+".out.ll", []byte(normalizeIR(actual)), 0666) err := os.WriteFile(pathPrefix+".out.ll", []byte(actual), 0666)
if err != nil { if err != nil {
t.Error("failed to write out new output:", err) t.Error("failed to write out new output:", err)
} }
@@ -100,8 +100,28 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
// equal. That means, only relevant lines are compared (excluding comments // equal. That means, only relevant lines are compared (excluding comments
// etc.). // etc.).
func fuzzyEqualIR(s1, s2 string) bool { func fuzzyEqualIR(s1, s2 string) bool {
s1 = normalizeIR(s1) // Golden files are written using the pre-LLVM21 'nocapture' spelling,
s2 = normalizeIR(s2) // which LLVM printed before any co-occurring attribute such as
// 'readonly' (e.g. "ptr nocapture readonly"). LLVM 21+ prints the
// equivalent 'captures(none)' instead, and after such attributes (e.g.
// "ptr readonly captures(none)"). Normalize both name and position back
// to the old spelling to keep a single golden file working across LLVM
// versions.
s1 = normalizeCapturesAttr(s1)
s2 = normalizeCapturesAttr(s2)
// LLVM 21+ also added an explicit 'nocreateundeforpoison' attribute to
// certain intrinsic declarations (e.g. llvm.umin) that were implicitly
// assumed not to create undef/poison before. It's unrelated to the
// escape-analysis behavior under test, so ignore it for comparison.
s1 = strings.ReplaceAll(s1, "nocreateundeforpoison ", "")
s2 = strings.ReplaceAll(s2, "nocreateundeforpoison ", "")
// LLVM 22 dropped the (redundant) i64 size argument from
// llvm.lifetime.start/end. Normalize away that argument so golden files
// written against the two-argument form still match.
s1 = lifetimeSizeArgRe.ReplaceAllString(s1, "$1")
s2 = lifetimeSizeArgRe.ReplaceAllString(s2, "$1")
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n")) lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n")) lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
@@ -118,29 +138,6 @@ func fuzzyEqualIR(s1, s2 string) bool {
return true return true
} }
func normalizeIR(s string) string {
// Golden files are written using the pre-LLVM21 'nocapture' spelling,
// which LLVM printed before any co-occurring attribute such as
// 'readonly' (e.g. "ptr nocapture readonly"). LLVM 21+ prints the
// equivalent 'captures(none)' instead, and after such attributes (e.g.
// "ptr readonly captures(none)"). Normalize both name and position back
// to the old spelling.
s = normalizeCapturesAttr(s)
// LLVM 21+ also added an explicit 'nocreateundeforpoison' attribute to
// certain intrinsic declarations (e.g. llvm.umin) that were implicitly
// assumed not to create undef/poison before. It's unrelated to the
// escape-analysis behavior under test, so ignore it for comparison.
s = strings.ReplaceAll(s, "nocreateundeforpoison ", "")
// LLVM 22 dropped the (redundant) i64 size argument from
// llvm.lifetime.start/end. Normalize away that argument so golden files
// written against the two-argument form still match.
s = lifetimeSizeArgRe.ReplaceAllString(s, "$1")
return s
}
// capturesNoneAttrRe matches a co-occurring attribute directly followed by // capturesNoneAttrRe matches a co-occurring attribute directly followed by
// 'captures(none)', which is how LLVM 21+ orders these two attributes when // 'captures(none)', which is how LLVM 21+ orders these two attributes when
// printing IR (the pre-LLVM21 'nocapture' attribute printed the other way // printing IR (the pre-LLVM21 'nocapture' attribute printed the other way
@@ -224,9 +221,7 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module {
// Compile AST to IR. // Compile AST to IR.
program := lprogram.LoadSSA() program := lprogram.LoadSSA()
pkg := lprogram.MainPkg() pkg := lprogram.MainPkg()
ssaPkg := program.Package(pkg.Pkg) mod, errs := compiler.CompilePackage(filename, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
ssaPkg.Build()
mod, errs := compiler.CompilePackage(filename, pkg, ssaPkg, machine, compilerConfig, false)
if errs != nil { if errs != nil {
for _, err := range errs { for _, err := range errs {
t.Error(err) t.Error(err)