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:
@@ -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]]
|
||||
|
||||
@@ -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
|
||||
@@ -9,7 +9,7 @@ func main() {
|
||||
const huge = 1 << 100
|
||||
const large = huge >> 38
|
||||
|
||||
fmt.Println(large)
|
||||
fmt.Println(int64(large))
|
||||
}
|
||||
|
||||
// Output:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"},
|
||||
|
||||
Reference in New Issue
Block a user