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.
13 "cmd/compile/internal/base"
14 "cmd/compile/internal/ir"
15 "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 // DotImportRefs maps idents introduced by importDot back to the
24 // ir.PkgName they were dot-imported through.
25 var DotImportRefs map[*ir.Ident]*ir.PkgName
27 // LookupNum looks up the symbol starting with prefix and ending with
28 // the decimal n. If prefix is too long, LookupNum panics.
29 func LookupNum(prefix string, n int) *types.Sym {
30 var buf [20]byte // plenty long enough for all current users
32 b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
33 return types.LocalPkg.LookupBytes(b)
36 // Given funarg struct list, return list of fn args.
37 func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field {
40 for _, t := range tl.Fields().Slice() {
42 if mustname && (s == nil || s.Name == "_") {
43 // invent a name so that we can refer to it in the trampoline
44 s = LookupNum(".anon", gen)
46 } else if s != nil && s.Pkg != types.LocalPkg {
47 // TODO(mdempsky): Preserve original position, name, and package.
50 a := ir.NewField(base.Pos, s, nil, t.Type)
53 args = append(args, a)
59 // newname returns a new ONAME Node associated with symbol s.
60 func NewName(s *types.Sym) *ir.Name {
61 n := ir.NewNameAt(base.Pos, s)
66 // NodAddr returns a node representing &n at base.Pos.
67 func NodAddr(n ir.Node) *ir.AddrExpr {
68 return NodAddrAt(base.Pos, n)
71 // nodAddrPos returns a node representing &n at position pos.
72 func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
74 return ir.NewAddrExpr(pos, n)
77 func markAddrOf(n ir.Node) ir.Node {
78 if IncrementalAddrtaken {
79 // We can only do incremental addrtaken computation when it is ok
80 // to typecheck the argument of the OADDR. That's only safe after the
81 // main typecheck has completed.
82 // The argument to OADDR needs to be typechecked because &x[i] takes
83 // the address of x if x is an array, but not if x is a slice.
84 // Note: OuterValue doesn't work correctly until n is typechecked.
85 n = typecheck(n, ctxExpr)
86 if x := ir.OuterValue(n); x.Op() == ir.ONAME {
87 x.Name().SetAddrtaken(true)
90 // Remember that we built an OADDR without computing the Addrtaken bit for
91 // its argument. We'll do that later in bulk using computeAddrtaken.
97 // If IncrementalAddrtaken is false, we do not compute Addrtaken for an OADDR Node
98 // when it is built. The Addrtaken bits are set in bulk by computeAddrtaken.
99 // If IncrementalAddrtaken is true, then when an OADDR Node is built the Addrtaken
100 // field of its argument is updated immediately.
101 var IncrementalAddrtaken = false
103 // If DirtyAddrtaken is true, then there are OADDR whose corresponding arguments
104 // have not yet been marked as Addrtaken.
105 var DirtyAddrtaken = false
107 func ComputeAddrtaken(top []ir.Node) {
108 for _, n := range top {
109 ir.Visit(n, func(n ir.Node) {
110 if n.Op() == ir.OADDR {
111 if x := ir.OuterValue(n.(*ir.AddrExpr).X); x.Op() == ir.ONAME {
112 x.Name().SetAddrtaken(true)
113 if x.Name().IsClosureVar() {
114 // Mark the original variable as Addrtaken so that capturevars
115 // knows not to pass it by value.
116 x.Name().Defn.Name().SetAddrtaken(true)
124 func NodNil() ir.Node {
125 n := ir.NewNilExpr(base.Pos)
126 n.SetType(types.Types[types.TNIL])
130 // AddImplicitDots finds missing fields in obj.field that
131 // will give the shortest unique addressing and
132 // modifies the tree with missing field names.
133 func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
134 n.X = typecheck(n.X, ctxType|ctxExpr)
143 if n.X.Op() == ir.OTYPE {
152 switch path, ambig := dotpath(s, t, nil, false); {
154 // rebuild elided dots
155 for c := len(path) - 1; c >= 0; c-- {
156 dot := ir.NewSelectorExpr(base.Pos, ir.ODOT, n.X, path[c].field.Sym)
157 dot.SetImplicit(true)
158 dot.SetType(path[c].field.Type)
162 base.Errorf("ambiguous selector %v", n)
169 func CalcMethods(t *types.Type) {
170 if t == nil || t.AllMethods().Len() != 0 {
174 // mark top-level method symbols
175 // so that expand1 doesn't consider them.
176 for _, f := range t.Methods().Slice() {
180 // generate all reachable methods
184 // check each method to be uniquely reachable
185 var ms []*types.Field
186 for i, sl := range slist {
188 sl.field.Sym.SetUniq(false)
191 path, _ := dotpath(sl.field.Sym, t, &f, false)
196 // dotpath may have dug out arbitrary fields, we only want methods.
201 // add it to the base type method list
203 f.Embedded = 1 // needs a trampoline
204 for _, d := range path {
205 if d.field.Type.IsPtr() {
213 for _, f := range t.Methods().Slice() {
217 ms = append(ms, t.Methods().Slice()...)
218 sort.Sort(types.MethodsByName(ms))
219 t.AllMethods().Set(ms)
222 // adddot1 returns the number of fields or methods named s at depth d in Type t.
223 // If exactly one exists, it will be returned in *save (if save is not nil),
224 // and dotlist will contain the path of embedded fields traversed to find it,
225 // in reverse order. If none exist, more will indicate whether t contains any
226 // embedded fields at depth d, so callers can decide whether to retry at
228 func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
233 defer t.SetRecur(false)
238 // We've reached our target depth. If t has any fields/methods
239 // named s, then we're done. Otherwise, we still need to check
240 // below for embedded fields.
241 c = lookdot0(s, t, save, ignorecase)
251 if !u.IsStruct() && !u.IsInterface() {
255 for _, f := range u.Fields().Slice() {
256 if f.Embedded == 0 || f.Sym == nil {
260 // Found an embedded field at target depth.
263 a, more1 := adddot1(s, f.Type, d, save, ignorecase)
264 if a != 0 && c == 0 {
276 // dotlist is used by adddot1 to record the path of embedded fields
277 // used to access a target field or method.
278 // Must be non-nil so that dotpath returns a non-nil slice even if d is zero.
279 var dotlist = make([]dlist, 10)
281 // Convert node n for assignment to type t.
282 func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
283 if n == nil || n.Type() == nil || n.Type().Broke() {
287 if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
288 base.Errorf("use of untyped nil")
291 n = convlit1(n, t, false, context)
295 if t.Kind() == types.TBLANK {
299 // Convert ideal bool from comparison to plain bool
300 // if the next step is non-bool (like interface{}).
301 if n.Type() == types.UntypedBool && !t.IsBoolean() {
302 if n.Op() == ir.ONAME || n.Op() == ir.OLITERAL {
303 r := ir.NewConvExpr(base.Pos, ir.OCONVNOP, nil, n)
304 r.SetType(types.Types[types.TBOOL])
311 if types.Identical(n.Type(), t) {
315 op, why := assignop(n.Type(), t)
317 base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why)
321 r := ir.NewConvExpr(base.Pos, op, t, n)
327 // Is type src assignment compatible to type dst?
328 // If so, return op code to use in conversion.
329 // If not, return OXXX. In this case, the string return parameter may
330 // hold a reason why. In all other cases, it'll be the empty string.
331 func assignop(src, dst *types.Type) (ir.Op, string) {
333 return ir.OCONVNOP, ""
335 if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
339 // 1. src type is identical to dst.
340 if types.Identical(src, dst) {
341 return ir.OCONVNOP, ""
344 // 2. src and dst have identical underlying types
345 // and either src or dst is not a named type or
346 // both are empty interface types.
347 // For assignable but different non-empty interface types,
348 // we want to recompute the itab. Recomputing the itab ensures
349 // that itabs are unique (thus an interface with a compile-time
350 // type I has an itab with interface type I).
351 if types.Identical(src.Underlying(), dst.Underlying()) {
352 if src.IsEmptyInterface() {
353 // Conversion between two empty interfaces
355 return ir.OCONVNOP, ""
357 if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
358 // Conversion between two types, at least one unnamed,
359 // needs no conversion. The exception is nonempty interfaces
360 // which need to have their itab updated.
361 return ir.OCONVNOP, ""
365 // 3. dst is an interface type and src implements dst.
366 if dst.IsInterface() && src.Kind() != types.TNIL {
367 var missing, have *types.Field
369 if implements(src, dst, &missing, &have, &ptr) {
370 // Call NeedITab/ITabAddr so that (src, dst)
371 // gets added to itabs early, which allows
372 // us to de-virtualize calls through this
373 // type/interface pair later. See CompileITabs in reflect.go
374 if types.IsDirectIface(src) && !dst.IsEmptyInterface() {
378 return ir.OCONVIFACE, ""
381 // we'll have complained about this method anyway, suppress spurious messages.
382 if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
383 return ir.OCONVIFACE, ""
387 if isptrto(src, types.TINTER) {
388 why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
389 } else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
390 why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
391 } else if have != nil && have.Sym == missing.Sym {
392 why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
393 "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
395 why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
396 } else if have != nil {
397 why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
398 "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
400 why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
406 if isptrto(dst, types.TINTER) {
407 why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
411 if src.IsInterface() && dst.Kind() != types.TBLANK {
412 var missing, have *types.Field
415 if implements(dst, src, &missing, &have, &ptr) {
416 why = ": need type assertion"
421 // 4. src is a bidirectional channel value, dst is a channel type,
422 // src and dst have identical element types, and
423 // either src or dst is not a named type.
424 if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
425 if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
426 return ir.OCONVNOP, ""
430 // 5. src is the predeclared identifier nil and dst is a nillable type.
431 if src.Kind() == types.TNIL {
439 return ir.OCONVNOP, ""
443 // 6. rule about untyped constants - already converted by DefaultLit.
445 // 7. Any typed value can be assigned to the blank identifier.
446 if dst.Kind() == types.TBLANK {
447 return ir.OCONVNOP, ""
453 // Can we convert a value of type src to a value of type dst?
454 // If so, return op code to use in conversion (maybe OCONVNOP).
455 // If not, return OXXX. In this case, the string return parameter may
456 // hold a reason why. In all other cases, it'll be the empty string.
457 // srcConstant indicates whether the value of type src is a constant.
458 func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
460 return ir.OCONVNOP, ""
462 if src == nil || dst == nil {
466 // Conversions from regular to go:notinheap are not allowed
467 // (unless it's unsafe.Pointer). These are runtime-specific
469 // (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
470 if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
471 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
474 // (b) Disallow string to []T where T is go:notinheap.
475 if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
476 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
480 // 1. src can be assigned to dst.
481 op, why := assignop(src, dst)
486 // The rules for interfaces are no different in conversions
487 // than assignments. If interfaces are involved, stop now
488 // with the good message from assignop.
489 // Otherwise clear the error.
490 if src.IsInterface() || dst.IsInterface() {
494 // 2. Ignoring struct tags, src and dst have identical underlying types.
495 if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
496 return ir.OCONVNOP, ""
499 // 3. src and dst are unnamed pointer types and, ignoring struct tags,
500 // their base types have identical underlying types.
501 if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
502 if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
503 return ir.OCONVNOP, ""
507 // 4. src and dst are both integer or floating point types.
508 if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
509 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
510 return ir.OCONVNOP, ""
515 // 5. src and dst are both complex types.
516 if src.IsComplex() && dst.IsComplex() {
517 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
518 return ir.OCONVNOP, ""
523 // Special case for constant conversions: any numeric
524 // conversion is potentially okay. We'll validate further
525 // within evconst. See #38117.
526 if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
530 // 6. src is an integer or has type []byte or []rune
531 // and dst is a string type.
532 if src.IsInteger() && dst.IsString() {
533 return ir.ORUNESTR, ""
536 if src.IsSlice() && dst.IsString() {
537 if src.Elem().Kind() == types.ByteType.Kind() {
538 return ir.OBYTES2STR, ""
540 if src.Elem().Kind() == types.RuneType.Kind() {
541 return ir.ORUNES2STR, ""
545 // 7. src is a string and dst is []byte or []rune.
547 if src.IsString() && dst.IsSlice() {
548 if dst.Elem().Kind() == types.ByteType.Kind() {
549 return ir.OSTR2BYTES, ""
551 if dst.Elem().Kind() == types.RuneType.Kind() {
552 return ir.OSTR2RUNES, ""
556 // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
557 if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
558 return ir.OCONVNOP, ""
561 // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
562 if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
563 return ir.OCONVNOP, ""
566 // src is map and dst is a pointer to corresponding hmap.
567 // This rule is needed for the implementation detail that
568 // go gc maps are implemented as a pointer to a hmap struct.
569 if src.Kind() == types.TMAP && dst.IsPtr() &&
570 src.MapType().Hmap == dst.Elem() {
571 return ir.OCONVNOP, ""
577 // Code to resolve elided DOTs in embedded types.
579 // A dlist stores a pointer to a TFIELD Type embedded within
580 // a TSTRUCT or TINTER Type.
585 // dotpath computes the unique shortest explicit selector path to fully qualify
586 // a selection expression x.f, where x is of type t and f is the symbol s.
587 // If no such path exists, dotpath returns nil.
588 // If there are multiple shortest paths to the same depth, ambig is true.
589 func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []dlist, ambig bool) {
590 // The embedding of types within structs imposes a tree structure onto
591 // types: structs parent the types they embed, and types parent their
592 // fields or methods. Our goal here is to find the shortest path to
593 // a field or method named s in the subtree rooted at t. To accomplish
594 // that, we iteratively perform depth-first searches of increasing depth
595 // until we either find the named field/method or exhaust the tree.
597 if d > len(dotlist) {
598 dotlist = append(dotlist, dlist{})
600 if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
601 return dotlist[:d], false
610 func expand0(t *types.Type) {
617 for _, f := range u.Fields().Slice() {
622 slist = append(slist, symlink{field: f})
628 u = types.ReceiverBaseType(t)
630 for _, f := range u.Methods().Slice() {
635 slist = append(slist, symlink{field: f})
640 func expand1(t *types.Type, top bool) {
655 if u.IsStruct() || u.IsInterface() {
656 for _, f := range u.Fields().Slice() {
663 expand1(f.Type, false)
670 func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, followptr bool) {
675 path, ambig := dotpath(s, t, &m, ignorecase)
678 base.Errorf("%v.%v is ambiguous", t, s)
683 for _, d := range path {
684 if d.field.Type.IsPtr() {
691 base.Errorf("%v.%v is a field, not a method", t, s)
692 return nil, followptr
698 func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
706 tms := t.Fields().Slice()
707 for _, im := range iface.Fields().Slice() {
708 for i < len(tms) && tms[i].Sym != im.Sym {
718 if !types.Identical(tm.Type, im.Type) {
729 t = types.ReceiverBaseType(t)
730 var tms []*types.Field
733 tms = t.AllMethods().Slice()
736 for _, im := range iface.Fields().Slice() {
740 for i < len(tms) && tms[i].Sym != im.Sym {
745 *samename, _ = ifacelookdot(im.Sym, t, true)
750 if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
756 followptr := tm.Embedded == 2
758 // if pointer receiver in method,
759 // the method does not exist for value types.
760 rcvr := tm.Type.Recv().Type
761 if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !types.IsInterfaceMethod(tm.Type) {
762 if false && base.Flag.LowerR != 0 {
763 base.Errorf("interface pointer mismatch")
776 func isptrto(t *types.Type, et types.Kind) bool {
793 // lookdot0 returns the number of fields or methods named s associated
794 // with Type t. If exactly one exists, it will be returned in *save
795 // (if save is not nil).
796 func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
803 if u.IsStruct() || u.IsInterface() {
804 for _, f := range u.Fields().Slice() {
805 if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
815 if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
816 // If t is a defined pointer type, then x.m is shorthand for (*x).m.
819 u = types.ReceiverBaseType(u)
821 for _, f := range u.Methods().Slice() {
822 if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
836 // Code to help generate trampoline functions for methods on embedded
837 // types. These are approx the same as the corresponding AddImplicitDots
838 // routines except that they expect to be called with unique tasks and
839 // they return the actual methods.
841 type symlink struct {