interp: fix support of 32 bits and big-endian arch

Force recompute of bits.UintSize, make related tests portable.

Fixes #1230.
This commit is contained in:
Marc Vertes
2021-08-27 14:54:05 +02:00
committed by GitHub
parent d2b25a7426
commit b7f9a39eff
9 changed files with 39 additions and 33 deletions

View File

@@ -63,10 +63,10 @@
exclude = []
[[issues.exclude-rules]]
path = "interp/.+_test\\.go"
path = ".+_test\\.go"
linters = ["goconst"]
[[issues.exclude-rules]]
path = "interp/.+_test\\.go"
path = ".+_test\\.go"
text = "var-declaration:"
[[issues.exclude-rules]]

View File

@@ -1,13 +0,0 @@
// A test program
// +build darwin,linux !arm
// +build go1.12 !go1.13
package main
func main() {
println("hello world")
}
// Output:
// hello world

View File

@@ -9,7 +9,7 @@ func main() {
const huge = 1 << 100
const large = huge >> 38
fmt.Println(large)
fmt.Println(int64(large))
}
// Output:

View File

@@ -2,7 +2,7 @@ package main
import "fmt"
const maxLen = int64(int(^uint(0) >> 1))
const maxLen = int64(int64(^uint64(0) >> 1))
func main() {
fmt.Println(maxLen)

View File

@@ -1,11 +1,14 @@
package main
import (
"fmt"
"math/bits"
"unsafe"
)
const SSize = 16
const (
SSize = 16
WSize = bits.UintSize / 8
)
type S struct {
X int
@@ -13,14 +16,19 @@ type S struct {
}
func main() {
bigEndian := (*(*[2]uint8)(unsafe.Pointer(&[]uint16{1}[0])))[0] == 0
var sBuf [SSize]byte
s := (*S)(unsafe.Pointer(&sBuf[0]))
s.X = 2
s.Y = 4
fmt.Println(sBuf)
if bigEndian {
println(sBuf[0+WSize-1], sBuf[WSize+WSize-1])
} else {
println(sBuf[0], sBuf[WSize])
}
}
// Output:
// [2 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0]
// 2 4

View File

@@ -2,10 +2,11 @@ package main
import (
"fmt"
"math/bits"
"unsafe"
)
const SSize = 24
const WSize = bits.UintSize / 8
type S struct {
X int
@@ -20,7 +21,8 @@ func main() {
{X: 3},
}
addr := unsafe.Pointer(&arr[0])
s := *(*S)(unsafe.Pointer(uintptr(addr) + SSize*2))
// s := *(*S)(unsafe.Pointer(uintptr(addr) + SSize*2))
s := *(*S)(unsafe.Pointer(uintptr(addr) + WSize*6))
fmt.Println(s.X)
}

View File

@@ -1,10 +1,12 @@
package main
import (
"fmt"
"math/bits"
"unsafe"
)
const WSize = bits.UintSize / 8
type S struct {
X int
Y int
@@ -13,12 +15,12 @@ type S struct {
func main() {
x := S{}
size := unsafe.Sizeof(x)
align := unsafe.Alignof(x.Y)
offset := unsafe.Offsetof(x.Z)
size := unsafe.Sizeof(x) / WSize
align := unsafe.Alignof(x.Y) / WSize
offset := unsafe.Offsetof(x.Z) / WSize
fmt.Println(size, align, offset)
println(size, align, offset)
}
// Output:
// 24 8 16
// 3 1 2

View File

@@ -7,11 +7,13 @@ import (
"flag"
"fmt"
"go/build"
"go/constant"
"go/scanner"
"go/token"
"io"
"io/fs"
"log"
"math/bits"
"os"
"os/signal"
"path"
@@ -696,17 +698,17 @@ func (interp *Interpreter) Use(values Exports) error {
// Checks if input values correspond to stdlib packages by looking for one
// well known stdlib package path.
if _, ok := values["fmt/fmt"]; ok {
fixStdio(interp)
fixStdlib(interp)
}
return nil
}
// fixStdio redefines interpreter stdlib symbols to use the standard input,
// fixStdlib redefines interpreter stdlib symbols to use the standard input,
// output and errror assigned to the interpreter. The changes are limited to
// the interpreter only.
// Note that it is possible to escape the virtualized stdio by
// read/write directly to file descriptors 0, 1, 2.
func fixStdio(interp *Interpreter) {
func fixStdlib(interp *Interpreter) {
p := interp.binPkg["fmt"]
if p == nil {
return
@@ -769,6 +771,11 @@ func fixStdio(interp *Interpreter) {
}
}
}
if p = interp.binPkg["math/bits"]; p != nil {
// Do not trust extracted value maybe from another arch.
p["UintSize"] = reflect.ValueOf(constant.MakeInt64(bits.UintSize))
}
}
// ignoreScannerError returns true if the error from Go scanner can be safely ignored

View File

@@ -76,7 +76,7 @@ func TestEvalShift(t *testing.T) {
i := interp.New(interp.Options{})
runTests(t, i, []testCase{
{src: "a, b, m := uint32(1), uint32(2), uint32(0); m = a + (1 << b)", res: "5"},
{src: "c := uint(1); d := uint(+(-(1 << c)))", res: "18446744073709551614"},
{src: "c := uint(1); d := uint64(+(-(1 << c)))", res: "18446744073709551614"},
{src: "e, f := uint32(0), uint32(0); f = 1 << -(e * 2)", res: "1"},
{src: "p := uint(0xdead); byte((1 << (p & 7)) - 1)", res: "31"},
{pre: func() { eval(t, i, "const k uint = 1 << 17") }, src: "int(k)", res: "131072"},