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*).
Этот коммит содержится в:
родитель
0704794def
коммит
27cbb53538
3 изменённых файлов: 11 добавлений и 4 удалений
|
@ -985,12 +985,9 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
||||||
case llvm.GetElementPtr:
|
case llvm.GetElementPtr:
|
||||||
ptr := llvmValue.Operand(0)
|
ptr := llvmValue.Operand(0)
|
||||||
index := llvmValue.Operand(1)
|
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()
|
numOperands := llvmValue.OperandsCount()
|
||||||
elementType := ptr.Type().ElementType()
|
elementType := ptr.Type().ElementType()
|
||||||
totalOffset := uint64(0)
|
totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
|
||||||
for i := 2; i < numOperands; i++ {
|
for i := 2; i < numOperands; i++ {
|
||||||
indexValue := llvmValue.Operand(i)
|
indexValue := llvmValue.Operand(i)
|
||||||
if checks && indexValue.IsAConstantInt().IsNil() {
|
if checks && indexValue.IsAConstantInt().IsNil() {
|
||||||
|
|
8
interp/testdata/consteval.ll
предоставленный
8
interp/testdata/consteval.ll
предоставленный
|
@ -3,6 +3,8 @@ target triple = "x86_64--linux"
|
||||||
|
|
||||||
@intToPtrResult = global i8 0
|
@intToPtrResult = global i8 0
|
||||||
@ptrToIntResult = global i8 0
|
@ptrToIntResult = global i8 0
|
||||||
|
@someArray = internal global {i16, i8, i8} zeroinitializer
|
||||||
|
@someArrayPointer = global i8* zeroinitializer
|
||||||
|
|
||||||
define void @runtime.initAll() {
|
define void @runtime.initAll() {
|
||||||
call void @main.init()
|
call void @main.init()
|
||||||
|
@ -12,6 +14,7 @@ define void @runtime.initAll() {
|
||||||
define internal void @main.init() {
|
define internal void @main.init() {
|
||||||
call void @testIntToPtr()
|
call void @testIntToPtr()
|
||||||
call void @testPtrToInt()
|
call void @testPtrToInt()
|
||||||
|
call void @testConstGEP()
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,3 +43,8 @@ b:
|
||||||
store i8 2, i8* @ptrToIntResult
|
store i8 2, i8* @ptrToIntResult
|
||||||
ret void
|
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
|
||||||
|
}
|
||||||
|
|
2
interp/testdata/consteval.out.ll
предоставленный
2
interp/testdata/consteval.out.ll
предоставленный
|
@ -3,6 +3,8 @@ target triple = "x86_64--linux"
|
||||||
|
|
||||||
@intToPtrResult = local_unnamed_addr global i8 2
|
@intToPtrResult = local_unnamed_addr global i8 2
|
||||||
@ptrToIntResult = 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 {
|
define void @runtime.initAll() local_unnamed_addr {
|
||||||
ret void
|
ret void
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче