예제 #1
0
파일: lower.go 프로젝트: mewmew/uc
// indexExpr lowers the given index expression to LLVM IR, emitting code to f.
func (m *Module) indexExpr(f *Function, n *ast.IndexExpr) value.Value {
	index := m.expr(f, n.Index)
	// Extend the index to a 64-bit integer.
	if !irtypes.Equal(index.Type(), irtypes.I64) {
		index = m.convert(f, index, irtypes.I64)
	}
	typ := m.typeOf(n.Name)
	array := m.valueFromIdent(f, n.Name)

	// Dereference pointer pointer.
	elem := typ
	addr := array
	zero := constZero(irtypes.I64)
	indices := []value.Value{zero, index}
	if typ, ok := typ.(*irtypes.Pointer); ok {
		elem = typ.Elem()

		// Emit load instruction.
		// TODO: Validate typ against array.Elem().
		loadInst, err := instruction.NewLoad(array)
		if err != nil {
			panic(fmt.Sprintf("unable to create load instruction; %v", err))
		}
		addr = f.emitInst(loadInst)
		indices = []value.Value{index}
	}

	// Emit getelementptr instruction.
	if m.isGlobal(n.Name) {
		var is []constant.Constant
		for _, index := range indices {
			i, ok := index.(constant.Constant)
			if !ok {
				break
			}
			is = append(is, i)
		}
		if len(is) == len(indices) {
			// In accordance with Clang, emit getelementptr constant expressions
			// for global variables.
			gepExpr, err := constant.NewGetElementPtr(elem, addr, is)
			if err != nil {
				panic(fmt.Sprintf("unable to create getelementptr expression; %v", err))
			}
			return gepExpr
		}
	}
	// TODO: Validate elem against array.Elem().
	gepInst, err := instruction.NewGetElementPtr(addr, indices)
	if err != nil {
		panic(fmt.Sprintf("unable to create getelementptr instruction; %v", err))
	}
	return f.emitInst(gepInst)
}
예제 #2
0
파일: lower.go 프로젝트: mewmew/uc
// ident lowers the given identifier to LLVM IR, emitting code to f.
func (m *Module) ident(f *Function, ident *ast.Ident) value.Value {
	switch typ := m.typeOf(ident).(type) {
	case *irtypes.Array:
		array := m.valueFromIdent(f, ident)
		zero := constZero(irtypes.I64)
		indices := []value.Value{zero, zero}

		// Emit getelementptr instruction.
		if m.isGlobal(ident) {
			var is []constant.Constant
			for _, index := range indices {
				i, ok := index.(constant.Constant)
				if !ok {
					break
				}
				is = append(is, i)
			}
			if len(is) == len(indices) {
				// In accordance with Clang, emit getelementptr constant expressions
				// for global variables.
				gepExpr, err := constant.NewGetElementPtr(typ, array, is)
				if err != nil {
					panic(fmt.Sprintf("unable to create getelementptr expression; %v", err))
				}
				return gepExpr
			}
		}
		gepInst, err := instruction.NewGetElementPtr(array, indices)
		if err != nil {
			panic(fmt.Sprintf("unable to create getelementptr instruction; %v", err))
		}
		return f.emitInst(gepInst)
	case *irtypes.Pointer:
		// Emit load instruction.
		// TODO: Validate typ against srcAddr.Elem().
		loadInst, err := instruction.NewLoad(m.valueFromIdent(f, ident))
		if err != nil {
			panic(fmt.Sprintf("unable to create load instruction; %v", err))
		}
		return f.emitInst(loadInst)
	default:
		return m.valueFromIdent(f, ident)
	}
}
예제 #3
0
파일: irx.go 프로젝트: 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)
}