libgo: add 32-bit RISC-V (RV32) support
authorMaciej W. Rozycki <macro@wdc.com>
Fri, 28 Aug 2020 15:05:56 +0000 (16:05 +0100)
committerIan Lance Taylor <iant@golang.org>
Thu, 1 Oct 2020 02:47:48 +0000 (19:47 -0700)
Add support for the 32-bit RISC-V (RV32) ISA matching the 64-bit RISC-V
(RV64) port except for async preemption added as a stub only.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/251179

23 files changed:
gcc/go/gofrontend/MERGE
libgo/configure
libgo/configure.ac
libgo/go/cmd/cgo/main.go
libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
libgo/go/cmd/internal/sys/arch.go
libgo/go/debug/elf/file.go
libgo/go/go/types/sizes.go
libgo/go/golang.org/x/sys/cpu/cpu_riscv.go [new file with mode: 0644]
libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
libgo/go/internal/bytealg/indexbyte_generic.go
libgo/go/internal/bytealg/indexbyte_native.go
libgo/go/internal/syscall/unix/sysnum_linux_generic.go
libgo/go/runtime/gcinfo_test.go
libgo/go/runtime/hash32.go
libgo/go/runtime/lfstack_32bit.go
libgo/go/runtime/mkpreempt.go
libgo/go/runtime/mpagealloc_32bit.go
libgo/go/syscall/endian_little.go
libgo/match.sh
libgo/misc/cgo/testcshared/testdata/libgo2/dup2.go
libgo/misc/cgo/testcshared/testdata/libgo2/dup3.go
libgo/testsuite/gotest

index 314ffd2efab74ab7635b14563cd918744da7fdb8..8d9fda54619d8243f238d8a20f3bd296c813cd00 100644 (file)
@@ -1,4 +1,4 @@
-9e55baf44ab63ba06af0b57038e7b3aab8216222
+c9c084bce713e258721e12041a351ec8ad33ad17
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 7be95718962488986f6b951717b2bab2da5fdfca..641d060ffac231b584b02db9ea6091a32f34e360 100755 (executable)
@@ -14226,8 +14226,21 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     ;;
-  riscv64-*-*)
-    GOARCH=riscv64
+  riscv*-*-*)
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if __riscv_xlen == 64
+#error 64-bit
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  GOARCH=riscv
+else
+  GOARCH=riscv64
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     ;;
   s390*-*-*)
     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
index abc58b87b532f25442375457ca3b850b75a7fbd4..f15f8d830bb272dd34f54af1a9df64e282d15df5 100644 (file)
@@ -342,8 +342,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
 [GOARCH=ppc64le],
 [GOARCH=ppc64])])
     ;;
