aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2020-07-26 21:28:48 +0200
committerRon Evans <[email protected]>2020-08-25 16:16:35 +0200
commit4fa1fc6e7215a53baf73b552a714ce8241a8da11 (patch)
treea2a789c29dfb97197e07cc68709b4442317c566f
parentccb803e35d8377264831f4be7b11e34cf855a741 (diff)
downloadtinygo-4fa1fc6e7215a53baf73b552a714ce8241a8da11.tar.gz
tinygo-4fa1fc6e7215a53baf73b552a714ce8241a8da11.zip
interp: don't panic in the Store method
Instead return an error, which indicates where it goes wrong. That's less user unfriendly than panicking.
-rw-r--r--interp/frame.go10
-rw-r--r--interp/values.go27
2 files changed, 22 insertions, 15 deletions
diff --git a/interp/frame.go b/interp/frame.go
index 28e610958..16984f93f 100644
--- a/interp/frame.go
+++ b/interp/frame.go
@@ -111,7 +111,10 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
if inst.IsVolatile() {
fr.builder.CreateStore(value.Value(), ptr.Value())
} else {
- ptr.Store(value.Value())
+ err := ptr.Store(value.Value())
+ if err != nil {
+ return nil, nil, fr.errorAt(inst, err)
+ }
}
case !inst.IsAGetElementPtrInst().IsNil():
value := fr.getLocal(inst.Operand(0))
@@ -422,7 +425,10 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
if err != nil {
return nil, nil, fr.errorAt(inst, err)
}
- dstArray.Store(val)
+ err = dstArray.Store(val)
+ if err != nil {
+ return nil, nil, fr.errorAt(inst, err)
+ }
// dst++
dstArrayValue, err := dstArray.GetElementPtr([]uint32{1})
if err != nil {
diff --git a/interp/values.go b/interp/values.go
index dba81fcef..ae29bf99d 100644
--- a/interp/values.go
+++ b/interp/values.go
@@ -16,7 +16,7 @@ type Value interface {
Type() llvm.Type // equal to Value().Type()
IsConstant() bool // returns true if this value is a constant value
Load() (llvm.Value, error) // dereference a pointer
- Store(llvm.Value) // store to a pointer
+ Store(llvm.Value) error // store to a pointer
GetElementPtr([]uint32) (Value, error) // returns an interior pointer
String() string // string representation, for debugging
}
@@ -68,8 +68,8 @@ func (v *LocalValue) Load() (llvm.Value, error) {
}
// Store stores to the underlying value if the value type is a pointer type,
-// otherwise it panics.
-func (v *LocalValue) Store(value llvm.Value) {
+// otherwise it returns an error.
+func (v *LocalValue) Store(value llvm.Value) error {
if !v.Underlying.IsAGlobalVariable().IsNil() {
if !value.IsConstant() {
v.MarkDirty()
@@ -77,29 +77,28 @@ func (v *LocalValue) Store(value llvm.Value) {
} else {
v.Underlying.SetInitializer(value)
}
- return
+ return nil
}
if !value.IsConstant() {
v.MarkDirty()
v.Eval.builder.CreateStore(value, v.Underlying)
- return
+ return nil
}
switch v.Underlying.Opcode() {
case llvm.GetElementPtr:
indices := v.getConstGEPIndices()
if indices[0] != 0 {
- panic("invalid GEP")
+ return errors.New("invalid GEP")
}
global := &LocalValue{v.Eval, v.Underlying.Operand(0)}
agg, err := global.Load()
if err != nil {
- panic(err) // TODO
+ return err
}
agg = llvm.ConstInsertValue(agg, value, indices[1:])
- global.Store(agg)
- return
+ return global.Store(agg)
default:
- panic("interp: store on a constant")
+ return errors.New("interp: store on a constant")
}
}
@@ -313,9 +312,11 @@ func (v *MapValue) Load() (llvm.Value, error) {
panic("interp: load from a map")
}
-// Store panics: maps are of reference type so cannot be stored to.
-func (v *MapValue) Store(value llvm.Value) {
- panic("interp: store on a map")
+// Store returns an error: maps are of reference type so cannot be stored to.
+func (v *MapValue) Store(value llvm.Value) error {
+ // This must be a bug, but it might be helpful to indicate the location
+ // anyway.
+ return errors.New("interp: store on a map")
}
// GetElementPtr panics: maps are of reference type so their (interior)