aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile16
-rw-r--r--builder/build.go9
-rw-r--r--builder/picolibc.go127
-rw-r--r--cgo/cgo.go5
-rw-r--r--compileopts/config.go6
-rw-r--r--compileopts/target.go4
m---------lib/picolibc0
-rw-r--r--lib/picolibc-include/picolibc.h0
-rw-r--r--main.go19
-rw-r--r--src/runtime/runtime_arm7tdmi.go14
-rw-r--r--src/runtime/runtime_cortexm.go20
-rw-r--r--src/runtime/runtime_tinygoriscv.go19
-rw-r--r--targets/cortex-m.json3
-rw-r--r--targets/gameboy-advance.json2
-rw-r--r--targets/riscv.json2
-rw-r--r--testdata/cgo/main.go7
-rw-r--r--testdata/cgo/out.txt1
18 files changed, 195 insertions, 62 deletions
diff --git a/.gitmodules b/.gitmodules
index 7e86215ef..af6e1809a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -17,3 +17,6 @@
[submodule "lib/wasi-libc"]
path = lib/wasi-libc
url = https://github.com/CraneStation/wasi-libc
+[submodule "lib/picolibc"]
+ path = lib/picolibc
+ url = https://github.com/keith-packard/picolibc.git
diff --git a/Makefile b/Makefile
index 6a18278c6..e16f225a8 100644
--- a/Makefile
+++ b/Makefile
@@ -312,6 +312,7 @@ release: tinygo gen-device wasi-libc
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
@mkdir -p build/release/tinygo/lib/nrfx
+ @mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
@mkdir -p build/release/tinygo/lib/wasi-libc
@mkdir -p build/release/tinygo/pkg/armv6m-none-eabi
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
@@ -325,10 +326,19 @@ release: tinygo gen-device wasi-libc
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
+ @cp -rp lib/picolibc/newlib/libc/ctype build/release/tinygo/lib/picolibc/newlib/libc
+ @cp -rp lib/picolibc/newlib/libc/include build/release/tinygo/lib/picolibc/newlib/libc
+ @cp -rp lib/picolibc/newlib/libc/locale build/release/tinygo/lib/picolibc/newlib/libc
+ @cp -rp lib/picolibc/newlib/libc/string build/release/tinygo/lib/picolibc/newlib/libc
+ @cp -rp lib/picolibc/newlib/libc/tinystdio build/release/tinygo/lib/picolibc/newlib/libc
+ @cp -rp lib/picolibc-include build/release/tinygo/lib
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
@cp -rp src build/release/tinygo/src
@cp -rp targets build/release/tinygo/targets
- ./build/tinygo build-builtins -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/compiler-rt.a
- ./build/tinygo build-builtins -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/compiler-rt.a
- ./build/tinygo build-builtins -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/compiler-rt.a
+ ./build/tinygo build-library -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/compiler-rt.a compiler-rt
+ ./build/tinygo build-library -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/compiler-rt.a compiler-rt
+ ./build/tinygo build-library -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/compiler-rt.a compiler-rt
+ ./build/tinygo build-library -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/picolibc.a picolibc
+ ./build/tinygo build-library -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/picolibc.a picolibc
+ ./build/tinygo build-library -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/picolibc.a picolibc
tar -czf build/release.tar.gz -C build/release tinygo
diff --git a/builder/build.go b/builder/build.go
index d3e9fcc7f..85a4dd515 100644
--- a/builder/build.go
+++ b/builder/build.go
@@ -145,6 +145,15 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
ldflags = append(ldflags, librt)
}
+ // Add libc.
+ if config.Target.Libc == "picolibc" {
+ libc, err := Picolibc.Load(config.Triple())
+ if err != nil {
+ return err
+ }
+ ldflags = append(ldflags, libc)
+ }
+
// Compile extra files.
root := goenv.Get("TINYGOROOT")
for i, path := range config.ExtraFiles() {
diff --git a/builder/picolibc.go b/builder/picolibc.go
new file mode 100644
index 000000000..31e2f0530
--- /dev/null
+++ b/builder/picolibc.go
@@ -0,0 +1,127 @@
+package builder
+
+import (
+ "path/filepath"
+
+ "github.com/tinygo-org/tinygo/goenv"
+)
+
+// Picolibc is a C library for bare metal embedded devices. It was originally
+// based on newlib.
+var Picolibc = Library{
+ name: "picolibc",
+ cflags: func() []string {
+ picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc")
+ return []string{"-Werror", "-Wall", "-std=gnu11", "-D_COMPILING_NEWLIB", "-fshort-enums", "--sysroot=" + picolibcDir, "-I" + picolibcDir + "/tinystdio", "-I" + goenv.Get("TINYGOROOT") + "/lib/picolibc-include"}
+ },
+ sourceDir: "lib/picolibc/newlib/libc",
+ sources: func(target string) []string {
+ return picolibcSources
+ },
+}
+
+var picolibcSources = []string{
+ "string/bcmp.c",
+ "string/bcopy.c",
+ "string/bzero.c",
+ "string/explicit_bzero.c",
+ "string/ffsl.c",
+ "string/ffsll.c",
+ "string/fls.c",
+ "string/flsl.c",
+ "string/flsll.c",
+ "string/gnu_basename.c",
+ "string/index.c",
+ "string/memccpy.c",
+ "string/memchr.c",
+ "string/memcmp.c",
+ "string/memcpy.c",
+ "string/memmem.c",
+ "string/memmove.c",
+ "string/mempcpy.c",
+ "string/memrchr.c",
+ "string/memset.c",
+ "string/rawmemchr.c",
+ "string/rindex.c",
+ "string/stpcpy.c",
+ "string/stpncpy.c",
+ "string/strcasecmp.c",
+ "string/strcasecmp_l.c",
+ "string/strcasestr.c",
+ "string/strcat.c",
+ "string/strchr.c",
+ "string/strchrnul.c",
+ "string/strcmp.c",
+ "string/strcoll.c",
+ "string/strcoll_l.c",
+ "string/strcpy.c",
+ "string/strcspn.c",
+ "string/strdup.c",
+ "string/strerror.c",
+ "string/strerror_r.c",
+ "string/strlcat.c",
+ "string/strlcpy.c",
+ "string/strlen.c",
+ "string/strlwr.c",
+ "string/strncasecmp.c",
+ "string/strncasecmp_l.c",
+ "string/strncat.c",
+ "string/strncmp.c",
+ "string/strncpy.c",
+ "string/strndup.c",
+ "string/strnlen.c",
+ "string/strnstr.c",
+ "string/strpbrk.c",
+ "string/strrchr.c",
+ "string/strsep.c",
+ "string/strsignal.c",
+ "string/strspn.c",
+ "string/strstr.c",
+ "string/strtok.c",
+ "string/strtok_r.c",
+ "string/strupr.c",
+ "string/strverscmp.c",
+ "string/strxfrm.c",
+ "string/strxfrm_l.c",
+ "string/swab.c",
+ "string/timingsafe_bcmp.c",
+ "string/timingsafe_memcmp.c",
+ "string/u_strerr.c",
+ "string/wcpcpy.c",
+ "string/wcpncpy.c",
+ "string/wcscasecmp.c",
+ "string/wcscasecmp_l.c",
+ "string/wcscat.c",
+ "string/wcschr.c",
+ "string/wcscmp.c",
+ "string/wcscoll.c",
+ "string/wcscoll_l.c",
+ "string/wcscpy.c",
+ "string/wcscspn.c",
+ "string/wcsdup.c",
+ "string/wcslcat.c",
+ "string/wcslcpy.c",
+ "string/wcslen.c",
+ "string/wcsncasecmp.c",
+ "string/wcsncasecmp_l.c",
+ "string/wcsncat.c",
+ "string/wcsncmp.c",
+ "string/wcsncpy.c",
+ "string/wcsnlen.c",
+ "string/wcspbrk.c",
+ "string/wcsrchr.c",
+ "string/wcsspn.c",
+ "string/wcsstr.c",
+ "string/wcstok.c",
+ "string/wcswidth.c",
+ "string/wcsxfrm.c",
+ "string/wcsxfrm_l.c",
+ "string/wcwidth.c",
+ "string/wmemchr.c",
+ "string/wmemcmp.c",
+ "string/wmemcpy.c",
+ "string/wmemmove.c",
+ "string/wmempcpy.c",
+ "string/wmemset.c",
+ "string/xpg_strerror_r.c",
+}
diff --git a/cgo/cgo.go b/cgo/cgo.go
index 58aaed81c..d6470a522 100644
--- a/cgo/cgo.go
+++ b/cgo/cgo.go
@@ -170,6 +170,11 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
enums: map[string]enumInfo{},
}
+ // Disable _FORTIFY_SOURCE as it causes problems on macOS.
+ // Note that it is only disabled for memcpy (etc) calls made from Go, which
+ // have better alternatives anyway.
+ cflags = append(cflags, "-D_FORTIFY_SOURCE=0")
+
// Add a new location for the following file.
generatedTokenPos := p.fset.AddFile(dir+"/!cgo.go", -1, 0)
generatedTokenPos.SetLines([]int{0})
diff --git a/compileopts/config.go b/compileopts/config.go
index d3f4bd1d0..e30679080 100644
--- a/compileopts/config.go
+++ b/compileopts/config.go
@@ -5,6 +5,7 @@ package compileopts
import (
"errors"
"fmt"
+ "path/filepath"
"regexp"
"strconv"
"strings"
@@ -163,6 +164,11 @@ func (c *Config) CFlags() []string {
for _, flag := range c.Target.CFlags {
cflags = append(cflags, strings.Replace(flag, "{root}", goenv.Get("TINYGOROOT"), -1))
}
+ if c.Target.Libc == "picolibc" {
+ root := goenv.Get("TINYGOROOT")
+ cflags = append(cflags, "--sysroot="+filepath.Join(root, "lib", "picolibc", "newlib", "libc"))
+ cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
+ }
return cflags
}
diff --git a/compileopts/target.go b/compileopts/target.go
index 637712c83..2071c73a5 100644
--- a/compileopts/target.go
+++ b/compileopts/target.go
@@ -32,6 +32,7 @@ type TargetSpec struct {
Compiler string `json:"compiler"`
Linker string `json:"linker"`
RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt)
+ Libc string `json:"libc"`
CFlags []string `json:"cflags"`
LDFlags []string `json:"ldflags"`
LinkerScript string `json:"linkerscript"`
@@ -84,6 +85,9 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
if spec2.RTLib != "" {
spec.RTLib = spec2.RTLib
}
+ if spec2.Libc != "" {
+ spec.Libc = spec2.Libc
+ }
spec.CFlags = append(spec.CFlags, spec2.CFlags...)
spec.LDFlags = append(spec.LDFlags, spec2.LDFlags...)
if spec2.LinkerScript != "" {
diff --git a/lib/picolibc b/lib/picolibc
new file mode 160000
+Subproject 80528c684b10aaee977397e7eb40c4784e6dc43
diff --git a/lib/picolibc-include/picolibc.h b/lib/picolibc-include/picolibc.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/lib/picolibc-include/picolibc.h
diff --git a/main.go b/main.go
index c21b1377b..d4361d13b 100644
--- a/main.go
+++ b/main.go
@@ -786,7 +786,7 @@ func main() {
}
err := Build(pkgName, *outpath, options)
handleCompilerError(err)
- case "build-builtins":
+ case "build-library":
// Note: this command is only meant to be used while making a release!
if *outpath == "" {
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
@@ -796,7 +796,22 @@ func main() {
if *target == "" {
fmt.Fprintln(os.Stderr, "No target (-target).")
}
- path, err := builder.CompilerRT.Load(*target)
+ if flag.NArg() != 1 {
+ fmt.Fprintf(os.Stderr, "Build-library only accepts exactly one library name as argument, %d given\n", flag.NArg())
+ usage()
+ os.Exit(1)
+ }
+ var lib *builder.Library
+ switch name := flag.Arg(0); name {
+ case "compiler-rt":
+ lib = &builder.CompilerRT
+ case "picolibc":
+ lib = &builder.Picolibc
+ default:
+ fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
+ os.Exit(1)
+ }
+ path, err := lib.Load(*target)
handleCompilerError(err)
copyFile(path, *outpath)
case "flash", "gdb":
diff --git a/src/runtime/runtime_arm7tdmi.go b/src/runtime/runtime_arm7tdmi.go
index d7629ad6d..b292f6468 100644
--- a/src/runtime/runtime_arm7tdmi.go
+++ b/src/runtime/runtime_arm7tdmi.go
@@ -76,17 +76,3 @@ func abort() {
for {
}
}
-
-// Implement memset for LLVM and compiler-rt.
-//go:export memset
-func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
- for i := uintptr(0); i < size; i++ {
- *(*byte)(unsafe.Pointer(uintptr(ptr) + i)) = c
- }
-}
-
-// Implement memmove for LLVM and compiler-rt.
-//go:export memmove
-func libc_memmove(dst, src unsafe.Pointer, size uintptr) {
- memmove(dst, src, size)
-}
diff --git a/src/runtime/runtime_cortexm.go b/src/runtime/runtime_cortexm.go
index 04b34039a..46f836770 100644
--- a/src/runtime/runtime_cortexm.go
+++ b/src/runtime/runtime_cortexm.go
@@ -95,23 +95,3 @@ func handleHardFault(sp *interruptStack) {
println()
abort()
}
-
-// Implement memset for LLVM and compiler-rt.
-//go:export memset
-func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
- for i := uintptr(0); i < size; i++ {
- *(*byte)(unsafe.Pointer(uintptr(ptr) + i)) = c
- }
-}
-
-// Implement memmove for LLVM and compiler-rt.
-//go:export memmove
-func libc_memmove(dst, src unsafe.Pointer, size uintptr) {
- memmove(dst, src, size)
-}
-
-// Implement memcpy for LLVM and compiler-rt.
-//go:export memcpy
-func libc_memcpy(dst, src unsafe.Pointer, size uintptr) {
- memcpy(dst, src, size)
-}
diff --git a/src/runtime/runtime_tinygoriscv.go b/src/runtime/runtime_tinygoriscv.go
deleted file mode 100644
index 691680b44..000000000
--- a/src/runtime/runtime_tinygoriscv.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build tinygo.riscv
-
-package runtime
-
-import "unsafe"
-
-// Implement memset for LLVM.
-//go:export memset
-func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
- for i := uintptr(0); i < size; i++ {
- *(*byte)(unsafe.Pointer(uintptr(ptr) + i)) = c
- }
-}
-
-// Implement memmove for LLVM.
-//go:export memmove
-func libc_memmove(dst, src unsafe.Pointer, size uintptr) {
- memmove(dst, src, size)
-}
diff --git a/targets/cortex-m.json b/targets/cortex-m.json
index 513a84634..979c09d1f 100644
--- a/targets/cortex-m.json
+++ b/targets/cortex-m.json
@@ -7,13 +7,12 @@
"scheduler": "tasks",
"linker": "ld.lld",
"rtlib": "compiler-rt",
+ "libc": "picolibc",
"cflags": [
"-Oz",
"-mthumb",
"-Werror",
"-fshort-enums",
- "-nostdlibinc",
- "-Wno-macro-redefined",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
diff --git a/targets/gameboy-advance.json b/targets/gameboy-advance.json
index 2ef4f8d1f..f7ac76ebb 100644
--- a/targets/gameboy-advance.json
+++ b/targets/gameboy-advance.json
@@ -7,6 +7,7 @@
"compiler": "clang",
"linker": "ld.lld",
"rtlib": "compiler-rt",
+ "libc": "picolibc",
"cflags": [
"-g",
"--target=thumb4-none-eabi",
@@ -14,7 +15,6 @@
"-Oz",
"-Werror",
"-fshort-enums",
- "-Wno-macro-redefined",
"-Qunused-arguments",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections"
diff --git a/targets/riscv.json b/targets/riscv.json
index f96354008..f74c1767d 100644
--- a/targets/riscv.json
+++ b/targets/riscv.json
@@ -7,13 +7,13 @@
"compiler": "clang",
"linker": "ld.lld",
"rtlib": "compiler-rt",
+ "libc": "picolibc",
"cflags": [
"--target=riscv32--none",
"-march=rv32imac",
"-mabi=ilp32",
"-Os",
"-Werror",
- "-nostdinc",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
diff --git a/testdata/cgo/main.go b/testdata/cgo/main.go
index 41bc6892c..557dea5cf 100644
--- a/testdata/cgo/main.go
+++ b/testdata/cgo/main.go
@@ -4,6 +4,7 @@ package main
int fortytwo(void);
#include "main.h"
int mul(int, int);
+#include <string.h>
*/
import "C"
@@ -109,6 +110,12 @@ func main() {
var _ C.option3_t = C.option3A
println("option 2A:", C.option2A)
println("option 3A:", C.option3A)
+
+ // libc: test whether C functions work at all.
+ buf1 := []byte("foobar\x00")
+ buf2 := make([]byte, len(buf1))
+ C.strcpy((*C.char)(unsafe.Pointer(&buf2[0])), (*C.char)(unsafe.Pointer(&buf1[0])))
+ println("copied string:", string(buf2[:C.strlen((*C.char)(unsafe.Pointer(&buf2[0])))]))
}
func printUnion(union C.joined_t) C.joined_t {
diff --git a/testdata/cgo/out.txt b/testdata/cgo/out.txt
index 73cb2b990..fcb688467 100644
--- a/testdata/cgo/out.txt
+++ b/testdata/cgo/out.txt
@@ -55,3 +55,4 @@ option F: 11
option G: 12
option 2A: 20
option 3A: 21
+copied string: foobar