Пример #1
0
func regSizeCastable(to, from types.T) bool {
	if types.IsPointer(to) && types.IsPointer(from) {
		return true
	}
	if isPointerType(to) && types.IsBasic(from, types.Uint) {
		return true
	}
	if types.IsBasic(to, types.Uint) && isPointerType(from) {
		return true
	}
	return false
}
Пример #2
0
func buildUnaryOpExpr(b *builder, expr *ast.OpExpr) tast.Expr {
	opTok := expr.Op
	op := opTok.Lit
	opPos := opTok.Pos

	B := b.buildExpr(expr.B)
	if B == nil {
		return nil
	}
	bref := B.R()
	if !bref.IsSingle() {
		b.Errorf(opPos, "%q on %s", op, bref)
		return nil
	}

	btyp := bref.T
	if op == "&" {
		return refAddress(b, opTok, B)
	} else if types.IsConst(btyp) {
		return unaryOpConst(b, opTok, B)
	} else if types.IsInteger(btyp) {
		return unaryOpInt(b, opTok, B)
	} else if types.IsBasic(btyp, types.Bool) {
		return unaryOpBool(b, opTok, B)
	}

	b.Errorf(opPos, "invalid unary operator %q", op)
	return nil
}
Пример #3
0
func makeArg(t *types.Arg) *ir.FuncArg {
	return &ir.FuncArg{
		Name:         t.Name,
		Size:         t.Size(),
		U8:           types.IsBasic(t.T, types.Uint8),
		RegSizeAlign: t.RegSizeAlign(),
	}
}
Пример #4
0
func buildStarExpr(b *builder, expr *tast.StarExpr) *ref {
	addr := b.buildExpr(expr.Expr)
	nilPointerPanic(b, addr.IR())
	t := addr.Type().(*types.Pointer).T
	retIR := ir.NewAddrRef(
		addr.IR(), // base
		t.Size(),  // size
		0,         // offset
		types.IsBasic(t, types.Uint8), // is byte?
		t.RegSizeAlign(),              // is aligned?
	)
	return newAddressableRef(t, retIR)
}
Пример #5
0
func buildBinaryOpExpr(b *builder, expr *tast.OpExpr) *ref {
	op := expr.Op.Lit
	A := b.buildExpr(expr.A)
	atyp := A.Type()
	if types.IsBasic(atyp, types.Bool) && (op == "&&" || op == "||") {
		switch op {
		case "&&":
			return buildLogicAnd(b, A, expr.B)
		case "||":
			return buildLogicOr(b, A, expr.B)
		}
		panic("unreachable")
	}

	B := b.buildExpr(expr.B)
	btyp := B.Type()
	if types.IsConst(atyp) && types.IsConst(btyp) {
		return binaryOpConst(b, op, A, B)
	}

	if op == ">>" || op == "<<" {
		ret := b.newTemp(atyp)
		buildShift(b, ret, A, B, op)
		return ret
	}

	if ok, t := types.SameBasic(atyp, btyp); ok {
		switch t {
		case types.Int, types.Int8:
			return binaryOpInt(b, op, A, B, t)
		case types.Uint, types.Uint8:
			return binaryOpUint(b, op, A, B, t)
		case types.Bool:
			return binaryOpBool(b, op, A, B)
		}
		panic("bug")
	}

	if types.IsNil(atyp) && types.IsNil(btyp) {
		return binaryOpNil(b, op, A, B)
	} else if types.BothPointer(atyp, btyp) {
		return binaryOpPtr(b, op, A, B)
	} else if types.BothFuncPointer(atyp, btyp) {
		return binaryOpPtr(b, op, A, B)
	} else if types.BothSlice(atyp, btyp) {
		return binaryOpSlice(b, op, A, B)
	}
	panic("bug")
}
Пример #6
0
func buildUnaryOpExpr(b *builder, expr *tast.OpExpr) *ref {
	op := expr.Op.Lit
	B := b.buildExpr(expr.B)
	btyp := B.Type()
	if op == "&" {
		ret := b.newTemp(&types.Pointer{btyp})
		b.b.Arith(ret.IR(), nil, op, B.IR())
		return ret
	} else if types.IsConst(btyp) {
		panic("bug")
	} else if types.IsInteger(btyp) {
		return unaryOpInt(b, op, B)
	} else if types.IsBasic(btyp, types.Bool) {
		return unaryOpBool(b, op, B)
	}
	panic("bug")
}
Пример #7
0
// IsBool checks if the ref is a single boolean ref.
func (r *Ref) IsBool() bool {
	return r.IsSingle() && types.IsBasic(r.Type(), types.Bool)
}
Пример #8
0
func (r *ref) IsBool() bool {
	if !r.IsSingle() {
		return false
	}
	return types.IsBasic(r.Type(), types.Bool)
}
Пример #9
0
func buildCallMake(b *builder, expr *ast.CallExpr, f tast.Expr) tast.Expr {
	args := buildExprList(b, expr.Args)
	if args == nil {
		return nil
	}

	n := args.R().Len()
	if n == 0 {
		b.Errorf(expr.Lparen.Pos, "make() takes at least one argument")
		return nil
	}

	argsList, ok := tast.MakeExprList(args)
	if !ok {
		b.Errorf(expr.Lparen.Pos, "make() only takes a literal list")
		return nil
	}

	arg0 := argsList.Exprs[0]
	t, ok := arg0.R().T.(*types.Type)
	if !ok {
		b.Errorf(expr.Lparen.Pos, "make() takes a type as the 1st argument")
		return nil
	}
	switch st := t.T.(type) {
	case *types.Slice:
		if n != 3 {
			b.Errorf(expr.Lparen.Pos, "make() slice takes 3 arguments")
			return nil
		}

		size := argsList.Exprs[1]
		pos := ast.ExprPos(expr.Args.Exprs[1])
		size = checkArrayIndex(b, size, pos)
		if size == nil {
			return nil
		}

		start := argsList.Exprs[2]
		startType := start.R().T
		startPos := ast.ExprPos(expr.Args.Exprs[2])
		if v, ok := types.NumConst(startType); ok {
			start = constCastUint(b, startPos, v, start)
			if start == nil {
				return nil
			}
		} else if !types.IsBasic(startType, types.Uint) {
			pt := types.PointerOf(startType)
			if pt == nil || !types.SameType(pt, st.T) {
				b.Errorf(startPos,
					"make() takes an uint or a typed pointer as the 3rd arg",
				)
				return nil
			}
		}

		callArgs := tast.NewExprList()
		callArgs.Append(arg0)
		callArgs.Append(size)
		callArgs.Append(start)

		r := tast.NewRef(st)
		return &tast.CallExpr{f, callArgs, r}
	}

	b.Errorf(expr.Lparen.Pos, "cannot make() type %s", t.T)
	return nil
}