diff --git a/interp/interpreter.go b/interp/interpreter.go index 864d6f65..605f4d8f 100644 --- a/interp/interpreter.go +++ b/interp/interpreter.go @@ -644,11 +644,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent case llvm.GetElementPtr: // GetElementPtr does pointer arithmetic, changing the offset of the // pointer into the underlying object. - var offset uint64 + var offset int64 for i := 1; i < len(operands); i += 2 { - index := operands[i].Uint() - elementSize := operands[i+1].Uint() - if int64(elementSize) < 0 { + index := operands[i].Int() + elementSize := operands[i+1].Int() + if elementSize < 0 { // This is a struct field. offset += index } else { @@ -662,7 +662,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent return nil, mem, r.errorAt(inst, err) } // GEP on fixed pointer value (for example, memory-mapped I/O). - ptrValue := operands[0].Uint() + offset + ptrValue := operands[0].Uint() + uint64(offset) locals[inst.localIndex] = makeLiteralInt(ptrValue, int(operands[0].len(r)*8)) continue } diff --git a/interp/testdata/basic.ll b/interp/testdata/basic.ll index 6d1d010f..0275dcbb 100644 --- a/interp/testdata/basic.ll +++ b/interp/testdata/basic.ll @@ -10,6 +10,8 @@ target triple = "x86_64--linux" @main.exposedValue1 = global i16 0 @main.exposedValue2 = global i16 0 @main.insertedValue = global {i8, i32, {float, {i64, i16}}} zeroinitializer +@main.gepArray = global [8 x i8] zeroinitializer +@main.negativeGEP = global ptr null declare void @runtime.printint64(i64) unnamed_addr @@ -88,6 +90,11 @@ entry: %agg2 = insertvalue {i8, i32, {float, {i64, i16}}} %agg, i64 5, 2, 1, 0 store {i8, i32, {float, {i64, i16}}} %agg2, ptr @main.insertedValue + ; negative GEP instruction + %ngep1 = getelementptr [8 x i8], ptr @main.negativeGEP, i32 0, i32 5 + %ngep2 = getelementptr [8 x i8], ptr %ngep1, i32 0, i32 -3 + store ptr %ngep2, ptr @main.negativeGEP + ret void } diff --git a/interp/testdata/basic.out.ll b/interp/testdata/basic.out.ll index 342d4965..2685850e 100644 --- a/interp/testdata/basic.out.ll +++ b/interp/testdata/basic.out.ll @@ -9,6 +9,8 @@ target triple = "x86_64--linux" @main.exposedValue1 = global i16 0 @main.exposedValue2 = local_unnamed_addr global i16 0 @main.insertedValue = local_unnamed_addr global { i8, i32, { float, { i64, i16 } } } zeroinitializer +@main.gepArray = local_unnamed_addr global [8 x i8] zeroinitializer +@main.negativeGEP = global ptr getelementptr inbounds (i8, ptr @main.negativeGEP, i64 2) declare void @runtime.printint64(i64) unnamed_addr