libgo: add 32-bit RISC-V (RV32) support

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
This commit is contained in:
Maciej W. Rozycki 2020-08-28 16:05:56 +01:00 committed by Ian Lance Taylor
parent 2dd7b93778
commit 2c5499b57c
23 changed files with 114 additions and 21 deletions

View file

@ -1,4 +1,4 @@
9e55baf44ab63ba06af0b57038e7b3aab8216222 c9c084bce713e258721e12041a351ec8ad33ad17
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.

15
libgo/configure vendored
View file

@ -14226,8 +14226,21 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;; ;;
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 GOARCH=riscv64
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;; ;;
s390*-*-*) s390*-*-*)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext

View file

@ -342,8 +342,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
[GOARCH=ppc64le], [GOARCH=ppc64le],
[GOARCH=ppc64])]) [GOARCH=ppc64])])
;; ;;
riscv64-*-*) riscv*-*-*)
GOARCH=riscv64 AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#if __riscv_xlen == 64
#error 64-bit
#endif
])],
[GOARCH=riscv],
[GOARCH=riscv64])
;; ;;
s390*-*-*) s390*-*-*)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([ AC_COMPILE_IFELSE([AC_LANG_SOURCE([

View file

@ -184,6 +184,7 @@ var ptrSizeMap = map[string]int64{
"ppc": 4, "ppc": 4,
"ppc64": 8, "ppc64": 8,
"ppc64le": 8, "ppc64le": 8,
"riscv": 4,
"riscv64": 8, "riscv64": 8,
"s390": 4, "s390": 4,
"s390x": 8, "s390x": 8,
@ -210,6 +211,7 @@ var intSizeMap = map[string]int64{
"ppc": 4, "ppc": 4,
"ppc64": 8, "ppc64": 8,
"ppc64le": 8, "ppc64le": 8,
"riscv": 4,
"riscv64": 8, "riscv64": 8,
"s390": 4, "s390": 4,
"s390x": 8, "s390x": 8,

View file

@ -8,8 +8,9 @@
# See: https://github.com/golang/go/issues/8912 # See: https://github.com/golang/go/issues/8912
[linux] [ppc64] skip [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 # See: https://github.com/golang/go/issues/36739
[linux] [riscv] skip
[linux] [riscv64] skip [linux] [riscv64] skip
cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c

View file

@ -19,6 +19,7 @@ const (
MIPS MIPS
MIPS64 MIPS64
PPC64 PPC64
RISCV
RISCV64 RISCV64
S390X S390X
Wasm Wasm
@ -143,6 +144,15 @@ var ArchPPC64LE = &Arch{
MinLC: 4, MinLC: 4,
} }
var ArchRISCV = &Arch{
Name: "riscv",
Family: RISCV,
ByteOrder: binary.LittleEndian,
PtrSize: 4,
RegSize: 4,
MinLC: 4,
}
var ArchRISCV64 = &Arch{ var ArchRISCV64 = &Arch{
Name: "riscv64", Name: "riscv64",
Family: RISCV64, Family: RISCV64,
@ -181,6 +191,7 @@ var Archs = [...]*Arch{
ArchMIPS64LE, ArchMIPS64LE,
ArchPPC64, ArchPPC64,
ArchPPC64LE, ArchPPC64LE,
ArchRISCV,
ArchRISCV64, ArchRISCV64,
ArchS390X, ArchS390X,
ArchWasm, ArchWasm,

View file

@ -617,6 +617,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
return f.applyRelocationsMIPS(dst, rels) return f.applyRelocationsMIPS(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_MIPS: case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
return f.applyRelocationsMIPS64(dst, rels) 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: case f.Class == ELFCLASS64 && f.Machine == EM_RISCV:
return f.applyRelocationsRISCV64(dst, rels) return f.applyRelocationsRISCV64(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_S390: case f.Class == ELFCLASS64 && f.Machine == EM_S390:
@ -1008,6 +1010,47 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
return nil 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 { func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
// 24 is the size of Rela64. // 24 is the size of Rela64.
if len(rels)%24 != 0 { if len(rels)%24 != 0 {

View file

@ -167,6 +167,7 @@ var gcArchSizes = map[string]*StdSizes{
"mips64le": {8, 8}, "mips64le": {8, 8},
"ppc64": {8, 8}, "ppc64": {8, 8},
"ppc64le": {8, 8}, "ppc64le": {8, 8},
"riscv": {4, 4},
"riscv64": {8, 8}, "riscv64": {8, 8},
"s390x": {8, 8}, "s390x": {8, 8},
"sparc64": {8, 8}, "sparc64": {8, 8},
@ -180,7 +181,8 @@ var gcArchSizes = map[string]*StdSizes{
// //
// Supported architectures for compiler "gc": // Supported architectures for compiler "gc":
// "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle", // "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 { func SizesFor(compiler, arch string) Sizes {
var m map[string]*StdSizes var m map[string]*StdSizes
switch compiler { switch compiler {

View file

@ -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

View file

@ -87,6 +87,7 @@ var (
asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true} asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true}
asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true} asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true}
asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, 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} asmArchRISCV64 = asmArch{name: "riscv64", bigEndian: false, stack: "SP", lr: true}
asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true} asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true}
asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false} asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false}
@ -102,6 +103,7 @@ var (
&asmArchMips64LE, &asmArchMips64LE,
&asmArchPpc64, &asmArchPpc64,
&asmArchPpc64LE, &asmArchPpc64LE,
&asmArchRISCV,
&asmArchRISCV64, &asmArchRISCV64,
&asmArchS390X, &asmArchS390X,
&asmArchWasm, &asmArchWasm,

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build ignore_for_gccgo // +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 package bytealg

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 package bytealg

View file

@ -9,7 +9,7 @@ package unix
// This file is named "generic" because at a certain point Linux started // This file is named "generic" because at a certain point Linux started
// standardizing on system call numbers across architectures. So far this // 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 ( const (
getrandomTrap uintptr = 278 getrandomTrap uintptr = 278

View file

@ -157,7 +157,7 @@ type BigStruct struct {
func infoBigStruct() []byte { func infoBigStruct() []byte {
switch runtime.GOARCH { switch runtime.GOARCH {
case "386", "arm", "mips", "mipsle": case "386", "arm", "mips", "mipsle", "riscv":
return []byte{ return []byte{
typePointer, // q *int typePointer, // q *int
typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte

View file

@ -6,7 +6,7 @@
// xxhash: https://code.google.com/p/xxhash/ // xxhash: https://code.google.com/p/xxhash/
// cityhash: https://code.google.com/p/cityhash/ // 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 package runtime

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 package runtime

View file

@ -83,6 +83,7 @@ var arches = map[string]func(){
"mips64x": func() { genMIPS(true) }, "mips64x": func() { genMIPS(true) },
"mipsx": func() { genMIPS(false) }, "mipsx": func() { genMIPS(false) },
"ppc64x": genPPC64, "ppc64x": genPPC64,
"riscv": genRISCV,
"riscv64": genRISCV64, "riscv64": genRISCV64,
"s390x": genS390X, "s390x": genS390X,
"wasm": genWasm, "wasm": genWasm,
@ -501,6 +502,11 @@ func genPPC64() {
p("JMP (CTR)") p("JMP (CTR)")
} }
func genRISCV() {
p("// No async preemption on riscv - see issue 36711")
p("UNDEF")
}
func genRISCV64() { func genRISCV64() {
// X0 (zero), X1 (LR), X2 (SP), X4 (g), X31 (TMP) are special. // X0 (zero), X1 (LR), X2 (SP), X4 (g), X31 (TMP) are special.
var l = layout{sp: "X2", stack: 8} var l = layout{sp: "X2", stack: 8}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 // 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 // allocator, even though it has 64-bit pointers. This is because any wasm

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 package syscall

View file

@ -116,7 +116,7 @@ for f in $gofiles; do
aix | android | darwin | dragonfly | freebsd | illumos | hurd | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) aix | android | darwin | dragonfly | freebsd | illumos | hurd | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag1=nonmatchingtag 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 tag1=nonmatchingtag
;; ;;
esac 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) aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag2=nonmatchingtag 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 tag2=nonmatchingtag
;; ;;
esac esac

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 package main

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux,arm64 linux,riscv64 // +build linux,arm64 linux,riscv,riscv64
package main package main

View file

@ -308,7 +308,7 @@ x)
aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag1=nonmatchingtag 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 tag1=nonmatchingtag
;; ;;
esac esac
@ -320,7 +320,7 @@ x)
aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
tag2=nonmatchingtag 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 tag2=nonmatchingtag
;; ;;
esac esac