1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/types"
19 func AssignConv(n ir.Node, t *types.Type, context string) ir.Node {
20 return assignconvfn(n, t, func() string { return context })
23 // LookupNum returns types.LocalPkg.LookupNum(prefix, n).
24 func LookupNum(prefix string, n int) *types.Sym {
25 return types.LocalPkg.LookupNum(prefix, n)
28 // Given funarg struct list, return list of fn args.
29 func NewFuncParams(origs []*types.Field, mustname bool) []*types.Field {
30 res := make([]*types.Field, len(origs))
31 for i, orig := range origs {
33 if mustname && (s == nil || s.Name == "_") {
34 // invent a name so that we can refer to it in the trampoline
35 s = LookupNum(".anon", i)
36 } else if s != nil && s.Pkg != types.LocalPkg {
37 // TODO(mdempsky): Preserve original position, name, and package.
40 p := types.NewField(orig.Pos, s, orig.Type)
41 p.SetIsDDD(orig.IsDDD())
47 // NodAddr returns a node representing &n at base.Pos.
48 func NodAddr(n ir.Node) *ir.AddrExpr {
49 return NodAddrAt(base.Pos, n)
52 // NodAddrAt returns a node representing &n at position pos.
53 func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
55 return ir.NewAddrExpr(pos, n)
58 func markAddrOf(n ir.Node) ir.Node {
59 if IncrementalAddrtaken {
60 // We can only do incremental addrtaken computation when it is ok
61 // to typecheck the argument of the OADDR. That's only safe after the
62 // main typecheck has completed, and not loading the inlined body.
63 // The argument to OADDR needs to be typechecked because &x[i] takes
64 // the address of x if x is an array, but not if x is a slice.
65 // Note: OuterValue doesn't work correctly until n is typechecked.
66 n = typecheck(n, ctxExpr)
67 if x := ir.OuterValue(n); x.Op() == ir.ONAME {
68 x.Name().SetAddrtaken(true)
71 // Remember that we built an OADDR without computing the Addrtaken bit for
72 // its argument. We'll do that later in bulk using computeAddrtaken.
78 // If IncrementalAddrtaken is false, we do not compute Addrtaken for an OADDR Node
79 // when it is built. The Addrtaken bits are set in bulk by computeAddrtaken.
80 // If IncrementalAddrtaken is true, then when an OADDR Node is built the Addrtaken
81 // field of its argument is updated immediately.
82 var IncrementalAddrtaken = false
84 // If DirtyAddrtaken is true, then there are OADDR whose corresponding arguments
85 // have not yet been marked as Addrtaken.
86 var DirtyAddrtaken = false
88 func ComputeAddrtaken(funcs []*ir.Func) {
89 var doVisit func(n ir.Node)
90 doVisit = func(n ir.Node) {
91 if n.Op() == ir.OADDR {
92 if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME {
93 x.Name().SetAddrtaken(true)
94 if x.Name().IsClosureVar() {
95 // Mark the original variable as Addrtaken so that capturevars
96 // knows not to pass it by value.
97 x.Name().Defn.Name().SetAddrtaken(true)
101 if n.Op() == ir.OCLOSURE {
102 ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doVisit)
106 for _, fn := range funcs {
107 ir.Visit(fn, doVisit)
111 // LinksymAddr returns a new expression that evaluates to the address
112 // of lsym. typ specifies the type of the addressed memory.
113 func LinksymAddr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *ir.AddrExpr {
114 n := ir.NewLinksymExpr(pos, lsym, typ)
115 return Expr(NodAddrAt(pos, n)).(*ir.AddrExpr)
118 func NodNil() ir.Node {
119 return ir.NewNilExpr(base.Pos, types.Types[types.TNIL])
122 // AddImplicitDots finds missing fields in obj.field that
123 // will give the shortest unique addressing and
124 // modifies the tree with missing field names.
125 func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
126 n.X = typecheck(n.X, ctxType|ctxExpr)
132 if n.X.Op() == ir.OTYPE {
141 switch path, ambig := dotpath(s, t, nil, false); {
143 // rebuild elided dots
144 for c := len(path) - 1; c >= 0; c-- {
145 dot := ir.NewSelectorExpr(n.Pos(), ir.ODOT, n.X, path[c].field.Sym)
146 dot.SetImplicit(true)
147 dot.SetType(path[c].field.Type)
151 base.Errorf("ambiguous selector %v", n)
158 // CalcMethods calculates all the methods (including embedding) of a non-interface
160 func CalcMethods(t *types.Type) {
161 if t == nil || t.AllMethods().Len() != 0 {
165 // mark top-level method symbols
166 // so that expand1 doesn't consider them.
167 for _, f := range t.Methods().Slice() {
171 // generate all reachable methods
175 // check each method to be uniquely reachable
176 var ms []*types.Field
177 for i, sl := range slist {
179 sl.field.Sym.SetUniq(false)
182 path, _ := dotpath(sl.field.Sym, t, &f, false)
187 // dotpath may have dug out arbitrary fields, we only want methods.
192 // add it to the base type method list
194 f.Embedded = 1 // needs a trampoline
195 for _, d := range path {
196 if d.field.Type.IsPtr() {
204 for _, f := range t.Methods().Slice() {
208 ms = append(ms, t.Methods().Slice()...)
209 sort.Sort(types.MethodsByName(ms))
213 // adddot1 returns the number of fields or methods named s at depth d in Type t.
214 // If exactly one exists, it will be returned in *save (if save is not nil),
215 // and dotlist will contain the path of embedded fields traversed to find it,
216 // in reverse order. If none exist, more will indicate whether t contains any
217 // embedded fields at depth d, so callers can decide whether to retry at
219 func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
224 defer t.SetRecur(false)
229 // We've reached our target depth. If t has any fields/methods
230 // named s, then we're done. Otherwise, we still need to check
231 // below for embedded fields.
232 c = lookdot0(s, t, save, ignorecase)
242 if !u.IsStruct() && !u.IsInterface() {
246 var fields *types.Fields
250 fields = u.AllMethods()
252 for _, f := range fields.Slice() {
253 if f.Embedded == 0 || f.Sym == nil {
257 // Found an embedded field at target depth.
260 a, more1 := adddot1(s, f.Type, d, save, ignorecase)
261 if a != 0 && c == 0 {
273 // dotlist is used by adddot1 to record the path of embedded fields
274 // used to access a target field or method.
275 // Must be non-nil so that dotpath returns a non-nil slice even if d is zero.
276 var dotlist = make([]dlist, 10)
278 // Convert node n for assignment to type t.
279 func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
280 if n == nil || n.Type() == nil {
284 if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
285 base.Errorf("use of untyped nil")
288 n = convlit1(n, t, false, context)
290 base.Fatalf("cannot assign %v to %v", n, t)
292 if n.Type().IsUntyped() {
293 base.Fatalf("%L has untyped type", n)
295 if t.Kind() == types.TBLANK {
298 if types.Identical(n.Type(), t) {
302 op, why := Assignop(n.Type(), t)
304 base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why)
308 r := ir.NewConvExpr(base.Pos, op, t, n)
314 // Is type src assignment compatible to type dst?
315 // If so, return op code to use in conversion.
316 // If not, return OXXX. In this case, the string return parameter may
317 // hold a reason why. In all other cases, it'll be the empty string.
318 func Assignop(src, dst *types.Type) (ir.Op, string) {
320 return ir.OCONVNOP, ""
322 if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
326 // 1. src type is identical to dst.
327 if types.Identical(src, dst) {
328 return ir.OCONVNOP, ""
330 return Assignop1(src, dst)
333 func Assignop1(src, dst *types.Type) (ir.Op, string) {
334 // 2. src and dst have identical underlying types and
335 // a. either src or dst is not a named type, or
336 // b. both are empty interface types, or
337 // c. at least one is a gcshape type.
338 // For assignable but different non-empty interface types,
339 // we want to recompute the itab. Recomputing the itab ensures
340 // that itabs are unique (thus an interface with a compile-time
341 // type I has an itab with interface type I).
342 if types.Identical(src.Underlying(), dst.Underlying()) {
343 if src.IsEmptyInterface() {
344 // Conversion between two empty interfaces
346 return ir.OCONVNOP, ""
348 if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
349 // Conversion between two types, at least one unnamed,
350 // needs no conversion. The exception is nonempty interfaces
351 // which need to have their itab updated.
352 return ir.OCONVNOP, ""
354 if src.IsShape() || dst.IsShape() {
355 // Conversion between a shape type and one of the types
356 // it represents also needs no conversion.
357 return ir.OCONVNOP, ""
361 // 3. dst is an interface type and src implements dst.
362 if dst.IsInterface() && src.Kind() != types.TNIL {
364 // Shape types implement things they have already
365 // been typechecked to implement, even if they
366 // don't have the methods for them.
367 return ir.OCONVIFACE, ""
370 // Unified IR uses OCONVIFACE for converting all derived types
371 // to interface type, not just type arguments themselves.
372 return ir.OCONVIFACE, ""
375 why := ImplementsExplain(src, dst)
377 return ir.OCONVIFACE, ""
379 return ir.OXXX, ":\n\t" + why
382 if isptrto(dst, types.TINTER) {
383 why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
387 if src.IsInterface() && dst.Kind() != types.TBLANK {
389 if Implements(dst, src) {
390 why = ": need type assertion"
395 // 4. src is a bidirectional channel value, dst is a channel type,
396 // src and dst have identical element types, and
397 // either src or dst is not a named type.
398 if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
399 if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
400 return ir.OCONVNOP, ""
404 // 5. src is the predeclared identifier nil and dst is a nillable type.
405 if src.Kind() == types.TNIL {
413 return ir.OCONVNOP, ""
417 // 6. rule about untyped constants - already converted by DefaultLit.
419 // 7. Any typed value can be assigned to the blank identifier.
420 if dst.Kind() == types.TBLANK {
421 return ir.OCONVNOP, ""
427 // Can we convert a value of type src to a value of type dst?
428 // If so, return op code to use in conversion (maybe OCONVNOP).
429 // If not, return OXXX. In this case, the string return parameter may
430 // hold a reason why. In all other cases, it'll be the empty string.
431 // srcConstant indicates whether the value of type src is a constant.
432 func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
434 return ir.OCONVNOP, ""
436 if src == nil || dst == nil {
440 // Conversions from regular to not-in-heap are not allowed
441 // (unless it's unsafe.Pointer). These are runtime-specific
443 // (a) Disallow (*T) to (*U) where T is not-in-heap but U isn't.
444 if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
445 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
448 // (b) Disallow string to []T where T is not-in-heap.
449 if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
450 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
454 // 1. src can be assigned to dst.
455 op, why := Assignop(src, dst)
460 // The rules for interfaces are no different in conversions
461 // than assignments. If interfaces are involved, stop now
462 // with the good message from assignop.
463 // Otherwise clear the error.
464 if src.IsInterface() || dst.IsInterface() {
468 // 2. Ignoring struct tags, src and dst have identical underlying types.
469 if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
470 return ir.OCONVNOP, ""
473 // 3. src and dst are unnamed pointer types and, ignoring struct tags,
474 // their base types have identical underlying types.
475 if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
476 if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
477 return ir.OCONVNOP, ""
481 // 4. src and dst are both integer or floating point types.
482 if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
483 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
484 return ir.OCONVNOP, ""
489 // 5. src and dst are both complex types.
490 if src.IsComplex() && dst.IsComplex() {
491 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
492 return ir.OCONVNOP, ""
497 // Special case for constant conversions: any numeric
498 // conversion is potentially okay. We'll validate further
499 // within evconst. See #38117.
500 if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
504 // 6. src is an integer or has type []byte or []rune
505 // and dst is a string type.
506 if src.IsInteger() && dst.IsString() {
507 return ir.ORUNESTR, ""
510 if src.IsSlice() && dst.IsString() {
511 if src.Elem().Kind() == types.ByteType.Kind() {
512 return ir.OBYTES2STR, ""
514 if src.Elem().Kind() == types.RuneType.Kind() {
515 return ir.ORUNES2STR, ""
519 // 7. src is a string and dst is []byte or []rune.
521 if src.IsString() && dst.IsSlice() {
522 if dst.Elem().Kind() == types.ByteType.Kind() {
523 return ir.OSTR2BYTES, ""
525 if dst.Elem().Kind() == types.RuneType.Kind() {
526 return ir.OSTR2RUNES, ""
530 // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
531 if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
532 return ir.OCONVNOP, ""
535 // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
536 if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
537 return ir.OCONVNOP, ""
540 // 10. src is map and dst is a pointer to corresponding hmap.
541 // This rule is needed for the implementation detail that
542 // go gc maps are implemented as a pointer to a hmap struct.
543 if src.Kind() == types.TMAP && dst.IsPtr() &&
544 src.MapType().Hmap == dst.Elem() {
545 return ir.OCONVNOP, ""
548 // 11. src is a slice and dst is an array or pointer-to-array.
549 // They must have same element type.
551 if dst.IsArray() && types.Identical(src.Elem(), dst.Elem()) {
552 return ir.OSLICE2ARR, ""
554 if dst.IsPtr() && dst.Elem().IsArray() &&
555 types.Identical(src.Elem(), dst.Elem().Elem()) {
556 return ir.OSLICE2ARRPTR, ""
563 // Code to resolve elided DOTs in embedded types.
565 // A dlist stores a pointer to a TFIELD Type embedded within
566 // a TSTRUCT or TINTER Type.
571 // dotpath computes the unique shortest explicit selector path to fully qualify
572 // a selection expression x.f, where x is of type t and f is the symbol s.
573 // If no such path exists, dotpath returns nil.
574 // If there are multiple shortest paths to the same depth, ambig is true.
575 func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []dlist, ambig bool) {
576 // The embedding of types within structs imposes a tree structure onto
577 // types: structs parent the types they embed, and types parent their
578 // fields or methods. Our goal here is to find the shortest path to
579 // a field or method named s in the subtree rooted at t. To accomplish
580 // that, we iteratively perform depth-first searches of increasing depth
581 // until we either find the named field/method or exhaust the tree.
583 if d > len(dotlist) {
584 dotlist = append(dotlist, dlist{})
586 if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
587 return dotlist[:d], false
596 func expand0(t *types.Type) {
603 for _, f := range u.AllMethods().Slice() {
608 slist = append(slist, symlink{field: f})
614 u = types.ReceiverBaseType(t)
616 for _, f := range u.Methods().Slice() {
621 slist = append(slist, symlink{field: f})
626 func expand1(t *types.Type, top bool) {
641 if u.IsStruct() || u.IsInterface() {
642 var fields *types.Fields
646 fields = u.AllMethods()
648 for _, f := range fields.Slice() {
655 expand1(f.Type, false)
662 func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) *types.Field {
668 path, _ := dotpath(s, t, &m, ignorecase)
680 // Implements reports whether t implements the interface iface. t can be
681 // an interface, a type parameter, or a concrete type.
682 func Implements(t, iface *types.Type) bool {
683 var missing, have *types.Field
685 return implements(t, iface, &missing, &have, &ptr)
688 // ImplementsExplain reports whether t implements the interface iface. t can be
689 // an interface, a type parameter, or a concrete type. If t does not implement
690 // iface, a non-empty string is returned explaining why.
691 func ImplementsExplain(t, iface *types.Type) string {
692 var missing, have *types.Field
694 if implements(t, iface, &missing, &have, &ptr) {
698 if isptrto(t, types.TINTER) {
699 return fmt.Sprintf("%v is pointer to interface, not interface", t)
700 } else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
701 return fmt.Sprintf("%v does not implement %v (%v method is marked 'nointerface')", t, iface, missing.Sym)
702 } else if have != nil && have.Sym == missing.Sym {
703 return fmt.Sprintf("%v does not implement %v (wrong type for %v method)\n"+
704 "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
706 return fmt.Sprintf("%v does not implement %v (%v method has pointer receiver)", t, iface, missing.Sym)
707 } else if have != nil {
708 return fmt.Sprintf("%v does not implement %v (missing %v method)\n"+
709 "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
711 return fmt.Sprintf("%v does not implement %v (missing %v method)", t, iface, missing.Sym)
714 // implements reports whether t implements the interface iface. t can be
715 // an interface, a type parameter, or a concrete type. If implements returns
716 // false, it stores a method of iface that is not implemented in *m. If the
717 // method name matches but the type is wrong, it additionally stores the type
718 // of the method (on t) in *samename.
719 func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
727 tms := t.AllMethods().Slice()
728 for _, im := range iface.AllMethods().Slice() {
729 for i < len(tms) && tms[i].Sym != im.Sym {
739 if !types.Identical(tm.Type, im.Type) {
750 t = types.ReceiverBaseType(t)
751 var tms []*types.Field
754 tms = t.AllMethods().Slice()
757 for _, im := range iface.AllMethods().Slice() {
758 for i < len(tms) && tms[i].Sym != im.Sym {
763 *samename = ifacelookdot(im.Sym, t, true)
768 if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
774 followptr := tm.Embedded == 2
776 // if pointer receiver in method,
777 // the method does not exist for value types.
778 rcvr := tm.Type.Recv().Type
779 if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !types.IsInterfaceMethod(tm.Type) {
780 if false && base.Flag.LowerR != 0 {
781 base.Errorf("interface pointer mismatch")
794 func isptrto(t *types.Type, et types.Kind) bool {
811 // lookdot0 returns the number of fields or methods named s associated
812 // with Type t. If exactly one exists, it will be returned in *save
813 // (if save is not nil).
814 func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
821 if u.IsStruct() || u.IsInterface() {
822 var fields *types.Fields
826 fields = u.AllMethods()
828 for _, f := range fields.Slice() {
829 if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
839 if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
840 // If t is a defined pointer type, then x.m is shorthand for (*x).m.
843 u = types.ReceiverBaseType(u)
845 for _, f := range u.Methods().Slice() {
846 if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
860 // Code to help generate trampoline functions for methods on embedded
861 // types. These are approx the same as the corresponding AddImplicitDots
862 // routines except that they expect to be called with unique tasks and
863 // they return the actual methods.
865 type symlink struct {