Compare commits

..

1 Commits

Author SHA1 Message Date
sago35 2a56d5e216 machine: add USBDevice.Attach and USBDevice.Detach
The USB device is attached to the bus automatically during startup,
before user code has a chance to finish its USB configuration (device
identifiers, extra HID interfaces, ...). Composite devices such as
keyboards may therefore be enumerated by the host with an incomplete
configuration.

Attach and Detach expose the soft-connect control (DP pull-up) so that
an application or library can detach in an init function, complete its
configuration, and attach again to let the host enumerate the finished
device. They can also be used to force re-enumeration without
replugging the cable.

Implemented for atsamd21, atsamd51, nrf52840, rp2040 and rp2350.
2026-07-28 22:03:38 +09:00
33 changed files with 184 additions and 284 deletions
+2 -2
View File
@@ -40,7 +40,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: '1.27.0-rc.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
cache: true
- name: Build TinyGo (LLVM ${{ matrix.version }})
run: go install -tags=llvm${{ matrix.version }}
+5 -5
View File
@@ -23,7 +23,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: '1.27.0-rc.3'
go-version: '1.27.0-rc.2'
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.27rc3-alpine
image: golang:1.27rc2-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.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
cache: true
- name: Restore LLVM source cache
uses: actions/cache/restore@v5
+4 -4
View File
@@ -34,7 +34,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: '1.27.0-rc.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
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.3'
go-version: '1.27.0-rc.2'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v8
+2 -2
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.27rc3 AS tinygo-llvm
FROM golang:1.27rc2 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.27rc3 AS tinygo-compiler
FROM golang:1.27rc2 AS tinygo-compiler
# Copy tinygo build.
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
+2 -23
View File
@@ -473,15 +473,9 @@ 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)
@@ -490,19 +484,6 @@ 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.$$$$))
@@ -529,7 +510,7 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
TEST_IOFS := false
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 known-working standard library packages.
@@ -538,8 +519,6 @@ 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
@@ -570,7 +549,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_WASIP2) ./tests/runtime_wasi
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi
tinygo-test-wasip2-sum-slow:
TINYGO=$(TINYGO) \
+2 -9
View File
@@ -24,7 +24,6 @@ import (
"sort"
"strconv"
"strings"
"sync"
"github.com/gofrs/flock"
"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
// 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.
@@ -400,13 +398,8 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
return nil
}
// 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.
// Compile AST to IR. The compiler.CompilePackage function will
// build the SSA as needed.
mod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())
defer mod.Context().Dispose()
defer mod.Dispose()
+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.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4321, 323, 0, 2268},
{"microbit", "examples/serial", 2842, 382, 8, 2264},
{"wioterminal", "examples/pininterrupt", 8039, 1665, 132, 7496},
{"hifive1b", "examples/echo", 4313, 323, 0, 2260},
{"microbit", "examples/serial", 2838, 382, 8, 2256},
{"wioterminal", "examples/pininterrupt", 8027, 1665, 132, 7488},
// TODO: also check wasm. Right now this is difficult, because
// 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.
//
// 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()
@@ -309,6 +306,9 @@ 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.
+5 -6
View File
@@ -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(normalizeIR(mod.String())), 0666)
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
if err != nil {
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
// and when regenerating golden files.
// 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.
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
@@ -413,7 +414,5 @@ func testCompilePackage(t *testing.T, options *compileopts.Options, file string)
// Compile AST to IR.
program := lprogram.LoadSSA()
pkg := lprogram.MainPkg()
ssaPkg := program.Package(pkg.Pkg)
ssaPkg.Build()
return CompilePackage(file, pkg, ssaPkg, machine, compilerConfig, false)
return CompilePackage(file, pkg, program.Package(pkg.Pkg), 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:
%chan.op = alloca %runtime.channelOp, align 8
%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
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 @llvm.lifetime.end.p0(ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value)
call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
ret void
}
; 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
; 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
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(ptr nonnull %chan.value)
call void @llvm.lifetime.start.p0(ptr nonnull %chan.op)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)
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
call void @llvm.lifetime.end.p0(ptr nonnull %chan.value)
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)
call void @llvm.lifetime.end.p0(i64 16, 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(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 @llvm.lifetime.end.p0(ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(i64 16, 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(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
call void @llvm.lifetime.end.p0(ptr nonnull %chan.op)
call void @llvm.lifetime.end.p0(i64 16, 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(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
%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(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
%2 = icmp eq i32 %1, 0
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: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
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 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
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 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
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 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
; 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
+18 -18
View File
@@ -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(ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(i64 12, 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(ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
%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
}
; 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
; 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
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(ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
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
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(ptr nonnull %hashmap.value)
call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(i64 4, 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(ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(ptr nonnull %hashmap.key)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(i64 24, 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(ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
%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
}
@@ -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(ptr nonnull %hashmap.value)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
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
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(ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(ptr nonnull %hashmap.value)
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)
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.
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)
+14
View File
@@ -68,6 +68,20 @@ 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.
+14
View File
@@ -71,6 +71,20 @@ 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.
-59
View File
@@ -112,11 +112,6 @@ 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.
@@ -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
// cpuInterruptFromPin selects an edge-triggered CPU interrupt line for GPIO.
+15
View File
@@ -89,6 +89,21 @@ 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)
+15
View File
@@ -46,6 +46,21 @@ 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()
+15
View File
@@ -49,6 +49,21 @@ 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()
-11
View File
@@ -163,17 +163,6 @@ 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
-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
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() }
+1 -10
View File
@@ -56,7 +56,6 @@ 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
)
@@ -511,7 +510,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)*bytesPerBlock + (bytesPerBlock - unsafe.Sizeof(objHeader{}))
oldSize := uintptr(lastBlock-firstBlock)*blocksPerStateByte + (bytesPerBlock - unsafe.Sizeof(objHeader{}))
if size <= oldSize {
// The requested size is less than the old size.
@@ -611,11 +610,6 @@ 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
}
@@ -856,9 +850,6 @@ func ReadMemStats(m *MemStats) {
// Record the total allocated bytes.
m.TotalAlloc = gcTotalAlloc
// Record the number of completed collection cycles.
m.NumGC = gcNumGC
gcLock.Unlock()
}
-1
View File
@@ -129,7 +129,6 @@ 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()
}
+1 -8
View File
@@ -47,14 +47,8 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
gcTotalAlloc += uint64(size)
gcMallocs++
heapptr += size
if heapptr < addr {
// The allocation size overflowed the heap pointer.
runtimePanic("out of memory")
}
for heapptr > heapEnd {
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
}
@@ -109,7 +103,6 @@ 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()
}
+7 -6
View File
@@ -43,12 +43,6 @@ 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() {
@@ -59,6 +53,13 @@ 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 {
+2 -2
View File
@@ -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 = (hash * 31) ^ hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)
hash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)
}
return hash
case reflectlite.Struct:
var hash uint32
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
default:
-5
View File
@@ -82,9 +82,4 @@ 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
}
-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
}
+1 -1
View File
@@ -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", "espradio"],
"build-tags": ["esp32", "esp"],
"scheduler": "tasks",
"serial": "uart",
"linker": "ld.lld",
+1 -2
View File
@@ -6,8 +6,7 @@
"features": "+32bit,+c,+m,+zmmul,-relax",
"build-tags": [
"esp32c3",
"esp",
"espradio"
"esp"
],
"serial": "usb",
"rtlib": "compiler-rt",
+1 -1
View File
@@ -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", "espradio"],
"build-tags": ["esp32s3", "esp"],
"scheduler": "tasks",
"serial": "usb",
"linker": "ld.lld",
+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:]
if *update {
err := os.WriteFile(pathPrefix+".out.ll", []byte(normalizeIR(actual)), 0666)
err := os.WriteFile(pathPrefix+".out.ll", []byte(actual), 0666)
if err != nil {
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
// etc.).
func fuzzyEqualIR(s1, s2 string) bool {
s1 = normalizeIR(s1)
s2 = normalizeIR(s2)
// 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")
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
@@ -118,29 +138,6 @@ 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
@@ -224,9 +221,7 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module {
// Compile AST to IR.
program := lprogram.LoadSSA()
pkg := lprogram.MainPkg()
ssaPkg := program.Package(pkg.Pkg)
ssaPkg.Build()
mod, errs := compiler.CompilePackage(filename, pkg, ssaPkg, machine, compilerConfig, false)
mod, errs := compiler.CompilePackage(filename, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
if errs != nil {
for _, err := range errs {
t.Error(err)