-  riscv64-*-*)
-    GOARCH=riscv64
+  riscv*-*-*)
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#if __riscv_xlen == 64
+#error 64-bit
+#endif
+])],
+[GOARCH=riscv],
+[GOARCH=riscv64])
     ;;
   s390*-*-*)
     AC_COMPILE_IFELSE([AC_LANG_SOURCE([
index 80f35681d75f0dfcd91cf1781ff1d4f74c5167fd..6de6d69ce6c832d39502bd40400b41946adb4bcc 100644 (file)
@@ -184,6 +184,7 @@ var ptrSizeMap = map[string]int64{
        "ppc":         4,
        "ppc64":       8,
        "ppc64le":     8,
+       "riscv":       4,
        "riscv64":     8,
        "s390":        4,
        "s390x":       8,
@@ -210,6 +211,7 @@ var intSizeMap = map[string]int64{
        "ppc":         4,
        "ppc64":       8,
        "ppc64le":     8,
+       "riscv":       4,
        "riscv64":     8,
        "s390":        4,
        "s390x":       8,
index 46b0ef4200e0746776ea699d61db290ca2106756..3030ee924ffabe04bd9261294c31397b3f0a3573 100644 (file)
@@ -8,8 +8,9 @@
 # See: https://github.com/golang/go/issues/8912
 [linux] [ppc64] skip
 
-# External linking is not supported on linux/riscv64.
+# External linking is not supported on linux/riscv, linux/riscv64.
 # See: https://github.com/golang/go/issues/36739
+[linux] [riscv] skip
 [linux] [riscv64] skip
 
 cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c
index e8687363defc502c17cdb97660b7c4ac886d799d..60a3b3c8ecdc9ac5564f821557b56d68e54efdee 100644 (file)
@@ -19,6 +19,7 @@ const (
        MIPS
        MIPS64
        PPC64
+       RISCV
        RISCV64
        S390X
        Wasm
@@ -143,6 +144,15 @@ var ArchPPC64LE = &Arch{
        MinLC:     4,
 }
 
+var ArchRISCV = &Arch{
+       Name:      "riscv",
+       Family:    RISCV,
+       ByteOrder: binary.LittleEndian,
+       PtrSize:   4,
+       RegSize:   4,
+       MinLC:     4,
+}
+
 var ArchRISCV64 = &Arch{
        Name:      "riscv64",
        Family:    RISCV64,
@@ -181,6 +191,7 @@ var Archs = [...]*Arch{
        ArchMIPS64LE,
        ArchPPC64,
        ArchPPC64LE,
+       ArchRISCV,
        ArchRISCV64,
        ArchS390X,
        ArchWasm,
index b9a8b1e0cbb545de13b882d0171326aeb2d2b2b8..48178d480d76b1cd1b476d07744b32c0cb430a3c 100644 (file)
@@ -617,6 +617,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
                return f.applyRelocationsMIPS(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
                return f.applyRelocationsMIPS64(dst, rels)
+       case f.Class == ELFCLASS32 && f.Machine == EM_RISCV:
+               return f.applyRelocationsRISCV(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_RISCV:
                return f.applyRelocationsRISCV64(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_S390:
@@ -1008,6 +1010,47 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
        return nil
 }
 
+func (f *File) applyRelocationsRISCV(dst []byte, rels []byte) error {
+       // 12 is the size of Rela32.
+       if len(rels)%12 != 0 {
+               return errors.New("length of relocation section is not a multiple of 12")
+       }
+
+       symbols, _, err := f.getSymbols(SHT_SYMTAB)
+       if err != nil {
+               return err
+       }
+
+       b := bytes.NewReader(rels)
+       var rela Rela32
+
+       for b.Len() > 0 {
+               binary.Read(b, f.ByteOrder, &rela)
+               symNo := rela.Info >> 8
+               t := R_RISCV(rela.Info & 0xff)
+
+               if symNo == 0 || symNo > uint32(len(symbols)) {
+                       continue
+               }
+               sym := &symbols[symNo-1]
+               needed, val := relocSymbolTargetOK(sym)
+               if !needed {
+                       continue
+               }
+
+               switch t {
+               case R_RISCV_32:
+                       if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
+                               continue
+                       }
+                       val32 := uint32(val) + uint32(rela.Addend)
+                       f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
+               }
+       }
+
+       return nil
+}
+
 func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
        // 24 is the size of Rela64.
        if len(rels)%24 != 0 {
index 6ab6157b82df48749e67bc12157066b530e54cd2..4787b242cc02ac65d49a2349bc4394eaf7bb5b29 100644 (file)
@@ -167,6 +167,7 @@ var gcArchSizes = map[string]*StdSizes{
        "mips64le": {8, 8},
        "ppc64":    {8, 8},
        "ppc64le":  {8, 8},
+       "riscv":    {4, 4},
        "riscv64":  {8, 8},
        "s390x":    {8, 8},
        "sparc64":  {8, 8},
@@ -180,7 +181,8 @@ var gcArchSizes = map[string]*StdSizes{
 //
 // Supported architectures for compiler "gc":
 // "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",
-// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm".
+// "mips64", "mips64le", "ppc64", "ppc64le", "riscv", "riscv64",
+// "s390x", "sparc64", "wasm".
 func SizesFor(compiler, arch string) Sizes {
        var m map[string]*StdSizes
        switch compiler {
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_riscv.go b/libgo/go/golang.org/x/sys/cpu/cpu_riscv.go
new file mode 100644 (file)
index 0000000..891cb98
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2020 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.
+
+// +build riscv
+
+package cpu
index e6bfe71539183f813649652ef4225c56a55b65d9..0f521503ac6ada60f1fef3d6d046036f10401731 100644 (file)
@@ -87,6 +87,7 @@ var (
        asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true}
        asmArchPpc64    = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true}
        asmArchPpc64LE  = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true}
+       asmArchRISCV    = asmArch{name: "riscv", bigEndian: false, stack: "SP", lr: true}
        asmArchRISCV64  = asmArch{name: "riscv64", bigEndian: false, stack: "SP", lr: true}
        asmArchS390X    = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true}
        asmArchWasm     = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false}
@@ -102,6 +103,7 @@ var (
                &asmArchMips64LE,
                &asmArchPpc64,
                &asmArchPpc64LE,
+               &asmArchRISCV,
                &asmArchRISCV64,
                &asmArchS390X,
                &asmArchWasm,
index a863d814b6bf21063a14811fc80d949d6ad69a90..46325dd7f07273e4e41c4639dfe58522d4bd071f 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build ignore_for_gccgo
-// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv64,!wasm
+// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv,!riscv64,!wasm
 
 package bytealg
 
index 20da788fb86ea0f3833ae03534604c1e613397fa..c427e669bbd34cddc93d8b5dc020d9f721fd810c 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv64 wasm
+// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv riscv64 wasm
 
 package bytealg
 
index 3e00703679a41c464102d268f2b1af91bfa748d5..3d34fdb73e38e2dae6563d68572666a62d20ce27 100644 (file)
@@ -9,7 +9,7 @@ package unix
 
 // This file is named "generic" because at a certain point Linux started
 // standardizing on system call numbers across architectures. So far this
-// means only arm64, nios2 and riscv use the standard numbers.
+// means only arm64, nios2, riscv and riscv64 use the standard numbers.
 
 const (
        getrandomTrap     uintptr = 278
index ddbe5dd5feadd5bba698a8ef9e54a6c7970fef2d..c26f411153fe659bb3e056b757c8e14a35056ce9 100644 (file)
@@ -157,7 +157,7 @@ type BigStruct struct {
 
 func infoBigStruct() []byte {
        switch runtime.GOARCH {
-       case "386", "arm", "mips", "mipsle":
+       case "386", "arm", "mips", "mipsle", "riscv":
                return []byte{
                        typePointer,                                                // q *int
                        typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
index fba6bc354b14d0842e089354b05a9cf724d1a400..89efc1cde5c44cb8fbf3dd8d49fd9bd033955c99 100644 (file)
@@ -6,7 +6,7 @@
 //   xxhash: https://code.google.com/p/xxhash/
 // cityhash: https://code.google.com/p/cityhash/
 
-// +build 386 arm armbe m68k mips mipsle nios2 ppc s390 sh shbe sparc
+// +build 386 arm armbe m68k mips mipsle nios2 ppc riscv s390 sh shbe sparc
 
 package runtime
 
index 6da037e3f366f844e3891abfdb23c10c47343821..b3194dc76685a82970b8b91e9d1cae47124526df 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc s390 sh shbe sparc
+// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc
 
 package runtime
 
index 1fe77663b9ca56619918cbd9d06d8ddbd406ab1f..268941d353205eac4701e662f5b8335e60b375c2 100644 (file)
@@ -83,6 +83,7 @@ var arches = map[string]func(){
        "mips64x": func() { genMIPS(true) },
        "mipsx":   func() { genMIPS(false) },
        "ppc64x":  genPPC64,
+       "riscv":   genRISCV,
        "riscv64": genRISCV64,
        "s390x":   genS390X,
        "wasm":    genWasm,
@@ -501,6 +502,11 @@ func genPPC64() {
        p("JMP (CTR)")
 }
 
+func genRISCV() {
+       p("// No async preemption on riscv - see issue 36711")
+       p("UNDEF")
+}
+
 func genRISCV64() {
        // X0 (zero), X1 (LR), X2 (SP), X4 (g), X31 (TMP) are special.
        var l = layout{sp: "X2", stack: 8}
index d18970ca26c9a3277a189eb80fa9f4b4d417e182..249b5fea01b4324e383dda8536ad2e6942f66627 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 arm mips mipsle wasm darwin,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc s390 sh shbe sparc
+// +build 386 arm mips mipsle wasm darwin,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc
 
 // wasm is a treated as a 32-bit architecture for the purposes of the page
 // allocator, even though it has 64-bit pointers. This is because any wasm
index 0cd2d7524c646f6e61bbd7428a9b14b6761553dd..22cac17ef117cfe1481c4c881775f4c024b24391 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 //
-// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv64 sh wasm
+// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv riscv64 sh wasm
 
 package syscall
 
index cd35942f8bcca4d03de4fb110e8a46cea6947efe..6f7b368f8bfd0151f16036e3edd042a80478c332 100755 (executable)
@@ -116,7 +116,7 @@ for f in $gofiles; do
        aix | android | darwin | dragonfly | freebsd | illumos | hurd | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
            tag1=nonmatchingtag
            ;;
-       386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
+       386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
            tag1=nonmatchingtag
            ;;
     esac
@@ -128,7 +128,7 @@ for f in $gofiles; do
        aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
            tag2=nonmatchingtag
            ;;
-       386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
+       386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
            tag2=nonmatchingtag
            ;;
     esac
index d343aa54d9a8779450092461213c8d748d26fb84..3b53e1ceea24f42d95cbf9cf4a2a5284636c421b 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux,!arm64,!riscv64 netbsd openbsd
+// +build darwin dragonfly freebsd linux,!arm64,!riscv,!riscv64 netbsd openbsd
 
 package main
 
index 459f0dc196874fbf53db87bf2d976f21d18c4043..79a37730c8425b8a7f18ba30375b45ca70638a20 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux,arm64 linux,riscv64
+// +build linux,arm64 linux,riscv,riscv64
 
 package main
 
index eadafa1a7cd63492554674a2e7de669a735bf1e6..5bb27ec1631a7d97b6241d22f41d82d7c1b4b077 100755 (executable)
@@ -308,7 +308,7 @@ x)
            aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
                tag1=nonmatchingtag
                ;;
-           386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
+           386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
                tag1=nonmatchingtag
                ;;
            esac
@@ -320,7 +320,7 @@ x)
            aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
                tag2=nonmatchingtag
                ;;
-           386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
+           386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
                tag2=nonmatchingtag
                ;;
            esac