Example #1
0
File: util.go Project: mewmew/uc
// constOne returns the integer constant one of the given type.
func constOne(typ irtypes.Type) constant.Constant {
	one, err := constant.NewInt(typ, "1")
	if err != nil {
		panic(fmt.Sprintf("unable to create integer constant one; %v", err))
	}
	return one
}
Example #2
0
File: util.go Project: mewmew/uc
// constZero returns the integer constant zero of the given type.
func constZero(typ irtypes.Type) constant.Constant {
	zero, err := constant.NewInt(typ, "0")
	if err != nil {
		panic(fmt.Sprintf("unable to create integer constant zero; %v", err))
	}
	return zero
}
Example #3
0
File: lower.go Project: mewmew/uc
// globalVarDecl lowers the given global variable declaration to LLVM IR,
// emitting code to m.
func (m *Module) globalVarDecl(n *ast.VarDecl) {
	// Input:
	//    int x;
	// Output:
	//    @x = global i32 0
	ident := n.Name()
	dbg.Printf("create global variable: %v", n)
	typ := toIrType(n.Type())
	var val value.Value
	switch {
	case n.Val != nil:
		panic("support for global variable initializer not yet implemented")
	case irtypes.IsInt(typ):
		var err error
		val, err = constant.NewInt(typ, "0")
		if err != nil {
			panic(fmt.Sprintf("unable to create integer constant; %v", err))
		}
	default:
		val = constant.NewZeroInitializer(typ)
	}
	global, err := ir.NewGlobalDef(ident.Name, val, false)
	if err != nil {
		panic(fmt.Sprintf("unable to create global variable definition %q", ident))
	}
	m.setIdentValue(ident, global)
	// Emit global variable definition.
	m.emitGlobal(global)
}
Example #4
0
File: util.go Project: 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)
}
Example #5
0
File: lower.go Project: mewmew/uc
// basicLit lowers the given basic literal to LLVM IR, emitting code to f.
func (m *Module) basicLit(f *Function, n *ast.BasicLit) value.Value {
	typ := m.typeOf(n)
	switch n.Kind {
	case token.CharLit:
		s, err := strconv.Unquote(n.Val)
		if err != nil {
			panic(fmt.Sprintf("unable to unquote character literal; %v", err))
		}
		val, err := constant.NewInt(typ, strconv.Itoa(int(s[0])))
		if err != nil {
			panic(fmt.Sprintf("unable to create integer constant; %v", err))
		}
		return val
	case token.IntLit:
		val, err := constant.NewInt(typ, n.Val)
		if err != nil {
			panic(fmt.Sprintf("unable to create integer constant; %v", err))
		}
		return val
	default:
		panic(fmt.Sprintf("support for basic literal kind %v not yet implemented", n.Kind))
	}
}
Example #6
0
File: irx.go Project: llir/llvm
// NewValue returns a new value based on the given type and value.
func NewValue(typ, val interface{}) (value.Value, error) {
	// TODO: Verify type equality between typ and val.Type().
	//    * handled by constant.NewInt
	//    * ...
	if typ, ok := typ.(types.Type); ok {
		switch val := val.(type) {
		case *LocalDummy:
			return val, nil
		case *Global:
			// TODO: Retreive type from val.typ once support for forward reference
			// of global variable declarations have been added.
			// TODO: Add type-check between ptrType and val.typ.
			if typ, ok := typ.(*types.Pointer); ok {
				return constant.NewPointer(typ, val.name)
			}
			return nil, errutil.Newf("invalid global type; expected *types.Pointer, got %T", typ)
		case *IntConst:
			return constant.NewInt(typ, val.val)
		case *NullPointerConst:
			if typ, ok := typ.(*types.Pointer); ok {
				return constant.NewNullPointer(typ)
			}
			return nil, errutil.Newf("invalid null pointer type; expected *types.Pointer, got %T", typ)
		case *CharArrayConst:
			return constant.NewCharArray(typ, val.val)
		case *ZeroInitializer:
			return constant.NewZeroInitializer(typ), nil
		case *GetElementPtrExpr:
			return constant.NewGetElementPtr(val.elem, val.addr, val.indices)
		default:
			pretty.Println(val)
			panic(fmt.Sprintf("support for value type %T not yet implemented", val))
		}
	}
	return nil, errutil.Newf("invalid value type; expected types.Type, got %T", typ)
}
Example #7
0
func init() {
	// i1
	var err error
	i1Typ, err = types.NewInt(1)
	if err != nil {
		log.Fatalln(err)
	}
	// i3
	i3Typ, err = types.NewInt(3)
	if err != nil {
		log.Fatalln(err)
	}
	// i5
	i5Typ, err = types.NewInt(5)
	if err != nil {
		log.Fatalln(err)
	}
	// i8
	i8Typ, err = types.NewInt(8)
	if err != nil {
		log.Fatalln(err)
	}
	// i32
	i32Typ, err = types.NewInt(32)
	if err != nil {
		log.Fatalln(err)
	}
	// i64
	i64Typ, err = types.NewInt(64)
	if err != nil {
		log.Fatalln(err)
	}
	// float
	f32Typ, err = types.NewFloat(types.Float32)
	if err != nil {
		log.Fatalln(err)
	}
	// double
	f64Typ, err = types.NewFloat(types.Float64)
	if err != nil {
		log.Fatalln(err)
	}
	// fp128
	f128Typ, err = types.NewFloat(types.Float128)
	if err != nil {
		log.Fatalln(err)
	}
	// ppc_fp128
	f128_ppcTyp, err = types.NewFloat(types.Float128_PPC)
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x i32>
	i32x2VecTyp, err = types.NewVector(i32Typ, 2)
	if err != nil {
		log.Fatalln(err)
	}
	// <3 x i32>
	i32x3VecTyp, err = types.NewVector(i32Typ, 3)
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x float>
	f32x2VecTyp, err = types.NewVector(f32Typ, 2)
	if err != nil {
		log.Fatalln(err)
	}
	// <3 x float>
	f32x3VecTyp, err = types.NewVector(f32Typ, 3)
	if err != nil {
		log.Fatalln(err)
	}
	// [2 x i32]
	i32x2ArrTyp, err = types.NewArray(i32Typ, 2)
	if err != nil {
		log.Fatalln(err)
	}
	// {i32, i8}
	i32i8StructTyp, err = types.NewStruct([]types.Type{i32Typ, i8Typ}, false)
	if err != nil {
		log.Fatalln(err)
	}
	// [2 x {i32, i8}]
	i32i8x2ArrTyp, err = types.NewArray(i32i8StructTyp, 2)
	if err != nil {
		log.Fatalln(err)
	}

	// i1 1
	i1One, err = constant.NewInt(i1Typ, "1")
	if err != nil {
		log.Fatalln(err)
	}
	// i8 3
	i8Three, err = constant.NewInt(i8Typ, "3")
	if err != nil {
		log.Fatalln(err)
	}
	// i8 4
	i8Four, err = constant.NewInt(i8Typ, "4")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 -13
	i32MinusThirteen, err = constant.NewInt(i32Typ, "-13")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 -4
	i32MinusFour, err = constant.NewInt(i32Typ, "-4")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 -3
	i32MinusThree, err = constant.NewInt(i32Typ, "-3")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 1
	i32One, err = constant.NewInt(i32Typ, "1")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 2
	i32Two, err = constant.NewInt(i32Typ, "2")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 3
	i32Three, err = constant.NewInt(i32Typ, "3")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 4
	i32Four, err = constant.NewInt(i32Typ, "4")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 15
	i32Fifteen, err = constant.NewInt(i32Typ, "15")
	if err != nil {
		log.Fatalln(err)
	}
	// i32 42
	i32FortyTwo, err = constant.NewInt(i32Typ, "42")
	if err != nil {
		log.Fatalln(err)
	}
	// float -3.0
	f32MinusThree, err = constant.NewFloat(f32Typ, "-3.0")
	if err != nil {
		log.Fatalln(err)
	}
	// float -4.0
	f32MinusFour, err = constant.NewFloat(f32Typ, "-4.0")
	if err != nil {
		log.Fatalln(err)
	}
	// float 1.0
	f32One, err = constant.NewFloat(f32Typ, "1.0")
	if err != nil {
		log.Fatalln(err)
	}
	// float 2.0
	f32Two, err = constant.NewFloat(f32Typ, "2.0")
	if err != nil {
		log.Fatalln(err)
	}
	// float 3.0
	f32Three, err = constant.NewFloat(f32Typ, "3.0")
	if err != nil {
		log.Fatalln(err)
	}
	// float 4.0
	f32Four, err = constant.NewFloat(f32Typ, "4.0")
	if err != nil {
		log.Fatalln(err)
	}
	// double 4.0
	f64Four, err = constant.NewFloat(f64Typ, "4.0")
	if err != nil {
		log.Fatalln(err)
	}
	// TODO: Uncomment when fp128 and ppc_fp128 are supported.
	/*
		// fp128 3.0
		f128Three, err = constant.NewFloat(f128Typ, "3.0")
		if err != nil {
			log.Fatalln(err)
		}
		// ppc_fp128 4.0
		f128_ppcFour, err = constant.NewFloat(f128_ppcTyp, "4.0")
		if err != nil {
			log.Fatalln(err)
		}
	*/
	// <3 x i32> <i32 1, i32 2, i32 3>
	i32x3OneTwoThree, err = constant.NewVector(i32x3VecTyp, []constant.Constant{i32One, i32Two, i32Three})
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x i32> <i32 3, i32 42>
	i32x2VecThreeFortyTwo, err = constant.NewVector(i32x2VecTyp, []constant.Constant{i32Three, i32FortyTwo})
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x i32> <i32 -3, i32 15>
	i32x2VecMinusThreeFifteen, err = constant.NewVector(i32x2VecTyp, []constant.Constant{i32MinusThree, i32Fifteen})
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x float> <float 3.0, float 4.0>
	f32x2VecThreeFour, err = constant.NewVector(f32x2VecTyp, []constant.Constant{f32Three, f32Four})
	if err != nil {
		log.Fatalln(err)
	}
	// <2 x float> <float -3.0, float 4.0>
	f32x2VecMinusThreeFour, err = constant.NewVector(f32x2VecTyp, []constant.Constant{f32MinusThree, f32Four})
	if err != nil {
		log.Fatalln(err)
	}
	// <3 x float> <float 3.0, float 2.0, float 1.0>
	f32x3VecThreeFourFifteen, err = constant.NewVector(f32x3VecTyp, []constant.Constant{f32Three, f32Two, f32One})
	if err != nil {
		log.Fatalln(err)
	}
	// {i32, i8} {i32 4, i8 3}
	i32i8FourThree, err = constant.NewStruct(i32i8StructTyp, []constant.Constant{i32Four, i8Three})
	if err != nil {
		log.Fatalln(err)
	}
	// {i32, i8} {i32 3, i8 4}
	i32i8ThreeFour, err = constant.NewStruct(i32i8StructTyp, []constant.Constant{i32Three, i8Four})
	if err != nil {
		log.Fatalln(err)
	}
}
Example #8
0
func TestIntString(t *testing.T) {
	golden := []struct {
		input string
		typ   types.Type
		want  string
		err   string
	}{
		// i=0
		{
			input: "true", typ: i1Typ,
			want: "i1 true",
		},
		// i=1
		{
			input: "1", typ: i1Typ,
			want: "i1 true",
		},
		// i=2
		{
			input: "false", typ: i1Typ,
			want: "i1 false",
		},
		// i=3
		{
			input: "0", typ: i1Typ,
			want: "i1 false",
		},
		// i=4
		{
			input: "2", typ: i1Typ,
			want: "", err: `invalid integer constant "2" for boolean type`,
		},
		// i=5
		{
			input: "true", typ: i32Typ,
			want: "", err: `integer constant "true" type mismatch; expected i1, got i32`,
		},
		// i=6
		{
			input: "false", typ: i32Typ,
			want: "", err: `integer constant "false" type mismatch; expected i1, got i32`,
		},
		// i=7
		{
			input: "42", typ: i32Typ,
			want: "i32 42",
		},
		// i=8
		{
			input: "-137438953472", typ: i64Typ,
			want: "i64 -137438953472",
		},
		// i=9
		{
			input: "3.0", typ: f32Typ,
			want: "", err: `invalid type "float" for integer constant`,
		},
		// i=10
		{
			input: "foo", typ: i64Typ,
			want: "", err: `unable to parse integer constant "foo"`,
		},
	}

	for i, g := range golden {
		v, err := constant.NewInt(g.typ, g.input)
		if !sameError(err, g.err) {
			t.Errorf("i=%d: error mismatch; expected %v, got %v", i, g.err, err)
			continue
		} else if err != nil {
			// Expected error match, check next test case.
			continue
		}
		got := fmt.Sprintf("%s %s", v.Type(), v)
		if got != g.want {
			t.Errorf("i=%d: string mismatch; expected %v, got %v", i, g.want, got)
		}
	}
}