interp: take care of constant globals

Constant globals can't have been modified, even if a pointer is passed
externally. Therefore, don't treat it as such in hasExternalStore.

In addition, it doesn't make sense to update values of constant globals
after the interp pass is finished. So don't do this.

TODO: track whether objects are actually modified and only update the
globals if this is the case.
This commit is contained in:
Ayke van Laethem
2021-11-11 02:41:29 +01:00
committed by Ron Evans
parent 7e68980c39
commit 1681ed02d3
4 changed files with 25 additions and 1 deletions
+6 -1
View File
@@ -41,6 +41,7 @@ type object struct {
globalName string // name, if not yet created (not guaranteed to be the final name)
buffer value // buffer with value as given by interp, nil if external
size uint32 // must match buffer.len(), if available
constant bool // true if this is a constant global
marked uint8 // 0 means unmarked, 1 means external read, 2 means external write
}
@@ -223,7 +224,7 @@ func (mv *memoryView) hasExternalLoadOrStore(v pointerValue) bool {
// possible for the interpreter to read from the object.
func (mv *memoryView) hasExternalStore(v pointerValue) bool {
obj := mv.get(v.index())
return obj.marked >= 2
return obj.marked >= 2 && !obj.constant
}
// get returns an object that can only be read from, as it may return an object
@@ -263,6 +264,9 @@ func (mv *memoryView) put(index uint32, obj object) {
if checks && mv.get(index).buffer.len(mv.r) != obj.buffer.len(mv.r) {
panic("put() with a differently-sized object")
}
if checks && obj.constant {
panic("interp: store to a constant")
}
mv.objects[index] = obj
}
@@ -1138,6 +1142,7 @@ func (r *runner) getValue(llvmValue llvm.Value) value {
obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.Type().ElementType()))
if initializer := llvmValue.Initializer(); !initializer.IsNil() {
obj.buffer = r.getValue(initializer)
obj.constant = llvmValue.IsGlobalConstant()
}
} else if !llvmValue.IsAFunction().IsNil() {
// OK