示例#1
0
文件: util.go 项目: mewmew/uc
// 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)
}
示例#2
0
文件: lower.go 项目: mewmew/uc
// cond lowers the given condition expression to LLVM IR, emitting code to f.
func (m *Module) cond(f *Function, expr ast.Expr) value.Value {
	cond := m.expr(f, expr)
	if irtypes.IsBool(cond.Type()) {
		return cond
	}
	// Create boolean expression if cond is not already of boolean type.
	//
	//    cond != 0
	// zero is the integer constant 0.
	zero := constZero(cond.Type())
	icmpInst, err := instruction.NewICmp(instruction.ICondNE, cond, zero)
	if err != nil {
		panic(fmt.Sprintf("unable to create icmp instruction; %v", err))
	}
	return f.emitInst(icmpInst)
}