Compare commits

...

1 Commits

Author SHA1 Message Date
Ayke van Laethem f50758ca5a interp: support GEP on fixed (MMIO) addresses
GetElementPtr would not work on values that weren't pointers. Because
fixed addresses (often used in memory-mapped I/O) are integers rather
than pointers in interp, it would return an error.

This resulted in the teensy40 target not compiling correctly since the
interp package rewrite. This commit should fix that.
2021-03-05 21:24:28 +01:00
4 changed files with 21 additions and 8 deletions
+2 -4
View File
@@ -11,19 +11,17 @@ import (
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
var errLiteralToPointer = errors.New("interp: trying to convert literal value to pointer")
// These errors are expected during normal execution and can be recovered from // These errors are expected during normal execution and can be recovered from
// by running the affected function at runtime instead of compile time. // by running the affected function at runtime instead of compile time.
var ( var (
errExpectedPointer = errors.New("interp: trying to use an integer as a pointer (memory-mapped I/O?)") errIntegerAsPointer = errors.New("interp: trying to use an integer as a pointer (memory-mapped I/O?)")
errUnsupportedInst = errors.New("interp: unsupported instruction") errUnsupportedInst = errors.New("interp: unsupported instruction")
errUnsupportedRuntimeInst = errors.New("interp: unsupported instruction (to be emitted at runtime)") errUnsupportedRuntimeInst = errors.New("interp: unsupported instruction (to be emitted at runtime)")
errMapAlreadyCreated = errors.New("interp: map already created") errMapAlreadyCreated = errors.New("interp: map already created")
) )
func isRecoverableError(err error) bool { func isRecoverableError(err error) bool {
return err == errExpectedPointer || err == errUnsupportedInst || err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated return err == errIntegerAsPointer || err == errUnsupportedInst || err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated
} }
// ErrorLine is one line in a traceback. The position may be missing. // ErrorLine is one line in a traceback. The position may be missing.
+1 -1
View File
@@ -102,7 +102,7 @@ func Run(mod llvm.Module, debug bool) error {
if callErr != nil { if callErr != nil {
if isRecoverableError(callErr.Err) { if isRecoverableError(callErr.Err) {
if r.debug { if r.debug {
fmt.Fprintln(os.Stderr, "not interpretring", r.pkgName, "because of error:", callErr.Err) fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
} }
mem.revert() mem.revert()
continue continue
+16 -1
View File
@@ -550,7 +550,22 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
} }
ptr, err := operands[0].asPointer(r) ptr, err := operands[0].asPointer(r)
if err != nil { if err != nil {
return nil, mem, r.errorAt(inst, err) if err != errIntegerAsPointer {
return nil, mem, r.errorAt(inst, err)
}
// GEP on fixed pointer value (for example, memory-mapped I/O).
ptrValue := operands[0].Uint() + offset
switch operands[0].len(r) {
case 8:
locals[inst.localIndex] = literalValue{uint64(ptrValue)}
case 4:
locals[inst.localIndex] = literalValue{uint32(ptrValue)}
case 2:
locals[inst.localIndex] = literalValue{uint16(ptrValue)}
default:
panic("pointer operand is not of a known pointer size")
}
continue
} }
ptr = ptr.addOffset(uint32(offset)) ptr = ptr.addOffset(uint32(offset))
locals[inst.localIndex] = ptr locals[inst.localIndex] = ptr
+2 -2
View File
@@ -348,7 +348,7 @@ func (v literalValue) clone() value {
} }
func (v literalValue) asPointer(r *runner) (pointerValue, error) { func (v literalValue) asPointer(r *runner) (pointerValue, error) {
return pointerValue{}, errLiteralToPointer return pointerValue{}, errIntegerAsPointer
} }
func (v literalValue) asRawValue(r *runner) rawValue { func (v literalValue) asRawValue(r *runner) rawValue {
@@ -949,7 +949,7 @@ func (v rawValue) clone() value {
func (v rawValue) asPointer(r *runner) (pointerValue, error) { func (v rawValue) asPointer(r *runner) (pointerValue, error) {
if v.buf[0] <= 255 { if v.buf[0] <= 255 {
// Probably a null pointer or memory-mapped I/O. // Probably a null pointer or memory-mapped I/O.
return pointerValue{}, errExpectedPointer return pointerValue{}, errIntegerAsPointer
} }
return pointerValue{v.buf[0]}, nil return pointerValue{v.buf[0]}, nil
} }