aboutsummaryrefslogtreecommitdiffhomepage
path: root/interp
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-10-14 15:55:50 +0200
committerRon Evans <[email protected]>2021-11-02 22:16:15 +0100
commit27cbb5353811bf50043b9616d530593108172be5 (patch)
tree2ac960a9188062dd213fc0a71b302df0109616a9 /interp
parent0704794def59aa78b4735124cebeef59713f40b4 (diff)
downloadtinygo-27cbb5353811bf50043b9616d530593108172be5.tar.gz
tinygo-27cbb5353811bf50043b9616d530593108172be5.zip
interp: support const getelementptr with non-zero first offset
This is uncommon, but it does happen if the source pointer is a bitcast of a global. For example, if a struct is cast to an i8*, it's possible to index beyond what would appear to be the size of the pointer (i8*).
Diffstat (limited to 'interp')
-rw-r--r--interp/memory.go5
-rw-r--r--interp/testdata/consteval.ll8
-rw-r--r--interp/testdata/consteval.out.ll2
3 files changed, 11 insertions, 4 deletions
diff --git a/interp/memory.go b/interp/memory.go
index 53b798a3e..c7024091b 100644
--- a/interp/memory.go
+++ b/interp/memory.go
@@ -985,12 +985,9 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
case llvm.GetElementPtr:
ptr := llvmValue.Operand(0)
index := llvmValue.Operand(1)
- if checks && index.IsAConstantInt().IsNil() || index.ZExtValue() != 0 {
- panic("expected first index of const gep to be i32 0")
- }
numOperands := llvmValue.OperandsCount()
elementType := ptr.Type().ElementType()
- totalOffset := uint64(0)
+ totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
for i := 2; i < numOperands; i++ {
indexValue := llvmValue.Operand(i)
if checks && indexValue.IsAConstantInt().IsNil() {
diff --git a/interp/testdata/consteval.ll b/interp/testdata/consteval.ll
index b3f664dee..9afb9ff7e 100644
--- a/interp/testdata/consteval.ll
+++ b/interp/testdata/consteval.ll
@@ -3,6 +3,8 @@ target triple = "x86_64--linux"
@intToPtrResult = global i8 0
@ptrToIntResult = global i8 0
+@someArray = internal global {i16, i8, i8} zeroinitializer
+@someArrayPointer = global i8* zeroinitializer
define void @runtime.initAll() {
call void @main.init()
@@ -12,6 +14,7 @@ define void @runtime.initAll() {
define internal void @main.init() {
call void @testIntToPtr()
call void @testPtrToInt()
+ call void @testConstGEP()
ret void
}
@@ -40,3 +43,8 @@ b:
store i8 2, i8* @ptrToIntResult
ret void
}
+
+define internal void @testConstGEP() {
+ store i8* getelementptr inbounds (i8, i8* bitcast ({i16, i8, i8}* @someArray to i8*), i32 2), i8** @someArrayPointer
+ ret void
+}
diff --git a/interp/testdata/consteval.out.ll b/interp/testdata/consteval.out.ll
index 175babbf7..5fac449e4 100644
--- a/interp/testdata/consteval.out.ll
+++ b/interp/testdata/consteval.out.ll
@@ -3,6 +3,8 @@ target triple = "x86_64--linux"
@intToPtrResult = local_unnamed_addr global i8 2
@ptrToIntResult = local_unnamed_addr global i8 2
+@someArray = internal global { i16, i8, i8 } zeroinitializer
+@someArrayPointer = local_unnamed_addr global i8* getelementptr inbounds ({ i16, i8, i8 }, { i16, i8, i8 }* @someArray, i64 0, i32 1)
define void @runtime.initAll() local_unnamed_addr {
ret void