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.
15 // The constant is known to runtime.
24 s := fmt.Sprintf("\nbefore %v", Curfn.Func.Nname.Sym)
25 dumplist(s, Curfn.Nbody)
30 // Final typecheck for any unused variables.
31 // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
32 for l := fn.Func.Dcl; l != nil; l = l.Next {
33 if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO {
34 typecheck(&l.N, Erv|Easgn)
38 // Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
39 for l := fn.Func.Dcl; l != nil; l = l.Next {
40 if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO && l.N.Name.Defn != nil && l.N.Name.Defn.Op == OTYPESW && l.N.Used {
41 l.N.Name.Defn.Left.Used = true
45 for l := fn.Func.Dcl; l != nil; l = l.Next {
46 if l.N.Op != ONAME || l.N.Class&^PHEAP != PAUTO || l.N.Sym.Name[0] == '&' || l.N.Used {
49 if defn := l.N.Name.Defn; defn != nil && defn.Op == OTYPESW {
53 lineno = defn.Left.Lineno
54 Yyerror("%v declared and not used", l.N.Sym)
55 defn.Left.Used = true // suppress repeats
58 Yyerror("%v declared and not used", l.N.Sym)
66 walkstmtlist(Curfn.Nbody)
68 s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
69 dumplist(s, Curfn.Nbody)
73 if Debug['W'] != 0 && Curfn.Func.Enter != nil {
74 s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
75 dumplist(s, Curfn.Func.Enter)
79 func walkstmtlist(l *NodeList) {
80 for ; l != nil; l = l.Next {
85 func samelist(a *NodeList, b *NodeList) bool {
86 for ; a != nil && b != nil; a, b = a.Next, b.Next {
94 func paramoutheap(fn *Node) bool {
95 for l := fn.Func.Dcl; l != nil; l = l.Next {
101 // stop early - parameters are over
111 // adds "adjust" to all the argument locations for the call n.
112 // n must be a defer or go node that has already been walked.
113 func adjustargs(n *Node, adjust int) {
118 for args := callfunc.List; args != nil; args = args.Next {
121 Yyerror("call arg not assignment")
125 // This is a temporary introduced by reorder1.
126 // The real store to the stack appears later in the arg list.
130 if lhs.Op != OINDREG {
131 Yyerror("call argument store does not use OINDREG")
134 // can't really check this in machine-indep code.
135 //if(lhs->val.u.reg != D_SP)
136 // yyerror("call arg assign not indreg(SP)");
137 lhs.Xoffset += int64(adjust)
141 func walkstmt(np **Node) {
146 if n.Dodata == 2 { // don't walk, generated by anylit.
152 walkstmtlist(n.Ninit)
157 Yyerror("%v is not a top level statement", n.Sym)
159 Yyerror("%v is not a top level statement", Oconv(int(n.Op), 0))
184 if n.Typecheck == 0 {
185 Fatalf("missing typecheck: %v", Nconv(n, obj.FmtSign))
191 if (*np).Op == OCOPY && n.Op == OCONVNOP {
192 n.Op = OEMPTY // don't leave plain values as statements.
195 // special case for a receive where we throw away
196 // the value received.
198 if n.Typecheck == 0 {
199 Fatalf("missing typecheck: %v", Nconv(n, obj.FmtSign))
204 walkexpr(&n.Left, &init)
205 n = mkcall1(chanfn("chanrecv1", 2, n.Left.Type), nil, &init, typename(n.Left.Type), n.Left, nodnil())
227 Yyerror("case statement out of place")
237 case OPRINT, OPRINTN:
238 walkprintfunc(&n.Left, &n.Ninit)
241 n.Left = copyany(n.Left, &n.Ninit, true)
244 walkexpr(&n.Left, &n.Ninit)
247 // make room for size & fn arguments.
248 adjustargs(n, 2*Widthptr)
252 walkstmtlist(n.Left.Ninit)
255 walkexpr(&n.Left, &init)
256 addinit(&n.Left, init)
260 walkstmtlist(n.Nbody)
263 walkexpr(&n.Left, &n.Ninit)
264 walkstmtlist(n.Nbody)
265 walkstmtlist(n.Rlist)
269 case OPRINT, OPRINTN:
270 walkprintfunc(&n.Left, &n.Ninit)
273 n.Left = copyany(n.Left, &n.Ninit, true)
276 walkexpr(&n.Left, &n.Ninit)
279 // make room for size & fn arguments.
280 adjustargs(n, 2*Widthptr)
283 walkexprlist(n.List, &n.Ninit)
287 if (Curfn.Type.Outnamed && count(n.List) > 1) || paramoutheap(Curfn) {
288 // assign to the function out parameters,
289 // so that reorder3 can fix up conflicts
293 for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
294 cl = ll.N.Class &^ PHEAP
303 if got, want := count(n.List), count(rl); got != want {
304 // order should have rewritten multi-value function calls
305 // with explicit OAS2FUNC nodes.
306 Fatalf("expected %v return arguments, have %v", want, got)
309 if samelist(rl, n.List) {
310 // special return in disguise
316 // move function calls out, to make reorder3's job easier.
317 walkexprlistsafe(n.List, &n.Ninit)
319 ll := ascompatee(n.Op, rl, n.List, &n.Ninit)
320 n.List = reorder3(ll)
321 for lr := n.List; lr != nil; lr = lr.Next {
322 lr.N = applywritebarrier(lr.N, &n.Ninit)
327 ll := ascompatte(n.Op, nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
343 Yyerror("fallthrough statement out of place")
348 Fatalf("walkstmt ended up with name: %v", Nconv(n, obj.FmtSign))
354 func isSmallMakeSlice(n *Node) bool {
355 if n.Op != OMAKESLICE {
365 return Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || Mpgetfix(r.Val().U.(*Mpint)) < (1<<16)/t.Type.Width)
368 // walk the whole tree of the body of an
369 // expression or simple statement.
370 // the types expressions are calculated.
371 // compile-time constants are evaluated.
372 // complex side effects like statements are appended to init
373 func walkexprlist(l *NodeList, init **NodeList) {
374 for ; l != nil; l = l.Next {
379 func walkexprlistsafe(l *NodeList, init **NodeList) {
380 for ; l != nil; l = l.Next {
381 l.N = safeexpr(l.N, init)
386 func walkexprlistcheap(l *NodeList, init **NodeList) {
387 for ; l != nil; l = l.Next {
388 l.N = cheapexpr(l.N, init)
393 func walkexpr(np **Node, init **NodeList) {
400 if init == &n.Ninit {
401 // not okay to use n->ninit when walking n,
402 // because we might replace n with some other node
403 // and would lose the init list.
404 Fatalf("walkexpr init == &n->ninit")
408 walkstmtlist(n.Ninit)
409 *init = concat(*init, n.Ninit)
413 // annoying case - not typechecked
415 walkexpr(&n.Left, init)
416 walkexpr(&n.Right, init)
423 Dump("walk-before", n)
426 if n.Typecheck != 1 {
427 Fatalf("missed typecheck: %v\n", Nconv(n, obj.FmtSign))
434 Fatalf("walkexpr: switch 1 unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
451 walkexpr(&n.Left, init)
454 walkexpr(&n.Left, init)
458 walkexpr(&n.Left, init)
462 if n.Op == ODOTPTR && n.Left.Type.Type.Width == 0 {
463 // No actual copy will be generated, so emit an explicit nil check.
464 n.Left = cheapexpr(n.Left, init)
466 checknil(n.Left, init)
469 walkexpr(&n.Left, init)
472 walkexpr(&n.Left, init)
473 walkexpr(&n.Right, init)
476 walkexpr(&n.Left, init)
479 walkexpr(&n.Left, init)
481 // replace len(*[10]int) with 10.
482 // delayed until now to preserve side effects.
489 safeexpr(n.Left, init)
490 Nodconst(n, n.Type, t.Bound)
495 walkexpr(&n.Left, init)
496 walkexpr(&n.Right, init)
498 n.Bounded = bounded(n.Right, 8*t.Width)
499 if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
500 Warn("shift bounds check elided")
503 // Use results from call expression as arguments for complex.
514 if n.Op == OCOMPLEX && n.Left == nil && n.Right == nil {
516 n.Right = n.List.Next.N
519 walkexpr(&n.Left, init)
520 walkexpr(&n.Right, init)
523 walkexpr(&n.Left, init)
524 walkexpr(&n.Right, init)
528 walkexpr(&n.Left, init)
529 walkexpr(&n.Right, init)
531 // Disable safemode while compiling this code: the code we
532 // generate internally can refer to unsafe.Pointer.
533 // In this case it can happen if we need to generate an ==
534 // for a struct containing a reflect.Value, which itself has
535 // an unexported field of type unsafe.Pointer.
536 old_safemode := safemode
539 walkcompare(&n, init)
540 safemode = old_safemode
543 walkexpr(&n.Left, init)
545 // cannot put side effects from n.Right on init,
546 // because they cannot run before n.Left is checked.
547 // save elsewhere and store on the eventual n.Right.
550 walkexpr(&n.Right, &ll)
551 addinit(&n.Right, ll)
553 case OPRINT, OPRINTN:
554 walkexprlist(n.List, init)
555 n = walkprint(n, init)
558 n = mkcall("gopanic", nil, init, n.Left)
561 n = mkcall("gorecover", n.Type, init, Nod(OADDR, nodfp, nil))
566 case OCLOSUREVAR, OCFUNC:
570 if n.Class&PHEAP == 0 && n.Class != PPARAMREF {
576 if n.List != nil && n.List.N.Op == OAS {
579 walkexpr(&n.Left, init)
580 walkexprlist(n.List, init)
581 ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
582 n.List = reorder1(ll)
585 if n.Left.Op == OCLOSURE {
586 // Transform direct call of a closure to call of a normal function.
587 // transformclosure already did all preparation work.
589 // Prepend captured variables to argument list.
590 n.List = concat(n.Left.Func.Enter, n.List)
592 n.Left.Func.Enter = nil
594 // Replace OCLOSURE with ONAME/PFUNC.
595 n.Left = n.Left.Func.Closure.Func.Nname
597 // Update type of OCALLFUNC node.
598 // Output arguments had not changed, but their offsets could.
599 if n.Left.Type.Outtuple == 1 {
600 t := getoutargx(n.Left.Type).Type
601 if t.Etype == TFIELD {
606 n.Type = getoutargx(n.Left.Type)
611 if n.List != nil && n.List.N.Op == OAS {
615 walkexpr(&n.Left, init)
616 walkexprlist(n.List, init)
618 if n.Left.Op == ONAME && n.Left.Sym.Name == "Sqrt" && n.Left.Sym.Pkg.Path == "math" {
619 switch Thearch.Thechar {
628 ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
629 n.List = reorder1(ll)
633 if n.List != nil && n.List.N.Op == OAS {
636 walkexpr(&n.Left, init)
637 walkexprlist(n.List, init)
638 ll := ascompatte(n.Op, n, false, getthis(t), list1(n.Left.Left), 0, init)
639 lr := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
643 n.List = reorder1(ll)
646 *init = concat(*init, n.Ninit)
649 walkexpr(&n.Left, init)
650 n.Left = safeexpr(n.Left, init)
656 if n.Right == nil || iszero(n.Right) && !instrumenting {
662 walkexpr(&n.Right, init)
665 // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
666 // It needs to be removed in all three places.
667 // That would allow inlining x.(struct{*int}) the same as x.(*int).
668 if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
669 // handled directly during cgen
670 walkexpr(&n.Right, init)
674 // x = i.(T); n.Left is x, n.Right.Left is i.
675 // orderstmt made sure x is addressable.
676 walkexpr(&n.Right.Left, init)
678 n1 := Nod(OADDR, n.Left, nil)
679 r := n.Right // i.(T)
681 if Debug_typeassert > 0 {
682 Warn("type assertion not inlined")
685 buf := "assert" + type2IET(r.Left.Type) + "2" + type2IET(r.Type)
686 fn := syslook(buf, 1)
687 substArgTypes(fn, r.Left.Type, r.Type)
689 n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
694 // x = <-c; n.Left is x, n.Right.Left is c.
695 // orderstmt made sure x is addressable.
696 walkexpr(&n.Right.Left, init)
698 n1 := Nod(OADDR, n.Left, nil)
699 r := n.Right.Left // the channel
700 n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
708 r = appendslice(r, init) // also works for append(slice, string).
710 r = walkappend(r, init, n)
714 // Left in place for back end.
715 // Do not add a new write barrier.
718 // Otherwise, lowered for race detector.
719 // Treat as ordinary assignment.
722 if n.Left != nil && n.Right != nil {
723 r := convas(Nod(OAS, n.Left, n.Right), init)
726 n = applywritebarrier(n, init)
730 *init = concat(*init, n.Ninit)
732 walkexprlistsafe(n.List, init)
733 walkexprlistsafe(n.Rlist, init)
734 ll := ascompatee(OAS, n.List, n.Rlist, init)
736 for lr := ll; lr != nil; lr = lr.Next {
737 lr.N = applywritebarrier(lr.N, init)
743 *init = concat(*init, n.Ninit)
747 walkexprlistsafe(n.List, init)
750 ll := ascompatet(n.Op, n.List, &r.Type, 0, init)
751 for lr := ll; lr != nil; lr = lr.Next {
752 lr.N = applywritebarrier(lr.N, init)
754 n = liststmt(concat(list1(r), ll))
757 // orderstmt made sure x is addressable.
759 *init = concat(*init, n.Ninit)
763 walkexprlistsafe(n.List, init)
764 walkexpr(&r.Left, init)
766 if isblank(n.List.N) {
769 n1 = Nod(OADDR, n.List.N, nil)
771 n1.Etype = 1 // addr does not escape
772 fn := chanfn("chanrecv2", 2, r.Left.Type)
773 r = mkcall1(fn, n.List.Next.N.Type, init, typename(r.Left.Type), r.Left, n1)
774 n = Nod(OAS, n.List.Next.N, r)
779 *init = concat(*init, n.Ninit)
783 walkexprlistsafe(n.List, init)
784 walkexpr(&r.Left, init)
785 walkexpr(&r.Right, init)
788 if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
789 switch algtype(t.Down) {
791 p = "mapaccess2_fast32"
793 p = "mapaccess2_fast64"
795 p = "mapaccess2_faststr"
801 // fast versions take key by value
804 // standard version takes key by reference
805 // orderexpr made sure key is addressable.
806 key = Nod(OADDR, r.Right, nil)
814 // var,b = mapaccess2*(t, m, i)
819 r = mkcall1(fn, getoutargx(fn.Type), init, typename(t), r.Left, key)
821 // mapaccess2* returns a typed bool, but due to spec changes,
822 // the boolean result of i.(T) is now untyped so we make it the
823 // same type as the variable on the lhs.
824 if !isblank(n.List.Next.N) {
825 r.Type.Type.Down.Type = n.List.Next.N.Type
830 // don't generate a = *var if a is _
832 var_ := temp(Ptrto(t.Type))
836 *init = list(*init, n)
837 n = Nod(OAS, a, Nod(OIND, var_, nil))
843 // TODO: ptr is always non-nil, so disable nil check for this OIND op.
846 *init = concat(*init, n.Ninit)
850 walkexpr(&map_, init)
853 // orderstmt made sure key is addressable.
854 key = Nod(OADDR, key, nil)
857 n = mkcall1(mapfndel("mapdelete", t), nil, init, typename(t), map_, key)
860 e := n.Rlist.N // i.(T)
861 // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
862 // It needs to be removed in all three places.
863 // That would allow inlining x.(struct{*int}) the same as x.(*int).
864 if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
865 // handled directly during gen.
866 walkexprlistsafe(n.List, init)
867 walkexpr(&e.Left, init)
872 // orderstmt made sure a is addressable.
873 *init = concat(*init, n.Ninit)
876 walkexprlistsafe(n.List, init)
877 walkexpr(&e.Left, init)
881 oktype := Types[TBOOL]
887 fromKind := type2IET(from.Type)
888 toKind := type2IET(t)
890 // Avoid runtime calls in a few cases of the form _, ok := i.(T).
891 // This is faster and shorter and allows the corresponding assertX2X2
892 // routines to skip nil checks on their last argument.
893 if isblank(n.List.N) {
896 case fromKind == "E" && toKind == "T":
897 tab := Nod(OITAB, from, nil) // type:eface::tab:iface
898 typ := Nod(OCONVNOP, typename(t), nil)
899 typ.Type = Ptrto(Types[TUINTPTR])
900 fast = Nod(OEQ, tab, typ)
901 case fromKind == "I" && toKind == "E",
902 fromKind == "E" && toKind == "E":
903 tab := Nod(OITAB, from, nil)
904 fast = Nod(ONE, nodnil(), tab)
907 if Debug_typeassert > 0 {
908 Warn("type assertion (ok only) inlined")
910 n = Nod(OAS, ok, fast)
916 var resptr *Node // &res
917 if isblank(n.List.N) {
920 resptr = Nod(OADDR, n.List.N, nil)
922 resptr.Etype = 1 // addr does not escape
924 if Debug_typeassert > 0 {
925 Warn("type assertion not inlined")
927 buf := "assert" + fromKind + "2" + toKind + "2"
928 fn := syslook(buf, 1)
929 substArgTypes(fn, from.Type, t)
930 call := mkcall1(fn, oktype, init, typename(t), from, resptr)
931 n = Nod(OAS, ok, call)
934 case ODOTTYPE, ODOTTYPE2:
935 if !isdirectiface(n.Type) || Isfat(n.Type) {
936 Fatalf("walkexpr ODOTTYPE") // should see inside OAS only
938 walkexpr(&n.Left, init)
941 walkexpr(&n.Left, init)
943 // Optimize convT2E as a two-word copy when T is pointer-shaped.
944 if isnilinter(n.Type) && isdirectiface(n.Left.Type) {
945 l := Nod(OEFACE, typename(n.Left.Type), n.Left)
947 l.Typecheck = n.Typecheck
952 // Build name of function: convI2E etc.
953 // Not all names are possible
954 // (e.g., we'll never generate convE2E or convE2I).
955 buf := "conv" + type2IET(n.Left.Type) + "2" + type2IET(n.Type)
956 fn := syslook(buf, 1)
958 if !Isinter(n.Left.Type) {
959 ll = list(ll, typename(n.Left.Type))
961 if !isnilinter(n.Type) {
962 ll = list(ll, typename(n.Type))
964 if !Isinter(n.Left.Type) && !isnilinter(n.Type) {
965 sym := Pkglookup(Tconv(n.Left.Type, obj.FmtLeft)+"."+Tconv(n.Type, obj.FmtLeft), itabpkg)
967 l := Nod(ONAME, nil, nil)
969 l.Type = Ptrto(Types[TUINT8])
974 ggloblsym(sym, int32(Widthptr), obj.DUPOK|obj.NOPTR)
977 l := Nod(OADDR, sym.Def, nil)
981 if isdirectiface(n.Left.Type) {
982 // For pointer types, we can make a special form of optimization
984 // These statements are put onto the expression init list:
985 // Itab *tab = atomicloadtype(&cache);
987 // tab = typ2Itab(type, itype, &cache);
989 // The CONVIFACE expression is replaced with this:
991 l := temp(Ptrto(Types[TUINT8]))
993 n1 := Nod(OAS, l, sym.Def)
995 *init = list(*init, n1)
997 fn := syslook("typ2Itab", 1)
998 n1 = Nod(OCALL, fn, nil)
1003 n2 := Nod(OIF, nil, nil)
1004 n2.Left = Nod(OEQ, l, nodnil())
1005 n2.Nbody = list1(Nod(OAS, l, n1))
1007 typecheck(&n2, Etop)
1008 *init = list(*init, n2)
1010 l = Nod(OEFACE, l, n.Left)
1011 l.Typecheck = n.Typecheck
1018 if Isinter(n.Left.Type) {
1019 ll = list(ll, n.Left)
1021 // regular types are passed by reference to avoid C vararg calls
1022 // orderexpr arranged for n.Left to be a temporary for all
1023 // the conversions it could see. comparison of an interface
1024 // with a non-interface, especially in a switch on interface value
1025 // with non-interface cases, is not visible to orderstmt, so we
1026 // have to fall back on allocating a temp here.
1027 if islvalue(n.Left) {
1028 ll = list(ll, Nod(OADDR, n.Left, nil))
1030 ll = list(ll, Nod(OADDR, copyexpr(n.Left, n.Left.Type, init), nil))
1032 dowidth(n.Left.Type)
1034 if n.Esc == EscNone && n.Left.Type.Width <= 1024 {
1035 // Allocate stack buffer for value stored in interface.
1036 r = temp(n.Left.Type)
1037 r = Nod(OAS, r, nil) // zero temp
1039 *init = list(*init, r)
1040 r = Nod(OADDR, r.Left, nil)
1046 if !Isinter(n.Left.Type) {
1047 substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
1049 substArgTypes(fn, n.Left.Type, n.Type)
1052 n = Nod(OCALL, fn, nil)
1057 case OCONV, OCONVNOP:
1058 if Thearch.Thechar == '5' {
1059 if Isfloat[n.Left.Type.Etype] {
1060 if n.Type.Etype == TINT64 {
1061 n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
1065 if n.Type.Etype == TUINT64 {
1066 n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
1071 if Isfloat[n.Type.Etype] {
1072 if n.Left.Type.Etype == TINT64 {
1073 n = mkcall("int64tofloat64", n.Type, init, conv(n.Left, Types[TINT64]))
1077 if n.Left.Type.Etype == TUINT64 {
1078 n = mkcall("uint64tofloat64", n.Type, init, conv(n.Left, Types[TUINT64]))
1084 walkexpr(&n.Left, init)
1087 walkexpr(&n.Left, init)
1089 n.Right = Nod(OCOM, n.Right, nil)
1090 typecheck(&n.Right, Erv)
1091 walkexpr(&n.Right, init)
1094 walkexpr(&n.Left, init)
1095 walkexpr(&n.Right, init)
1099 walkexpr(&n.Left, init)
1100 walkexpr(&n.Right, init)
1102 // rewrite complex div into function call.
1103 et := n.Left.Type.Etype
1105 if Iscomplex[et] && n.Op == ODIV {
1107 n = mkcall("complex128div", Types[TCOMPLEX128], init, conv(n.Left, Types[TCOMPLEX128]), conv(n.Right, Types[TCOMPLEX128]))
1112 // Nothing to do for float divisions.
1117 // Try rewriting as shifts or magic multiplies.
1120 // rewrite 64-bit div and mod into function calls
1121 // on 32-bit architectures.
1124 if Widthreg >= 8 || (et != TUINT64 && et != TINT64) {
1138 n = mkcall(fn, n.Type, init, conv(n.Left, Types[et]), conv(n.Right, Types[et]))
1142 walkexpr(&n.Left, init)
1144 // save the original node for bounds checking elision.
1145 // If it was a ODIV/OMOD walk might rewrite it.
1148 walkexpr(&n.Right, init)
1150 // if range of type cannot exceed static array bound,
1151 // disable bounds check.
1156 if t != nil && Isptr[t.Etype] {
1159 if Isfixedarray(t) {
1160 n.Bounded = bounded(r, t.Bound)
1161 if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) {
1162 Warn("index bounds check elided")
1164 if Smallintconst(n.Right) && !n.Bounded {
1165 Yyerror("index out of bounds")
1167 } else if Isconst(n.Left, CTSTR) {
1168 n.Bounded = bounded(r, int64(len(n.Left.Val().U.(string))))
1169 if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) {
1170 Warn("index bounds check elided")
1172 if Smallintconst(n.Right) {
1174 Yyerror("index out of bounds")
1176 // replace "abc"[1] with 'b'.
1177 // delayed until now because "abc"[1] is not
1178 // an ideal constant.
1179 v := Mpgetfix(n.Right.Val().U.(*Mpint))
1181 Nodconst(n, n.Type, int64(n.Left.Val().U.(string)[v]))
1187 if Isconst(n.Right, CTINT) {
1188 if Mpcmpfixfix(n.Right.Val().U.(*Mpint), &mpzero) < 0 || Mpcmpfixfix(n.Right.Val().U.(*Mpint), Maxintval[TINT]) > 0 {
1189 Yyerror("index out of bounds")
1197 walkexpr(&n.Left, init)
1198 walkexpr(&n.Right, init)
1202 if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
1203 switch algtype(t.Down) {
1205 p = "mapaccess1_fast32"
1207 p = "mapaccess1_fast64"
1209 p = "mapaccess1_faststr"
1215 // fast versions take key by value
1218 // standard version takes key by reference.
1219 // orderexpr made sure key is addressable.
1220 key = Nod(OADDR, n.Right, nil)
1225 n = mkcall1(mapfn(p, t), Ptrto(t.Type), init, typename(t), n.Left, key)
1226 n = Nod(OIND, n, nil)
1231 Fatalf("walkexpr ORECV") // should see inside OAS only
1233 case OSLICE, OSLICEARR, OSLICESTR:
1234 walkexpr(&n.Left, init)
1235 walkexpr(&n.Right.Left, init)
1236 if n.Right.Left != nil && iszero(n.Right.Left) {
1237 // Reduce x[0:j] to x[:j].
1240 walkexpr(&n.Right.Right, init)
1243 case OSLICE3, OSLICE3ARR:
1244 walkexpr(&n.Left, init)
1245 walkexpr(&n.Right.Left, init)
1246 if n.Right.Left != nil && iszero(n.Right.Left) {
1247 // Reduce x[0:j:k] to x[:j:k].
1250 walkexpr(&n.Right.Right.Left, init)
1251 walkexpr(&n.Right.Right.Right, init)
1253 r := n.Right.Right.Right
1254 if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) {
1255 // Reduce x[i:j:cap(x)] to x[i:j].
1256 n.Right.Right = n.Right.Right.Left
1257 if n.Op == OSLICE3 {
1266 walkexpr(&n.Left, init)
1269 if n.Esc == EscNone {
1270 if n.Type.Type.Width >= 1<<16 {
1271 Fatalf("large ONEW with EscNone: %v", n)
1273 r := temp(n.Type.Type)
1274 r = Nod(OAS, r, nil) // zero temp
1276 *init = list(*init, r)
1277 r = Nod(OADDR, r.Left, nil)
1281 n = callnew(n.Type.Type)
1284 // If one argument to the comparison is an empty string,
1285 // comparing the lengths instead will yield the same result
1286 // without the function call.
1288 if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
1289 // TODO(marvin): Fix Node.EType type union.
1290 r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
1298 // s + "badgerbadgerbadger" == "badgerbadgerbadger"
1299 if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
1300 // TODO(marvin): Fix Node.EType type union.
1301 r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
1310 // TODO(marvin): Fix Node.EType type union.
1311 if Op(n.Etype) == OEQ || Op(n.Etype) == ONE {
1312 // prepare for rewrite below
1313 n.Left = cheapexpr(n.Left, init)
1315 n.Right = cheapexpr(n.Right, init)
1317 r = mkcall("eqstring", Types[TBOOL], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
1319 // quick check of len before full compare for == or !=
1320 // eqstring assumes that the lengths are equal
1321 // TODO(marvin): Fix Node.EType type union.
1322 if Op(n.Etype) == OEQ {
1323 // len(left) == len(right) && eqstring(left, right)
1324 r = Nod(OANDAND, Nod(OEQ, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
1326 // len(left) != len(right) || !eqstring(left, right)
1327 r = Nod(ONOT, r, nil)
1329 r = Nod(OOROR, Nod(ONE, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
1335 // sys_cmpstring(s1, s2) :: 0
1336 r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
1338 // TODO(marvin): Fix Node.EType type union.
1339 r = Nod(Op(n.Etype), r, Nodintconst(0))
1343 if n.Type.Etype != TBOOL {
1344 Fatalf("cmp %v", n.Type)
1353 // order should make sure we only see OAS(node, OAPPEND), which we handle above.
1354 Fatalf("append outside assignment")
1357 n = copyany(n, init, instrumenting)
1359 // cannot use chanfn - closechan takes any, not chan any
1361 fn := syslook("closechan", 1)
1363 substArgTypes(fn, n.Left.Type)
1364 n = mkcall1(fn, nil, init, n.Left)
1367 n = mkcall1(chanfn("makechan", 1, n.Type), n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]))
1372 fn := syslook("makemap", 1)
1374 a := nodnil() // hmap buffer
1375 r := nodnil() // bucket buffer
1376 if n.Esc == EscNone {
1377 // Allocate hmap buffer on stack.
1378 var_ := temp(hmap(t))
1380 a = Nod(OAS, var_, nil) // zero temp
1382 *init = list(*init, a)
1383 a = Nod(OADDR, var_, nil)
1385 // Allocate one bucket on stack.
1386 // Maximum key/value size is 128 bytes, larger objects
1387 // are stored with an indirection. So max bucket size is 2048+eps.
1388 var_ = temp(mapbucket(t))
1390 r = Nod(OAS, var_, nil) // zero temp
1392 *init = list(*init, r)
1393 r = Nod(OADDR, var_, nil)
1396 substArgTypes(fn, hmap(t), mapbucket(t), t.Down, t.Type)
1397 n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
1403 r = safeexpr(l, init)
1407 if n.Esc == EscNone {
1408 if !isSmallMakeSlice(n) {
1409 Fatalf("non-small OMAKESLICE with EscNone: %v", n)
1413 t = aindex(r, t.Type) // [r]T
1415 a := Nod(OAS, var_, nil) // zero temp
1417 *init = list(*init, a)
1418 r := Nod(OSLICE, var_, Nod(OKEY, nil, l)) // arr[:l]
1419 r = conv(r, n.Type) // in case n.Type is named.
1424 // makeslice(t *Type, nel int64, max int64) (ary []any)
1425 fn := syslook("makeslice", 1)
1427 substArgTypes(fn, t.Type) // any-1
1428 n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
1433 if n.Esc == EscNone {
1434 t := aindex(Nodintconst(4), Types[TUINT8])
1436 a = Nod(OADDR, var_, nil)
1439 // intstring(*[4]byte, rune)
1440 n = mkcall("intstring", n.Type, init, a, conv(n.Left, Types[TINT64]))
1444 if n.Esc == EscNone {
1445 // Create temporary buffer for string on stack.
1446 t := aindex(Nodintconst(tmpstringbufsize), Types[TUINT8])
1448 a = Nod(OADDR, temp(t), nil)
1451 // slicebytetostring(*[32]byte, []byte) string;
1452 n = mkcall("slicebytetostring", n.Type, init, a, n.Left)
1454 // slicebytetostringtmp([]byte) string;
1455 case OARRAYBYTESTRTMP:
1456 n = mkcall("slicebytetostringtmp", n.Type, init, n.Left)
1458 // slicerunetostring(*[32]byte, []rune) string;
1462 if n.Esc == EscNone {
1463 // Create temporary buffer for string on stack.
1464 t := aindex(Nodintconst(tmpstringbufsize), Types[TUINT8])
1466 a = Nod(OADDR, temp(t), nil)
1469 n = mkcall("slicerunetostring", n.Type, init, a, n.Left)
1471 // stringtoslicebyte(*32[byte], string) []byte;
1475 if n.Esc == EscNone {
1476 // Create temporary buffer for slice on stack.
1477 t := aindex(Nodintconst(tmpstringbufsize), Types[TUINT8])
1479 a = Nod(OADDR, temp(t), nil)
1482 n = mkcall("stringtoslicebyte", n.Type, init, a, conv(n.Left, Types[TSTRING]))
1484 // stringtoslicebytetmp(string) []byte;
1485 case OSTRARRAYBYTETMP:
1486 n = mkcall("stringtoslicebytetmp", n.Type, init, conv(n.Left, Types[TSTRING]))
1488 // stringtoslicerune(*[32]rune, string) []rune
1492 if n.Esc == EscNone {
1493 // Create temporary buffer for slice on stack.
1494 t := aindex(Nodintconst(tmpstringbufsize), Types[TINT32])
1496 a = Nod(OADDR, temp(t), nil)
1499 n = mkcall("stringtoslicerune", n.Type, init, a, n.Left)
1501 // ifaceeq(i1 any-1, i2 any-2) (ret bool);
1503 if !Eqtype(n.Left.Type, n.Right.Type) {
1504 Fatalf("ifaceeq %v %v %v", Oconv(int(n.Op), 0), n.Left.Type, n.Right.Type)
1507 if isnilinter(n.Left.Type) {
1508 fn = syslook("efaceeq", 1)
1510 fn = syslook("ifaceeq", 1)
1513 n.Right = cheapexpr(n.Right, init)
1514 n.Left = cheapexpr(n.Left, init)
1515 substArgTypes(fn, n.Right.Type, n.Left.Type)
1516 r := mkcall1(fn, n.Type, init, n.Left, n.Right)
1517 // TODO(marvin): Fix Node.EType type union.
1518 if Op(n.Etype) == ONE {
1519 r = Nod(ONOT, r, nil)
1522 // check itable/type before full compare.
1523 // TODO(marvin): Fix Node.EType type union.
1524 if Op(n.Etype) == OEQ {
1525 r = Nod(OANDAND, Nod(OEQ, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
1527 r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
1534 case OARRAYLIT, OMAPLIT, OSTRUCTLIT, OPTRLIT:
1535 var_ := temp(n.Type)
1536 anylit(0, n, var_, init)
1541 n1 = assignconv(n1, n.Left.Type.Type, "chan send")
1543 n1 = Nod(OADDR, n1, nil)
1544 n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
1547 n = walkclosure(n, init)
1550 n = walkpartialcall(n, init)
1553 // Expressions that are constant at run time but not
1554 // considered const by the language spec are not turned into
1555 // constants until walk. For example, if n is y%1 == 0, the
1556 // walk of y%1 may have replaced it by 0.
1557 // Check whether n with its updated args is itself now a constant.
1562 if n.Op == OLITERAL {
1568 if Debug['w'] != 0 && n != nil {
1576 func reduceSlice(n *Node) *Node {
1578 if r != nil && r.Op == OLEN && samesafeexpr(n.Left, r.Left) {
1579 // Reduce x[i:len(x)] to x[i:].
1582 if (n.Op == OSLICE || n.Op == OSLICESTR) && n.Right.Left == nil && n.Right.Right == nil {
1583 // Reduce x[:] to x.
1584 if Debug_slice > 0 {
1585 Warn("slice: omit slice operation")
1592 func ascompatee1(op Op, l *Node, r *Node, init **NodeList) *Node {
1593 // convas will turn map assigns into function calls,
1594 // making it impossible for reorder3 to work.
1597 if l.Op == OINDEXMAP {
1601 return convas(n, init)
1604 func ascompatee(op Op, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
1605 // check assign expression list to
1606 // a expression list. called in
1607 // expr-list = expr-list
1609 // ensure order of evaluation for function calls
1610 for ll := nl; ll != nil; ll = ll.Next {
1611 ll.N = safeexpr(ll.N, init)
1613 for lr := nr; lr != nil; lr = lr.Next {
1614 lr.N = safeexpr(lr.N, init)
1620 for ; ll != nil && lr != nil; ll, lr = ll.Next, lr.Next {
1621 // Do not generate 'x = x' during return. See issue 4014.
1622 if op == ORETURN && ll.N == lr.N {
1625 nn = list(nn, ascompatee1(op, ll.N, lr.N, init))
1628 // cannot happen: caller checked that lists had same length
1629 if ll != nil || lr != nil {
1630 Yyerror("error in shape across %v %v %v / %d %d [%s]", Hconv(nl, obj.FmtSign), Oconv(int(op), 0), Hconv(nr, obj.FmtSign), count(nl), count(nr), Curfn.Func.Nname.Sym.Name)
1635 // l is an lv and rt is the type of an rv
1636 // return 1 if this implies a function call
1637 // evaluating the lv or a function call
1638 // in the conversion of the types
1639 func fncall(l *Node, rt *Type) bool {
1640 if l.Ullman >= UINF || l.Op == OINDEXMAP {
1644 if needwritebarrier(l, &r) {
1647 if Eqtype(l.Type, rt) {
1653 func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
1660 // check assign type list to
1661 // a expression list. called in
1662 // expr-list = func()
1663 r := Structfirst(&saver, nr)
1668 for ll = nl; ll != nil; ll = ll.Next {
1674 r = structnext(&saver)
1678 // any lv that causes a fn call must be
1679 // deferred until all the return arguments
1680 // have been pulled from the output arguments
1681 if fncall(l, r.Type) {
1683 typecheck(&tmp, Erv)
1684 a = Nod(OAS, l, tmp)
1690 a = Nod(OAS, l, nodarg(r, fp))
1693 if a.Ullman >= UINF {
1694 Dump("ascompatet ucount", a)
1699 r = structnext(&saver)
1702 if ll != nil || r != nil {
1703 Yyerror("ascompatet: assignment count mismatch: %d = %d", count(nl), structcount(*nr))
1707 Fatalf("ascompatet: too many function calls evaluating parameters")
1709 return concat(nn, mm)
1712 // package all the arguments that match a ... T parameter into a []T.
1713 func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList, ddd *Node) *NodeList {
1714 esc := uint16(EscUnknown)
1719 tslice := typ(TARRAY)
1720 tslice.Type = l.Type.Type
1724 if count(lr0) == 0 {
1728 n = Nod(OCOMPLIT, nil, typenod(tslice))
1729 if ddd != nil && prealloc[ddd] != nil {
1730 prealloc[n] = prealloc[ddd] // temporary to use
1736 Fatalf("mkdotargslice: typecheck failed")
1741 a := Nod(OAS, nodarg(l, fp), n)
1742 nn = list(nn, convas(a, init))
1746 // helpers for shape errors
1747 func dumptypes(nl **Type, what string) string {
1753 for l := Structfirst(&savel, nl); l != nil; l = structnext(&savel) {
1763 fmt_ += fmt.Sprintf("[no arguments %s]", what)
1768 func dumpnodetypes(l *NodeList, what string) string {
1774 for ; l != nil; l = l.Next {
1781 fmt_ += Tconv(r.Type, 0)
1785 fmt_ += fmt.Sprintf("[no arguments %s]", what)
1790 // check assign expression list to
1791 // a type list. called in
1794 func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
1798 l := Structfirst(&savel, nl)
1805 // f(g()) where g has multiple return values
1810 if r != nil && lr.Next == nil && r.Type.Etype == TSTRUCT && r.Type.Funarg {
1811 // optimization - can do block copy
1812 if eqtypenoname(r.Type, *nl) {
1813 a := nodarg(*nl, fp)
1814 r = Nod(OCONVNOP, r, nil)
1816 nn = list1(convas(Nod(OAS, a, r), init))
1820 // conversions involved.
1821 // copy into temporaries.
1824 for l := Structfirst(&savel, &r.Type); l != nil; l = structnext(&savel) {
1826 alist = list(alist, a)
1829 a = Nod(OAS2, nil, nil)
1834 *init = list(*init, a)
1837 l = Structfirst(&savel, nl)
1841 if l != nil && l.Isddd {
1842 // the ddd parameter must be last
1843 ll = structnext(&savel)
1846 Yyerror("... must be last argument")
1850 // only if we are assigning a single ddd
1851 // argument to a ddd parameter then it is
1852 // passed thru unencapsulated
1853 if r != nil && lr.Next == nil && isddd && Eqtype(l.Type, r.Type) {
1854 a = Nod(OAS, nodarg(l, fp), r)
1860 // normal case -- make a slice of all
1861 // remaining arguments and pass it to
1862 // the ddd parameter.
1863 nn = mkdotargslice(lr, nn, l, fp, init, call.Right)
1868 if l == nil || r == nil {
1869 if l != nil || r != nil {
1870 l1 = dumptypes(nl, "expected")
1871 l2 = dumpnodetypes(lr0, "given")
1873 Yyerror("not enough arguments to %v\n%s\n%s", Oconv(int(op), 0), l1, l2)
1875 Yyerror("too many arguments to %v\n%s\n%s", Oconv(int(op), 0), l1, l2)
1882 a = Nod(OAS, nodarg(l, fp), r)
1886 l = structnext(&savel)
1895 for lr = nn; lr != nil; lr = lr.Next {
1901 // generate code for print
1902 func walkprint(nn *Node, init **NodeList) *Node {
1914 // Hoist all the argument evaluation up before the lock.
1915 walkexprlistcheap(all, init)
1917 calls = list(calls, mkcall("printlock", nil, init))
1919 for l := all; l != nil; l = l.Next {
1921 calls = list(calls, mkcall("printsp", nil, init))
1924 notfirst = op == OPRINTN
1927 if n.Op == OLITERAL {
1928 switch n.Val().Ctype() {
1930 defaultlit(&n, runetype)
1933 defaultlit(&n, Types[TINT64])
1936 defaultlit(&n, Types[TFLOAT64])
1940 if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL {
1941 defaultlit(&n, Types[TINT64])
1945 if n.Type == nil || n.Type.Etype == TFORW {
1951 if Isinter(n.Type) {
1952 if isnilinter(n.Type) {
1953 on = syslook("printeface", 1)
1955 on = syslook("printiface", 1)
1957 substArgTypes(on, n.Type) // any-1
1958 } else if Isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR {
1959 on = syslook("printpointer", 1)
1960 substArgTypes(on, n.Type) // any-1
1961 } else if Isslice(n.Type) {
1962 on = syslook("printslice", 1)
1963 substArgTypes(on, n.Type) // any-1
1964 } else if Isint[et] {
1966 if (t.Sym.Pkg == Runtimepkg || compiling_runtime != 0) && t.Sym.Name == "hex" {
1967 on = syslook("printhex", 0)
1969 on = syslook("printuint", 0)
1972 on = syslook("printint", 0)
1974 } else if Isfloat[et] {
1975 on = syslook("printfloat", 0)
1976 } else if Iscomplex[et] {
1977 on = syslook("printcomplex", 0)
1978 } else if et == TBOOL {
1979 on = syslook("printbool", 0)
1980 } else if et == TSTRING {
1981 on = syslook("printstring", 0)
1983 badtype(OPRINT, n.Type, nil)
1987 t = *getinarg(on.Type)
1995 if !Eqtype(t, n.Type) {
1996 n = Nod(OCONV, n, nil)
2000 r = Nod(OCALL, on, nil)
2002 calls = list(calls, r)
2006 calls = list(calls, mkcall("printnl", nil, nil))
2009 calls = list(calls, mkcall("printunlock", nil, init))
2011 typechecklist(calls, Etop)
2012 walkexprlist(calls, init)
2014 r = Nod(OEMPTY, nil, nil)
2021 func callnew(t *Type) *Node {
2023 fn := syslook("newobject", 1)
2024 substArgTypes(fn, t)
2025 return mkcall1(fn, Ptrto(t), nil, typename(t))
2028 func iscallret(n *Node) bool {
2030 return n.Op == OINDREG && n.Reg == int16(Thearch.REGSP)
2033 func isstack(n *Node) bool {
2036 // If n is *autotmp and autotmp = &foo, replace n with foo.
2037 // We introduce such temps when initializing struct literals.
2038 if n.Op == OIND && n.Left.Op == ONAME && strings.HasPrefix(n.Left.Sym.Name, "autotmp_") {
2039 defn := n.Left.Name.Defn
2040 if defn != nil && defn.Op == OAS && defn.Right.Op == OADDR {
2047 return n.Reg == int16(Thearch.REGSP)
2051 case PAUTO, PPARAM, PPARAMOUT:
2059 func isglobal(n *Node) bool {
2073 // Do we need a write barrier for the assignment l = r?
2074 func needwritebarrier(l *Node, r *Node) bool {
2075 if use_writebarrier == 0 {
2079 if l == nil || isblank(l) {
2083 // No write barrier for write of non-pointers.
2086 if !haspointers(l.Type) {
2090 // No write barrier for write to stack.
2095 // No write barrier for implicit zeroing.
2100 // Ignore no-op conversions when making decision.
2101 // Ensures that xp = unsafe.Pointer(&x) is treated
2102 // the same as xp = &x.
2103 for r.Op == OCONVNOP {
2107 // No write barrier for zeroing or initialization to constant.
2108 if iszero(r) || r.Op == OLITERAL {
2112 // No write barrier for storing static (read-only) data.
2113 if r.Op == ONAME && strings.HasPrefix(r.Sym.Name, "statictmp_") {
2117 // No write barrier for storing address of stack values,
2118 // which are guaranteed only to be written to the stack.
2119 if r.Op == OADDR && isstack(r.Left) {
2123 // No write barrier for storing address of global, which
2124 // is live no matter what.
2125 if r.Op == OADDR && isglobal(r.Left) {
2129 // Otherwise, be conservative and use write barrier.
2133 // TODO(rsc): Perhaps componentgen should run before this.
2135 func applywritebarrier(n *Node, init **NodeList) *Node {
2136 if n.Left != nil && n.Right != nil && needwritebarrier(n.Left, n.Right) {
2138 Warnl(int(n.Lineno), "marking %v for barrier", Nconv(n.Left, 0))
2146 func convas(n *Node, init **NodeList) *Node {
2148 Fatalf("convas: not OAS %v", Oconv(int(n.Op), 0))
2155 if n.Left == nil || n.Right == nil {
2161 if lt == nil || rt == nil {
2165 if isblank(n.Left) {
2166 defaultlit(&n.Right, nil)
2170 if n.Left.Op == OINDEXMAP {
2174 walkexpr(&map_, init)
2175 walkexpr(&key, init)
2176 walkexpr(&val, init)
2178 // orderexpr made sure key and val are addressable.
2179 key = Nod(OADDR, key, nil)
2181 val = Nod(OADDR, val, nil)
2182 n = mkcall1(mapfn("mapassign1", map_.Type), nil, init, typename(map_.Type), map_, key, val)
2186 if !Eqtype(lt, rt) {
2187 n.Right = assignconv(n.Right, lt, "assignment")
2188 walkexpr(&n.Right, init)
2196 // from ascompat[te]
2197 // evaluating actual function arguments.
2199 // if there is exactly one function expr,
2200 // then it is done first. otherwise must
2201 // make temp variables
2202 func reorder1(all *NodeList) *NodeList {
2205 c := 0 // function calls
2206 t := 0 // total parameters
2208 for l := all; l != nil; l = l.Next {
2212 if n.Ullman >= UINF {
2217 if c == 0 || t == 1 {
2221 var g *NodeList // fncalls assigned to tempnames
2222 var f *Node // last fncall assigned to stack
2223 var r *NodeList // non fncalls and tempnames assigned to stack
2226 for l := all; l != nil; l = l.Next {
2228 if n.Ullman < UINF {
2239 // make assignment of fncall to tempname
2240 a = temp(n.Right.Type)
2242 a = Nod(OAS, a, n.Right)
2245 // put normal arg assignment on list
2246 // with fncall replaced by tempname
2258 // from ascompat[ee]
2260 // simultaneous assignment. there cannot
2261 // be later use of an earlier lvalue.
2263 // function calls have been removed.
2264 func reorder3(all *NodeList) *NodeList {
2267 // If a needed expression may be affected by an
2268 // earlier assignment, make an early copy of that
2269 // expression and use the copy instead.
2272 var mapinit *NodeList
2273 for list := all; list != nil; list = list.Next {
2276 // Save subexpressions needed on left side.
2277 // Drill through non-dereferences.
2279 if l.Op == ODOT || l.Op == OPAREN {
2284 if l.Op == OINDEX && Isfixedarray(l.Left.Type) {
2285 reorder3save(&l.Right, all, list, &early)
2295 Fatalf("reorder3 unexpected lvalue %v", Oconv(int(l.Op), obj.FmtSharp))
2300 case OINDEX, OINDEXMAP:
2301 reorder3save(&l.Left, all, list, &early)
2302 reorder3save(&l.Right, all, list, &early)
2303 if l.Op == OINDEXMAP {
2304 list.N = convas(list.N, &mapinit)
2308 reorder3save(&l.Left, all, list, &early)
2311 // Save expression on right side.
2312 reorder3save(&list.N.Right, all, list, &early)
2315 early = concat(mapinit, early)
2316 return concat(early, all)
2319 // if the evaluation of *np would be affected by the
2320 // assignments in all up to but not including stop,
2321 // copy into a temporary during *early and
2322 // replace *np with that temp.
2323 func reorder3save(np **Node, all *NodeList, stop *NodeList, early **NodeList) {
2325 if !aliased(n, all, stop) {
2332 *early = list(*early, q)
2336 // what's the outer value that a write to n affects?
2337 // outer value means containing struct or array.
2338 func outervalue(n *Node) *Node {
2341 Fatalf("OXDOT in walk")
2343 if n.Op == ODOT || n.Op == OPAREN || n.Op == OCONVNOP {
2348 if n.Op == OINDEX && Isfixedarray(n.Left.Type) {
2359 // Is it possible that the computation of n might be
2360 // affected by writes in as up to but not including stop?
2361 func aliased(n *Node, all *NodeList, stop *NodeList) bool {
2366 // Look for obvious aliasing: a variable being assigned
2367 // during the all list and appearing in n.
2368 // Also record whether there are any writes to main memory.
2369 // Also record whether there are any writes to variables
2370 // whose addresses have been taken.
2375 for l := all; l != stop; l = l.Next {
2376 a = outervalue(l.N.Left)
2387 case PAUTO, PPARAM, PPARAMOUT:
2400 // The variables being written do not appear in n.
2401 // However, n might refer to computed addresses
2402 // that are being written.
2404 // If no computed addresses are affected by the writes, no aliasing.
2405 if memwrite == 0 && varwrite == 0 {
2409 // If n does not refer to computed addresses
2410 // (that is, if n only refers to variables whose addresses
2411 // have not been taken), no aliasing.
2416 // Otherwise, both the writes and n refer to computed memory addresses.
2417 // Assume that they might conflict.
2421 // does the evaluation of n only refer to variables
2422 // whose addresses have not been taken?
2423 // (and no other memory)
2424 func varexpr(n *Node) bool {
2435 case PAUTO, PPARAM, PPARAMOUT:
2460 ODOT, // but not ODOTPTR
2465 return varexpr(n.Left) && varexpr(n.Right)
2472 // is the name l mentioned in r?
2473 func vmatch2(l *Node, r *Node) bool {
2478 // match each right given left
2486 if vmatch2(l, r.Left) {
2489 if vmatch2(l, r.Right) {
2492 for ll := r.List; ll != nil; ll = ll.Next {
2493 if vmatch2(l, ll.N) {
2500 // is any name mentioned in l also mentioned in r?
2501 // called by sinit.go
2502 func vmatch1(l *Node, r *Node) bool {
2503 // isolate all left sides
2504 if l == nil || r == nil {
2510 case PPARAM, PPARAMREF, PAUTO:
2513 // assignment to non-stack variable
2514 // must be delayed if right has function calls.
2516 if r.Ullman >= UINF {
2521 return vmatch2(l, r)
2527 if vmatch1(l.Left, r) {
2530 if vmatch1(l.Right, r) {
2533 for ll := l.List; ll != nil; ll = ll.Next {
2534 if vmatch1(ll.N, r) {
2541 // walk through argin parameters.
2542 // generate and return code to allocate
2543 // copies of escaped parameters to the heap.
2544 func paramstoheap(argin **Type, out int) *NodeList {
2550 for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
2552 if v != nil && v.Sym != nil && v.Sym.Name[0] == '~' && v.Sym.Name[1] == 'r' { // unnamed result
2556 // For precise stacks, the garbage collector assumes results
2557 // are always live, so zero them always.
2559 // Defer might stop a panic and show the
2560 // return values as they exist at the time of panic.
2561 // Make sure to zero them on entry to the function.
2562 nn = list(nn, Nod(OAS, nodarg(t, -1), nil))
2565 if v == nil || v.Class&PHEAP == 0 {
2569 // generate allocation & copying code
2570 if compiling_runtime != 0 {
2571 Yyerror("%v escapes to heap, not allowed in runtime.", v)
2573 if prealloc[v] == nil {
2574 prealloc[v] = callnew(v.Type)
2576 nn = list(nn, Nod(OAS, v.Name.Heapaddr, prealloc[v]))
2577 if v.Class&^PHEAP != PPARAMOUT {
2578 as = Nod(OAS, v, v.Name.Param.Stackparam)
2579 v.Name.Param.Stackparam.Typecheck = 1
2580 typecheck(&as, Etop)
2581 as = applywritebarrier(as, &nn)
2589 // walk through argout parameters copying back to stack
2590 func returnsfromheap(argin **Type) *NodeList {
2595 for t := Structfirst(&savet, argin); t != nil; t = structnext(&savet) {
2597 if v == nil || v.Class != PHEAP|PPARAMOUT {
2600 nn = list(nn, Nod(OAS, v.Name.Param.Stackparam, v))
2606 // take care of migrating any function in/out args
2607 // between the stack and the heap. adds code to
2608 // curfn's before and after lists.
2611 lineno = Curfn.Lineno
2612 nn := paramstoheap(getthis(Curfn.Type), 0)
2613 nn = concat(nn, paramstoheap(getinarg(Curfn.Type), 0))
2614 nn = concat(nn, paramstoheap(Getoutarg(Curfn.Type), 1))
2615 Curfn.Func.Enter = concat(Curfn.Func.Enter, nn)
2616 lineno = Curfn.Func.Endlineno
2617 Curfn.Func.Exit = returnsfromheap(Getoutarg(Curfn.Type))
2621 func vmkcall(fn *Node, t *Type, init **NodeList, va []*Node) *Node {
2622 if fn.Type == nil || fn.Type.Etype != TFUNC {
2623 Fatalf("mkcall %v %v", fn, fn.Type)
2627 n := fn.Type.Intuple
2628 for i := 0; i < n; i++ {
2629 args = list(args, va[i])
2632 r := Nod(OCALL, fn, nil)
2634 if fn.Type.Outtuple > 0 {
2635 typecheck(&r, Erv|Efnstruct)
2644 func mkcall(name string, t *Type, init **NodeList, args ...*Node) *Node {
2645 return vmkcall(syslook(name, 0), t, init, args)
2648 func mkcall1(fn *Node, t *Type, init **NodeList, args ...*Node) *Node {
2649 return vmkcall(fn, t, init, args)
2652 func conv(n *Node, t *Type) *Node {
2653 if Eqtype(n.Type, t) {
2656 n = Nod(OCONV, n, nil)
2662 func chanfn(name string, n int, t *Type) *Node {
2663 if t.Etype != TCHAN {
2664 Fatalf("chanfn %v", t)
2666 fn := syslook(name, 1)
2669 Fatalf("chanfn %d", n)
2671 substArgTypes(fn, t.Type)
2673 substArgTypes(fn, t.Type, t.Type)
2678 func mapfn(name string, t *Type) *Node {
2679 if t.Etype != TMAP {
2680 Fatalf("mapfn %v", t)
2682 fn := syslook(name, 1)
2683 substArgTypes(fn, t.Down, t.Type, t.Down, t.Type)
2687 func mapfndel(name string, t *Type) *Node {
2688 if t.Etype != TMAP {
2689 Fatalf("mapfn %v", t)
2691 fn := syslook(name, 1)
2692 substArgTypes(fn, t.Down, t.Type, t.Down)
2696 func writebarrierfn(name string, l *Type, r *Type) *Node {
2697 fn := syslook(name, 1)
2698 substArgTypes(fn, l, r)
2702 func addstr(n *Node, init **NodeList) *Node {
2703 // orderexpr rewrote OADDSTR to have a list of strings.
2707 Yyerror("addstr count %d too small", c)
2711 if n.Esc == EscNone {
2713 for l := n.List; l != nil; l = l.Next {
2714 if n.Op == OLITERAL {
2715 sz += int64(len(n.Val().U.(string)))
2719 // Don't allocate the buffer if the result won't fit.
2720 if sz < tmpstringbufsize {
2721 // Create temporary buffer for result string on stack.
2722 t := aindex(Nodintconst(tmpstringbufsize), Types[TUINT8])
2724 buf = Nod(OADDR, temp(t), nil)
2728 // build list of string arguments
2731 for l := n.List; l != nil; l = l.Next {
2732 args = list(args, conv(l.N, Types[TSTRING]))
2737 // small numbers of strings use direct runtime helpers.
2738 // note: orderexpr knows this cutoff too.
2739 fn = fmt.Sprintf("concatstring%d", c)
2741 // large numbers of strings are passed to the runtime as a slice.
2742 fn = "concatstrings"
2745 t.Type = Types[TSTRING]
2747 slice := Nod(OCOMPLIT, nil, typenod(t))
2748 if prealloc[n] != nil {
2749 prealloc[slice] = prealloc[n]
2751 slice.List = args.Next // skip buf arg
2753 args = list(args, slice)
2757 cat := syslook(fn, 1)
2758 r := Nod(OCALL, cat, nil)
2767 // expand append(l1, l2...) to
2770 // if n := len(l1) + len(l2) - cap(s); n > 0 {
2771 // s = growslice_n(s, n)
2773 // s = s[:len(l1)+len(l2)]
2774 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
2778 // l2 is allowed to be a string.
2779 func appendslice(n *Node, init **NodeList) *Node {
2780 walkexprlistsafe(n.List, init)
2782 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
2783 // and n are name or literal, but those may index the slice we're
2784 // modifying here. Fix explicitly.
2785 for l := n.List; l != nil; l = l.Next {
2786 l.N = cheapexpr(l.N, init)
2792 s := temp(l1.Type) // var s []T
2794 l = list(l, Nod(OAS, s, l1)) // s = l1
2796 nt := temp(Types[TINT])
2798 nif := Nod(OIF, nil, nil)
2800 // n := len(s) + len(l2) - cap(s)
2801 nif.Ninit = list1(Nod(OAS, nt, Nod(OSUB, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)), Nod(OCAP, s, nil))))
2803 nif.Left = Nod(OGT, nt, Nodintconst(0))
2805 // instantiate growslice_n(Type*, []any, int) []any
2806 fn := syslook("growslice_n", 1) // growslice_n(<type>, old []T, n int64) (ret []T)
2807 substArgTypes(fn, s.Type.Type, s.Type.Type)
2809 // s = growslice_n(T, s, n)
2810 nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
2814 if haspointers(l1.Type.Type) {
2815 // copy(s[len(l1):len(l1)+len(l2)], l2)
2816 nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
2820 fn := syslook("typedslicecopy", 1)
2821 substArgTypes(fn, l1.Type, l2.Type)
2822 nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2)
2824 } else if instrumenting {
2825 // rely on runtime to instrument copy.
2826 // copy(s[len(l1):len(l1)+len(l2)], l2)
2827 nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
2832 if l2.Type.Etype == TSTRING {
2833 fn = syslook("slicestringcopy", 1)
2835 fn = syslook("slicecopy", 1)
2837 substArgTypes(fn, l1.Type, l2.Type)
2838 nt := mkcall1(fn, Types[TINT], &l, nptr1, nptr2, Nodintconst(s.Type.Type.Width))
2841 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
2842 nptr1 := Nod(OINDEX, s, Nod(OLEN, l1, nil))
2844 nptr1.Bounded = true
2845 nptr1 = Nod(OADDR, nptr1, nil)
2847 nptr2 := Nod(OSPTR, l2, nil)
2849 fn := syslook("memmove", 1)
2850 substArgTypes(fn, s.Type.Type, s.Type.Type)
2852 nwid := cheapexpr(conv(Nod(OLEN, l2, nil), Types[TUINTPTR]), &l)
2854 nwid = Nod(OMUL, nwid, Nodintconst(s.Type.Type.Width))
2855 nt := mkcall1(fn, nil, &l, nptr1, nptr2, nwid)
2859 // s = s[:len(l1)+len(l2)]
2860 nt = Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))
2862 nt = Nod(OSLICE, s, Nod(OKEY, nil, nt))
2864 l = list(l, Nod(OAS, s, nt))
2866 typechecklist(l, Etop)
2868 *init = concat(*init, l)
2872 // Rewrite append(src, x, y, z) so that any side effects in
2873 // x, y, z (including runtime panics) are evaluated in
2874 // initialization statements before the append.
2875 // For normal code generation, stop there and leave the
2876 // rest to cgen_append.
2878 // For race detector, expand append(src, a [, b]* ) to
2882 // const argc = len(args) - 1
2883 // if cap(s) - len(s) < argc {
2884 // s = growslice(s, len(s)+argc)
2893 func walkappend(n *Node, init **NodeList, dst *Node) *Node {
2894 if !samesafeexpr(dst, n.List.N) {
2896 l.N = safeexpr(l.N, init)
2897 walkexpr(&l.N, init)
2899 walkexprlistsafe(n.List.Next, init)
2901 // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
2902 // and n are name or literal, but those may index the slice we're
2903 // modifying here. Fix explicitly.
2904 // Using cheapexpr also makes sure that the evaluation
2905 // of all arguments (and especially any panics) happen
2906 // before we begin to modify the slice in a visible way.
2907 for l := n.List.Next; l != nil; l = l.Next {
2908 l.N = cheapexpr(l.N, init)
2913 // Resolve slice type of multi-valued return.
2914 if Istype(nsrc.Type, TSTRUCT) {
2915 nsrc.Type = nsrc.Type.Type.Type
2917 argc := count(n.List) - 1
2922 // General case, with no function calls left as arguments.
2923 // Leave for gen, except that instrumentation requires old form.
2930 ns := temp(nsrc.Type)
2931 l = list(l, Nod(OAS, ns, nsrc)) // s = src
2933 na := Nodintconst(int64(argc)) // const argc
2934 nx := Nod(OIF, nil, nil) // if cap(s) - len(s) < argc
2935 nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
2937 fn := syslook("growslice", 1) // growslice(<type>, old []T, mincap int) (ret []T)
2938 substArgTypes(fn, ns.Type.Type, ns.Type.Type)
2940 nx.Nbody = list1(Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, Nod(OADD, Nod(OLEN, ns, nil), na))))
2944 nn := temp(Types[TINT])
2945 l = list(l, Nod(OAS, nn, Nod(OLEN, ns, nil))) // n = len(s)
2947 nx = Nod(OSLICE, ns, Nod(OKEY, nil, Nod(OADD, nn, na))) // ...s[:n+argc]
2949 l = list(l, Nod(OAS, ns, nx)) // s = s[:n+argc]
2951 for a := n.List.Next; a != nil; a = a.Next {
2952 nx = Nod(OINDEX, ns, nn) // s[n] ...
2954 l = list(l, Nod(OAS, nx, a.N)) // s[n] = arg
2956 l = list(l, Nod(OAS, nn, Nod(OADD, nn, Nodintconst(1)))) // n = n + 1
2960 typechecklist(l, Etop)
2962 *init = concat(*init, l)
2966 // Lower copy(a, b) to a memmove call or a runtime call.
2970 // if n > len(b) { n = len(b) }
2971 // memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
2975 // Also works if b is a string.
2977 func copyany(n *Node, init **NodeList, runtimecall bool) *Node {
2978 if haspointers(n.Left.Type.Type) {
2979 fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
2980 return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right)
2985 if n.Right.Type.Etype == TSTRING {
2986 fn = syslook("slicestringcopy", 1)
2988 fn = syslook("slicecopy", 1)
2990 substArgTypes(fn, n.Left.Type, n.Right.Type)
2991 return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width))
2994 walkexpr(&n.Left, init)
2995 walkexpr(&n.Right, init)
2996 nl := temp(n.Left.Type)
2997 nr := temp(n.Right.Type)
2999 l = list(l, Nod(OAS, nl, n.Left))
3000 l = list(l, Nod(OAS, nr, n.Right))
3002 nfrm := Nod(OSPTR, nr, nil)
3003 nto := Nod(OSPTR, nl, nil)
3005 nlen := temp(Types[TINT])
3008 l = list(l, Nod(OAS, nlen, Nod(OLEN, nl, nil)))
3010 // if n > len(frm) { n = len(frm) }
3011 nif := Nod(OIF, nil, nil)
3013 nif.Left = Nod(OGT, nlen, Nod(OLEN, nr, nil))
3014 nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
3018 fn := syslook("memmove", 1)
3020 substArgTypes(fn, nl.Type.Type, nl.Type.Type)
3021 nwid := temp(Types[TUINTPTR])
3022 l = list(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR])))
3023 nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width))
3024 l = list(l, mkcall1(fn, nil, init, nto, nfrm, nwid))
3026 typechecklist(l, Etop)
3028 *init = concat(*init, l)
3032 func eqfor(t *Type, needsize *int) *Node {
3033 // Should only arrive here with large memory or
3034 // a struct/array containing a non-memory field/element.
3035 // Small memory is handled inline, and single non-memory
3036 // is handled during type check (OCMPSTR etc).
3037 a := algtype1(t, nil)
3039 if a != AMEM && a != -1 {
3040 Fatalf("eqfor %v", t)
3044 n := syslook("memequal", 1)
3045 substArgTypes(n, t, t)
3050 sym := typesymprefix(".eq", t)
3053 ntype := Nod(OTFUNC, nil, nil)
3054 ntype.List = list(ntype.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
3055 ntype.List = list(ntype.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
3056 ntype.Rlist = list(ntype.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TBOOL])))
3057 typecheck(&ntype, Etype)
3063 func countfield(t *Type) int {
3065 for t1 := t.Type; t1 != nil; t1 = t1.Down {
3071 func walkcompare(np **Node, init **NodeList) {
3074 // Given interface value l and concrete value r, rewrite
3077 // x, ok := l.(type(r)); ok && x == r
3078 // Handle != similarly.
3079 // This avoids the allocation that would be required
3080 // to convert r to l for comparison.
3084 if Isinter(n.Left.Type) && !Isinter(n.Right.Type) {
3087 } else if !Isinter(n.Left.Type) && Isinter(n.Right.Type) {
3094 if haspointers(r.Type) {
3095 a := Nod(OAS, x, nil)
3097 *init = list(*init, a)
3099 ok := temp(Types[TBOOL])
3102 a := Nod(ODOTTYPE, l, nil)
3106 // x, ok := l.(type(r))
3107 expr := Nod(OAS2, nil, nil)
3109 expr.List = list1(x)
3110 expr.List = list(expr.List, ok)
3111 expr.Rlist = list1(a)
3112 typecheck(&expr, Etop)
3113 walkexpr(&expr, init)
3116 r = Nod(OANDAND, ok, Nod(OEQ, x, r))
3118 r = Nod(OOROR, Nod(ONOT, ok, nil), Nod(ONE, x, r))
3120 *init = list(*init, expr)
3121 finishcompare(np, n, r, init)
3125 // Must be comparison of array or struct.
3126 // Otherwise back end handles it.
3143 for cmpl != nil && cmpl.Op == OCONVNOP {
3147 for cmpr != nil && cmpr.Op == OCONVNOP {
3151 if !islvalue(cmpl) || !islvalue(cmpr) {
3152 Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
3156 a := Nod(OAS, l, Nod(OADDR, cmpl, nil))
3157 a.Right.Etype = 1 // addr does not escape
3159 *init = list(*init, a)
3162 a = Nod(OAS, r, Nod(OADDR, cmpr, nil))
3163 a.Right.Etype = 1 // addr does not escape
3165 *init = list(*init, a)
3167 var andor Op = OANDAND
3173 if t.Etype == TARRAY && t.Bound <= 4 && issimple[t.Type.Etype] {
3174 // Four or fewer elements of a basic type.
3175 // Unroll comparisons.
3178 for i := 0; int64(i) < t.Bound; i++ {
3179 li = Nod(OINDEX, l, Nodintconst(int64(i)))
3180 ri = Nod(OINDEX, r, Nodintconst(int64(i)))
3181 a = Nod(n.Op, li, ri)
3185 expr = Nod(andor, expr, a)
3190 expr = Nodbool(n.Op == OEQ)
3192 finishcompare(np, n, expr, init)
3196 if t.Etype == TARRAY {
3197 // Zero- or single-element array, of any type.
3200 finishcompare(np, n, Nodbool(n.Op == OEQ), init)
3203 l0 := Nod(OINDEX, l, Nodintconst(0))
3204 r0 := Nod(OINDEX, r, Nodintconst(0))
3205 a := Nod(n.Op, l0, r0)
3206 finishcompare(np, n, a, init)
3211 if t.Etype == TSTRUCT && countfield(t) <= 4 {
3212 // Struct of four or fewer fields.
3213 // Inline comparisons.
3216 for t1 := t.Type; t1 != nil; t1 = t1.Down {
3217 if isblanksym(t1.Sym) {
3220 li = Nod(OXDOT, l, newname(t1.Sym))
3221 ri = Nod(OXDOT, r, newname(t1.Sym))
3222 a = Nod(n.Op, li, ri)
3226 expr = Nod(andor, expr, a)
3231 expr = Nodbool(n.Op == OEQ)
3233 finishcompare(np, n, expr, init)
3237 // Chose not to inline. Call equality function directly.
3239 call := Nod(OCALL, eqfor(t, &needsize), nil)
3241 call.List = list(call.List, l)
3242 call.List = list(call.List, r)
3244 call.List = list(call.List, Nodintconst(t.Width))
3248 r = Nod(ONOT, r, nil)
3251 finishcompare(np, n, r, init)
3255 func finishcompare(np **Node, n, r *Node, init **NodeList) {
3256 // Using np here to avoid passing &r to typecheck.
3261 if r.Type != n.Type {
3262 r = Nod(OCONVNOP, r, nil)
3269 func samecheap(a *Node, b *Node) bool {
3272 for a != nil && b != nil && a.Op == b.Op {
3283 if ar.Op != ONAME || br.Op != ONAME || ar.Sym != br.Sym {
3290 if !Isconst(ar, CTINT) || !Isconst(br, CTINT) || Mpcmpfixfix(ar.Val().U.(*Mpint), br.Val().U.(*Mpint)) != 0 {
3302 func walkrotate(np **Node) {
3303 if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
3309 // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
3313 if (n.Op != OOR && n.Op != OXOR) || (l.Op != OLSH && l.Op != ORSH) || (r.Op != OLSH && r.Op != ORSH) || n.Type == nil || Issigned[n.Type.Etype] || l.Op == r.Op {
3317 // Want same, side effect-free expression on lhs of both shifts.
3318 if !samecheap(l.Left, r.Left) {
3322 // Constants adding to width?
3323 w := int(l.Type.Width * 8)
3325 if Smallintconst(l.Right) && Smallintconst(r.Right) {
3326 sl := int(Mpgetfix(l.Right.Val().U.(*Mpint)))
3328 sr := int(Mpgetfix(r.Right.Val().U.(*Mpint)))
3329 if sr >= 0 && sl+sr == w {
3330 // Rewrite left shift half to left rotate.
3338 // Remove rotate 0 and rotate w.
3339 s := int(Mpgetfix(n.Right.Val().U.(*Mpint)))
3341 if s == 0 || s == w {
3352 // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
3356 // walkmul rewrites integer multiplication by powers of two as shifts.
3357 func walkmul(np **Node, init **NodeList) {
3359 if !Isint[n.Type.Etype] {
3365 if n.Right.Op == OLITERAL {
3368 } else if n.Left.Op == OLITERAL {
3377 // x*0 is 0 (and side effects of x).
3380 if Mpgetfix(nr.Val().U.(*Mpint)) == 0 {
3382 Nodconst(n, n.Type, 0)
3386 // nr is a constant.
3393 // negative power of 2, like -16
3399 w = int(nl.Type.Width * 8)
3400 if pow+1 >= w { // too big, shouldn't happen
3404 nl = cheapexpr(nl, init)
3413 n = Nod(OLSH, nl, Nodintconst(int64(pow)))
3417 n = Nod(OMINUS, n, nil)
3425 // walkdiv rewrites division by a constant as less expensive
3427 func walkdiv(np **Node, init **NodeList) {
3428 // if >= 0, nr is 1<<pow // 1 if nr is negative.
3431 if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
3436 if n.Right.Op != OLITERAL {
3440 // nr is a constant.
3441 nl := cheapexpr(n.Left, init)
3445 // special cases of mod/div
3447 w := int(nl.Type.Width * 8)
3449 s := 0 // 1 if nr is negative.
3450 pow := powtwo(nr) // if >= 0, nr is 1<<pow
3452 // negative power of 2
3459 // divisor too large.
3464 // try to do division by multiply by (2^w)/d
3465 // see hacker's delight chapter 10
3466 // TODO: support 64-bit magic multiply here.
3470 if Issigned[nl.Type.Etype] {
3471 m.Sd = Mpgetfix(nr.Val().U.(*Mpint))
3474 m.Ud = uint64(Mpgetfix(nr.Val().U.(*Mpint)))
3482 // We have a quick division method so use it
3485 // rewrite as A%B = A - (A/B*B).
3486 n1 := Nod(ODIV, nl, nr)
3488 n2 := Nod(OMUL, n1, nr)
3489 n = Nod(OSUB, nl, n2)
3493 switch Simtype[nl.Type.Etype] {
3497 // n1 = nl * magic >> w (HMUL)
3498 case TUINT8, TUINT16, TUINT32:
3499 nc := Nod(OXXX, nil, nil)
3501 Nodconst(nc, nl.Type, int64(m.Um))
3502 n1 := Nod(OHMUL, nl, nc)
3505 // Select a Go type with (at least) twice the width.
3507 switch Simtype[nl.Type.Etype] {
3511 case TUINT8, TUINT16:
3512 twide = Types[TUINT32]
3515 twide = Types[TUINT64]
3518 twide = Types[TINT32]
3521 twide = Types[TINT64]
3524 // add numerator (might overflow).
3526 n2 := Nod(OADD, conv(n1, twide), conv(nl, twide))
3529 nc := Nod(OXXX, nil, nil)
3531 Nodconst(nc, Types[TUINT], int64(m.S))
3532 n = conv(Nod(ORSH, n2, nc), nl.Type)
3535 nc := Nod(OXXX, nil, nil)
3537 Nodconst(nc, Types[TUINT], int64(m.S))
3538 n = Nod(ORSH, n1, nc)
3541 // n1 = nl * magic >> w
3542 case TINT8, TINT16, TINT32:
3543 nc := Nod(OXXX, nil, nil)
3545 Nodconst(nc, nl.Type, m.Sm)
3546 n1 := Nod(OHMUL, nl, nc)
3549 // add the numerator.
3550 n1 = Nod(OADD, n1, nl)
3554 nc = Nod(OXXX, nil, nil)
3556 Nodconst(nc, Types[TUINT], int64(m.S))
3557 n2 := conv(Nod(ORSH, n1, nc), nl.Type)
3559 // add 1 iff n1 is negative.
3560 nc = Nod(OXXX, nil, nil)
3562 Nodconst(nc, Types[TUINT], int64(w)-1)
3563 n3 := Nod(ORSH, nl, nc) // n4 = -1 iff n1 is negative.
3564 n = Nod(OSUB, n2, n3)
3568 n = Nod(OMINUS, n, nil)
3579 Nodconst(n, n.Type, 0)
3591 if Issigned[n.Type.Etype] {
3593 // signed modulo 2^pow is like ANDing
3594 // with the last pow bits, but if nl < 0,
3595 // nl & (2^pow-1) is (nl+1)%2^pow - 1.
3596 nc := Nod(OXXX, nil, nil)
3598 Nodconst(nc, Types[Simtype[TUINT]], int64(w)-1)
3599 n1 := Nod(ORSH, nl, nc) // n1 = -1 iff nl < 0.
3602 n1 = cheapexpr(n1, init)
3604 // n = (nl+ε)&1 -ε where ε=1 iff nl<0.
3605 n2 := Nod(OSUB, nl, n1)
3607 nc := Nod(OXXX, nil, nil)
3608 Nodconst(nc, nl.Type, 1)
3609 n3 := Nod(OAND, n2, nc)
3610 n = Nod(OADD, n3, n1)
3612 // n = (nl+ε)&(nr-1) - ε where ε=2^pow-1 iff nl<0.
3613 nc := Nod(OXXX, nil, nil)
3615 Nodconst(nc, nl.Type, (1<<uint(pow))-1)
3616 n2 := Nod(OAND, n1, nc) // n2 = 2^pow-1 iff nl<0.
3618 n2 = cheapexpr(n2, init)
3620 n3 := Nod(OADD, nl, n2)
3621 n4 := Nod(OAND, n3, nc)
3622 n = Nod(OSUB, n4, n2)
3627 // arithmetic right shift does not give the correct rounding.
3628 // if nl >= 0, nl >> n == nl / nr
3629 // if nl < 0, we want to add 2^n-1 first.
3630 nc := Nod(OXXX, nil, nil)
3632 Nodconst(nc, Types[Simtype[TUINT]], int64(w)-1)
3633 n1 := Nod(ORSH, nl, nc) // n1 = -1 iff nl < 0.
3636 n.Left = Nod(OSUB, nl, n1)
3638 // Do a logical right right on -1 to keep pow bits.
3639 nc := Nod(OXXX, nil, nil)
3641 Nodconst(nc, Types[Simtype[TUINT]], int64(w)-int64(pow))
3642 n2 := Nod(ORSH, conv(n1, tounsigned(nl.Type)), nc)
3643 n.Left = Nod(OADD, nl, conv(n2, nl.Type))
3646 // n = (nl + 2^pow-1) >> pow
3649 nc = Nod(OXXX, nil, nil)
3650 Nodconst(nc, Types[Simtype[TUINT]], int64(pow))
3656 n = Nod(OMINUS, n, nil)
3661 nc := Nod(OXXX, nil, nil)
3666 Nodconst(nc, nl.Type, Mpgetfix(nr.Val().U.(*Mpint))-1)
3671 Nodconst(nc, Types[Simtype[TUINT]], int64(pow))
3686 // return 1 if integer n must be in range [0, max), 0 otherwise
3687 func bounded(n *Node, max int64) bool {
3688 if n.Type == nil || !Isint[n.Type.Etype] {
3692 sign := Issigned[n.Type.Etype]
3693 bits := int32(8 * n.Type.Width)
3695 if Smallintconst(n) {
3696 v := Mpgetfix(n.Val().U.(*Mpint))
3697 return 0 <= v && v < max
3703 if Smallintconst(n.Left) {
3704 v = Mpgetfix(n.Left.Val().U.(*Mpint))
3705 } else if Smallintconst(n.Right) {
3706 v = Mpgetfix(n.Right.Val().U.(*Mpint))
3709 if 0 <= v && v < max {
3714 if !sign && Smallintconst(n.Right) {
3715 v := Mpgetfix(n.Right.Val().U.(*Mpint))
3716 if 0 <= v && v <= max {
3722 if !sign && Smallintconst(n.Right) {
3723 v := Mpgetfix(n.Right.Val().U.(*Mpint))
3724 for bits > 0 && v >= 2 {
3731 if !sign && Smallintconst(n.Right) {
3732 v := Mpgetfix(n.Right.Val().U.(*Mpint))
3733 if v > int64(bits) {
3740 if !sign && bits <= 62 && 1<<uint(bits) <= max {
3747 func usefield(n *Node) {
3748 if obj.Fieldtrack_enabled == 0 {
3754 Fatalf("usefield %v", Oconv(int(n.Op), 0))
3764 field := dotField[typeSym{t.Orig, n.Right.Sym}]
3766 Fatalf("usefield %v %v without paramfld", n.Left.Type, n.Right.Sym)
3768 if field.Note == nil || !strings.Contains(*field.Note, "go:\"track\"") {
3773 if field.Lastfn == Curfn {
3776 field.Lastfn = Curfn
3777 field.Outer = n.Left.Type
3778 if Isptr[field.Outer.Etype] {
3779 field.Outer = field.Outer.Type
3781 if field.Outer.Sym == nil {
3782 Yyerror("tracked field must be in named struct type")
3784 if !exportname(field.Sym.Name) {
3785 Yyerror("tracked field must be exported (upper case)")
3788 Curfn.Func.Fieldtrack = append(Curfn.Func.Fieldtrack, field)
3791 func candiscardlist(l *NodeList) bool {
3792 for ; l != nil; l = l.Next {
3793 if !candiscard(l.N) {
3800 func candiscard(n *Node) bool {
3809 // Discardable as long as the subpieces are.
3864 // Discardable as long as we know it's not division by zero.
3866 if Isconst(n.Right, CTINT) && mpcmpfixc(n.Right.Val().U.(*Mpint), 0) != 0 {
3869 if Isconst(n.Right, CTFLT) && mpcmpfltc(n.Right.Val().U.(*Mpflt), 0) != 0 {
3874 // Discardable as long as we know it won't fail because of a bad size.
3875 case OMAKECHAN, OMAKEMAP:
3876 if Isconst(n.Left, CTINT) && mpcmpfixc(n.Left.Val().U.(*Mpint), 0) == 0 {
3881 // Difficult to tell what sizes are okay.
3886 if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
3896 // func(a1, a2, a3) {
3897 // print(a1, a2, a3)
3899 // and same for println.
3901 var walkprintfunc_prgen int
3903 func walkprintfunc(np **Node, init **NodeList) {
3907 walkstmtlist(n.Ninit)
3908 *init = concat(*init, n.Ninit)
3912 t := Nod(OTFUNC, nil, nil)
3914 var printargs *NodeList
3917 for l := n.List; l != nil; l = l.Next {
3918 buf = fmt.Sprintf("a%d", num)
3920 a = Nod(ODCLFIELD, newname(Lookup(buf)), typenod(l.N.Type))
3921 t.List = list(t.List, a)
3922 printargs = list(printargs, a.Left)
3925 fn := Nod(ODCLFUNC, nil, nil)
3926 walkprintfunc_prgen++
3927 buf = fmt.Sprintf("print·%d", walkprintfunc_prgen)
3928 fn.Func.Nname = newname(Lookup(buf))
3929 fn.Func.Nname.Name.Defn = fn
3930 fn.Func.Nname.Name.Param.Ntype = t
3931 declare(fn.Func.Nname, PFUNC)
3937 a = Nod(n.Op, nil, nil)
3946 typecheck(&fn, Etop)
3947 typechecklist(fn.Nbody, Etop)
3948 xtop = list(xtop, fn)
3951 a = Nod(OCALL, nil, nil)
3952 a.Left = fn.Func.Nname