Beispiel #1
0
// NewGlobalDecl returns a new external global variable declaration of the given
// name and underlying type. The variable is read-only if immutable is true.
func NewGlobalDecl(name string, underlying types.Type, immutable bool) (*GlobalDecl, error) {
	typ, err := types.NewPointer(underlying)
	if err != nil {
		return nil, errutil.Err(err)
	}
	return &GlobalDecl{name: name, typ: typ, underlying: underlying, immutable: immutable}, nil
}
Beispiel #2
0
// NewAlloca returns a new alloca instruction based on the given element type
// and number of elments.
//
// Pre-condition:
//    1. elem is a valid pointer element type (i.e. any type except void, label
//       and metadata)
func NewAlloca(elem types.Type, nelems int) (*Alloca, error) {
	// Determine result type.
	typ, err := types.NewPointer(elem)
	if err != nil {
		return nil, errutil.Err(err)
	}
	return &Alloca{elem: elem, nelems: nelems, typ: typ}, nil
}
Beispiel #3
0
func TestPointerString(t *testing.T) {
	golden := []struct {
		elem types.Type
		want string
		err  string
	}{
		// i=0
		{
			elem: i32Typ,
			want: "i32*",
		},
		// i=1
		{
			elem: f16Typ,
			want: "half*",
		},
		// i=2
		{
			elem: funcTyp,
			want: "i32 (i32)*",
		},
		// i=3
		{
			elem: i8PtrTyp,
			want: "i8**",
		},
		// i=4
		{
			elem: voidTyp, // void*
			want: "", err: `invalid pointer to "void"; use i8* instead`,
		},
		// i=5
		{
			elem: labelTyp, // label*
			want: "", err: `invalid pointer to "label"`,
		},
	}

	for i, g := range golden {
		typ, err := types.NewPointer(g.elem)
		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 := typ.String()
		if got != g.want {
			t.Errorf("i=%d: string mismatch; expected %v, got %v", i, g.want, got)
		}
	}
}
Beispiel #4
0
Datei: util.go Projekt: mewmew/uc
// toIrType converts the given uC type to the corresponding LLVM IR type.
func toIrType(n uctypes.Type) irtypes.Type {
	//TODO: implement, placeholder implementation
	var t irtypes.Type
	var err error
	switch ucType := n.(type) {
	case *uctypes.Basic:
		switch ucType.Kind {
		case uctypes.Int:
			//TODO: Get int width from compile env
			t, err = irtypes.NewInt(32)
		case uctypes.Char:
			t, err = irtypes.NewInt(8)
		case uctypes.Void:
			t = irtypes.NewVoid()
		}
	case *uctypes.Array:
		elem := toIrType(ucType.Elem)
		if ucType.Len == 0 {
			t, err = irtypes.NewPointer(elem)
		} else {
			t, err = irtypes.NewArray(elem, ucType.Len)
		}
	case *uctypes.Func:
		var params []*irtypes.Param
		variadic := false
		for _, p := range ucType.Params {
			//TODO: Add support for variadic
			if uctypes.IsVoid(p.Type) {
				break
			}
			pt := toIrType(p.Type)
			dbg.Printf("converting type %#v to %#v", p.Type, pt)
			params = append(params, irtypes.NewParam(pt, p.Name))
		}
		result := toIrType(ucType.Result)
		t, err = irtypes.NewFunc(result, params, variadic)
	default:
		panic(fmt.Sprintf("support for translating type %T not yet implemented.", ucType))
	}
	if err != nil {
		panic(errutil.Err(err))
	}
	if t == nil {
		panic(errutil.Newf("Conversion failed: %#v", n))
	}
	return t
}
Beispiel #5
0
// NewGetElementPtr returns a new getelementptr instruction based on the given
// source address and element indices.
//
// Pre-condition:
//    1. srcAddr is of pointer type
//    2. indices used to index structure fields are integer constants
func NewGetElementPtr(srcAddr value.Value, indices []value.Value) (*GetElementPtr, error) {
	// Validate that srcAddr is of pointer type.
	srcAddrType, ok := srcAddr.Type().(*types.Pointer)
	if !ok {
		return nil, errutil.Newf("invalid source address pointer type; expected *types.Pointer, got %T", srcAddr.Type())
	}
	// Validate that indices used to index structure fields are integer
	// constants.
	e := srcAddrType.Elem()
	for i, index := range indices {
		if i == 0 {
			// Ignore checking the 0th index as it simply follows the pointer of
			// srcAddr.
			//
			// ref: http://llvm.org/docs/GetElementPtr.html#why-is-the-extra-0-index-required
			continue
		}
		switch ee := e.(type) {
		case *types.Pointer:
			// ref: http://llvm.org/docs/GetElementPtr.html#what-is-dereferenced-by-gep
			return nil, errutil.Newf(`unable to index into element of pointer type; for more information, see http://llvm.org/docs/GetElementPtr.html#what-is-dereferenced-by-gep`)
		case *types.Array:
			e = ee.Elem()
		case *types.Struct:
			idx, ok := index.(*constant.Int)
			if !ok {
				return nil, errutil.Newf("invalid index type for structure element; expected *constant.Int, got %T", index)
			}
			e = ee.Fields()[idx.Value().Int64()]
		default:
			panic(fmt.Sprintf("instruction.NewGetElementPtr: support for indexing element type %T not yet implemented", e))
		}
	}
	// Determine result type.
	typ, err := types.NewPointer(e)
	if err != nil {
		return nil, errutil.Err(err)
	}
	// Determine element type.
	elem := srcAddrType.Elem()
	return &GetElementPtr{srcAddr: srcAddr, indices: indices, typ: typ, elem: elem}, nil
}
Beispiel #6
0
Datei: expr.go Projekt: llir/llvm
// NewGetElementPtr returns a new getelementptr expression based on the given
// element type, address and element indices.
//
// Preconditions:
//    * elem is of the same type as addr.Type().Elem().
//    * addr is of pointer type.
//    * indices used to index structure fields are integer constants.
func NewGetElementPtr(elem types.Type, addr value.Value, indices []Constant) (*GetElementPtr, error) {
	// Sanity checks.
	addrType, ok := addr.Type().(*types.Pointer)
	if !ok {
		return nil, errutil.Newf("invalid pointer type; expected *types.Pointer, got %T", addr.Type())
	}
	if !types.Equal(elem, addrType.Elem()) {
		return nil, errutil.Newf("type mismatch between %v and %v", elem, addrType.Elem())
	}

	e := addrType.Elem()
	for i, index := range indices {
		if i == 0 {
			// Ignore checking the 0th index as it simply follows the pointer of
			// addr.
			//
			// ref: http://llvm.org/docs/GetElementPtr.html#why-is-the-extra-0-index-required
			continue
		}
		switch ee := e.(type) {
		case *types.Pointer:
			// ref: http://llvm.org/docs/GetElementPtr.html#what-is-dereferenced-by-gep
			return nil, errutil.Newf(`unable to index into element of pointer type; for more information, see http://llvm.org/docs/GetElementPtr.html#what-is-dereferenced-by-gep`)
		case *types.Array:
			e = ee.Elem()
		case *types.Struct:
			idx, ok := index.(*Int)
			if !ok {
				return nil, errutil.Newf("invalid index type for structure element; expected *constant.Int, got %T", index)
			}
			e = ee.Fields()[idx.Value().Int64()]
		default:
			panic(fmt.Sprintf("constant.NewGetElementPtr: support for indexing element type %T not yet implemented", e))
		}
	}
	typ, err := types.NewPointer(e)
	if err != nil {
		return nil, errutil.Err(err)
	}
	return &GetElementPtr{typ: typ, elem: elem, addr: addr, indices: indices}, nil
}
Beispiel #7
0
Datei: irx.go Projekt: llir/llvm
// NewPointerType returns a new pointer type based on the given element type.
func NewPointerType(elem interface{}) (*types.Pointer, error) {
	if elem, ok := elem.(types.Type); ok {
		return types.NewPointer(elem)
	}
	return nil, errutil.Newf("invalid pointer element type; expected types.Type, got %T", elem)
}
Beispiel #8
0
func init() {
	var err error
	// Void type.
	// void
	voidTyp = types.NewVoid()

	// Integer types.
	// i1
	i1Typ, err = types.NewInt(1)
	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)
	}

	// Floating point types.
	// half
	f16Typ, err = types.NewFloat(types.Float16)
	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)
	}
	// x86_fp80
	f80_x86Typ, err = types.NewFloat(types.Float80_x86)
	if err != nil {
		log.Fatalln(err)
	}
	// ppc_fp128
	f128_ppcTyp, err = types.NewFloat(types.Float128_PPC)

	// MMX type.
	// x86_mmx
	mmxTyp = types.NewMMX()

	// Label type.
	// label
	labelTyp = types.NewLabel()

	// Metadata type.
	// metadata
	metadataTyp = types.NewMetadata()

	// Function types.
	// void ()
	voidFuncTyp, err = types.NewFunc(voidTyp, nil, false)
	if err != nil {
		log.Fatalln(err)
	}
	// i32 ()
	i32FuncTyp, err = types.NewFunc(i32Typ, nil, false)
	if err != nil {
		log.Fatalln(err)
	}
	// void (i32)
	i32Param := types.NewParam(i32Typ, "")
	i32Params := []*types.Param{i32Param}
	voidFunci32Typ, err = types.NewFunc(voidTyp, i32Params, false)
	if err != nil {
		log.Fatalln(err)
	}
	// void (float)
	f32Param := types.NewParam(f32Typ, "")
	f32Params := []*types.Param{f32Param}
	voidFuncf32Typ, err = types.NewFunc(voidTyp, f32Params, false)
	if err != nil {
		log.Fatalln(err)
	}
	// void (i32, ...)
	voidFunci32EllipsisTyp, err = types.NewFunc(voidTyp, i32Params, true)
	if err != nil {
		log.Fatalln(err)
	}
	// i32 (i32)
	funcTyp, err = types.NewFunc(i32Typ, i32Params, false)
	if err != nil {
		log.Fatalln(err)
	}

	// Pointer types.
	// i8*
	i8PtrTyp, err = types.NewPointer(i8Typ)
	if err != nil {
		log.Fatalln(err)
	}
	// half*
	f16PtrTyp, err = types.NewPointer(f16Typ)
	if err != nil {
		log.Fatalln(err)
	}
	// x86_mmx*
	mmxPtrTyp, err = types.NewPointer(mmxTyp)
	if err != nil {
		log.Fatalln(err)
	}
	// i32 (i32)*
	funcPtrTyp, err = types.NewPointer(funcTyp)
	if err != nil {
		log.Fatalln(err)
	}

	// Vector types.
	// <1 x i8>
	i8x1VecTyp, err = types.NewVector(i8Typ, 1)
	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)
	}
	// <3 x half>
	f16x3VecTyp, err = types.NewVector(f16Typ, 3)
	if err != nil {
		log.Fatalln(err)
	}
	// <4 x float>
	f32x4VecTyp, err = types.NewVector(f32Typ, 4)
	if err != nil {
		log.Fatalln(err)
	}
	// <5 x double>
	f64x5VecTyp, err = types.NewVector(f64Typ, 5)
	if err != nil {
		log.Fatalln(err)
	}
	// <6 x fp128>
	f128x6VecTyp, err = types.NewVector(f128Typ, 6)
	if err != nil {
		log.Fatalln(err)
	}
	// <7 x x86_fp80>
	f80_x86x7VecTyp, err = types.NewVector(f80_x86Typ, 7)
	if err != nil {
		log.Fatalln(err)
	}
	// <8 x ppc_fp128>
	f128_ppcx8VecTyp, err = types.NewVector(f128_ppcTyp, 8)
	if err != nil {
		log.Fatalln(err)
	}
	// <9 x i8*>
	i8Ptrx9VecTyp, err = types.NewVector(i8PtrTyp, 9)
	if err != nil {
		log.Fatalln(err)
	}
	// <10 x half*>
	f16Ptrx10VecTyp, err = types.NewVector(f16PtrTyp, 10)
	if err != nil {
		log.Fatalln(err)
	}

	// Array types.
	// [1 x i8]
	i8x1ArrTyp, err = types.NewArray(i8Typ, 1)
	if err != nil {
		log.Fatalln(err)
	}
	// [2 x i32]
	i32x2ArrTyp, err = types.NewArray(i32Typ, 2)
	if err != nil {
		log.Fatalln(err)
	}
	// [3 x i32]
	i32x3ArrTyp, err = types.NewArray(i32Typ, 3)
	if err != nil {
		log.Fatalln(err)
	}
	// [3 x half]
	f16x3ArrTyp, err = types.NewArray(f16Typ, 3)
	if err != nil {
		log.Fatalln(err)
	}
	// [4 x float]
	f32x4ArrTyp, err = types.NewArray(f32Typ, 4)
	if err != nil {
		log.Fatalln(err)
	}
	// [5 x double]
	f64x5ArrTyp, err = types.NewArray(f64Typ, 5)
	if err != nil {
		log.Fatalln(err)
	}
	// [6 x fp128]
	f128x6ArrTyp, err = types.NewArray(f128Typ, 6)
	if err != nil {
		log.Fatalln(err)
	}
	// [7 x x86_fp80]
	f80_x86x7ArrTyp, err = types.NewArray(f80_x86Typ, 7)
	if err != nil {
		log.Fatalln(err)
	}
	// [8 x ppc_fp128]
	f128_ppcx8ArrTyp, err = types.NewArray(f128_ppcTyp, 8)
	if err != nil {
		log.Fatalln(err)
	}
	// [9 x i8*]
	i8Ptrx9ArrTyp, err = types.NewArray(i8PtrTyp, 9)
	if err != nil {
		log.Fatalln(err)
	}
	// [10 x half*]
	f16Ptrx10ArrTyp, err = types.NewArray(f16PtrTyp, 10)
	if err != nil {
		log.Fatalln(err)
	}

	// Structure types.
	// {i32, i8}
	fields := []types.Type{i32Typ, i8Typ}
	i32i8structTyp, err = types.NewStruct(fields, false)
	if err != nil {
		log.Fatalln(err)
	}
	// {i32, i32}
	fields = []types.Type{i32Typ, i32Typ}
	i32i32structTyp, err = types.NewStruct(fields, false)
	if err != nil {
		log.Fatalln(err)
	}
	// {i32, i8, i8}
	fields = []types.Type{i32Typ, i8Typ, i8Typ}
	i32i8i8structTyp, err = types.NewStruct(fields, false)
	if err != nil {
		log.Fatalln(err)
	}
	// {i1, float, x86_mmx, i32 (i32)*, <1 x i8>, [3 x half]}
	fields = []types.Type{i1Typ, f32Typ, mmxTyp, funcPtrTyp, i8x1VecTyp, f16x3ArrTyp}
	structTyp, err = types.NewStruct(fields, false)
	if err != nil {
		log.Fatalln(err)
	}
}