Skip to content

Commit 62cf491

Browse files
committed
all: pretend to be linux/arm in baremetal targets
So far, we've pretended to be js/wasm in baremetal targets to make the stdlib happy. Unfortunately, this has various problems because syscall/js (a dependency of many stdlib packages) thinks it can do JS calls, and emulating them gets quite hard with all changes to the syscall/js packages in Go 1.12. This commit does a few things: * It lets baremetal targets pretend to be linux/arm instead of js/wasm. * It lets the loader only select particular packages from the src overlay, instead of inserting them just before GOROOT. This makes it possible to pick which packages to overlay for a given target. * It adds a baremetal-only syscall package that stubs out almost all syscalls.
1 parent 792274e commit 62cf491

17 files changed

+723
-57
lines changed

compiler/compiler.go

+32-5
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ func (c *Compiler) selectGC() string {
162162
func (c *Compiler) Compile(mainPath string) error {
163163
// Prefix the GOPATH with the system GOROOT, as GOROOT is already set to
164164
// the TinyGo root.
165-
gopath := c.GOPATH
166-
if gopath == "" {
167-
gopath = runtime.GOROOT()
165+
overlayGopath := c.GOPATH
166+
if overlayGopath == "" {
167+
overlayGopath = runtime.GOROOT()
168168
} else {
169-
gopath = runtime.GOROOT() + string(filepath.ListSeparator) + gopath
169+
overlayGopath = runtime.GOROOT() + string(filepath.ListSeparator) + overlayGopath
170170
}
171171

172172
wd, err := os.Getwd()
@@ -175,15 +175,42 @@ func (c *Compiler) Compile(mainPath string) error {
175175
}
176176
lprogram := &loader.Program{
177177
Build: &build.Context{
178+
GOARCH: c.GOARCH,
179+
GOOS: c.GOOS,
180+
GOROOT: runtime.GOROOT(),
181+
GOPATH: c.GOPATH,
182+
CgoEnabled: true,
183+
UseAllFiles: false,
184+
Compiler: "gc", // must be one of the recognized compilers
185+
BuildTags: append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...),
186+
},
187+
OverlayBuild: &build.Context{
178188
GOARCH: c.GOARCH,
179189
GOOS: c.GOOS,
180190
GOROOT: c.RootDir,
181-
GOPATH: gopath,
191+
GOPATH: overlayGopath,
182192
CgoEnabled: true,
183193
UseAllFiles: false,
184194
Compiler: "gc", // must be one of the recognized compilers
185195
BuildTags: append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...),
186196
},
197+
ShouldOverlay: func(path string) bool {
198+
switch path {
199+
case "machine", "os", "reflect", "runtime", "sync":
200+
return true
201+
default:
202+
if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") {
203+
return true
204+
} else if path == "syscall" {
205+
for _, tag := range c.BuildTags {
206+
if tag == "avr" || tag == "cortexm" {
207+
return true
208+
}
209+
}
210+
}
211+
}
212+
return false
213+
},
187214
TypeChecker: types.Config{
188215
Sizes: &StdSizes{
189216
IntSize: int64(c.targetData.TypeAllocSize(c.intType)),

loader/loader.go

+14-8
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import (
1414

1515
// Program holds all packages and some metadata about the program as a whole.
1616
type Program struct {
17-
Build *build.Context
18-
Packages map[string]*Package
19-
sorted []*Package
20-
fset *token.FileSet
21-
TypeChecker types.Config
22-
Dir string // current working directory (for error reporting)
23-
CFlags []string
17+
Build *build.Context
18+
OverlayBuild *build.Context
19+
ShouldOverlay func(path string) bool
20+
Packages map[string]*Package
21+
sorted []*Package
22+
fset *token.FileSet
23+
TypeChecker types.Config
24+
Dir string // current working directory (for error reporting)
25+
CFlags []string
2426
}
2527

2628
// Package holds a loaded package, its imports, and its parsed files.
@@ -42,7 +44,11 @@ func (p *Program) Import(path, srcDir string) (*Package, error) {
4244
}
4345

4446
// Load this package.
45-
buildPkg, err := p.Build.Import(path, srcDir, build.ImportComment)
47+
ctx := p.Build
48+
if p.ShouldOverlay(path) {
49+
ctx = p.OverlayBuild
50+
}
51+
buildPkg, err := ctx.Import(path, srcDir, build.ImportComment)
4652
if err != nil {
4753
return nil, err
4854
}

src/os/file_wasm.go renamed to src/os/file_other.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build wasm
1+
// +build avr cortexm wasm
22

33
package os
44

src/os/file_unix.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build darwin linux
1+
// +build darwin linux,!avr,!cortexm
22

33
package os
44

src/runtime/arch_arm.go

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build arm,!avr,!cortexm
2+
13
package runtime
24

35
const GOARCH = "arm"

src/runtime/arch_tinygoarm.go renamed to src/runtime/arch_cortexm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build tinygo.arm
1+
// +build cortexm
22

33
package runtime
44

src/runtime/arch_wasm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build wasm,!tinygo.arm,!avr
1+
// +build wasm
22

33
package runtime
44

src/runtime/override_js.go

-28
This file was deleted.

src/runtime/runtime_tinygoarm.go renamed to src/runtime/runtime_cortexm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build tinygo.arm
1+
// +build cortexm
22

33
package runtime
44

src/runtime/runtime_unix.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build darwin linux
1+
// +build darwin linux,!avr,!cortexm
22

33
package runtime
44

src/runtime/runtime_wasm.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build wasm,!tinygo.arm,!avr
1+
// +build wasm
22

33
package runtime
44

src/syscall/str.go

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2009 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package syscall
6+
7+
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
8+
if val < 0 {
9+
return "-" + uitoa(uint(-val))
10+
}
11+
return uitoa(uint(val))
12+
}
13+
14+
func uitoa(val uint) string {
15+
var buf [32]byte // big enough for int64
16+
i := len(buf) - 1
17+
for val >= 10 {
18+
buf[i] = byte(val%10 + '0')
19+
i--
20+
val /= 10
21+
}
22+
buf[i] = byte(val + '0')
23+
return string(buf[i:])
24+
}

src/syscall/syscall_baremetal.go

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package syscall
2+
3+
// Most code here has been copied from the Go sources:
4+
// https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go
5+
// It has the following copyright note:
6+
//
7+
// Copyright 2018 The Go Authors. All rights reserved.
8+
// Use of this source code is governed by a BSD-style
9+
// license that can be found in the LICENSE file.
10+
11+
// An Errno is an unsigned number describing an error condition.
12+
// It implements the error interface. The zero Errno is by convention
13+
// a non-error, so code to convert from Errno to error should use:
14+
// err = nil
15+
// if errno != 0 {
16+
// err = errno
17+
// }
18+
type Errno uintptr
19+
20+
func (e Errno) Error() string {
21+
if 0 <= int(e) && int(e) < len(errorstr) {
22+
s := errorstr[e]
23+
if s != "" {
24+
return s
25+
}
26+
}
27+
return "errno " + itoa(int(e))
28+
}
29+
30+
func (e Errno) Temporary() bool {
31+
return e == EINTR || e == EMFILE || e.Timeout()
32+
}
33+
34+
func (e Errno) Timeout() bool {
35+
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
36+
}
37+
38+
// A Signal is a number describing a process signal.
39+
// It implements the os.Signal interface.
40+
type Signal int
41+
42+
const (
43+
_ Signal = iota
44+
SIGCHLD
45+
SIGINT
46+
SIGKILL
47+
SIGTRAP
48+
SIGQUIT
49+
SIGTERM
50+
)
51+
52+
// File system
53+
54+
const (
55+
Stdin = 0
56+
Stdout = 1
57+
Stderr = 2
58+
)
59+
60+
const (
61+
O_RDONLY = 0
62+
O_WRONLY = 1
63+
O_RDWR = 2
64+
65+
O_CREAT = 0100
66+
O_CREATE = O_CREAT
67+
O_TRUNC = 01000
68+
O_APPEND = 02000
69+
O_EXCL = 0200
70+
O_SYNC = 010000
71+
72+
O_CLOEXEC = 0
73+
)
74+
75+
func Getenv(key string) (value string, found bool) {
76+
return "", false // stub
77+
}
78+
79+
func Open(path string, mode int, perm uint32) (fd int, err error) {
80+
return 0, ENOSYS
81+
}
82+
83+
func Read(fd int, p []byte) (n int, err error) {
84+
return 0, ENOSYS
85+
}
86+
87+
func Seek(fd int, offset int64, whence int) (off int64, err error) {
88+
return 0, ENOSYS
89+
}
90+
91+
func Close(fd int) (err error) {
92+
return ENOSYS
93+
}
94+
95+
// Processes
96+
97+
type WaitStatus uint32
98+
99+
func (w WaitStatus) Exited() bool { return false }
100+
func (w WaitStatus) ExitStatus() int { return 0 }
101+
func (w WaitStatus) Signaled() bool { return false }
102+
func (w WaitStatus) Signal() Signal { return 0 }
103+
func (w WaitStatus) CoreDump() bool { return false }
104+
func (w WaitStatus) Stopped() bool { return false }
105+
func (w WaitStatus) Continued() bool { return false }
106+
func (w WaitStatus) StopSignal() Signal { return 0 }
107+
func (w WaitStatus) TrapCause() int { return 0 }
108+
109+
// XXX made up
110+
type Rusage struct {
111+
Utime Timeval
112+
Stime Timeval
113+
}
114+
115+
// XXX made up
116+
type ProcAttr struct {
117+
Dir string
118+
Env []string
119+
Files []uintptr
120+
Sys *SysProcAttr
121+
}
122+
123+
type SysProcAttr struct {
124+
}
125+
126+
func Getegid() int { return 1 }
127+
func Geteuid() int { return 1 }
128+
func Getgid() int { return 1 }
129+
func Getgroups() ([]int, error) { return []int{1}, nil }
130+
func Getppid() int { return 2 }
131+
func Getpid() int { return 3 }
132+
func Gettimeofday(tv *Timeval) error { return ENOSYS }
133+
func Getuid() int { return 1 }
134+
func Kill(pid int, signum Signal) error { return ENOSYS }
135+
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
136+
return 0, ENOSYS
137+
}
138+
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
139+
return 0, 0, ENOSYS
140+
}
141+
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
142+
return 0, ENOSYS
143+
}
144+
145+
type Timeval struct {
146+
Sec int64
147+
Usec int64
148+
}

0 commit comments

Comments
 (0)