Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions interp/interp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func TestInterp(t *testing.T) {
"copy",
"interface",
"revert",
"store",
"alloc",
} {
name := name // make local to this closure
Expand Down
29 changes: 22 additions & 7 deletions interp/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,26 +330,41 @@ func (mv *memoryView) store(v value, p pointerValue) bool {
if checks && mv.hasExternalLoadOrStore(p) {
panic("interp: store to object with external load/store")
}
obj := mv.get(p.index())
index := p.index()
var obj object
writable := false
if mv.objects != nil {
obj, writable = mv.objects[index]
}
if !writable {
obj = mv.get(index)
}
if obj.buffer == nil {
// External global, return false (for a failure).
return false
}
if checks && p.offset()+v.len(mv.r) > obj.size {
valueLen := v.len(mv.r)
if checks && p.offset()+valueLen > obj.size {
panic("interp: store out of bounds")
}
if p.offset() == 0 && v.len(mv.r) == obj.buffer.len(mv.r) {
obj.buffer = v
if p.offset() == 0 && valueLen == obj.buffer.len(mv.r) {
obj.buffer = v.clone()
} else {
obj = obj.clone()
if !writable {
obj = obj.clone()
}
buffer := obj.buffer.asRawValue(mv.r)
obj.buffer = buffer
v := v.asRawValue(mv.r)
for i := uint32(0); i < v.len(mv.r); i++ {
if writable {
// A partial load from this object may share the destination buffer.
v.buf = append([]uint64(nil), v.buf...)
}
for i := uint32(0); i < valueLen; i++ {
buffer.buf[p.offset()+i] = v.buf[i]
}
}
mv.put(p.index(), obj)
mv.put(index, obj)
return true // success
}

Expand Down
32 changes: 32 additions & 0 deletions interp/testdata/store.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"

@overlap.buf = global [4 x i8] c"\01\02\03\04"
@alias.src = global [4 x i8] c"\05\06\07\08"
@alias.dst = global [2 x i8] zeroinitializer

define void @runtime.initAll() unnamed_addr {
entry:
call void @overlap.init(ptr undef)
call void @alias.init(ptr undef)
ret void
}

define internal void @overlap.init(ptr %context) unnamed_addr {
entry:
%tail = getelementptr [4 x i8], ptr @overlap.buf, i32 0, i32 3
store i8 9, ptr %tail
%val = load i16, ptr @overlap.buf
%dst = getelementptr [4 x i8], ptr @overlap.buf, i32 0, i32 1
store i16 %val, ptr %dst
ret void
}

define internal void @alias.init(ptr %context) unnamed_addr {
entry:
%src = getelementptr [4 x i8], ptr @alias.src, i32 0, i32 1
%val = load i16, ptr %src
store i16 %val, ptr @alias.dst
store i8 9, ptr @alias.dst
ret void
}
11 changes: 11 additions & 0 deletions interp/testdata/store.out.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"

@overlap.buf = local_unnamed_addr global [4 x i8] c"\01\01\02\09"
@alias.src = local_unnamed_addr global [4 x i8] c"\05\06\07\08"
@alias.dst = local_unnamed_addr global [2 x i8] c"\09\07"

define void @runtime.initAll() unnamed_addr {
entry:
ret void
}
Loading