mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-19 12:04:03 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8716e5699a | |||
| ef5c7ccee9 | |||
| 7262fee17b | |||
| ac45c35924 | |||
| 338af91ae6 | |||
| d74f70bdd0 | |||
| 80506a9cea | |||
| c33682cf00 | |||
| 570a3deac2 | |||
| c4219439eb | |||
| 7a9c649268 | |||
| 213d10838f | |||
| b573ef3813 | |||
| 854f91ecf2 | |||
| c2346570fb |
@@ -40,7 +40,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Restore LLVM source cache
|
||||
uses: actions/cache/restore@v5
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||
run: go install -tags=llvm${{ matrix.version }}
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Run go mod tidy
|
||||
run: go mod tidy
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
# statically linked binary.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: golang:1.27rc2-alpine
|
||||
image: golang:1.27rc3-alpine
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
@@ -160,7 +160,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Install wasmtime
|
||||
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||
@@ -204,7 +204,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
@@ -323,7 +323,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Restore LLVM source cache
|
||||
uses: actions/cache/restore@v5
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Restore cached LLVM source
|
||||
uses: actions/cache/restore@v5
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Download TinyGo build
|
||||
uses: actions/download-artifact@v8
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Download TinyGo build
|
||||
uses: actions/download-artifact@v8
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '1.27.0-rc.2'
|
||||
go-version: '1.27.0-rc.3'
|
||||
cache: true
|
||||
- name: Download TinyGo build
|
||||
uses: actions/download-artifact@v8
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||
FROM golang:1.27rc2 AS tinygo-llvm
|
||||
FROM golang:1.27rc3 AS tinygo-llvm
|
||||
|
||||
RUN apt-get update && \
|
||||
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
|
||||
# all the build tools etc).
|
||||
FROM golang:1.27rc2 AS tinygo-compiler
|
||||
FROM golang:1.27rc3 AS tinygo-compiler
|
||||
|
||||
# Copy tinygo build.
|
||||
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
||||
|
||||
+23
-2
@@ -473,9 +473,15 @@ TEST_PACKAGES_NONWASM = \
|
||||
# (just like wasm).
|
||||
# * picolibc math functions apparently are less precise, the math package
|
||||
# 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_NONBAREMETAL = \
|
||||
$(TEST_PACKAGES_NONWASM) \
|
||||
$(TEST_PACKAGES_NOBOUNDARYSLICES) \
|
||||
math \
|
||||
$(nil)
|
||||
|
||||
@@ -484,6 +490,19 @@ TEST_PACKAGES_NOWASI = \
|
||||
crypto/ecdsa \
|
||||
$(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-stdlib-tests-pass:
|
||||
$(eval jointmp := $(shell echo /tmp/join.$$$$))
|
||||
@@ -510,7 +529,7 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||
TEST_IOFS := false
|
||||
endif
|
||||
|
||||
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic|TestAsValidation'
|
||||
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic|TestAsValidation|TestUnmarshalNestingLimitSlice|TestUnmarshalNestingLimitStruct'
|
||||
TEST_ADDITIONAL_FLAGS ?=
|
||||
|
||||
# Test known-working standard library packages.
|
||||
@@ -519,6 +538,8 @@ TEST_ADDITIONAL_FLAGS ?=
|
||||
tinygo-test:
|
||||
@# 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.
|
||||
@# 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)
|
||||
ifeq ($(TEST_ENCODING_XML),true)
|
||||
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) -stack-size=16MB encoding/xml
|
||||
@@ -549,7 +570,7 @@ tinygo-test-wasip1-fast:
|
||||
tinygo-test-wasip2-slow:
|
||||
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-test-wasip2-fast:
|
||||
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi
|
||||
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASIP2) ./tests/runtime_wasi
|
||||
|
||||
tinygo-test-wasip2-sum-slow:
|
||||
TINYGO=$(TINYGO) \
|
||||
|
||||
+9
-2
@@ -24,6 +24,7 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gofrs/flock"
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
@@ -269,6 +270,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
// 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 := lprogram.LoadSSA()
|
||||
buildProgram := sync.OnceFunc(program.Build)
|
||||
|
||||
// Add jobs to compile each package.
|
||||
// Packages that have a cache hit will not be compiled again.
|
||||
@@ -398,8 +400,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile AST to IR. The compiler.CompilePackage function will
|
||||
// build the SSA as needed.
|
||||
// SSA package builds may run concurrently, but the resulting
|
||||
// functions cannot be inspected until all builds have finished:
|
||||
// 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())
|
||||
defer mod.Context().Dispose()
|
||||
defer mod.Dispose()
|
||||
|
||||
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
|
||||
// This is a small number of very diverse targets that we want to test.
|
||||
tests := []sizeTest{
|
||||
// microcontrollers
|
||||
{"hifive1b", "examples/echo", 4313, 323, 0, 2260},
|
||||
{"microbit", "examples/serial", 2838, 382, 8, 2256},
|
||||
{"wioterminal", "examples/pininterrupt", 8027, 1665, 132, 7488},
|
||||
{"hifive1b", "examples/echo", 4321, 323, 0, 2268},
|
||||
{"microbit", "examples/serial", 2842, 382, 8, 2264},
|
||||
{"wioterminal", "examples/pininterrupt", 8039, 1665, 132, 7496},
|
||||
|
||||
// TODO: also check wasm. Right now this is difficult, because
|
||||
// wasm binaries are run through wasm-opt and therefore the
|
||||
|
||||
@@ -296,6 +296,9 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
c := newCompilerContext(moduleName, machine, config, dumpSSA)
|
||||
defer c.dispose()
|
||||
@@ -306,9 +309,6 @@ func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package,
|
||||
c.runtimePkg = ssaPkg.Prog.ImportedPackage("runtime").Pkg
|
||||
c.program = ssaPkg.Prog
|
||||
|
||||
// Convert AST to SSA.
|
||||
ssaPkg.Build()
|
||||
|
||||
// Assign names to function-local named types before compiling the
|
||||
// package, so that types declared in different functions (or in
|
||||
// different instantiations of a generic function) do not collide.
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestCompiler(t *testing.T) {
|
||||
|
||||
// Update test if needed. Do not check the result.
|
||||
if *flagUpdate {
|
||||
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
|
||||
err := os.WriteFile(outPath, []byte(normalizeIR(mod.String())), 0666)
|
||||
if err != nil {
|
||||
t.Error("failed to write updated output file:", err)
|
||||
}
|
||||
@@ -174,9 +174,8 @@ func TestOptimizedLargeAggregateABI(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeIR canonicalizes LLVM IR so a single golden file keeps matching
|
||||
// across LLVM versions. Golden files are written against LLVM <21; newer LLVM
|
||||
// prints some attributes differently.
|
||||
// normalizeIR canonicalizes LLVM-version-specific IR spellings for comparison
|
||||
// and when regenerating golden files.
|
||||
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
|
||||
@@ -414,5 +413,7 @@ func testCompilePackage(t *testing.T, options *compileopts.Options, file string)
|
||||
// Compile AST to IR.
|
||||
program := lprogram.LoadSSA()
|
||||
pkg := lprogram.MainPkg()
|
||||
return CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
|
||||
ssaPkg := program.Package(pkg.Pkg)
|
||||
ssaPkg.Build()
|
||||
return CompilePackage(file, pkg, ssaPkg, machine, compilerConfig, false)
|
||||
}
|
||||
|
||||
Vendored
+16
-16
@@ -19,33 +19,33 @@ define hidden void @main.chanIntSend(ptr dereferenceable_or_null(36) %ch, ptr %c
|
||||
entry:
|
||||
%chan.op = alloca %runtime.channelOp, align 8
|
||||
%chan.value = alloca i32, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value)
|
||||
store i32 3, ptr %chan.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||
call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
||||
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(ptr nonnull %chan.value)
|
||||
ret void
|
||||
}
|
||||
|
||||
; 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(ptr nocapture) #2
|
||||
|
||||
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)
|
||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
|
||||
declare void @llvm.lifetime.end.p0(ptr nocapture) #2
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%chan.op = alloca %runtime.channelOp, align 8
|
||||
%chan.value = alloca i32, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #3
|
||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
|
||||
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(ptr nonnull %chan.op)
|
||||
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 {
|
||||
entry:
|
||||
%chan.op = alloca %runtime.channelOp, align 8
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||
call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -65,9 +65,9 @@ entry:
|
||||
define hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%chan.op = alloca %runtime.channelOp, align 8
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
|
||||
%0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #3
|
||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ entry:
|
||||
%select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8
|
||||
%select.send.value = alloca i32, align 4
|
||||
store i32 1, ptr %select.send.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %select.states.alloca)
|
||||
store ptr %ch1, ptr %select.states.alloca, align 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
|
||||
@@ -86,7 +86,7 @@ entry:
|
||||
%.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12
|
||||
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
|
||||
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %select.states.alloca)
|
||||
%1 = extractvalue { i32, i1 } %select.result, 0
|
||||
%2 = icmp eq i32 %1, 0
|
||||
br i1 %2, label %select.done, label %select.next
|
||||
|
||||
Vendored
+5
-5
@@ -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: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 readonly captures(none), ptr, ptr) #0
|
||||
declare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(ptr %context) unnamed_addr #1 {
|
||||
@@ -31,7 +31,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
||||
declare void @llvm.memcpy.p0.p0.i32(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i32, i1 immarg) #2
|
||||
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2
|
||||
|
||||
; 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 {
|
||||
@@ -344,7 +344,7 @@ if.then: ; preds = %typeassert.next
|
||||
declare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #0
|
||||
|
||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
||||
declare void @llvm.memset.p0.i32(ptr writeonly captures(none), i8, i32, i1 immarg) #7
|
||||
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #7
|
||||
|
||||
; 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 {
|
||||
@@ -423,12 +423,12 @@ if.then: ; preds = %entry
|
||||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||
declare void @llvm.lifetime.start.p0(ptr captures(none)) #8
|
||||
declare void @llvm.lifetime.start.p0(ptr nocapture) #8
|
||||
|
||||
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)
|
||||
declare void @llvm.lifetime.end.p0(ptr captures(none)) #8
|
||||
declare void @llvm.lifetime.end.p0(ptr nocapture) #8
|
||||
|
||||
declare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #0
|
||||
|
||||
|
||||
Vendored
+18
-18
@@ -21,23 +21,23 @@ entry:
|
||||
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
||||
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
||||
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||
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
|
||||
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||
%4 = load i32, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||
ret i32 %4
|
||||
}
|
||||
|
||||
; 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(ptr nocapture) #3
|
||||
|
||||
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)
|
||||
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3
|
||||
declare void @llvm.lifetime.end.p0(ptr nocapture) #3
|
||||
|
||||
; 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 {
|
||||
@@ -47,13 +47,13 @@ entry:
|
||||
%0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0
|
||||
%1 = insertvalue %main.hasPadding %0, i32 %s.i, 1
|
||||
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||
store i32 5, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||
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 @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -64,17 +64,17 @@ define hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(48) %m, [2
|
||||
entry:
|
||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||
%hashmap.value = alloca i32, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||
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
|
||||
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||
%1 = load i32, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@@ -83,17 +83,17 @@ define hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(48) %m, [2
|
||||
entry:
|
||||
%hashmap.key = alloca [2 x %main.hasPadding], align 8
|
||||
%hashmap.value = alloca i32, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.value)
|
||||
store i32 5, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
|
||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||
%hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12
|
||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||
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 @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.key)
|
||||
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -177,8 +177,15 @@ func Build(pkgName, outpath string, config *compileopts.Config) error {
|
||||
// Pick a default output path based on the main directory.
|
||||
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 {
|
||||
// Moving failed. Do a file copy.
|
||||
inf, err := os.Open(result.Binary)
|
||||
|
||||
@@ -68,20 +68,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
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() {
|
||||
// Load Pad Calibration data from non-volatile memory
|
||||
// This requires registers that are not included in the SVD file.
|
||||
|
||||
@@ -71,20 +71,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
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() {
|
||||
// Load Pad Calibration data from non-volatile memory
|
||||
// This requires registers that are not included in the SVD file.
|
||||
|
||||
@@ -112,6 +112,11 @@ func (p Pin) configure(config PinConfig, signal uint32) {
|
||||
// Configure the pad with the given IO mux configuration.
|
||||
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 {
|
||||
case PinOutput:
|
||||
// Set the 'output enable' bit.
|
||||
@@ -293,6 +298,60 @@ 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
|
||||
|
||||
// cpuInterruptFromPin selects an edge-triggered CPU interrupt line for GPIO.
|
||||
|
||||
@@ -89,21 +89,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
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() {
|
||||
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() {
|
||||
nrf.USBD.USBPULLUP.Set(0)
|
||||
}
|
||||
|
||||
func handleUSBIRQ(interrupt.Interrupt) {
|
||||
if nrf.USBD.EVENTS_SOF.Get() == 1 {
|
||||
nrf.USBD.EVENTS_SOF.Set(0)
|
||||
|
||||
@@ -46,21 +46,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
rp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
status := rp.USBCTRL_REGS.INTS.Get()
|
||||
|
||||
|
||||
@@ -49,21 +49,6 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
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) {
|
||||
status := rp.USB.INTS.Get()
|
||||
|
||||
|
||||
@@ -163,6 +163,17 @@ func (f *File) Truncate(size int64) (err error) {
|
||||
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 {
|
||||
if f.handle == nil {
|
||||
return ErrClosed
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package os
|
||||
|
||||
import "syscall"
|
||||
|
||||
// Getpagesize returns the underlying system's memory page size.
|
||||
func Getpagesize() int { return syscall.Getpagesize() }
|
||||
@@ -6,11 +6,6 @@
|
||||
|
||||
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) IsDir() bool { return fs.Mode().IsDir() }
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ var (
|
||||
endBlock gcBlock // the block just past the end of the available space
|
||||
gcTotalAlloc uint64 // total number of bytes allocated
|
||||
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
|
||||
)
|
||||
|
||||
@@ -510,7 +511,7 @@ func realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||
lastBlock := firstBlock.findHead()
|
||||
|
||||
// Calculate the size of the original allocation body.
|
||||
oldSize := uintptr(lastBlock-firstBlock)*blocksPerStateByte + (bytesPerBlock - unsafe.Sizeof(objHeader{}))
|
||||
oldSize := uintptr(lastBlock-firstBlock)*bytesPerBlock + (bytesPerBlock - unsafe.Sizeof(objHeader{}))
|
||||
|
||||
if size <= oldSize {
|
||||
// The requested size is less than the old size.
|
||||
@@ -610,6 +611,11 @@ func runGC() (freeBytes uintptr) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -850,6 +856,9 @@ func ReadMemStats(m *MemStats) {
|
||||
// Record the total allocated bytes.
|
||||
m.TotalAlloc = gcTotalAlloc
|
||||
|
||||
// Record the number of completed collection cycles.
|
||||
m.NumGC = gcNumGC
|
||||
|
||||
gcLock.Unlock()
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ func ReadMemStats(m *MemStats) {
|
||||
m.Mallocs = 0 // not provided by bdwgc
|
||||
m.Frees = 0 // not provided by bdwgc
|
||||
m.Sys = uint64(gcMemStats.obtained_from_os_bytes)
|
||||
m.NumGC = uint32(gcMemStats.gc_no)
|
||||
|
||||
gcLock.Unlock()
|
||||
}
|
||||
|
||||
@@ -47,8 +47,14 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
||||
gcTotalAlloc += uint64(size)
|
||||
gcMallocs++
|
||||
heapptr += size
|
||||
for heapptr >= heapEnd {
|
||||
if heapptr < addr {
|
||||
// The allocation size overflowed the heap pointer.
|
||||
runtimePanic("out of memory")
|
||||
}
|
||||
for heapptr > heapEnd {
|
||||
// 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() {
|
||||
continue
|
||||
}
|
||||
@@ -103,6 +109,7 @@ func ReadMemStats(m *MemStats) {
|
||||
m.HeapAlloc = gcTotalAlloc
|
||||
m.HeapObjects = gcMallocs
|
||||
m.Alloc = m.HeapAlloc
|
||||
m.NumGC = 0 // this GC never collects, so no cycle ever completes
|
||||
|
||||
gcLock.Unlock()
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@ func gcMarkReachable() {
|
||||
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.
|
||||
scanCurrentStack()
|
||||
if !task.OnSystemStack() {
|
||||
@@ -53,13 +59,6 @@ func gcMarkReachable() {
|
||||
// Scan globals.
|
||||
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.
|
||||
for i := uint32(0); i < numCPU; i++ {
|
||||
if i == core {
|
||||
|
||||
@@ -807,13 +807,13 @@ func hashmapInterfaceHash(itf interface{}, seed uintptr) uint32 {
|
||||
case reflectlite.Array:
|
||||
var hash uint32
|
||||
for i := 0; i < x.Len(); i++ {
|
||||
hash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)
|
||||
hash = (hash * 31) ^ hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)
|
||||
}
|
||||
return hash
|
||||
case reflectlite.Struct:
|
||||
var hash uint32
|
||||
for i := 0; i < x.NumField(); i++ {
|
||||
hash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Field(i)), seed)
|
||||
hash = (hash * 31) ^ hashmapInterfaceHash(valueInterfaceUnsafe(x.Field(i)), seed)
|
||||
}
|
||||
return hash
|
||||
default:
|
||||
|
||||
@@ -82,4 +82,9 @@ type MemStats struct {
|
||||
|
||||
// GCSys is bytes of memory in garbage collection metadata.
|
||||
GCSys uint64
|
||||
|
||||
// NumGC is the number of completed GC cycles.
|
||||
//
|
||||
// The leaking collector never collects, so it always reports 0.
|
||||
NumGC uint32
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//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
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"inheritable-only": true,
|
||||
"cpu": "esp32",
|
||||
"features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+dfpaccel,+div32,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed",
|
||||
"build-tags": ["esp32", "esp"],
|
||||
"build-tags": ["esp32", "esp", "espradio"],
|
||||
"scheduler": "tasks",
|
||||
"serial": "uart",
|
||||
"linker": "ld.lld",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"features": "+32bit,+c,+m,+zmmul,-relax",
|
||||
"build-tags": [
|
||||
"esp32c3",
|
||||
"esp"
|
||||
"esp",
|
||||
"espradio"
|
||||
],
|
||||
"serial": "usb",
|
||||
"rtlib": "compiler-rt",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"inheritable-only": true,
|
||||
"cpu": "esp32s3",
|
||||
"features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+div32,+esp32s3,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed",
|
||||
"build-tags": ["esp32s3", "esp"],
|
||||
"build-tags": ["esp32s3", "esp", "espradio"],
|
||||
"scheduler": "tasks",
|
||||
"serial": "usb",
|
||||
"linker": "ld.lld",
|
||||
|
||||
+29
-24
@@ -76,7 +76,7 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
|
||||
actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:]
|
||||
|
||||
if *update {
|
||||
err := os.WriteFile(pathPrefix+".out.ll", []byte(actual), 0666)
|
||||
err := os.WriteFile(pathPrefix+".out.ll", []byte(normalizeIR(actual)), 0666)
|
||||
if err != nil {
|
||||
t.Error("failed to write out new output:", err)
|
||||
}
|
||||
@@ -100,28 +100,8 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu
|
||||
// equal. That means, only relevant lines are compared (excluding comments
|
||||
// etc.).
|
||||
func fuzzyEqualIR(s1, s2 string) bool {
|
||||
// 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 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")
|
||||
s1 = normalizeIR(s1)
|
||||
s2 = normalizeIR(s2)
|
||||
|
||||
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
|
||||
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
|
||||
@@ -138,6 +118,29 @@ func fuzzyEqualIR(s1, s2 string) bool {
|
||||
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
|
||||
// 'captures(none)', which is how LLVM 21+ orders these two attributes when
|
||||
// printing IR (the pre-LLVM21 'nocapture' attribute printed the other way
|
||||
@@ -221,7 +224,9 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module {
|
||||
// Compile AST to IR.
|
||||
program := lprogram.LoadSSA()
|
||||
pkg := lprogram.MainPkg()
|
||||
mod, errs := compiler.CompilePackage(filename, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
|
||||
ssaPkg := program.Package(pkg.Pkg)
|
||||
ssaPkg.Build()
|
||||
mod, errs := compiler.CompilePackage(filename, pkg, ssaPkg, machine, compilerConfig, false)
|
||||
if errs != nil {
|
||||
for _, err := range errs {
|
||||
t.Error(err)
|
||||
|
||||
Reference in New Issue
Block a user