]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/walk/expr.go
9047211879d5323e8ef1799a7f989c42acbccf71
[gostls13.git] / src / cmd / compile / internal / walk / expr.go
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.
4
5 package walk
6
7 import (
8         "fmt"
9         "go/constant"
10         "internal/buildcfg"
11         "strings"
12
13         "cmd/compile/internal/base"
14         "cmd/compile/internal/ir"
15         "cmd/compile/internal/reflectdata"
16         "cmd/compile/internal/staticdata"
17         "cmd/compile/internal/typecheck"
18         "cmd/compile/internal/types"
19         "cmd/internal/obj"
20         "cmd/internal/objabi"
21 )
22
23 // The result of walkExpr MUST be assigned back to n, e.g.
24 //
25 //      n.Left = walkExpr(n.Left, init)
26 func walkExpr(n ir.Node, init *ir.Nodes) ir.Node {
27         if n == nil {
28                 return n
29         }
30
31         if n, ok := n.(ir.InitNode); ok && init == n.PtrInit() {
32                 // not okay to use n->ninit when walking n,
33                 // because we might replace n with some other node
34                 // and would lose the init list.
35                 base.Fatalf("walkExpr init == &n->ninit")
36         }
37
38         if len(n.Init()) != 0 {
39                 walkStmtList(n.Init())
40                 init.Append(ir.TakeInit(n)...)
41         }
42
43         lno := ir.SetPos(n)
44
45         if base.Flag.LowerW > 1 {
46                 ir.Dump("before walk expr", n)
47         }
48
49         if n.Typecheck() != 1 {
50                 base.Fatalf("missed typecheck: %+v", n)
51         }
52
53         if n.Type().IsUntyped() {
54                 base.Fatalf("expression has untyped type: %+v", n)
55         }
56
57         n = walkExpr1(n, init)
58
59         // Eagerly compute sizes of all expressions for the back end.
60         if typ := n.Type(); typ != nil && typ.Kind() != types.TBLANK && !typ.IsFuncArgStruct() {
61                 types.CheckSize(typ)
62         }
63         if n, ok := n.(*ir.Name); ok && n.Heapaddr != nil {
64                 types.CheckSize(n.Heapaddr.Type())
65         }
66         if ir.IsConst(n, constant.String) {
67                 // Emit string symbol now to avoid emitting
68                 // any concurrently during the backend.
69                 _ = staticdata.StringSym(n.Pos(), constant.StringVal(n.Val()))
70         }
71
72         if base.Flag.LowerW != 0 && n != nil {
73                 ir.Dump("after walk expr", n)
74         }
75
76         base.Pos = lno
77         return n
78 }
79
80 func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
81         switch n.Op() {
82         default:
83                 ir.Dump("walk", n)
84                 base.Fatalf("walkExpr: switch 1 unknown op %+v", n.Op())
85                 panic("unreachable")
86
87         case ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP:
88                 return n
89
90         case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL, ir.OLINKSYMOFFSET:
91                 // TODO(mdempsky): Just return n; see discussion on CL 38655.
92                 // Perhaps refactor to use Node.mayBeShared for these instead.
93                 // If these return early, make sure to still call
94                 // StringSym for constant strings.
95                 return n
96
97         case ir.OMETHEXPR:
98                 // TODO(mdempsky): Do this right after type checking.
99                 n := n.(*ir.SelectorExpr)
100                 return n.FuncName()
101
102         case ir.OMIN, ir.OMAX:
103                 n := n.(*ir.CallExpr)
104                 return walkMinMax(n, init)
105
106         case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.OSPTR, ir.OITAB, ir.OIDATA:
107                 n := n.(*ir.UnaryExpr)
108                 n.X = walkExpr(n.X, init)
109                 return n
110
111         case ir.ODOTMETH, ir.ODOTINTER:
112                 n := n.(*ir.SelectorExpr)
113                 n.X = walkExpr(n.X, init)
114                 return n
115
116         case ir.OADDR:
117                 n := n.(*ir.AddrExpr)
118                 n.X = walkExpr(n.X, init)
119                 return n
120
121         case ir.ODEREF:
122                 n := n.(*ir.StarExpr)
123                 n.X = walkExpr(n.X, init)
124                 return n
125
126         case ir.OMAKEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH,
127                 ir.OUNSAFEADD:
128                 n := n.(*ir.BinaryExpr)
129                 n.X = walkExpr(n.X, init)
130                 n.Y = walkExpr(n.Y, init)
131                 return n
132
133         case ir.OUNSAFESLICE:
134                 n := n.(*ir.BinaryExpr)
135                 return walkUnsafeSlice(n, init)
136
137         case ir.OUNSAFESTRING:
138                 n := n.(*ir.BinaryExpr)
139                 return walkUnsafeString(n, init)
140
141         case ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
142                 n := n.(*ir.UnaryExpr)
143                 return walkUnsafeData(n, init)
144
145         case ir.ODOT, ir.ODOTPTR:
146                 n := n.(*ir.SelectorExpr)
147                 return walkDot(n, init)
148
149         case ir.ODOTTYPE, ir.ODOTTYPE2:
150                 n := n.(*ir.TypeAssertExpr)
151                 return walkDotType(n, init)
152
153         case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
154                 n := n.(*ir.DynamicTypeAssertExpr)
155                 return walkDynamicDotType(n, init)
156
157         case ir.OLEN, ir.OCAP:
158                 n := n.(*ir.UnaryExpr)
159                 return walkLenCap(n, init)
160
161         case ir.OCOMPLEX:
162                 n := n.(*ir.BinaryExpr)
163                 n.X = walkExpr(n.X, init)
164                 n.Y = walkExpr(n.Y, init)
165                 return n
166
167         case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
168                 n := n.(*ir.BinaryExpr)
169                 return walkCompare(n, init)
170
171         case ir.OANDAND, ir.OOROR:
172                 n := n.(*ir.LogicalExpr)
173                 return walkLogical(n, init)
174
175         case ir.OPRINT, ir.OPRINTN:
176                 return walkPrint(n.(*ir.CallExpr), init)
177
178         case ir.OPANIC:
179                 n := n.(*ir.UnaryExpr)
180                 return mkcall("gopanic", nil, init, n.X)
181
182         case ir.ORECOVERFP:
183                 return walkRecoverFP(n.(*ir.CallExpr), init)
184
185         case ir.OCFUNC:
186                 return n
187
188         case ir.OCALLINTER, ir.OCALLFUNC:
189                 n := n.(*ir.CallExpr)
190                 return walkCall(n, init)
191
192         case ir.OAS, ir.OASOP:
193                 return walkAssign(init, n)
194
195         case ir.OAS2:
196                 n := n.(*ir.AssignListStmt)
197                 return walkAssignList(init, n)
198
199         // a,b,... = fn()
200         case ir.OAS2FUNC:
201                 n := n.(*ir.AssignListStmt)
202                 return walkAssignFunc(init, n)
203
204         // x, y = <-c
205         // order.stmt made sure x is addressable or blank.
206         case ir.OAS2RECV:
207                 n := n.(*ir.AssignListStmt)
208                 return walkAssignRecv(init, n)
209
210         // a,b = m[i]
211         case ir.OAS2MAPR:
212                 n := n.(*ir.AssignListStmt)
213                 return walkAssignMapRead(init, n)
214
215         case ir.ODELETE:
216                 n := n.(*ir.CallExpr)
217                 return walkDelete(init, n)
218
219         case ir.OAS2DOTTYPE:
220                 n := n.(*ir.AssignListStmt)
221                 return walkAssignDotType(n, init)
222
223         case ir.OCONVIFACE:
224                 n := n.(*ir.ConvExpr)
225                 return walkConvInterface(n, init)
226
227         case ir.OCONV, ir.OCONVNOP:
228                 n := n.(*ir.ConvExpr)
229                 return walkConv(n, init)
230
231         case ir.OSLICE2ARR:
232                 n := n.(*ir.ConvExpr)
233                 return walkSliceToArray(n, init)
234
235         case ir.OSLICE2ARRPTR:
236                 n := n.(*ir.ConvExpr)
237                 n.X = walkExpr(n.X, init)
238                 return n
239
240         case ir.ODIV, ir.OMOD:
241                 n := n.(*ir.BinaryExpr)
242                 return walkDivMod(n, init)
243
244         case ir.OINDEX:
245                 n := n.(*ir.IndexExpr)
246                 return walkIndex(n, init)
247
248         case ir.OINDEXMAP:
249                 n := n.(*ir.IndexExpr)
250                 return walkIndexMap(n, init)
251
252         case ir.ORECV:
253                 base.Fatalf("walkExpr ORECV") // should see inside OAS only
254                 panic("unreachable")
255
256         case ir.OSLICEHEADER:
257                 n := n.(*ir.SliceHeaderExpr)
258                 return walkSliceHeader(n, init)
259
260         case ir.OSTRINGHEADER:
261                 n := n.(*ir.StringHeaderExpr)
262                 return walkStringHeader(n, init)
263
264         case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
265                 n := n.(*ir.SliceExpr)
266                 return walkSlice(n, init)
267
268         case ir.ONEW:
269                 n := n.(*ir.UnaryExpr)
270                 return walkNew(n, init)
271
272         case ir.OADDSTR:
273                 return walkAddString(n.(*ir.AddStringExpr), init)
274
275         case ir.OAPPEND:
276                 // order should make sure we only see OAS(node, OAPPEND), which we handle above.
277                 base.Fatalf("append outside assignment")
278                 panic("unreachable")
279
280         case ir.OCOPY:
281                 return walkCopy(n.(*ir.BinaryExpr), init, base.Flag.Cfg.Instrumenting && !base.Flag.CompilingRuntime)
282
283         case ir.OCLEAR:
284                 n := n.(*ir.UnaryExpr)
285                 return walkClear(n)
286
287         case ir.OCLOSE:
288                 n := n.(*ir.UnaryExpr)
289                 return walkClose(n, init)
290
291         case ir.OMAKECHAN:
292                 n := n.(*ir.MakeExpr)
293                 return walkMakeChan(n, init)
294
295         case ir.OMAKEMAP:
296                 n := n.(*ir.MakeExpr)
297                 return walkMakeMap(n, init)
298
299         case ir.OMAKESLICE:
300                 n := n.(*ir.MakeExpr)
301                 return walkMakeSlice(n, init)
302
303         case ir.OMAKESLICECOPY:
304                 n := n.(*ir.MakeExpr)
305                 return walkMakeSliceCopy(n, init)
306
307         case ir.ORUNESTR:
308                 n := n.(*ir.ConvExpr)
309                 return walkRuneToString(n, init)
310
311         case ir.OBYTES2STR, ir.ORUNES2STR:
312                 n := n.(*ir.ConvExpr)
313                 return walkBytesRunesToString(n, init)
314
315         case ir.OBYTES2STRTMP:
316                 n := n.(*ir.ConvExpr)
317                 return walkBytesToStringTemp(n, init)
318
319         case ir.OSTR2BYTES:
320                 n := n.(*ir.ConvExpr)
321                 return walkStringToBytes(n, init)
322
323         case ir.OSTR2BYTESTMP:
324                 n := n.(*ir.ConvExpr)
325                 return walkStringToBytesTemp(n, init)
326
327         case ir.OSTR2RUNES:
328                 n := n.(*ir.ConvExpr)
329                 return walkStringToRunes(n, init)
330
331         case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT:
332                 return walkCompLit(n, init)
333
334         case ir.OSEND:
335                 n := n.(*ir.SendStmt)
336                 return walkSend(n, init)
337
338         case ir.OCLOSURE:
339                 return walkClosure(n.(*ir.ClosureExpr), init)
340
341         case ir.OMETHVALUE:
342                 return walkMethodValue(n.(*ir.SelectorExpr), init)
343         }
344
345         // No return! Each case must return (or panic),
346         // to avoid confusion about what gets returned
347         // in the presence of type assertions.
348 }
349
350 // walk the whole tree of the body of an
351 // expression or simple statement.
352 // the types expressions are calculated.
353 // compile-time constants are evaluated.
354 // complex side effects like statements are appended to init.
355 func walkExprList(s []ir.Node, init *ir.Nodes) {
356         for i := range s {
357                 s[i] = walkExpr(s[i], init)
358         }
359 }
360
361 func walkExprListCheap(s []ir.Node, init *ir.Nodes) {
362         for i, n := range s {
363                 s[i] = cheapExpr(n, init)
364                 s[i] = walkExpr(s[i], init)
365         }
366 }
367
368 func walkExprListSafe(s []ir.Node, init *ir.Nodes) {
369         for i, n := range s {
370                 s[i] = safeExpr(n, init)
371                 s[i] = walkExpr(s[i], init)
372         }
373 }
374
375 // return side-effect free and cheap n, appending side effects to init.
376 // result may not be assignable.
377 func cheapExpr(n ir.Node, init *ir.Nodes) ir.Node {
378         switch n.Op() {
379         case ir.ONAME, ir.OLITERAL, ir.ONIL:
380                 return n
381         }
382
383         return copyExpr(n, n.Type(), init)
384 }
385
386 // return side effect-free n, appending side effects to init.
387 // result is assignable if n is.
388 func safeExpr(n ir.Node, init *ir.Nodes) ir.Node {
389         if n == nil {
390                 return nil
391         }
392
393         if len(n.Init()) != 0 {
394                 walkStmtList(n.Init())
395                 init.Append(ir.TakeInit(n)...)
396         }
397
398         switch n.Op() {
399         case ir.ONAME, ir.OLITERAL, ir.ONIL, ir.OLINKSYMOFFSET:
400                 return n
401
402         case ir.OLEN, ir.OCAP:
403                 n := n.(*ir.UnaryExpr)
404                 l := safeExpr(n.X, init)
405                 if l == n.X {
406                         return n
407                 }
408                 a := ir.Copy(n).(*ir.UnaryExpr)
409                 a.X = l
410                 return walkExpr(typecheck.Expr(a), init)
411
412         case ir.ODOT, ir.ODOTPTR:
413                 n := n.(*ir.SelectorExpr)
414                 l := safeExpr(n.X, init)
415                 if l == n.X {
416                         return n
417                 }
418                 a := ir.Copy(n).(*ir.SelectorExpr)
419                 a.X = l
420                 return walkExpr(typecheck.Expr(a), init)
421
422         case ir.ODEREF:
423                 n := n.(*ir.StarExpr)
424                 l := safeExpr(n.X, init)
425                 if l == n.X {
426                         return n
427                 }
428                 a := ir.Copy(n).(*ir.StarExpr)
429                 a.X = l
430                 return walkExpr(typecheck.Expr(a), init)
431
432         case ir.OINDEX, ir.OINDEXMAP:
433                 n := n.(*ir.IndexExpr)
434                 l := safeExpr(n.X, init)
435                 r := safeExpr(n.Index, init)
436                 if l == n.X && r == n.Index {
437                         return n
438                 }
439                 a := ir.Copy(n).(*ir.IndexExpr)
440                 a.X = l
441                 a.Index = r
442                 return walkExpr(typecheck.Expr(a), init)
443
444         case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT:
445                 n := n.(*ir.CompLitExpr)
446                 if isStaticCompositeLiteral(n) {
447                         return n
448                 }
449         }
450
451         // make a copy; must not be used as an lvalue
452         if ir.IsAddressable(n) {
453                 base.Fatalf("missing lvalue case in safeExpr: %v", n)
454         }
455         return cheapExpr(n, init)
456 }
457
458 func copyExpr(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node {
459         l := typecheck.TempAt(base.Pos, ir.CurFunc, t)
460         appendWalkStmt(init, ir.NewAssignStmt(base.Pos, l, n))
461         return l
462 }
463
464 func walkAddString(n *ir.AddStringExpr, init *ir.Nodes) ir.Node {
465         c := len(n.List)
466
467         if c < 2 {
468                 base.Fatalf("walkAddString count %d too small", c)
469         }
470
471         buf := typecheck.NodNil()
472         if n.Esc() == ir.EscNone {
473                 sz := int64(0)
474                 for _, n1 := range n.List {
475                         if n1.Op() == ir.OLITERAL {
476                                 sz += int64(len(ir.StringVal(n1)))
477                         }
478                 }
479
480                 // Don't allocate the buffer if the result won't fit.
481                 if sz < tmpstringbufsize {
482                         // Create temporary buffer for result string on stack.
483                         buf = stackBufAddr(tmpstringbufsize, types.Types[types.TUINT8])
484                 }
485         }
486
487         // build list of string arguments
488         args := []ir.Node{buf}
489         for _, n2 := range n.List {
490                 args = append(args, typecheck.Conv(n2, types.Types[types.TSTRING]))
491         }
492
493         var fn string
494         if c <= 5 {
495                 // small numbers of strings use direct runtime helpers.
496                 // note: order.expr knows this cutoff too.
497                 fn = fmt.Sprintf("concatstring%d", c)
498         } else {
499                 // large numbers of strings are passed to the runtime as a slice.
500                 fn = "concatstrings"
501
502                 t := types.NewSlice(types.Types[types.TSTRING])
503                 // args[1:] to skip buf arg
504                 slice := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, t, args[1:])
505                 slice.Prealloc = n.Prealloc
506                 args = []ir.Node{buf, slice}
507                 slice.SetEsc(ir.EscNone)
508         }
509
510         cat := typecheck.LookupRuntime(fn)
511         r := ir.NewCallExpr(base.Pos, ir.OCALL, cat, nil)
512         r.Args = args
513         r1 := typecheck.Expr(r)
514         r1 = walkExpr(r1, init)
515         r1.SetType(n.Type())
516
517         return r1
518 }
519
520 type hookInfo struct {
521         paramType   types.Kind
522         argsNum     int
523         runtimeFunc string
524 }
525
526 var hooks = map[string]hookInfo{
527         "strings.EqualFold": {paramType: types.TSTRING, argsNum: 2, runtimeFunc: "libfuzzerHookEqualFold"},
528 }
529
530 // walkCall walks an OCALLFUNC or OCALLINTER node.
531 func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
532         if n.Op() == ir.OCALLMETH {
533                 base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
534         }
535         if n.Op() == ir.OCALLINTER || n.X.Op() == ir.OMETHEXPR {
536                 // We expect both interface call reflect.Type.Method and concrete
537                 // call reflect.(*rtype).Method.
538                 usemethod(n)
539         }
540         if n.Op() == ir.OCALLINTER {
541                 reflectdata.MarkUsedIfaceMethod(n)
542         }
543
544         if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.OCLOSURE {
545                 directClosureCall(n)
546         }
547
548         if ir.IsFuncPCIntrinsic(n) {
549                 // For internal/abi.FuncPCABIxxx(fn), if fn is a defined function, rewrite
550                 // it to the address of the function of the ABI fn is defined.
551                 name := n.X.(*ir.Name).Sym().Name
552                 arg := n.Args[0]
553                 var wantABI obj.ABI
554                 switch name {
555                 case "FuncPCABI0":
556                         wantABI = obj.ABI0
557                 case "FuncPCABIInternal":
558                         wantABI = obj.ABIInternal
559                 }
560                 if isIfaceOfFunc(arg) {
561                         fn := arg.(*ir.ConvExpr).X.(*ir.Name)
562                         abi := fn.Func.ABI
563                         if abi != wantABI {
564                                 base.ErrorfAt(n.Pos(), 0, "internal/abi.%s expects an %v function, %s is defined as %v", name, wantABI, fn.Sym().Name, abi)
565                         }
566                         var e ir.Node = ir.NewLinksymExpr(n.Pos(), fn.Sym().LinksymABI(abi), types.Types[types.TUINTPTR])
567                         e = ir.NewAddrExpr(n.Pos(), e)
568                         e.SetType(types.Types[types.TUINTPTR].PtrTo())
569                         return typecheck.Expr(ir.NewConvExpr(n.Pos(), ir.OCONVNOP, n.Type(), e))
570                 }
571                 // fn is not a defined function. It must be ABIInternal.
572                 // Read the address from func value, i.e. *(*uintptr)(idata(fn)).
573                 if wantABI != obj.ABIInternal {
574                         base.ErrorfAt(n.Pos(), 0, "internal/abi.%s does not accept func expression, which is ABIInternal", name)
575                 }
576                 arg = walkExpr(arg, init)
577                 var e ir.Node = ir.NewUnaryExpr(n.Pos(), ir.OIDATA, arg)
578                 e.SetType(n.Type().PtrTo())
579                 e.SetTypecheck(1)
580                 e = ir.NewStarExpr(n.Pos(), e)
581                 e.SetType(n.Type())
582                 e.SetTypecheck(1)
583                 return e
584         }
585
586         walkCall1(n, init)
587         return n
588 }
589
590 func walkCall1(n *ir.CallExpr, init *ir.Nodes) {
591         if n.Walked() {
592                 return // already walked
593         }
594         n.SetWalked(true)
595
596         if n.Op() == ir.OCALLMETH {
597                 base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
598         }
599
600         args := n.Args
601         params := n.X.Type().Params()
602
603         n.X = walkExpr(n.X, init)
604         walkExprList(args, init)
605
606         for i, arg := range args {
607                 // Validate argument and parameter types match.
608                 param := params[i]
609                 if !types.Identical(arg.Type(), param.Type) {
610                         base.FatalfAt(n.Pos(), "assigning %L to parameter %v (type %v)", arg, param.Sym, param.Type)
611                 }
612
613                 // For any argument whose evaluation might require a function call,
614                 // store that argument into a temporary variable,
615                 // to prevent that calls from clobbering arguments already on the stack.
616                 if mayCall(arg) {
617                         // assignment of arg to Temp
618                         tmp := typecheck.TempAt(base.Pos, ir.CurFunc, param.Type)
619                         init.Append(convas(typecheck.Stmt(ir.NewAssignStmt(base.Pos, tmp, arg)).(*ir.AssignStmt), init))
620                         // replace arg with temp
621                         args[i] = tmp
622                 }
623         }
624
625         funSym := n.X.Sym()
626         if base.Debug.Libfuzzer != 0 && funSym != nil {
627                 if hook, found := hooks[funSym.Pkg.Path+"."+funSym.Name]; found {
628                         if len(args) != hook.argsNum {
629                                 panic(fmt.Sprintf("%s.%s expects %d arguments, but received %d", funSym.Pkg.Path, funSym.Name, hook.argsNum, len(args)))
630                         }
631                         var hookArgs []ir.Node
632                         for _, arg := range args {
633                                 hookArgs = append(hookArgs, tracecmpArg(arg, types.Types[hook.paramType], init))
634                         }
635                         hookArgs = append(hookArgs, fakePC(n))
636                         init.Append(mkcall(hook.runtimeFunc, nil, init, hookArgs...))
637                 }
638         }
639 }
640
641 // walkDivMod walks an ODIV or OMOD node.
642 func walkDivMod(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
643         n.X = walkExpr(n.X, init)
644         n.Y = walkExpr(n.Y, init)
645
646         // rewrite complex div into function call.
647         et := n.X.Type().Kind()
648
649         if types.IsComplex[et] && n.Op() == ir.ODIV {
650                 t := n.Type()
651                 call := mkcall("complex128div", types.Types[types.TCOMPLEX128], init, typecheck.Conv(n.X, types.Types[types.TCOMPLEX128]), typecheck.Conv(n.Y, types.Types[types.TCOMPLEX128]))
652                 return typecheck.Conv(call, t)
653         }
654
655         // Nothing to do for float divisions.
656         if types.IsFloat[et] {
657                 return n
658         }
659
660         // rewrite 64-bit div and mod on 32-bit architectures.
661         // TODO: Remove this code once we can introduce
662         // runtime calls late in SSA processing.
663         if types.RegSize < 8 && (et == types.TINT64 || et == types.TUINT64) {
664                 if n.Y.Op() == ir.OLITERAL {
665                         // Leave div/mod by constant powers of 2 or small 16-bit constants.
666                         // The SSA backend will handle those.
667                         switch et {
668                         case types.TINT64:
669                                 c := ir.Int64Val(n.Y)
670                                 if c < 0 {
671                                         c = -c
672                                 }
673                                 if c != 0 && c&(c-1) == 0 {
674                                         return n
675                                 }
676                         case types.TUINT64:
677                                 c := ir.Uint64Val(n.Y)
678                                 if c < 1<<16 {
679                                         return n
680                                 }
681                                 if c != 0 && c&(c-1) == 0 {
682                                         return n
683                                 }
684                         }
685                 }
686                 var fn string
687                 if et == types.TINT64 {
688                         fn = "int64"
689                 } else {
690                         fn = "uint64"
691                 }
692                 if n.Op() == ir.ODIV {
693                         fn += "div"
694                 } else {
695                         fn += "mod"
696                 }
697                 return mkcall(fn, n.Type(), init, typecheck.Conv(n.X, types.Types[et]), typecheck.Conv(n.Y, types.Types[et]))
698         }
699         return n
700 }
701
702 // walkDot walks an ODOT or ODOTPTR node.
703 func walkDot(n *ir.SelectorExpr, init *ir.Nodes) ir.Node {
704         usefield(n)
705         n.X = walkExpr(n.X, init)
706         return n
707 }
708
709 // walkDotType walks an ODOTTYPE or ODOTTYPE2 node.
710 func walkDotType(n *ir.TypeAssertExpr, init *ir.Nodes) ir.Node {
711         n.X = walkExpr(n.X, init)
712         // Set up interface type addresses for back end.
713         if !n.Type().IsInterface() && !n.X.Type().IsEmptyInterface() {
714                 n.ITab = reflectdata.ITabAddrAt(base.Pos, n.Type(), n.X.Type())
715         }
716         return n
717 }
718
719 // walkDynamicDotType walks an ODYNAMICDOTTYPE or ODYNAMICDOTTYPE2 node.
720 func walkDynamicDotType(n *ir.DynamicTypeAssertExpr, init *ir.Nodes) ir.Node {
721         n.X = walkExpr(n.X, init)
722         n.RType = walkExpr(n.RType, init)
723         n.ITab = walkExpr(n.ITab, init)
724         return n
725 }
726
727 // walkIndex walks an OINDEX node.
728 func walkIndex(n *ir.IndexExpr, init *ir.Nodes) ir.Node {
729         n.X = walkExpr(n.X, init)
730
731         // save the original node for bounds checking elision.
732         // If it was a ODIV/OMOD walk might rewrite it.
733         r := n.Index
734
735         n.Index = walkExpr(n.Index, init)
736
737         // if range of type cannot exceed static array bound,
738         // disable bounds check.
739         if n.Bounded() {
740                 return n
741         }
742         t := n.X.Type()
743         if t != nil && t.IsPtr() {
744                 t = t.Elem()
745         }
746         if t.IsArray() {
747                 n.SetBounded(bounded(r, t.NumElem()))
748                 if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Index, constant.Int) {
749                         base.Warn("index bounds check elided")
750                 }
751         } else if ir.IsConst(n.X, constant.String) {
752                 n.SetBounded(bounded(r, int64(len(ir.StringVal(n.X)))))
753                 if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Index, constant.Int) {
754                         base.Warn("index bounds check elided")
755                 }
756         }
757         return n
758 }
759
760 // mapKeyArg returns an expression for key that is suitable to be passed
761 // as the key argument for runtime map* functions.
762 // n is the map indexing or delete Node (to provide Pos).
763 func mapKeyArg(fast int, n, key ir.Node, assigned bool) ir.Node {
764         if fast == mapslow {
765                 // standard version takes key by reference.
766                 // orderState.expr made sure key is addressable.
767                 return typecheck.NodAddr(key)
768         }
769         if assigned {
770                 // mapassign does distinguish pointer vs. integer key.
771                 return key
772         }
773         // mapaccess and mapdelete don't distinguish pointer vs. integer key.
774         switch fast {
775         case mapfast32ptr:
776                 return ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.Types[types.TUINT32], key)
777         case mapfast64ptr:
778                 return ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.Types[types.TUINT64], key)
779         default:
780                 // fast version takes key by value.
781                 return key
782         }
783 }
784
785 // walkIndexMap walks an OINDEXMAP node.
786 // It replaces m[k] with *map{access1,assign}(maptype, m, &k)
787 func walkIndexMap(n *ir.IndexExpr, init *ir.Nodes) ir.Node {
788         n.X = walkExpr(n.X, init)
789         n.Index = walkExpr(n.Index, init)
790         map_ := n.X
791         t := map_.Type()
792         fast := mapfast(t)
793         key := mapKeyArg(fast, n, n.Index, n.Assigned)
794         args := []ir.Node{reflectdata.IndexMapRType(base.Pos, n), map_, key}
795
796         var mapFn ir.Node
797         switch {
798         case n.Assigned:
799                 mapFn = mapfn(mapassign[fast], t, false)
800         case t.Elem().Size() > zeroValSize:
801                 args = append(args, reflectdata.ZeroAddr(t.Elem().Size()))
802                 mapFn = mapfn("mapaccess1_fat", t, true)
803         default:
804                 mapFn = mapfn(mapaccess1[fast], t, false)
805         }
806         call := mkcall1(mapFn, nil, init, args...)
807         call.SetType(types.NewPtr(t.Elem()))
808         call.MarkNonNil() // mapaccess1* and mapassign always return non-nil pointers.
809         star := ir.NewStarExpr(base.Pos, call)
810         star.SetType(t.Elem())
811         star.SetTypecheck(1)
812         return star
813 }
814
815 // walkLogical walks an OANDAND or OOROR node.
816 func walkLogical(n *ir.LogicalExpr, init *ir.Nodes) ir.Node {
817         n.X = walkExpr(n.X, init)
818
819         // cannot put side effects from n.Right on init,
820         // because they cannot run before n.Left is checked.
821         // save elsewhere and store on the eventual n.Right.
822         var ll ir.Nodes
823
824         n.Y = walkExpr(n.Y, &ll)
825         n.Y = ir.InitExpr(ll, n.Y)
826         return n
827 }
828
829 // walkSend walks an OSEND node.
830 func walkSend(n *ir.SendStmt, init *ir.Nodes) ir.Node {
831         n1 := n.Value
832         n1 = typecheck.AssignConv(n1, n.Chan.Type().Elem(), "chan send")
833         n1 = walkExpr(n1, init)
834         n1 = typecheck.NodAddr(n1)
835         return mkcall1(chanfn("chansend1", 2, n.Chan.Type()), nil, init, n.Chan, n1)
836 }
837
838 // walkSlice walks an OSLICE, OSLICEARR, OSLICESTR, OSLICE3, or OSLICE3ARR node.
839 func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node {
840         n.X = walkExpr(n.X, init)
841         n.Low = walkExpr(n.Low, init)
842         if n.Low != nil && ir.IsZero(n.Low) {
843                 // Reduce x[0:j] to x[:j] and x[0:j:k] to x[:j:k].
844                 n.Low = nil
845         }
846         n.High = walkExpr(n.High, init)
847         n.Max = walkExpr(n.Max, init)
848
849         if (n.Op() == ir.OSLICE || n.Op() == ir.OSLICESTR) && n.Low == nil && n.High == nil {
850                 // Reduce x[:] to x.
851                 if base.Debug.Slice > 0 {
852                         base.Warn("slice: omit slice operation")
853                 }
854                 return n.X
855         }
856         return n
857 }
858
859 // walkSliceHeader walks an OSLICEHEADER node.
860 func walkSliceHeader(n *ir.SliceHeaderExpr, init *ir.Nodes) ir.Node {
861         n.Ptr = walkExpr(n.Ptr, init)
862         n.Len = walkExpr(n.Len, init)
863         n.Cap = walkExpr(n.Cap, init)
864         return n
865 }
866
867 // walkStringHeader walks an OSTRINGHEADER node.
868 func walkStringHeader(n *ir.StringHeaderExpr, init *ir.Nodes) ir.Node {
869         n.Ptr = walkExpr(n.Ptr, init)
870         n.Len = walkExpr(n.Len, init)
871         return n
872 }
873
874 // return 1 if integer n must be in range [0, max), 0 otherwise.
875 func bounded(n ir.Node, max int64) bool {
876         if n.Type() == nil || !n.Type().IsInteger() {
877                 return false
878         }
879
880         sign := n.Type().IsSigned()
881         bits := int32(8 * n.Type().Size())
882
883         if ir.IsSmallIntConst(n) {
884                 v := ir.Int64Val(n)
885                 return 0 <= v && v < max
886         }
887
888         switch n.Op() {
889         case ir.OAND, ir.OANDNOT:
890                 n := n.(*ir.BinaryExpr)
891                 v := int64(-1)
892                 switch {
893                 case ir.IsSmallIntConst(n.X):
894                         v = ir.Int64Val(n.X)
895                 case ir.IsSmallIntConst(n.Y):
896                         v = ir.Int64Val(n.Y)
897                         if n.Op() == ir.OANDNOT {
898                                 v = ^v
899                                 if !sign {
900                                         v &= 1<<uint(bits) - 1
901                                 }
902                         }
903                 }
904                 if 0 <= v && v < max {
905                         return true
906                 }
907
908         case ir.OMOD:
909                 n := n.(*ir.BinaryExpr)
910                 if !sign && ir.IsSmallIntConst(n.Y) {
911                         v := ir.Int64Val(n.Y)
912                         if 0 <= v && v <= max {
913                                 return true
914                         }
915                 }
916
917         case ir.ODIV:
918                 n := n.(*ir.BinaryExpr)
919                 if !sign && ir.IsSmallIntConst(n.Y) {
920                         v := ir.Int64Val(n.Y)
921                         for bits > 0 && v >= 2 {
922                                 bits--
923                                 v >>= 1
924                         }
925                 }
926
927         case ir.ORSH:
928                 n := n.(*ir.BinaryExpr)
929                 if !sign && ir.IsSmallIntConst(n.Y) {
930                         v := ir.Int64Val(n.Y)
931                         if v > int64(bits) {
932                                 return true
933                         }
934                         bits -= int32(v)
935                 }
936         }
937
938         if !sign && bits <= 62 && 1<<uint(bits) <= max {
939                 return true
940         }
941
942         return false
943 }
944
945 // usemethod checks calls for uses of Method and MethodByName of reflect.Value,
946 // reflect.Type, reflect.(*rtype), and reflect.(*interfaceType).
947 func usemethod(n *ir.CallExpr) {
948         // Don't mark reflect.(*rtype).Method, etc. themselves in the reflect package.
949         // Those functions may be alive via the itab, which should not cause all methods
950         // alive. We only want to mark their callers.
951         if base.Ctxt.Pkgpath == "reflect" {
952                 // TODO: is there a better way than hardcoding the names?
953                 switch fn := ir.CurFunc.Nname.Sym().Name; {
954                 case fn == "(*rtype).Method", fn == "(*rtype).MethodByName":
955                         return
956                 case fn == "(*interfaceType).Method", fn == "(*interfaceType).MethodByName":
957                         return
958                 case fn == "Value.Method", fn == "Value.MethodByName":
959                         return
960                 // StructOf defines closures that look up methods. They only look up methods
961                 // reachable via interfaces. The DCE does not remove such methods. It is ok
962                 // to not flag closures in StructOf as ReflectMethods and let the DCE run
963                 // even if StructOf is reachable.
964                 //
965                 // (*rtype).MethodByName calls into StructOf so flagging StructOf as
966                 // ReflectMethod would disable the DCE even when the name of a method
967                 // to look up is a compile-time constant.
968                 case strings.HasPrefix(fn, "StructOf.func"):
969                         return
970                 }
971         }
972
973         dot, ok := n.X.(*ir.SelectorExpr)
974         if !ok {
975                 return
976         }
977
978         // looking for either direct method calls and interface method calls of:
979         //      reflect.Type.Method        - func(int) reflect.Method
980         //      reflect.Type.MethodByName  - func(string) (reflect.Method, bool)
981         //
982         //      reflect.Value.Method       - func(int) reflect.Value
983         //      reflect.Value.MethodByName - func(string) reflect.Value
984         methodName := dot.Sel.Name
985         t := dot.Selection.Type
986
987         // Check the number of arguments and return values.
988         if t.NumParams() != 1 || (t.NumResults() != 1 && t.NumResults() != 2) {
989                 return
990         }
991
992         // Check the type of the argument.
993         switch pKind := t.Param(0).Type.Kind(); {
994         case methodName == "Method" && pKind == types.TINT,
995                 methodName == "MethodByName" && pKind == types.TSTRING:
996
997         default:
998                 // not a call to Method or MethodByName of reflect.{Type,Value}.
999                 return
1000         }
1001
1002         // Check that first result type is "reflect.Method" or "reflect.Value".
1003         // Note that we have to check sym name and sym package separately, as
1004         // we can't check for exact string "reflect.Method" reliably
1005         // (e.g., see #19028 and #38515).
1006         switch s := t.Result(0).Type.Sym(); {
1007         case s != nil && types.ReflectSymName(s) == "Method",
1008                 s != nil && types.ReflectSymName(s) == "Value":
1009
1010         default:
1011                 // not a call to Method or MethodByName of reflect.{Type,Value}.
1012                 return
1013         }
1014
1015         var targetName ir.Node
1016         switch dot.Op() {
1017         case ir.ODOTINTER:
1018                 if methodName == "MethodByName" {
1019                         targetName = n.Args[0]
1020                 }
1021         case ir.OMETHEXPR:
1022                 if methodName == "MethodByName" {
1023                         targetName = n.Args[1]
1024                 }
1025         default:
1026                 base.FatalfAt(dot.Pos(), "usemethod: unexpected dot.Op() %s", dot.Op())
1027         }
1028
1029         if ir.IsConst(targetName, constant.String) {
1030                 name := constant.StringVal(targetName.Val())
1031
1032                 r := obj.Addrel(ir.CurFunc.LSym)
1033                 r.Type = objabi.R_USENAMEDMETHOD
1034                 r.Sym = staticdata.StringSymNoCommon(name)
1035         } else {
1036                 ir.CurFunc.LSym.Set(obj.AttrReflectMethod, true)
1037         }
1038 }
1039
1040 func usefield(n *ir.SelectorExpr) {
1041         if !buildcfg.Experiment.FieldTrack {
1042                 return
1043         }
1044
1045         switch n.Op() {
1046         default:
1047                 base.Fatalf("usefield %v", n.Op())
1048
1049         case ir.ODOT, ir.ODOTPTR:
1050                 break
1051         }
1052
1053         field := n.Selection
1054         if field == nil {
1055                 base.Fatalf("usefield %v %v without paramfld", n.X.Type(), n.Sel)
1056         }
1057         if field.Sym != n.Sel {
1058                 base.Fatalf("field inconsistency: %v != %v", field.Sym, n.Sel)
1059         }
1060         if !strings.Contains(field.Note, "go:\"track\"") {
1061                 return
1062         }
1063
1064         outer := n.X.Type()
1065         if outer.IsPtr() {
1066                 outer = outer.Elem()
1067         }
1068         if outer.Sym() == nil {
1069                 base.Errorf("tracked field must be in named struct type")
1070         }
1071
1072         sym := reflectdata.TrackSym(outer, field)
1073         if ir.CurFunc.FieldTrack == nil {
1074                 ir.CurFunc.FieldTrack = make(map[*obj.LSym]struct{})
1075         }
1076         ir.CurFunc.FieldTrack[sym] = struct{}{}
1077 }