Пример #1
0
func (v Target) genConvert(a *allocator, instr *ssa.Convert) {
	op := ssa.GetOperands(instr)[0]

	checkTypeSupported(op.Type())
	checkTypeSupported(instr.Type())

	targetStoresz := TypeStoreSizeInBits(instr.Type())
	targetsz := TypeSizeInBits(instr.Type())
	opsz := TypeSizeInBits(op.Type())

	switch instr.ConvertType() {
	case ssa.ConvertBitcast:
		v.moveValToVal(a, op, instr)

	case ssa.ConvertTrunc:
		v.moveIntToReg(a, op, "rax")
		if !isRegSizeBits(targetsz) {
			v.wop("andq $%d, #rax", (1<<uint(targetsz))-1)
		}
		v.wop("mov%s #%s, %s", sizeSuffixBits(targetStoresz), regToSize("rax", targetStoresz), a.valStr(instr))

	case ssa.ConvertZExt:
		v.moveIntToReg(a, op, "rax")
		v.moveRegToVal(a, "rax", instr)

	case ssa.ConvertSExt:
		v.genSExt(a, instr, op, opsz, targetStoresz, targetsz)

	case ssa.ConvertIntToPtr, ssa.ConvertPtrToInt:
		v.moveIntToReg(a, op, "rax")
		v.moveRegToVal(a, "rax", instr)

	default:
		panic("unim")
	}
}
Пример #2
0
// this function is bad
func checkConvert(instr *ssa.Convert) error {
	ops := ssa.GetOperands(instr)
	srcType := ops[0].Type()
	destType := instr.Type()

	mustBeInt := make([]types.Type, 0, 2)
	mustBeFloat := make([]types.Type, 0, 2)
	mustBePointer := make([]types.Type, 0, 2)

	switch instr.ConvertType() {
	case ssa.ConvertSExt, ssa.ConvertZExt, ssa.ConvertTrunc:
		mustBeInt = append(mustBeInt, srcType, destType)

	case ssa.ConvertBitcast:
		mustBePointer = append(mustBePointer, srcType, destType)

	case ssa.ConvertFExt, ssa.ConvertFTrunc:
		mustBeFloat = append(mustBeFloat, srcType, destType)

	case ssa.ConvertFToUI, ssa.ConvertFToSI:
		mustBeFloat = append(mustBeFloat, srcType)
		mustBeInt = append(mustBeInt, destType)

	case ssa.ConvertUIToF, ssa.ConvertSIToF:
		mustBeFloat = append(mustBeFloat, destType)
		mustBeInt = append(mustBeInt, srcType)

	case ssa.ConvertPtrToInt:
		mustBePointer = append(mustBePointer, srcType)
		mustBeInt = append(mustBeInt, destType)

	case ssa.ConvertIntToPtr:
		mustBeInt = append(mustBeInt, srcType)
		mustBePointer = append(mustBePointer, destType)

	default:
		panic("unim")
	}

	for _, t := range mustBeInt {
		if err := errIfNotIntType(instr, t); err != nil {
			return err
		}
	}
	for _, t := range mustBeFloat {
		if err := errIfNotFloatType(instr, t); err != nil {
			return err
		}
	}
	for _, t := range mustBePointer {
		if err := errIfNotPointerType(instr, t); err != nil {
			return err
		}
	}

	instrError := func(message string) error {
		return &InstrError{
			Instr:   instr,
			Message: message,
		}
	}

	switch instr.ConvertType() {
	case ssa.ConvertSExt, ssa.ConvertZExt:
		if srcType.(*types.Int).Width() >= destType.(*types.Int).Width() {
			return instrError("sext/zext requires src width < dest width")
		}

	case ssa.ConvertTrunc:
		if srcType.(*types.Int).Width() <= destType.(*types.Int).Width() {
			return instrError("trunc requires src width > dest width")
		}

	case ssa.ConvertBitcast:
		// do nothing

	case ssa.ConvertFExt:
		if srcType.(*types.Float).Type().CanExtendTo(destType.(*types.Float).Type()) {
			return instrError("fext cannot convert from " + srcType.String() + " to " + destType.String())
		}

	case ssa.ConvertFTrunc:
		if srcType.(*types.Float).Type().CanTruncateTo(destType.(*types.Float).Type()) {
			return instrError("ftrunc cannot convert from " + srcType.String() + " to " + destType.String())
		}

	case ssa.ConvertFToUI, ssa.ConvertFToSI, ssa.ConvertUIToF, ssa.ConvertSIToF, ssa.ConvertPtrToInt, ssa.ConvertIntToPtr:
		// nothing to do

	default:
		panic("unim")
	}

	return nil
}