From cdba4fa8ccde75839dcbbbac30ebfd727aeff909 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 8 Jul 2021 23:52:40 +0200 Subject: [PATCH] interp: don't ignore array indices for untyped objects This fixes https://github.com/tinygo-org/tinygo/issues/1884. My original plan to fix this was much more complicated, but then I realized that the output type doesn't matter anyway and I can simply cast the type to an *i8 and perform a GEP on that pointer. --- interp/interp.go | 2 +- interp/memory.go | 11 +++++++++++ testdata/init.go | 15 +++++++++++++++ testdata/init.txt | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/interp/interp.go b/interp/interp.go index 8da27705..d3976ef7 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -15,7 +15,7 @@ import ( // package is changed in a way that affects the output so that cached package // builds will be invalidated. // This version is independent of the TinyGo version number. -const Version = 1 +const Version = 2 // last change: fix GEP on untyped pointers // Enable extra checks, which should be disabled by default. // This may help track down bugs by adding a few more sanity checks. diff --git a/interp/memory.go b/interp/memory.go index ccd98c8b..53b798a3 100644 --- a/interp/memory.go +++ b/interp/memory.go @@ -572,6 +572,17 @@ func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Val } if llvmType.IsNil() { + if v.offset() != 0 { + // If there is an offset, make sure to use a GEP to index into the + // pointer. Because there is no expected type, we use whatever is + // most convenient: an *i8 type. It is trivial to index byte-wise. + if llvmValue.Type() != mem.r.i8ptrType { + llvmValue = llvm.ConstBitCast(llvmValue, mem.r.i8ptrType) + } + llvmValue = llvm.ConstInBoundsGEP(llvmValue, []llvm.Value{ + llvm.ConstInt(llvmValue.Type().Context().Int32Type(), uint64(v.offset()), false), + }) + } return llvmValue, nil } diff --git a/testdata/init.go b/testdata/init.go index 6e7d9e7b..5cb7f2d2 100644 --- a/testdata/init.go +++ b/testdata/init.go @@ -13,6 +13,8 @@ func main() { println("v5:", len(v5), v5 == nil) println("v6:", v6) println("v7:", cap(v7), string(v7)) + println("v8:", v8) + println("v9:", len(v9), v9[0], v9[1], v9[2]) println(uint8SliceSrc[0]) println(uint8SliceDst[0]) @@ -35,6 +37,8 @@ var ( v5 = map[string]int{} v6 = float64(v1) < 2.6 v7 = []byte("foo") + v8 string + v9 []int uint8SliceSrc = []uint8{3, 100} uint8SliceDst []uint8 @@ -48,4 +52,15 @@ func init() { intSliceDst = make([]int16, len(intSliceSrc)) copy(intSliceDst, intSliceSrc) + + v8 = sliceString("foobarbaz", 3, 8) + v9 = sliceSlice([]int{0, 1, 2, 3, 4, 5}, 2, 5) +} + +func sliceString(s string, start, end int) string { + return s[start:end] +} + +func sliceSlice(s []int, start, end int) []int { + return s[start:end] } diff --git a/testdata/init.txt b/testdata/init.txt index c421c115..a6b9736c 100644 --- a/testdata/init.txt +++ b/testdata/init.txt @@ -7,6 +7,8 @@ v4: 0 true v5: 0 false v6: false v7: 3 foo +v8: barba +v9: 3 2 3 4 3 3 5