@@ -17,6 +17,7 @@ package interp
17
17
import (
18
18
"encoding/binary"
19
19
"errors"
20
+ "fmt"
20
21
"math"
21
22
"math/big"
22
23
"strconv"
@@ -104,28 +105,28 @@ func (mv *memoryView) revert() {
104
105
// means that the interpreter can still read from it, but cannot write to it as
105
106
// that would mean the external read (done at runtime) reads from a state that
106
107
// would not exist had the whole initialization been done at runtime.
107
- func (mv * memoryView ) markExternalLoad (llvmValue llvm.Value ) {
108
- mv .markExternal (llvmValue , 1 )
108
+ func (mv * memoryView ) markExternalLoad (llvmValue llvm.Value ) error {
109
+ return mv .markExternal (llvmValue , 1 )
109
110
}
110
111
111
112
// markExternalStore marks the given LLVM value as having an external write.
112
113
// This means that the interpreter can no longer read from it or write to it, as
113
114
// that would happen in a different order than if all initialization were
114
115
// happening at runtime.
115
- func (mv * memoryView ) markExternalStore (llvmValue llvm.Value ) {
116
- mv .markExternal (llvmValue , 2 )
116
+ func (mv * memoryView ) markExternalStore (llvmValue llvm.Value ) error {
117
+ return mv .markExternal (llvmValue , 2 )
117
118
}
118
119
119
120
// markExternal is a helper for markExternalLoad and markExternalStore, and
120
121
// should not be called directly.
121
- func (mv * memoryView ) markExternal (llvmValue llvm.Value , mark uint8 ) {
122
+ func (mv * memoryView ) markExternal (llvmValue llvm.Value , mark uint8 ) error {
122
123
if llvmValue .IsUndef () || llvmValue .IsNull () {
123
124
// Null and undef definitely don't contain (valid) pointers.
124
- return
125
+ return nil
125
126
}
126
127
if ! llvmValue .IsAInstruction ().IsNil () || ! llvmValue .IsAArgument ().IsNil () {
127
128
// These are considered external by default, there is nothing to mark.
128
- return
129
+ return nil
129
130
}
130
131
131
132
if ! llvmValue .IsAGlobalValue ().IsNil () {
@@ -144,7 +145,10 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) {
144
145
// Using mark '2' (which means read/write access) because
145
146
// even from an object that is only read from, the resulting
146
147
// loaded pointer can be written to.
147
- mv .markExternal (initializer , 2 )
148
+ err := mv .markExternal (initializer , 2 )
149
+ if err != nil {
150
+ return err
151
+ }
148
152
}
149
153
} else {
150
154
// This is a function. Go through all instructions and mark all
@@ -170,7 +174,10 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) {
170
174
for i := 0 ; i < numOperands ; i ++ {
171
175
// Using mark '2' (which means read/write access)
172
176
// because this might be a store instruction.
173
- mv .markExternal (inst .Operand (i ), 2 )
177
+ err := mv .markExternal (inst .Operand (i ), 2 )
178
+ if err != nil {
179
+ return err
180
+ }
174
181
}
175
182
}
176
183
}
@@ -179,9 +186,12 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) {
179
186
} else if ! llvmValue .IsAConstantExpr ().IsNil () {
180
187
switch llvmValue .Opcode () {
181
188
case llvm .IntToPtr , llvm .PtrToInt , llvm .BitCast , llvm .GetElementPtr :
182
- mv .markExternal (llvmValue .Operand (0 ), mark )
189
+ err := mv .markExternal (llvmValue .Operand (0 ), mark )
190
+ if err != nil {
191
+ return err
192
+ }
183
193
default :
184
- panic ("interp: unknown constant expression" )
194
+ return fmt . Errorf ("interp: unknown constant expression '%s'" , instructionNameMap [ llvmValue . Opcode ()] )
185
195
}
186
196
} else if ! llvmValue .IsAInlineAsm ().IsNil () {
187
197
// Inline assembly can modify globals but only exported globals. Let's
@@ -196,18 +206,25 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) {
196
206
numElements := llvmType .StructElementTypesCount ()
197
207
for i := 0 ; i < numElements ; i ++ {
198
208
element := llvm .ConstExtractValue (llvmValue , []uint32 {uint32 (i )})
199
- mv .markExternal (element , mark )
209
+ err := mv .markExternal (element , mark )
210
+ if err != nil {
211
+ return err
212
+ }
200
213
}
201
214
case llvm .ArrayTypeKind :
202
215
numElements := llvmType .ArrayLength ()
203
216
for i := 0 ; i < numElements ; i ++ {
204
217
element := llvm .ConstExtractValue (llvmValue , []uint32 {uint32 (i )})
205
- mv .markExternal (element , mark )
218
+ err := mv .markExternal (element , mark )
219
+ if err != nil {
220
+ return err
221
+ }
206
222
}
207
223
default :
208
- panic ("interp: unknown type kind in markExternalValue" )
224
+ return errors . New ("interp: unknown type kind in markExternalValue" )
209
225
}
210
226
}
227
+ return nil
211
228
}
212
229
213
230
// hasExternalLoadOrStore returns true if this object has an external load or
0 commit comments