diff --git a/interpreter.go b/interpreter.go index 2c48c90e..a0c7a53b 100644 --- a/interpreter.go +++ b/interpreter.go @@ -134,18 +134,29 @@ func (p *Program) interpret(instrs []ssa.Instruction, paramKeys []*ssa.Parameter if err != nil { return i, err } - switch typ := instr.Type().Underlying().(type) { + typeFrom := instr.X.Type().Underlying() + switch typeTo := instr.Type().Underlying().(type) { case *types.Basic: - if _, ok := instr.X.Type().Underlying().(*types.Pointer); ok && typ.Kind() == types.UnsafePointer { - locals[instr] = &PointerBitCastValue{typ, x} - } else if xtyp, ok := instr.X.Type().Underlying().(*types.Basic); ok && xtyp.Kind() == types.UnsafePointer && typ.Kind() == types.Uintptr { - locals[instr] = &PointerToUintptrValue{x} + if typeTo.Kind() == types.String { + return i, errors.New("todo: init: cannot convert string") + } + + if _, ok := typeFrom.(*types.Pointer); ok && typeTo.Kind() == types.UnsafePointer { + locals[instr] = &PointerBitCastValue{typeTo, x} + } else if typeFrom, ok := typeFrom.(*types.Basic); ok { + if typeFrom.Kind() == types.UnsafePointer && typeTo.Kind() == types.Uintptr { + locals[instr] = &PointerToUintptrValue{x} + } else if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 { + locals[instr] = &ConstValue{Expr: ssa.NewConst(x.(*ConstValue).Expr.Value, typeTo)} + } else { + return i, errors.New("todo: init: unknown basic-to-basic convert: " + instr.String()) + } } else { return i, errors.New("todo: init: unknown basic convert: " + instr.String()) } case *types.Pointer: - if xtyp, ok := instr.X.Type().Underlying().(*types.Basic); ok && xtyp.Kind() == types.UnsafePointer { - locals[instr] = &PointerBitCastValue{typ, x} + if typeFrom, ok := typeFrom.(*types.Basic); ok && typeFrom.Kind() == types.UnsafePointer { + locals[instr] = &PointerBitCastValue{typeTo, x} } else { panic("expected unsafe pointer conversion") }