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 }
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 }
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(), } }
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) }
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") }
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") }
// IsBool checks if the ref is a single boolean ref. func (r *Ref) IsBool() bool { return r.IsSingle() && types.IsBasic(r.Type(), types.Bool) }
func (r *ref) IsBool() bool { if !r.IsSingle() { return false } return types.IsBasic(r.Type(), types.Bool) }
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 }