// convert converts the given value to the specified type, emitting code to f. // No conversion is made, if v is already of the correct type. func (m *Module) convert(f *Function, v value.Value, to irtypes.Type) value.Value { // Early return if v is already of the correct type. from := v.Type() if irtypes.Equal(from, to) { return v } fromType, ok := from.(*irtypes.Int) if !ok { panic(fmt.Sprintf("support for converting from type %T not yet implemented", from)) } toType, ok := to.(*irtypes.Int) if !ok { panic(fmt.Sprintf("support for converting to type %T not yet implemented", to)) } // Convert constant values. if v, ok := v.(constant.Constant); ok { switch v := v.(type) { case *constant.Int: v, err := constant.NewInt(toType, v.ValueString()) if err != nil { panic(fmt.Sprintf("unable to create integer constant; %v", err)) } return v default: panic(fmt.Sprintf("support for converting type %T not yet implemented", v)) } } // TODO: Add proper support for converting signed and unsigned values, using // sext and zext, respectively. // Convert unsigned values. if irtypes.IsBool(fromType) { // Zero extend boolean values. zextInst, err := instruction.NewZExt(v, toType) if err != nil { panic(fmt.Sprintf("unable to create sext instruction; %v", err)) } return f.emitInst(zextInst) } // Convert signed values. if toType.Size() > fromType.Size() { // Sign extend. sextInst, err := instruction.NewSExt(v, toType) if err != nil { panic(fmt.Sprintf("unable to create sext instruction; %v", err)) } return f.emitInst(sextInst) } // Truncate. truncInst, err := instruction.NewTrunc(v, toType) if err != nil { panic(fmt.Sprintf("unable to create trunc instruction; %v", err)) } return f.emitInst(truncInst) }