コード例 #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
ファイル: irx.go プロジェクト: llir/llvm
// NewZExtInst returns a new zext instruction based on the given value and
// target type.
func NewZExtInst(fromType, fromVal, to interface{}) (*instruction.ZExt, error) {
	from, err := NewValue(fromType, fromVal)
	if err != nil {
		return nil, errutil.Err(err)
	}
	if to, ok := to.(types.Type); ok {
		return instruction.NewZExt(from, to)
	}
	return nil, errutil.Newf("invalid target type; expected types.Type, got %T", to)
}
コード例 #3
0
ファイル: lower.go プロジェクト: mewmew/uc
// unaryExpr lowers the given unary expression to LLVM IR, emitting code to f.
func (m *Module) unaryExpr(f *Function, n *ast.UnaryExpr) value.Value {
	switch n.Op {
	// -expr
	case token.Sub:
		// Input:
		//    void f() {
		//       int x;
		//       -x;              // <-- relevant line
		//    }
		// Output:
		//    %2 = sub i32 0, %1
		expr := m.expr(f, n.X)
		zero := constZero(expr.Type())
		subInst, err := instruction.NewSub(zero, expr)
		if err != nil {
			panic(fmt.Sprintf("unable to create sub instruction; %v", err))
		}
		// Emit sub instruction.
		return f.emitInst(subInst)
	// !expr
	case token.Not:
		// TODO: Replace `(x != 0) ^ 1` with `x == 0`. Using the former for now to
		// simplify test cases, as they are generated by Clang.

		// Input:
		//    int g() {
		//       int y;
		//       !y;              // <-- relevant line
		//    }
		// Output:
		//    %2 = icmp ne i32 %1, 0
		//    %3 = xor i1 %2, true
		cond := m.cond(f, n.X)
		one := constOne(cond.Type())
		xorInst, err := instruction.NewXor(cond, one)
		if err != nil {
			panic(fmt.Sprintf("unable to create xor instruction; %v", err))
		}
		// Emit xor instruction.
		notCond := f.emitInst(xorInst)
		zextInst, err := instruction.NewZExt(notCond, m.typeOf(n.X))
		if err != nil {
			panic(fmt.Sprintf("unable to create zext instruction; %v", err))
		}
		// Emit zext instruction.
		return f.emitInst(zextInst)
	default:
		panic(fmt.Sprintf("support for unary operator %v not yet implemented", n.Op))
	}
}
コード例 #4
0
ファイル: fix.go プロジェクト: llir/llvm
// fixValueInst replaces dummy values within the given value instruction with
// their corresponding local variables.
func (m dummyMap) fixValueInst(oldValInst instruction.ValueInst) instruction.ValueInst {
	switch oldValInst := oldValInst.(type) {
	// Binary Operations
	case *instruction.Add:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewAdd(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FAdd:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewFAdd(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Sub:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewSub(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FSub:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewFSub(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Mul:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewMul(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FMul:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewFMul(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.UDiv:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewUDiv(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.SDiv:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewSDiv(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FDiv:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewFDiv(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.URem:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewURem(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.SRem:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewSRem(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FRem:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewFRem(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst

	// Bitwise Binary Operations
	case *instruction.ShL:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewShL(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.LShR:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewLShR(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.AShR:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewAShR(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.And:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewAnd(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Or:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewOr(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Xor:
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewXor(x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst

	// Vector Operations
	case *instruction.ExtractElement:
		panic("irx.dummyMap.fixValueInst: ExtractElement not yet implemented")
	case *instruction.InsertElement:
		panic("irx.dummyMap.fixValueInst: InsertElement not yet implemented")
	case *instruction.ShuffleVector:
		panic("irx.dummyMap.fixValueInst: ShuffleVector not yet implemented")

	// Aggregate Operations
	case *instruction.ExtractValue:
		panic("irx.dummyMap.fixValueInst: ExtractValue not yet implemented")
	case *instruction.InsertValue:
		panic("irx.dummyMap.fixValueInst: InsertValue not yet implemented")

	// Memory Access and Addressing Operations
	case *instruction.Alloca:
		// Nothing to do; alloca contains no dummy values.
		return oldValInst
	case *instruction.Load:
		srcAddr := m.fixValue(oldValInst.SrcAddr())
		inst, err := instruction.NewLoad(srcAddr)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.CmpXchg:
		panic("irx.dummyMap.fixValueInst: CmpXchg not yet implemented")
	case *instruction.AtomicRMW:
		panic("irx.dummyMap.fixValueInst: AtomicRMW not yet implemented")
	case *instruction.GetElementPtr:
		srcAddr := m.fixValue(oldValInst.SrcAddr())
		var indices []value.Value
		for _, oldIndex := range oldValInst.Indices() {
			index := m.fixValue(oldIndex)
			indices = append(indices, index)
		}
		inst, err := instruction.NewGetElementPtr(srcAddr, indices)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst

	// Conversion Operations
	case *instruction.Trunc:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewTrunc(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.ZExt:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewZExt(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.SExt:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewSExt(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FPTrunc:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewFPTrunc(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FPExt:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewFPExt(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FPToUI:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewFPToUI(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FPToSI:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewFPToSI(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.UIToFP:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewUIToFP(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.SIToFP:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewSIToFP(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.PtrToInt:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewPtrToInt(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.IntToPtr:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewIntToPtr(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.BitCast:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewBitCast(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.AddrSpaceCast:
		from := m.fixValue(oldValInst.From())
		to := oldValInst.RetType()
		inst, err := instruction.NewAddrSpaceCast(from, to)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst

	// Other Operations
	case *instruction.ICmp:
		cond := oldValInst.Cond()
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewICmp(cond, x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.FCmp:
		panic("irx.dummyMap.fixValueInst: FCmp not yet implemented")
	case *instruction.PHI:
		oldIncs := oldValInst.Incs()
		var incs []*instruction.Incoming
		for _, oldInc := range oldIncs {
			val := m.fixValue(oldInc.Value())
			pred := m.fixNamedValue(oldInc.Pred())
			inc, err := instruction.NewIncoming(val, pred)
			if err != nil {
				panic(errutil.Err(err))
			}
			incs = append(incs, inc)
		}
		inst, err := instruction.NewPHI(incs)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Select:
		cond := m.fixValue(oldValInst.Cond())
		x := m.fixValue(oldValInst.X())
		y := m.fixValue(oldValInst.Y())
		inst, err := instruction.NewSelect(cond, x, y)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.Call:
		result := oldValInst.RetType()
		// TODO: Fix value of callee if the type of Callee changes from string to
		// value.Value.
		callee := oldValInst.Callee()
		var args []value.Value
		for _, oldArg := range oldValInst.Args() {
			arg := m.fixValue(oldArg)
			args = append(args, arg)
		}
		inst, err := instruction.NewCall(result, callee, args)
		if err != nil {
			panic(errutil.Err(err))
		}
		return inst
	case *instruction.VAArg:
		panic("irx.dummyMap.fixValueInst: VAArg not yet implemented")
	case *instruction.LandingPad:
		panic("irx.dummyMap.fixValueInst: LandingPad not yet implemented")
	case *instruction.CatchPad:
		panic("irx.dummyMap.fixValueInst: CatchPad not yet implemented")
	case *instruction.CleanupPad:
		panic("irx.dummyMap.fixValueInst: CleanupPad not yet implemented")
	default:
		panic("irx.dummyMap.fixValueInst: not yet implemented")
	}
}