Example #1
0
// typAndValue returns a type and value from the type checker for an expression.
func (c *compiler) typAndValue(e ast.Expr) (types.TypeAndValue, bool) {
	tv, found := c.Types[e]
	if !found {
		c.errorf(e.Span().Start, "no type info for expression")
	}
	return tv, found
}
Example #2
0
// indirection dereferences a pointer and generate code to load it.
func (c *compiler) indirection(e ast.Expr, n *node, lv *arch.LV) *node {
	pos := e.Span().Start
	n = c.rvalue(n, lv)
	ptr, ok := lv.Type.(*types.Pointer)

	if !ok {
		c.errorf(pos, "indirection through non pointer")
		return nil
	} else if isVoidPointer(lv.Type) {
		c.errorf(pos, "dereferencing void pointer")
		return nil
	}

	lv.Ident = false
	lv.Type = ptr.Elem().Underlying()
	return n
}
Example #3
0
// typExprInternal is the main driver that type checks an expression.
func (c *checker) typExprInternal(e ast.Expr) Type {
	switch e := e.(type) {
	case *ast.EnumDecl:
		return c.typEnumDecl(e)

	case *ast.VarDecl:
		// defaults to int if there is no type, for declarations such as
		// volatile count = 0; and such
		if e.Type == nil {
			return Typ[Int]
		}
		return c.typExpr(e.Type)

	case *ast.BasicType:
		return c.typBasic(e)

	case *ast.RecordType:
		return c.typRecord(e)

	case *ast.FuncType:
		return c.typFunc(e)

	case *ast.ParenExpr:
		return c.typExpr(e.X)

	case *ast.StarExpr:
		return NewPointer(c.typExpr(e.X), nil)

	case nil:
		c.errorf(scan.NoPos, "invalid nil node")

	default:
		c.errorf(e.Span().Start, "%T: %v is not a type", e, e)
	}

	typ := Typ[Invalid]
	return typ
}
Example #4
0
// constExpr type checks an expression for a constant value.
func (c *checker) constExpr(x *operand, e ast.Expr) {
	c.expr(x, e)
	if x.mode != constant_ {
		c.errorf(e.Span().Start, "expected constant declaration, got %v", x.typ)
	}
}
Example #5
0
// exprInternal is the main driver, it does a recursive descent
// through the expressions to type check them.
func (c *checker) exprInternal(x *operand, e ast.Expr) exprType {
	x.mode = invalid
	x.typ = Typ[Invalid]

	pos := e.Span().Start
	switch e := e.(type) {
	case *ast.BadExpr:
		goto Error

	case *ast.BasicType:
		x.typ = c.typBasic(e)
		x.expr = e
		x.mode = typexpr
		return expression

	case *ast.Ident:
		c.ident(x, e, false)

	case *ast.StringLit:
		var text string
		for _, lit := range e.Lits {
			text += lit.Text[1 : len(lit.Text)-1]
		}
		text = strconv.Quote(text)
		x.setConst(scan.String, text)
		if x.mode == invalid {
			c.invalidAST(pos, "invalid literal %v", text)
		}

	case *ast.BasicLit:
		x.setConst(e.Type, e.Text)
		if x.mode == invalid {
			c.invalidAST(pos, "invalid literal %v", e.Text)
			goto Error
		}

	case *ast.CompositeLit:
		var y operand
		for _, elt := range e.Elts {
			c.expr(&y, elt)
			if y.mode != constant_ {
				c.errorf(y.pos(), "constant expression expected")
			}
		}

	case *ast.CallExpr:
		return c.call(x, e)

	case *ast.BinaryExpr:
		c.binary(x, e.X, e.Y, e.Op.Type)
		if x.mode == invalid {
			goto Error
		}

	case *ast.StarExpr:
		c.expr(x, e.X)
		switch x.mode {
		case invalid:
			goto Error
		case typexpr:
			x.typ = NewPointer(x.typ, nil)
		default:
			if typ, ok := x.typ.Underlying().(*Pointer); ok {
				x.mode = variable
				x.typ = typ.base
			} else {
				c.invalidOp(pos, "cannot indirect %s", x)
			}
		}

	case *ast.IndexExpr:
		c.expr(x, e.X)
		if x.mode == invalid {
			goto Error
		}

		valid := false
		switch typ := x.typ.Underlying().(type) {
		case *Pointer:
			valid = true
			if x.mode != variable {
				x.mode = value
			}
			x.typ = typ.Elem()
		}

		if !valid {
			c.invalidOp(x.pos(), "cannot index %s", x)
			goto Error
		}

		if e.Index == nil {
			c.invalidAST(pos, "missing index for %s", x)
			goto Error
		}
		c.index(e.Index)

	case *ast.UnaryExpr:
		c.expr(x, e.X)
		if x.mode == invalid {
			goto Error
		}
		c.unary(x, e, e.Op.Type)
		if x.mode == invalid {
			goto Error
		}

	case *ast.ParenExpr:
		exprType := c.expr(x, e.X)
		x.expr = e
		return exprType

	case *ast.SizeofExpr:
		c.expr(x, e.X)
		if x.mode == invalid {
			goto Error
		}

		typ := x.typ
		ptr, ok := typ.(*Pointer)
		if ok && ptr.Decay() != nil {
			typ = ptr.Decay()
		}

		x.mode = constant_
		x.val = constant.MakeInt64(int64(c.conf.Sizes.Sizeof(typ)))
		x.typ = Typ[Int]

	case *ast.SelectorExpr:
		c.selector(x, e)

	case *ast.CondExpr:
		var y, z, w operand
		c.expr(&y, e.Cond)
		c.expr(&z, e.X)
		c.expr(&w, e.Y)
		x.mode = value
		x.typ = z.typ

	case *ast.CastExpr:
		typ := c.typExpr(e.Type)
		c.expr(x, e.X)
		x.typ = typ

	case *ast.RecordType:
		x.mode = typexpr
		x.typ = c.typExpr(e)

	default:
		panic(fmt.Sprintf("%s: unknown expression type %T", e.Span().Start, e))
	}

	x.expr = e
	return expression

Error:
	x.mode = invalid
	x.expr = e
	return statement
}
Example #6
0
// exprInternal is the main function for generating code by figuring
// out what kind of expression it is.
func (c *compiler) exprInternal(e ast.Expr, lv *arch.LV) *node {
	lv.Ident = false

	pos := e.Span().Start
	tv, found := c.typAndValue(e)
	if !found {
		return nil
	}

	// for constants we can just get the value right away
	if tv.Value != nil {
		lv.Type = tv.Type
		lv.Value = tv.Value
		switch tv.Type {
		case types.Typ[types.UntypedString]:
			str, err := strconv.Unquote(tv.Value.String())
			if err != nil {
				c.errorf(pos, "invalid constant %v: %v", tv.Value, err)
			}
			c.cg.Data()
			lab := c.cg.Label()
			c.cg.Lab(lab)
			c.cg.Defs(str)
			c.cg.Defb(0)
			c.cg.Align(len(str)+1, c.cg.Int())
			lv.Addr = lab
			return newNode(opLdlab, lv, nil, nil, nil)

		default:
			return newNode(opLit, lv, nil, nil, nil)
		}
	}

	switch e := e.(type) {
	case *ast.BinaryExpr:
		return c.binaryExpr(e, lv)

	case *ast.UnaryExpr:
		return c.unaryExpr(e, lv)

	case *ast.SizeofExpr:
		return c.sizeofExpr(e, lv, tv)

	case *ast.StarExpr:
		return c.starExpr(e, lv)

	case *ast.CallExpr:
		return c.callExpr(e, lv)

	case *ast.Ident:
		return c.ident(e, lv, tv)

	case *ast.ParenExpr:
		return c.exprInternal(e.X, lv)

	case *ast.IndexExpr:
		return c.indexExpr(e, lv)

	case *ast.SelectorExpr:
		return c.selectorExpr(e, lv)

	case *ast.CondExpr:
		return c.condExpr(e, lv)

	case *ast.CastExpr:
		return c.castExpr(e, lv, tv)

	case *ast.BasicType:
		lv.Type = tv.Type

	default:
		c.errorf(pos, "invalid expression: %T", e)
	}

	return nil
}