| | |
| | |
| | |
| |
|
| | package noder |
| |
|
| | import ( |
| | "go/constant" |
| |
|
| | "cmd/compile/internal/ir" |
| | "cmd/compile/internal/syntax" |
| | "cmd/compile/internal/typecheck" |
| | "cmd/compile/internal/types" |
| | "cmd/compile/internal/types2" |
| | "cmd/internal/src" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | type ImplicitNode interface { |
| | ir.Node |
| | SetImplicit(x bool) |
| | } |
| |
|
| | |
| | func Implicit(n ImplicitNode) ImplicitNode { |
| | n.SetImplicit(true) |
| | return n |
| | } |
| |
|
| | |
| | func typed(typ *types.Type, n ir.Node) ir.Node { |
| | n.SetType(typ) |
| | n.SetTypecheck(1) |
| | return n |
| | } |
| |
|
| | |
| |
|
| | |
| | |
| | func FixValue(typ *types.Type, val constant.Value) constant.Value { |
| | assert(typ.Kind() != types.TFORW) |
| | switch { |
| | case typ.IsInteger(): |
| | val = constant.ToInt(val) |
| | case typ.IsFloat(): |
| | val = constant.ToFloat(val) |
| | case typ.IsComplex(): |
| | val = constant.ToComplex(val) |
| | } |
| | if !typ.IsUntyped() { |
| | val = typecheck.ConvertVal(val, typ, false) |
| | } |
| | ir.AssertValidTypeForConst(typ, val) |
| | return val |
| | } |
| |
|
| | |
| |
|
| | func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr { |
| | n := typecheck.NodAddrAt(pos, x) |
| | typed(types.NewPtr(x.Type()), n) |
| | return n |
| | } |
| |
|
| | func Deref(pos src.XPos, typ *types.Type, x ir.Node) *ir.StarExpr { |
| | n := ir.NewStarExpr(pos, x) |
| | typed(typ, n) |
| | return n |
| | } |
| |
|
| | |
| |
|
| | func idealType(tv syntax.TypeAndValue) types2.Type { |
| | |
| | |
| | |
| | |
| | typ := types2.Unalias(tv.Type) |
| | if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 { |
| | switch basic.Kind() { |
| | case types2.UntypedNil: |
| | |
| | |
| | case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex: |
| | typ = types2.Typ[types2.Uint] |
| | if tv.Value != nil { |
| | s := constant.ToInt(tv.Value) |
| | assert(s.Kind() == constant.Int) |
| | if constant.Sign(s) < 0 { |
| | typ = types2.Typ[types2.Int] |
| | } |
| | } |
| | case types2.UntypedBool: |
| | typ = types2.Typ[types2.Bool] |
| | case types2.UntypedString: |
| | typ = types2.Typ[types2.String] |
| | case types2.UntypedRune: |
| | typ = types2.Typ[types2.Int32] |
| | default: |
| | return nil |
| | } |
| | } |
| | return typ |
| | } |
| |
|
| | func isTypeParam(t types2.Type) bool { |
| | _, ok := types2.Unalias(t).(*types2.TypeParam) |
| | return ok |
| | } |
| |
|
| | |
| | |
| | func isNotInHeap(typ types2.Type) bool { |
| | typ = types2.Unalias(typ) |
| | if named, ok := typ.(*types2.Named); ok { |
| | if obj := named.Obj(); obj.Name() == "nih" && obj.Pkg().Path() == "internal/runtime/sys" { |
| | return true |
| | } |
| | typ = named.Underlying() |
| | } |
| |
|
| | switch typ := typ.(type) { |
| | case *types2.Array: |
| | return isNotInHeap(typ.Elem()) |
| | case *types2.Struct: |
| | for i := 0; i < typ.NumFields(); i++ { |
| | if isNotInHeap(typ.Field(i).Type()) { |
| | return true |
| | } |
| | } |
| | return false |
| | default: |
| | return false |
| | } |
| | } |
| |
|