1 // Copyright 2020 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.
9 "cmd/compile/internal/base"
10 "cmd/compile/internal/types"
18 // An Expr is a Node that can appear as an expression.
24 // A miniExpr is a miniNode with extra fields common to expressions.
25 // TODO(rsc): Once we are sure about the contents, compact the bools
26 // into a bit field and leave extra bits available for implementations
27 // embedding miniExpr. Right now there are ~60 unused bits sitting here.
28 type miniExpr struct {
31 init Nodes // TODO(rsc): Don't require every Node to have an init
36 miniExprNonNil = 1 << iota
39 miniExprImplicit // for use by implementations; not supported by every Expr
43 func (*miniExpr) isExpr() {}
45 func (n *miniExpr) Type() *types.Type { return n.typ }
46 func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
47 func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 }
48 func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil }
49 func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 }
50 func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) }
51 func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 }
52 func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) }
53 func (n *miniExpr) Init() Nodes { return n.init }
54 func (n *miniExpr) PtrInit() *Nodes { return &n.init }
55 func (n *miniExpr) SetInit(x Nodes) { n.init = x }
57 // An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
58 type AddStringExpr struct {
64 func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr {
72 // An AddrExpr is an address-of expression &X.
73 // It may end up being a normal address-of or an allocation of a composite literal.
74 type AddrExpr struct {
77 Prealloc *Name // preallocated storage if any
80 func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
81 if x == nil || x.Typecheck() != 1 {
82 base.FatalfAt(pos, "missed typecheck: %L", x)
88 case OARRAYLIT, OMAPLIT, OSLICELIT, OSTRUCTLIT:
93 if r, ok := OuterValue(x).(*Name); ok && r.Op() == ONAME {
96 // If r is a closure variable, we need to mark its canonical
97 // variable as addrtaken too, so that closure conversion
98 // captures it by reference.
100 // Exception: if we've already marked the variable as
101 // capture-by-value, then that means this variable isn't
102 // logically modified, and we must be taking its address to pass
103 // to a runtime function that won't mutate it. In that case, we
104 // only need to make sure our own copy is addressable.
105 if r.IsClosureVar() && !r.Byval() {
106 r.Canonical().SetAddrtaken(true)
111 n.SetType(types.NewPtr(x.Type()))
117 func (n *AddrExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
118 func (n *AddrExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
120 func (n *AddrExpr) SetOp(op Op) {
123 panic(n.no("SetOp " + op.String()))
129 // A BasicLit is a literal of basic type.
130 type BasicLit struct {
135 // NewBasicLit returns an OLITERAL representing val with the given type.
136 func NewBasicLit(pos src.XPos, typ *types.Type, val constant.Value) Node {
137 AssertValidTypeForConst(typ, val)
139 n := &BasicLit{val: val}
147 func (n *BasicLit) Val() constant.Value { return n.val }
148 func (n *BasicLit) SetVal(val constant.Value) { n.val = val }
150 // NewConstExpr returns an OLITERAL representing val, copying the
151 // position and type from orig.
152 func NewConstExpr(val constant.Value, orig Node) Node {
153 return NewBasicLit(orig.Pos(), orig.Type(), val)
156 // A BinaryExpr is a binary expression X Op Y,
157 // or Op(X, Y) for builtin functions that do not become calls.
158 type BinaryExpr struct {
162 RType Node `mknode:"-"` // see reflectdata/helpers.go
165 func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
166 n := &BinaryExpr{X: x, Y: y}
172 func (n *BinaryExpr) SetOp(op Op) {
175 panic(n.no("SetOp " + op.String()))
176 case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
177 OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
178 OCOPY, OCOMPLEX, OUNSAFEADD, OUNSAFESLICE, OUNSAFESTRING,
184 // A CallExpr is a function call Fun(Args).
185 type CallExpr struct {
190 RType Node `mknode:"-"` // see reflectdata/helpers.go
191 KeepAlive []*Name // vars to be kept alive until call returns
196 func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
197 n := &CallExpr{Fun: fun}
204 func (*CallExpr) isStmt() {}
206 func (n *CallExpr) SetOp(op Op) {
209 panic(n.no("SetOp " + op.String()))
211 OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
213 OGETG, OGETCALLERPC, OGETCALLERSP,
214 OMAKE, OMAX, OMIN, OPRINT, OPRINTLN,
215 ORECOVER, ORECOVERFP:
220 // A ClosureExpr is a function literal expression.
221 type ClosureExpr struct {
223 Func *Func `mknode:"-"`
225 IsGoWrap bool // whether this is wrapper closure of a go statement
228 // A CompLitExpr is a composite literal Type{Vals}.
229 // Before type-checking, the type is Ntype.
230 type CompLitExpr struct {
232 List Nodes // initialized values
233 RType Node `mknode:"-"` // *runtime._type for OMAPLIT map types
235 // For OSLICELIT, Len is the backing array length.
236 // For OMAPLIT, Len is the number of entries that we've removed from List and
237 // generated explicit mapassign calls for. This is used to inform the map alloc hint.
241 func NewCompLitExpr(pos src.XPos, op Op, typ *types.Type, list []Node) *CompLitExpr {
242 n := &CompLitExpr{List: list}
251 func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
252 func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
254 func (n *CompLitExpr) SetOp(op Op) {
257 panic(n.no("SetOp " + op.String()))
258 case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
263 // A ConvExpr is a conversion Type(X).
264 // It may end up being a value or a type.
265 type ConvExpr struct {
269 // For implementing OCONVIFACE expressions.
271 // TypeWord is an expression yielding a *runtime._type or
272 // *runtime.itab value to go in the type word of the iface/eface
273 // result. See reflectdata.ConvIfaceTypeWord for further details.
275 // SrcRType is an expression yielding a *runtime._type value for X,
276 // if it's not pointer-shaped and needs to be heap allocated.
277 TypeWord Node `mknode:"-"`
278 SrcRType Node `mknode:"-"`
280 // For -d=checkptr instrumentation of conversions from
281 // unsafe.Pointer to *Elem or *[Len]Elem.
283 // TODO(mdempsky): We only ever need one of these, but currently we
284 // don't decide which one until walk. Longer term, it probably makes
285 // sense to have a dedicated IR op for `(*[Len]Elem)(ptr)[:n:m]`
287 ElemRType Node `mknode:"-"`
288 ElemElemRType Node `mknode:"-"`
291 func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
299 func (n *ConvExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
300 func (n *ConvExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
301 func (n *ConvExpr) CheckPtr() bool { return n.flags&miniExprCheckPtr != 0 }
302 func (n *ConvExpr) SetCheckPtr(b bool) { n.flags.set(miniExprCheckPtr, b) }
304 func (n *ConvExpr) SetOp(op Op) {
307 panic(n.no("SetOp " + op.String()))
308 case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARR, OSLICE2ARRPTR:
313 // An IndexExpr is an index expression X[Index].
314 type IndexExpr struct {
318 RType Node `mknode:"-"` // see reflectdata/helpers.go
322 func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr {
323 n := &IndexExpr{X: x, Index: index}
329 func (n *IndexExpr) SetOp(op Op) {
332 panic(n.no("SetOp " + op.String()))
333 case OINDEX, OINDEXMAP:
338 // A KeyExpr is a Key: Value composite literal key.
339 type KeyExpr struct {
345 func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
346 n := &KeyExpr{Key: key, Value: value}
352 // A StructKeyExpr is an Field: Value composite literal key.
353 type StructKeyExpr struct {
359 func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr {
360 n := &StructKeyExpr{Field: field, Value: value}
366 func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym }
368 // An InlinedCallExpr is an inlined function call.
369 type InlinedCallExpr struct {
372 ReturnVars Nodes // must be side-effect free
375 func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
376 n := &InlinedCallExpr{}
380 n.ReturnVars = retvars
384 func (n *InlinedCallExpr) SingleResult() Node {
385 if have := len(n.ReturnVars); have != 1 {
386 base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have)
388 if !n.Type().HasShape() && n.ReturnVars[0].Type().HasShape() {
389 // If the type of the call is not a shape, but the type of the return value
390 // is a shape, we need to do an implicit conversion, so the real type
391 // of n is maintained.
392 r := NewConvExpr(n.Pos(), OCONVNOP, n.Type(), n.ReturnVars[0])
396 return n.ReturnVars[0]
399 // A LogicalExpr is an expression X Op Y where Op is && or ||.
400 // It is separate from BinaryExpr to make room for statements
401 // that must be executed before Y but after X.
402 type LogicalExpr struct {
408 func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr {
409 n := &LogicalExpr{X: x, Y: y}
415 func (n *LogicalExpr) SetOp(op Op) {
418 panic(n.no("SetOp " + op.String()))
424 // A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
425 // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
426 // but *not* OMAKE (that's a pre-typechecking CallExpr).
427 type MakeExpr struct {
429 RType Node `mknode:"-"` // see reflectdata/helpers.go
434 func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
435 n := &MakeExpr{Len: len, Cap: cap}
441 func (n *MakeExpr) SetOp(op Op) {
444 panic(n.no("SetOp " + op.String()))
445 case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
450 // A NilExpr represents the predefined untyped constant nil.
451 type NilExpr struct {
455 func NewNilExpr(pos src.XPos, typ *types.Type) *NilExpr {
457 base.FatalfAt(pos, "missing type")
467 // A ParenExpr is a parenthesized expression (X).
468 // It may end up being a value or a type.
469 type ParenExpr struct {
474 func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
475 n := &ParenExpr{X: x}
481 func (n *ParenExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
482 func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
484 // A ResultExpr represents a direct access to a result.
485 type ResultExpr struct {
487 Index int64 // index of the result expr.
490 func NewResultExpr(pos src.XPos, typ *types.Type, index int64) *ResultExpr {
491 n := &ResultExpr{Index: index}
498 // A LinksymOffsetExpr refers to an offset within a global variable.
499 // It is like a SelectorExpr but without the field name.
500 type LinksymOffsetExpr struct {
506 func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *LinksymOffsetExpr {
508 base.FatalfAt(pos, "nil type")
510 n := &LinksymOffsetExpr{Linksym: lsym, Offset_: offset}
512 n.op = OLINKSYMOFFSET
517 // NewLinksymExpr is NewLinksymOffsetExpr, but with offset fixed at 0.
518 func NewLinksymExpr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *LinksymOffsetExpr {
519 return NewLinksymOffsetExpr(pos, lsym, 0, typ)
522 // NewNameOffsetExpr is NewLinksymOffsetExpr, but taking a *Name
523 // representing a global variable instead of an *obj.LSym directly.
524 func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *LinksymOffsetExpr {
525 if name == nil || IsBlank(name) || !(name.Op() == ONAME && name.Class == PEXTERN) {
526 base.FatalfAt(pos, "cannot take offset of nil, blank name or non-global variable: %v", name)
528 return NewLinksymOffsetExpr(pos, name.Linksym(), offset, typ)
531 // A SelectorExpr is a selector expression X.Sel.
532 type SelectorExpr struct {
535 // Sel is the name of the field or method being selected, without (in the
536 // case of methods) any preceding type specifier. If the field/method is
537 // exported, than the Sym uses the local package regardless of the package
538 // of the containing type.
540 // The actual selected field - may not be filled in until typechecking.
541 Selection *types.Field
542 Prealloc *Name // preallocated storage for OMETHVALUE, if any
545 func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
546 n := &SelectorExpr{X: x, Sel: sel}
552 func (n *SelectorExpr) SetOp(op Op) {
555 panic(n.no("SetOp " + op.String()))
556 case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OMETHVALUE, OMETHEXPR:
561 func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
562 func (n *SelectorExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
563 func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
564 func (n *SelectorExpr) Offset() int64 { return n.Selection.Offset }
566 func (n *SelectorExpr) FuncName() *Name {
567 if n.Op() != OMETHEXPR {
568 panic(n.no("FuncName"))
570 fn := NewNameAt(n.Selection.Pos, MethodSym(n.X.Type(), n.Sel), n.Type())
572 if n.Selection.Nname != nil {
573 // TODO(austin): Nname is nil for interface method
574 // expressions (I.M), so we can't attach a Func to
576 fn.Func = n.Selection.Nname.(*Name).Func
581 // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
582 type SliceExpr struct {
590 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
591 n := &SliceExpr{X: x, Low: low, High: high, Max: max}
597 func (n *SliceExpr) SetOp(op Op) {
600 panic(n.no("SetOp " + op.String()))
601 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
606 // IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
607 // o must be a slicing op.
608 func (o Op) IsSlice3() bool {
610 case OSLICE, OSLICEARR, OSLICESTR:
612 case OSLICE3, OSLICE3ARR:
615 base.Fatalf("IsSlice3 op %v", o)
619 // A SliceHeader expression constructs a slice header from its parts.
620 type SliceHeaderExpr struct {
627 func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
628 n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap}
635 // A StringHeaderExpr expression constructs a string header from its parts.
636 type StringHeaderExpr struct {
642 func NewStringHeaderExpr(pos src.XPos, ptr, len Node) *StringHeaderExpr {
643 n := &StringHeaderExpr{Ptr: ptr, Len: len}
646 n.typ = types.Types[types.TSTRING]
650 // A StarExpr is a dereference expression *X.
651 // It may end up being a value or a type.
652 type StarExpr struct {
657 func NewStarExpr(pos src.XPos, x Node) *StarExpr {
664 func (n *StarExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
665 func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
667 // A TypeAssertionExpr is a selector expression X.(Type).
668 // Before type-checking, the type is Ntype.
669 type TypeAssertExpr struct {
673 // Runtime type information provided by walkDotType for
674 // assertions from non-empty interface to concrete type.
675 ITab Node `mknode:"-"` // *runtime.itab for Type implementing X's type
677 // An internal/abi.TypeAssert descriptor to pass to the runtime.
681 func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
682 n := &TypeAssertExpr{X: x}
691 func (n *TypeAssertExpr) SetOp(op Op) {
694 panic(n.no("SetOp " + op.String()))
695 case ODOTTYPE, ODOTTYPE2:
700 // A DynamicTypeAssertExpr asserts that X is of dynamic type RType.
701 type DynamicTypeAssertExpr struct {
705 // SrcRType is an expression that yields a *runtime._type value
706 // representing X's type. It's used in failed assertion panic
710 // RType is an expression that yields a *runtime._type value
711 // representing the asserted type.
713 // BUG(mdempsky): If ITab is non-nil, RType may be nil.
716 // ITab is an expression that yields a *runtime.itab value
717 // representing the asserted type within the assertee expression's
718 // original interface type.
720 // ITab is only used for assertions from non-empty interface type to
721 // a concrete (i.e., non-interface) type. For all other assertions,
726 func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr {
727 n := &DynamicTypeAssertExpr{X: x, RType: rtype}
733 func (n *DynamicTypeAssertExpr) SetOp(op Op) {
736 panic(n.no("SetOp " + op.String()))
737 case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2:
742 // A UnaryExpr is a unary expression Op X,
743 // or Op(X) for a builtin function that does not end up being a call.
744 type UnaryExpr struct {
749 func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
750 n := &UnaryExpr{X: x}
756 func (n *UnaryExpr) SetOp(op Op) {
759 panic(n.no("SetOp " + op.String()))
760 case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
761 OCAP, OCLEAR, OCLOSE, OIMAG, OLEN, ONEW, OPANIC, OREAL,
762 OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR,
763 OUNSAFESTRINGDATA, OUNSAFESLICEDATA:
768 func IsZero(n Node) bool {
774 switch u := n.Val(); u.Kind() {
775 case constant.String:
776 return constant.StringVal(u) == ""
778 return !constant.BoolVal(u)
780 return constant.Sign(u) == 0
784 n := n.(*CompLitExpr)
785 for _, n1 := range n.List {
787 n1 = n1.(*KeyExpr).Value
796 n := n.(*CompLitExpr)
797 for _, n1 := range n.List {
798 n1 := n1.(*StructKeyExpr)
799 if !IsZero(n1.Value) {
810 func IsAddressable(n Node) bool {
814 if n.X.Type() != nil && n.X.Type().IsArray() {
815 return IsAddressable(n.X)
817 if n.X.Type() != nil && n.X.Type().IsString() {
821 case ODEREF, ODOTPTR:
825 n := n.(*SelectorExpr)
826 return IsAddressable(n.X)
830 if n.Class == PFUNC {
842 // StaticValue analyzes n to find the earliest expression that always
843 // evaluates to the same value as n, which might be from an enclosing
846 // For example, given:
854 // calling StaticValue on the "int(y)" expression returns the outer
856 func StaticValue(n Node) Node {
858 if n.Op() == OCONVNOP {
863 if n.Op() == OINLCALL {
864 n = n.(*InlinedCallExpr).SingleResult()
868 n1 := staticValue1(n)
876 func staticValue1(nn Node) Node {
877 if nn.Op() != ONAME {
880 n := nn.(*Name).Canonical()
881 if n.Class != PAUTO {
894 defn := defn.(*AssignStmt)
897 defn := defn.(*AssignListStmt)
898 for i, lhs := range defn.Lhs {
904 base.Fatalf("%v missing from LHS of %v", n, defn)
909 base.Fatalf("RHS is nil: %v", defn)
919 // Reassigned takes an ONAME node, walks the function in which it is
920 // defined, and returns a boolean indicating whether the name has any
921 // assignments other than its declaration.
922 // NB: global variables are always considered to be re-assigned.
923 // TODO: handle initial declaration not including an assignment and
924 // followed by a single assignment?
925 func Reassigned(name *Name) bool {
926 if name.Op() != ONAME {
927 base.Fatalf("reassigned %v", name)
929 // no way to reliably check for no-reassignment of globals, assume it can be
930 if name.Curfn == nil {
934 if name.Addrtaken() {
935 return true // conservatively assume it's reassigned indirectly
938 // TODO(mdempsky): This is inefficient and becoming increasingly
939 // unwieldy. Figure out a way to generalize escape analysis's
940 // reassignment detection for use by inlining and devirtualization.
942 // isName reports whether n is a reference to name.
943 isName := func(x Node) bool {
947 n, ok := OuterValue(x).(*Name)
948 return ok && n.Canonical() == name
951 var do func(n Node) bool
952 do = func(n Node) bool {
956 if isName(n.X) && n != name.Defn {
959 case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2:
960 n := n.(*AssignListStmt)
961 for _, p := range n.Lhs {
962 if isName(p) && n != name.Defn {
967 n := n.(*AssignOpStmt)
974 base.FatalfAt(n.Pos(), "%v not marked addrtaken", name)
978 if isName(n.Key) || isName(n.Value) {
982 n := n.(*ClosureExpr)
989 return Any(name.Curfn, do)
992 // StaticCalleeName returns the ONAME/PFUNC for n, if known.
993 func StaticCalleeName(n Node) *Name {
996 n := n.(*SelectorExpr)
997 return MethodExprName(n)
1000 if n.Class == PFUNC {
1004 return n.(*ClosureExpr).Func.Nname
1009 // IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation.
1010 var IsIntrinsicCall = func(*CallExpr) bool { return false }
1012 // SameSafeExpr checks whether it is safe to reuse one of l and r
1013 // instead of computing both. SameSafeExpr assumes that l and r are
1014 // used in the same statement or expression. In order for it to be
1015 // safe to reuse l or r, they must:
1016 // - be the same expression
1017 // - not have side-effects (no function calls, no channel ops);
1018 // however, panics are ok
1019 // - not cause inappropriate aliasing; e.g. two string to []byte
1020 // conversions, must result in two distinct slices
1022 // The handling of OINDEXMAP is subtle. OINDEXMAP can occur both
1023 // as an lvalue (map assignment) and an rvalue (map access). This is
1024 // currently OK, since the only place SameSafeExpr gets used on an
1025 // lvalue expression is for OSLICE and OAPPEND optimizations, and it
1026 // is correct in those settings.
1027 func SameSafeExpr(l Node, r Node) bool {
1028 for l.Op() == OCONVNOP {
1031 for r.Op() == OCONVNOP {
1034 if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) {
1043 l := l.(*SelectorExpr)
1044 r := r.(*SelectorExpr)
1045 return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X)
1050 return SameSafeExpr(l.X, r.X)
1052 case ONOT, OBITNOT, OPLUS, ONEG:
1055 return SameSafeExpr(l.X, r.X)
1060 // Some conversions can't be reused, such as []byte(str).
1061 // Allow only numeric-ish types. This is a bit conservative.
1062 return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X)
1064 case OINDEX, OINDEXMAP:
1067 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index)
1069 case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
1070 l := l.(*BinaryExpr)
1071 r := r.(*BinaryExpr)
1072 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y)
1075 return constant.Compare(l.Val(), token.EQL, r.Val())
1084 // ShouldCheckPtr reports whether pointer checking should be enabled for
1085 // function fn at a given level. See debugHelpFooter for defined
1087 func ShouldCheckPtr(fn *Func, level int) bool {
1088 return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
1091 // ShouldAsanCheckPtr reports whether pointer checking should be enabled for
1092 // function fn when -asan is enabled.
1093 func ShouldAsanCheckPtr(fn *Func) bool {
1094 return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
1097 // IsReflectHeaderDataField reports whether l is an expression p.Data
1098 // where p has type reflect.SliceHeader or reflect.StringHeader.
1099 func IsReflectHeaderDataField(l Node) bool {
1100 if l.Type() != types.Types[types.TUINTPTR] {
1107 l := l.(*SelectorExpr)
1108 tsym = l.X.Type().Sym()
1110 l := l.(*SelectorExpr)
1111 tsym = l.X.Type().Elem().Sym()
1116 if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" {
1119 return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
1122 func ParamNames(ft *types.Type) []Node {
1123 args := make([]Node, ft.NumParams())
1124 for i, f := range ft.Params() {
1125 args[i] = f.Nname.(*Name)
1130 // MethodSym returns the method symbol representing a method name
1131 // associated with a specific receiver type.
1133 // Method symbols can be used to distinguish the same method appearing
1134 // in different method sets. For example, T.M and (*T).M have distinct
1137 // The returned symbol will be marked as a function.
1138 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym {
1139 sym := MethodSymSuffix(recv, msym, "")
1144 // MethodSymSuffix is like MethodSym, but allows attaching a
1145 // distinguisher suffix. To avoid collisions, the suffix must not
1146 // start with a letter, number, or period.
1147 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
1149 base.Fatalf("blank method name")
1155 base.Fatalf("declared pointer receiver type: %v", recv)
1157 rsym = recv.Elem().Sym()
1160 // Find the package the receiver type appeared in. For
1161 // anonymous receiver types (i.e., anonymous structs with
1162 // embedded fields), use the "go" pseudo-package instead.
1170 // The parentheses aren't really necessary, but
1171 // they're pretty traditional at this point.
1172 fmt.Fprintf(&b, "(%-S)", recv)
1174 fmt.Fprintf(&b, "%-S", recv)
1177 // A particular receiver type may have multiple non-exported
1178 // methods with the same name. To disambiguate them, include a
1179 // package qualifier for names that came from a different
1180 // package than the receiver type.
1181 if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
1183 b.WriteString(msym.Pkg.Prefix)
1187 b.WriteString(msym.Name)
1188 b.WriteString(suffix)
1189 return rpkg.LookupBytes(b.Bytes())
1192 // LookupMethodSelector returns the types.Sym of the selector for a method
1193 // named in local symbol name, as well as the types.Sym of the receiver.
1195 // TODO(prattmic): this does not attempt to handle method suffixes (wrappers).
1196 func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) {
1197 typeName, methName := splitType(name)
1199 return nil, nil, fmt.Errorf("%s doesn't contain type split", name)
1202 if len(typeName) > 3 && typeName[:2] == "(*" && typeName[len(typeName)-1] == ')' {
1203 // Symbol name is for a pointer receiver method. We just want
1204 // the base type name.
1205 typeName = typeName[2 : len(typeName)-1]
1208 typ = pkg.Lookup(typeName)
1209 meth = pkg.Selector(methName)
1210 return typ, meth, nil
1213 // splitType splits a local symbol name into type and method (fn). If this a
1214 // free function, typ == "".
1216 // N.B. closures and methods can be ambiguous (e.g., bar.func1). These cases
1217 // are returned as methods.
1218 func splitType(name string) (typ, fn string) {
1219 // Types are split on the first dot, ignoring everything inside
1220 // brackets (instantiation of type parameter, usually including
1223 for i, r := range name {
1224 if r == '.' && bracket == 0 {
1225 return name[:i], name[i+1:]
1237 // MethodExprName returns the ONAME representing the method
1238 // referenced by expression n, which must be a method selector,
1239 // method expression, or method value.
1240 func MethodExprName(n Node) *Name {
1241 name, _ := MethodExprFunc(n).Nname.(*Name)
1245 // MethodExprFunc is like MethodExprName, but returns the types.Field instead.
1246 func MethodExprFunc(n Node) *types.Field {
1248 case ODOTMETH, OMETHEXPR, OMETHVALUE:
1249 return n.(*SelectorExpr).Selection
1251 base.Fatalf("unexpected node: %v (%v)", n, n.Op())
1252 panic("unreachable")