]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/gc/ssa.go
[dev.ssa] Merge remote-tracking branch 'origin/master' into ssamerge
[gostls13.git] / src / cmd / compile / internal / gc / ssa.go
1 // Copyright 2015 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 gc
6
7 import (
8         "bytes"
9         "fmt"
10         "html"
11         "math"
12         "os"
13         "strings"
14
15         "cmd/compile/internal/ssa"
16         "cmd/internal/obj"
17         "cmd/internal/obj/x86"
18 )
19
20 // Smallest possible faulting page at address zero.
21 const minZeroPage = 4096
22
23 var ssaConfig *ssa.Config
24 var ssaExp ssaExport
25
26 func initssa() *ssa.Config {
27         ssaExp.unimplemented = false
28         ssaExp.mustImplement = true
29         if ssaConfig == nil {
30                 ssaConfig = ssa.NewConfig(Thearch.Thestring, &ssaExp, Ctxt, Debug['N'] == 0)
31         }
32         return ssaConfig
33 }
34
35 func shouldssa(fn *Node) bool {
36         if Thearch.Thestring != "amd64" {
37                 return false
38         }
39
40         // Environment variable control of SSA CG
41         // 1. IF GOSSAFUNC == current function name THEN
42         //       compile this function with SSA and log output to ssa.html
43
44         // 2. IF GOSSAHASH == "" THEN
45         //       compile this function (and everything else) with SSA
46
47         // 3. IF GOSSAHASH == "n" or "N"
48         //       IF GOSSAPKG == current package name THEN
49         //          compile this function (and everything in this package) with SSA
50         //       ELSE
51         //          use the old back end for this function.
52         //       This is for compatibility with existing test harness and should go away.
53
54         // 4. IF GOSSAHASH is a suffix of the binary-rendered SHA1 hash of the function name THEN
55         //          compile this function with SSA
56         //       ELSE
57         //          compile this function with the old back end.
58
59         // Plan is for 3 to be removed when the tests are revised.
60         // SSA is now default, and is disabled by setting
61         // GOSSAHASH to n or N, or selectively with strings of
62         // 0 and 1.
63
64         name := fn.Func.Nname.Sym.Name
65
66         funcname := os.Getenv("GOSSAFUNC")
67         if funcname != "" {
68                 // If GOSSAFUNC is set, compile only that function.
69                 return name == funcname
70         }
71
72         pkg := os.Getenv("GOSSAPKG")
73         if pkg != "" {
74                 // If GOSSAPKG is set, compile only that package.
75                 return localpkg.Name == pkg
76         }
77
78         return initssa().DebugHashMatch("GOSSAHASH", name)
79 }
80
81 // buildssa builds an SSA function.
82 func buildssa(fn *Node) *ssa.Func {
83         name := fn.Func.Nname.Sym.Name
84         printssa := strings.HasSuffix(name, "_ssa") || strings.Contains(name, "_ssa.") || name == os.Getenv("GOSSAFUNC")
85         if printssa {
86                 fmt.Println("generating SSA for", name)
87                 dumpslice("buildssa-enter", fn.Func.Enter.Slice())
88                 dumplist("buildssa-body", fn.Nbody)
89                 dumpslice("buildssa-exit", fn.Func.Exit.Slice())
90         }
91
92         var s state
93         s.pushLine(fn.Lineno)
94         defer s.popLine()
95
96         // TODO(khr): build config just once at the start of the compiler binary
97
98         ssaExp.log = printssa
99
100         s.config = initssa()
101         s.f = s.config.NewFunc()
102         s.f.Name = name
103         s.exitCode = fn.Func.Exit
104         s.panics = map[funcLine]*ssa.Block{}
105
106         if name == os.Getenv("GOSSAFUNC") {
107                 // TODO: tempfile? it is handy to have the location
108                 // of this file be stable, so you can just reload in the browser.
109                 s.config.HTML = ssa.NewHTMLWriter("ssa.html", s.config, name)
110                 // TODO: generate and print a mapping from nodes to values and blocks
111         }
112         defer func() {
113                 if !printssa {
114                         s.config.HTML.Close()
115                 }
116         }()
117
118         // Allocate starting block
119         s.f.Entry = s.f.NewBlock(ssa.BlockPlain)
120
121         // Allocate starting values
122         s.labels = map[string]*ssaLabel{}
123         s.labeledNodes = map[*Node]*ssaLabel{}
124         s.startmem = s.entryNewValue0(ssa.OpInitMem, ssa.TypeMem)
125         s.sp = s.entryNewValue0(ssa.OpSP, Types[TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead
126         s.sb = s.entryNewValue0(ssa.OpSB, Types[TUINTPTR])
127
128         s.startBlock(s.f.Entry)
129         s.vars[&memVar] = s.startmem
130
131         s.varsyms = map[*Node]interface{}{}
132
133         // Generate addresses of local declarations
134         s.decladdrs = map[*Node]*ssa.Value{}
135         for _, n := range fn.Func.Dcl {
136                 switch n.Class {
137                 case PPARAM:
138                         aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
139                         s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp)
140                 case PAUTO | PHEAP:
141                         // TODO this looks wrong for PAUTO|PHEAP, no vardef, but also no definition
142                         aux := s.lookupSymbol(n, &ssa.AutoSymbol{Typ: n.Type, Node: n})
143                         s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp)
144                 case PPARAM | PHEAP, PPARAMOUT | PHEAP:
145                 // This ends up wrong, have to do it at the PARAM node instead.
146                 case PAUTO, PPARAMOUT:
147                         // processed at each use, to prevent Addr coming
148                         // before the decl.
149                 case PFUNC:
150                         // local function - already handled by frontend
151                 default:
152                         str := ""
153                         if n.Class&PHEAP != 0 {
154                                 str = ",heap"
155                         }
156                         s.Unimplementedf("local variable with class %s%s unimplemented", classnames[n.Class&^PHEAP], str)
157                 }
158         }
159
160         // Convert the AST-based IR to the SSA-based IR
161         s.stmts(fn.Func.Enter)
162         s.stmtList(fn.Nbody)
163
164         // fallthrough to exit
165         if s.curBlock != nil {
166                 s.stmts(s.exitCode)
167                 m := s.mem()
168                 b := s.endBlock()
169                 b.Kind = ssa.BlockRet
170                 b.Control = m
171         }
172
173         // Check that we used all labels
174         for name, lab := range s.labels {
175                 if !lab.used() && !lab.reported {
176                         yyerrorl(int(lab.defNode.Lineno), "label %v defined and not used", name)
177                         lab.reported = true
178                 }
179                 if lab.used() && !lab.defined() && !lab.reported {
180                         yyerrorl(int(lab.useNode.Lineno), "label %v not defined", name)
181                         lab.reported = true
182                 }
183         }
184
185         // Check any forward gotos. Non-forward gotos have already been checked.
186         for _, n := range s.fwdGotos {
187                 lab := s.labels[n.Left.Sym.Name]
188                 // If the label is undefined, we have already have printed an error.
189                 if lab.defined() {
190                         s.checkgoto(n, lab.defNode)
191                 }
192         }
193
194         if nerrors > 0 {
195                 s.f.Free()
196                 return nil
197         }
198
199         // Link up variable uses to variable definitions
200         s.linkForwardReferences()
201
202         // Don't carry reference this around longer than necessary
203         s.exitCode = Nodes{}
204
205         // Main call to ssa package to compile function
206         ssa.Compile(s.f)
207
208         return s.f
209 }
210
211 type state struct {
212         // configuration (arch) information
213         config *ssa.Config
214
215         // function we're building
216         f *ssa.Func
217
218         // labels and labeled control flow nodes (OFOR, OSWITCH, OSELECT) in f
219         labels       map[string]*ssaLabel
220         labeledNodes map[*Node]*ssaLabel
221
222         // gotos that jump forward; required for deferred checkgoto calls
223         fwdGotos []*Node
224         // Code that must precede any return
225         // (e.g., copying value of heap-escaped paramout back to true paramout)
226         exitCode Nodes
227
228         // unlabeled break and continue statement tracking
229         breakTo    *ssa.Block // current target for plain break statement
230         continueTo *ssa.Block // current target for plain continue statement
231
232         // current location where we're interpreting the AST
233         curBlock *ssa.Block
234
235         // variable assignments in the current block (map from variable symbol to ssa value)
236         // *Node is the unique identifier (an ONAME Node) for the variable.
237         vars map[*Node]*ssa.Value
238
239         // all defined variables at the end of each block.  Indexed by block ID.
240         defvars []map[*Node]*ssa.Value
241
242         // addresses of PPARAM and PPARAMOUT variables.
243         decladdrs map[*Node]*ssa.Value
244
245         // symbols for PEXTERN, PAUTO and PPARAMOUT variables so they can be reused.
246         varsyms map[*Node]interface{}
247
248         // starting values.  Memory, stack pointer, and globals pointer
249         startmem *ssa.Value
250         sp       *ssa.Value
251         sb       *ssa.Value
252
253         // line number stack.  The current line number is top of stack
254         line []int32
255
256         // list of panic calls by function name and line number.
257         // Used to deduplicate panic calls.
258         panics map[funcLine]*ssa.Block
259
260         // list of FwdRef values.
261         fwdRefs []*ssa.Value
262 }
263
264 type funcLine struct {
265         f    *Node
266         line int32
267 }
268
269 type ssaLabel struct {
270         target         *ssa.Block // block identified by this label
271         breakTarget    *ssa.Block // block to break to in control flow node identified by this label
272         continueTarget *ssa.Block // block to continue to in control flow node identified by this label
273         defNode        *Node      // label definition Node (OLABEL)
274         // Label use Node (OGOTO, OBREAK, OCONTINUE).
275         // Used only for error detection and reporting.
276         // There might be multiple uses, but we only need to track one.
277         useNode  *Node
278         reported bool // reported indicates whether an error has already been reported for this label
279 }
280
281 // defined reports whether the label has a definition (OLABEL node).
282 func (l *ssaLabel) defined() bool { return l.defNode != nil }
283
284 // used reports whether the label has a use (OGOTO, OBREAK, or OCONTINUE node).
285 func (l *ssaLabel) used() bool { return l.useNode != nil }
286
287 // label returns the label associated with sym, creating it if necessary.
288 func (s *state) label(sym *Sym) *ssaLabel {
289         lab := s.labels[sym.Name]
290         if lab == nil {
291                 lab = new(ssaLabel)
292                 s.labels[sym.Name] = lab
293         }
294         return lab
295 }
296
297 func (s *state) Logf(msg string, args ...interface{})   { s.config.Logf(msg, args...) }
298 func (s *state) Log() bool                              { return s.config.Log() }
299 func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(s.peekLine(), msg, args...) }
300 func (s *state) Unimplementedf(msg string, args ...interface{}) {
301         s.config.Unimplementedf(s.peekLine(), msg, args...)
302 }
303 func (s *state) Warnl(line int, msg string, args ...interface{}) { s.config.Warnl(line, msg, args...) }
304 func (s *state) Debug_checknil() bool                            { return s.config.Debug_checknil() }
305
306 var (
307         // dummy node for the memory variable
308         memVar = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "mem"}}
309
310         // dummy nodes for temporary variables
311         ptrVar   = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "ptr"}}
312         capVar   = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "cap"}}
313         typVar   = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "typ"}}
314         idataVar = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "idata"}}
315         okVar    = Node{Op: ONAME, Class: Pxxx, Sym: &Sym{Name: "ok"}}
316 )
317
318 // startBlock sets the current block we're generating code in to b.
319 func (s *state) startBlock(b *ssa.Block) {
320         if s.curBlock != nil {
321                 s.Fatalf("starting block %v when block %v has not ended", b, s.curBlock)
322         }
323         s.curBlock = b
324         s.vars = map[*Node]*ssa.Value{}
325 }
326
327 // endBlock marks the end of generating code for the current block.
328 // Returns the (former) current block.  Returns nil if there is no current
329 // block, i.e. if no code flows to the current execution point.
330 func (s *state) endBlock() *ssa.Block {
331         b := s.curBlock
332         if b == nil {
333                 return nil
334         }
335         for len(s.defvars) <= int(b.ID) {
336                 s.defvars = append(s.defvars, nil)
337         }
338         s.defvars[b.ID] = s.vars
339         s.curBlock = nil
340         s.vars = nil
341         b.Line = s.peekLine()
342         return b
343 }
344
345 // pushLine pushes a line number on the line number stack.
346 func (s *state) pushLine(line int32) {
347         s.line = append(s.line, line)
348 }
349
350 // popLine pops the top of the line number stack.
351 func (s *state) popLine() {
352         s.line = s.line[:len(s.line)-1]
353 }
354
355 // peekLine peek the top of the line number stack.
356 func (s *state) peekLine() int32 {
357         return s.line[len(s.line)-1]
358 }
359
360 func (s *state) Error(msg string, args ...interface{}) {
361         yyerrorl(int(s.peekLine()), msg, args...)
362 }
363
364 // newValue0 adds a new value with no arguments to the current block.
365 func (s *state) newValue0(op ssa.Op, t ssa.Type) *ssa.Value {
366         return s.curBlock.NewValue0(s.peekLine(), op, t)
367 }
368
369 // newValue0A adds a new value with no arguments and an aux value to the current block.
370 func (s *state) newValue0A(op ssa.Op, t ssa.Type, aux interface{}) *ssa.Value {
371         return s.curBlock.NewValue0A(s.peekLine(), op, t, aux)
372 }
373
374 // newValue0I adds a new value with no arguments and an auxint value to the current block.
375 func (s *state) newValue0I(op ssa.Op, t ssa.Type, auxint int64) *ssa.Value {
376         return s.curBlock.NewValue0I(s.peekLine(), op, t, auxint)
377 }
378
379 // newValue1 adds a new value with one argument to the current block.
380 func (s *state) newValue1(op ssa.Op, t ssa.Type, arg *ssa.Value) *ssa.Value {
381         return s.curBlock.NewValue1(s.peekLine(), op, t, arg)
382 }
383
384 // newValue1A adds a new value with one argument and an aux value to the current block.
385 func (s *state) newValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
386         return s.curBlock.NewValue1A(s.peekLine(), op, t, aux, arg)
387 }
388
389 // newValue1I adds a new value with one argument and an auxint value to the current block.
390 func (s *state) newValue1I(op ssa.Op, t ssa.Type, aux int64, arg *ssa.Value) *ssa.Value {
391         return s.curBlock.NewValue1I(s.peekLine(), op, t, aux, arg)
392 }
393
394 // newValue2 adds a new value with two arguments to the current block.
395 func (s *state) newValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value {
396         return s.curBlock.NewValue2(s.peekLine(), op, t, arg0, arg1)
397 }
398
399 // newValue2I adds a new value with two arguments and an auxint value to the current block.
400 func (s *state) newValue2I(op ssa.Op, t ssa.Type, aux int64, arg0, arg1 *ssa.Value) *ssa.Value {
401         return s.curBlock.NewValue2I(s.peekLine(), op, t, aux, arg0, arg1)
402 }
403
404 // newValue3 adds a new value with three arguments to the current block.
405 func (s *state) newValue3(op ssa.Op, t ssa.Type, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
406         return s.curBlock.NewValue3(s.peekLine(), op, t, arg0, arg1, arg2)
407 }
408
409 // newValue3I adds a new value with three arguments and an auxint value to the current block.
410 func (s *state) newValue3I(op ssa.Op, t ssa.Type, aux int64, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
411         return s.curBlock.NewValue3I(s.peekLine(), op, t, aux, arg0, arg1, arg2)
412 }
413
414 // entryNewValue0 adds a new value with no arguments to the entry block.
415 func (s *state) entryNewValue0(op ssa.Op, t ssa.Type) *ssa.Value {
416         return s.f.Entry.NewValue0(s.peekLine(), op, t)
417 }
418
419 // entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
420 func (s *state) entryNewValue0A(op ssa.Op, t ssa.Type, aux interface{}) *ssa.Value {
421         return s.f.Entry.NewValue0A(s.peekLine(), op, t, aux)
422 }
423
424 // entryNewValue0I adds a new value with no arguments and an auxint value to the entry block.
425 func (s *state) entryNewValue0I(op ssa.Op, t ssa.Type, auxint int64) *ssa.Value {
426         return s.f.Entry.NewValue0I(s.peekLine(), op, t, auxint)
427 }
428
429 // entryNewValue1 adds a new value with one argument to the entry block.
430 func (s *state) entryNewValue1(op ssa.Op, t ssa.Type, arg *ssa.Value) *ssa.Value {
431         return s.f.Entry.NewValue1(s.peekLine(), op, t, arg)
432 }
433
434 // entryNewValue1 adds a new value with one argument and an auxint value to the entry block.
435 func (s *state) entryNewValue1I(op ssa.Op, t ssa.Type, auxint int64, arg *ssa.Value) *ssa.Value {
436         return s.f.Entry.NewValue1I(s.peekLine(), op, t, auxint, arg)
437 }
438
439 // entryNewValue1A adds a new value with one argument and an aux value to the entry block.
440 func (s *state) entryNewValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
441         return s.f.Entry.NewValue1A(s.peekLine(), op, t, aux, arg)
442 }
443
444 // entryNewValue2 adds a new value with two arguments to the entry block.
445 func (s *state) entryNewValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value {
446         return s.f.Entry.NewValue2(s.peekLine(), op, t, arg0, arg1)
447 }
448
449 // const* routines add a new const value to the entry block.
450 func (s *state) constBool(c bool) *ssa.Value {
451         return s.f.ConstBool(s.peekLine(), Types[TBOOL], c)
452 }
453 func (s *state) constInt8(t ssa.Type, c int8) *ssa.Value {
454         return s.f.ConstInt8(s.peekLine(), t, c)
455 }
456 func (s *state) constInt16(t ssa.Type, c int16) *ssa.Value {
457         return s.f.ConstInt16(s.peekLine(), t, c)
458 }
459 func (s *state) constInt32(t ssa.Type, c int32) *ssa.Value {
460         return s.f.ConstInt32(s.peekLine(), t, c)
461 }
462 func (s *state) constInt64(t ssa.Type, c int64) *ssa.Value {
463         return s.f.ConstInt64(s.peekLine(), t, c)
464 }
465 func (s *state) constFloat32(t ssa.Type, c float64) *ssa.Value {
466         return s.f.ConstFloat32(s.peekLine(), t, c)
467 }
468 func (s *state) constFloat64(t ssa.Type, c float64) *ssa.Value {
469         return s.f.ConstFloat64(s.peekLine(), t, c)
470 }
471 func (s *state) constInt(t ssa.Type, c int64) *ssa.Value {
472         if s.config.IntSize == 8 {
473                 return s.constInt64(t, c)
474         }
475         if int64(int32(c)) != c {
476                 s.Fatalf("integer constant too big %d", c)
477         }
478         return s.constInt32(t, int32(c))
479 }
480
481 func (s *state) stmts(a Nodes) {
482         for _, x := range a.Slice() {
483                 s.stmt(x)
484         }
485 }
486
487 // ssaStmtList converts the statement n to SSA and adds it to s.
488 func (s *state) stmtList(l *NodeList) {
489         for ; l != nil; l = l.Next {
490                 s.stmt(l.N)
491         }
492 }
493
494 // ssaStmt converts the statement n to SSA and adds it to s.
495 func (s *state) stmt(n *Node) {
496         s.pushLine(n.Lineno)
497         defer s.popLine()
498
499         // If s.curBlock is nil, then we're about to generate dead code.
500         // We can't just short-circuit here, though,
501         // because we check labels and gotos as part of SSA generation.
502         // Provide a block for the dead code so that we don't have
503         // to add special cases everywhere else.
504         if s.curBlock == nil {
505                 dead := s.f.NewBlock(ssa.BlockPlain)
506                 s.startBlock(dead)
507         }
508
509         s.stmtList(n.Ninit)
510         switch n.Op {
511
512         case OBLOCK:
513                 s.stmtList(n.List)
514
515         // No-ops
516         case OEMPTY, ODCLCONST, ODCLTYPE, OFALL:
517
518         // Expression statements
519         case OCALLFUNC, OCALLMETH, OCALLINTER:
520                 s.call(n, callNormal)
521                 if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class == PFUNC &&
522                         (compiling_runtime != 0 && n.Left.Sym.Name == "throw" ||
523                                 n.Left.Sym.Pkg == Runtimepkg && (n.Left.Sym.Name == "gopanic" || n.Left.Sym.Name == "selectgo")) {
524                         m := s.mem()
525                         b := s.endBlock()
526                         b.Kind = ssa.BlockExit
527                         b.Control = m
528                         // TODO: never rewrite OPANIC to OCALLFUNC in the
529                         // first place.  Need to wait until all backends
530                         // go through SSA.
531                 }
532         case ODEFER:
533                 s.call(n.Left, callDefer)
534         case OPROC:
535                 s.call(n.Left, callGo)
536
537         case OAS2DOTTYPE:
538                 res, resok := s.dottype(n.Rlist.N, true)
539                 s.assign(n.List.N, res, needwritebarrier(n.List.N, n.Rlist.N), false, n.Lineno)
540                 s.assign(n.List.Next.N, resok, false, false, n.Lineno)
541                 return
542
543         case ODCL:
544                 if n.Left.Class&PHEAP == 0 {
545                         return
546                 }
547                 if compiling_runtime != 0 {
548                         Fatalf("%v escapes to heap, not allowed in runtime.", n)
549                 }
550
551                 // TODO: the old pass hides the details of PHEAP
552                 // variables behind ONAME nodes. Figure out if it's better
553                 // to rewrite the tree and make the heapaddr construct explicit
554                 // or to keep this detail hidden behind the scenes.
555                 palloc := prealloc[n.Left]
556                 if palloc == nil {
557                         palloc = callnew(n.Left.Type)
558                         prealloc[n.Left] = palloc
559                 }
560                 r := s.expr(palloc)
561                 s.assign(n.Left.Name.Heapaddr, r, false, false, n.Lineno)
562
563         case OLABEL:
564                 sym := n.Left.Sym
565
566                 if isblanksym(sym) {
567                         // Empty identifier is valid but useless.
568                         // See issues 11589, 11593.
569                         return
570                 }
571
572                 lab := s.label(sym)
573
574                 // Associate label with its control flow node, if any
575                 if ctl := n.Name.Defn; ctl != nil {
576                         switch ctl.Op {
577                         case OFOR, OSWITCH, OSELECT:
578                                 s.labeledNodes[ctl] = lab
579                         }
580                 }
581
582                 if !lab.defined() {
583                         lab.defNode = n
584                 } else {
585                         s.Error("label %v already defined at %v", sym, Ctxt.Line(int(lab.defNode.Lineno)))
586                         lab.reported = true
587                 }
588                 // The label might already have a target block via a goto.
589                 if lab.target == nil {
590                         lab.target = s.f.NewBlock(ssa.BlockPlain)
591                 }
592
593                 // go to that label (we pretend "label:" is preceded by "goto label")
594                 b := s.endBlock()
595                 b.AddEdgeTo(lab.target)
596                 s.startBlock(lab.target)
597
598         case OGOTO:
599                 sym := n.Left.Sym
600
601                 lab := s.label(sym)
602                 if lab.target == nil {
603                         lab.target = s.f.NewBlock(ssa.BlockPlain)
604                 }
605                 if !lab.used() {
606                         lab.useNode = n
607                 }
608
609                 if lab.defined() {
610                         s.checkgoto(n, lab.defNode)
611                 } else {
612                         s.fwdGotos = append(s.fwdGotos, n)
613                 }
614
615                 b := s.endBlock()
616                 b.AddEdgeTo(lab.target)
617
618         case OAS, OASWB:
619                 // Check whether we can generate static data rather than code.
620                 // If so, ignore n and defer data generation until codegen.
621                 // Failure to do this causes writes to readonly symbols.
622                 if gen_as_init(n, true) {
623                         var data []*Node
624                         if s.f.StaticData != nil {
625                                 data = s.f.StaticData.([]*Node)
626                         }
627                         s.f.StaticData = append(data, n)
628                         return
629                 }
630
631                 var t *Type
632                 if n.Right != nil {
633                         t = n.Right.Type
634                 } else {
635                         t = n.Left.Type
636                 }
637
638                 // Evaluate RHS.
639                 rhs := n.Right
640                 if rhs != nil && (rhs.Op == OSTRUCTLIT || rhs.Op == OARRAYLIT) {
641                         // All literals with nonzero fields have already been
642                         // rewritten during walk.  Any that remain are just T{}
643                         // or equivalents.  Use the zero value.
644                         if !iszero(rhs) {
645                                 Fatalf("literal with nonzero value in SSA: %v", rhs)
646                         }
647                         rhs = nil
648                 }
649                 var r *ssa.Value
650                 needwb := n.Op == OASWB && rhs != nil
651                 deref := !canSSAType(t)
652                 if deref {
653                         if rhs == nil {
654                                 r = nil // Signal assign to use OpZero.
655                         } else {
656                                 r = s.addr(rhs, false)
657                         }
658                 } else {
659                         if rhs == nil {
660                                 r = s.zeroVal(t)
661                         } else {
662                                 r = s.expr(rhs)
663                         }
664                 }
665                 if rhs != nil && rhs.Op == OAPPEND {
666                         // Yuck!  The frontend gets rid of the write barrier, but we need it!
667                         // At least, we need it in the case where growslice is called.
668                         // TODO: Do the write barrier on just the growslice branch.
669                         // TODO: just add a ptr graying to the end of growslice?
670                         // TODO: check whether we need to do this for ODOTTYPE and ORECV also.
671                         // They get similar wb-removal treatment in walk.go:OAS.
672                         needwb = true
673                 }
674
675                 s.assign(n.Left, r, needwb, deref, n.Lineno)
676
677         case OIF:
678                 bThen := s.f.NewBlock(ssa.BlockPlain)
679                 bEnd := s.f.NewBlock(ssa.BlockPlain)
680                 var bElse *ssa.Block
681                 if n.Rlist != nil {
682                         bElse = s.f.NewBlock(ssa.BlockPlain)
683                         s.condBranch(n.Left, bThen, bElse, n.Likely)
684                 } else {
685                         s.condBranch(n.Left, bThen, bEnd, n.Likely)
686                 }
687
688                 s.startBlock(bThen)
689                 s.stmtList(n.Nbody)
690                 if b := s.endBlock(); b != nil {
691                         b.AddEdgeTo(bEnd)
692                 }
693
694                 if n.Rlist != nil {
695                         s.startBlock(bElse)
696                         s.stmtList(n.Rlist)
697                         if b := s.endBlock(); b != nil {
698                                 b.AddEdgeTo(bEnd)
699                         }
700                 }
701                 s.startBlock(bEnd)
702
703         case ORETURN:
704                 s.stmtList(n.List)
705                 s.stmts(s.exitCode)
706                 m := s.mem()
707                 b := s.endBlock()
708                 b.Kind = ssa.BlockRet
709                 b.Control = m
710         case ORETJMP:
711                 s.stmtList(n.List)
712                 s.stmts(s.exitCode)
713                 m := s.mem()
714                 b := s.endBlock()
715                 b.Kind = ssa.BlockRetJmp
716                 b.Aux = n.Left.Sym
717                 b.Control = m
718
719         case OCONTINUE, OBREAK:
720                 var op string
721                 var to *ssa.Block
722                 switch n.Op {
723                 case OCONTINUE:
724                         op = "continue"
725                         to = s.continueTo
726                 case OBREAK:
727                         op = "break"
728                         to = s.breakTo
729                 }
730                 if n.Left == nil {
731                         // plain break/continue
732                         if to == nil {
733                                 s.Error("%s is not in a loop", op)
734                                 return
735                         }
736                         // nothing to do; "to" is already the correct target
737                 } else {
738                         // labeled break/continue; look up the target
739                         sym := n.Left.Sym
740                         lab := s.label(sym)
741                         if !lab.used() {
742                                 lab.useNode = n.Left
743                         }
744                         if !lab.defined() {
745                                 s.Error("%s label not defined: %v", op, sym)
746                                 lab.reported = true
747                                 return
748                         }
749                         switch n.Op {
750                         case OCONTINUE:
751                                 to = lab.continueTarget
752                         case OBREAK:
753                                 to = lab.breakTarget
754                         }
755                         if to == nil {
756                                 // Valid label but not usable with a break/continue here, e.g.:
757                                 // for {
758                                 //      continue abc
759                                 // }
760                                 // abc:
761                                 // for {}
762                                 s.Error("invalid %s label %v", op, sym)
763                                 lab.reported = true
764                                 return
765                         }
766                 }
767
768                 b := s.endBlock()
769                 b.AddEdgeTo(to)
770
771         case OFOR:
772                 // OFOR: for Ninit; Left; Right { Nbody }
773                 bCond := s.f.NewBlock(ssa.BlockPlain)
774                 bBody := s.f.NewBlock(ssa.BlockPlain)
775                 bIncr := s.f.NewBlock(ssa.BlockPlain)
776                 bEnd := s.f.NewBlock(ssa.BlockPlain)
777
778                 // first, jump to condition test
779                 b := s.endBlock()
780                 b.AddEdgeTo(bCond)
781
782                 // generate code to test condition
783                 s.startBlock(bCond)
784                 if n.Left != nil {
785                         s.condBranch(n.Left, bBody, bEnd, 1)
786                 } else {
787                         b := s.endBlock()
788                         b.Kind = ssa.BlockPlain
789                         b.AddEdgeTo(bBody)
790                 }
791
792                 // set up for continue/break in body
793                 prevContinue := s.continueTo
794                 prevBreak := s.breakTo
795                 s.continueTo = bIncr
796                 s.breakTo = bEnd
797                 lab := s.labeledNodes[n]
798                 if lab != nil {
799                         // labeled for loop
800                         lab.continueTarget = bIncr
801                         lab.breakTarget = bEnd
802                 }
803
804                 // generate body
805                 s.startBlock(bBody)
806                 s.stmtList(n.Nbody)
807
808                 // tear down continue/break
809                 s.continueTo = prevContinue
810                 s.breakTo = prevBreak
811                 if lab != nil {
812                         lab.continueTarget = nil
813                         lab.breakTarget = nil
814                 }
815
816                 // done with body, goto incr
817                 if b := s.endBlock(); b != nil {
818                         b.AddEdgeTo(bIncr)
819                 }
820
821                 // generate incr
822                 s.startBlock(bIncr)
823                 if n.Right != nil {
824                         s.stmt(n.Right)
825                 }
826                 if b := s.endBlock(); b != nil {
827                         b.AddEdgeTo(bCond)
828                 }
829                 s.startBlock(bEnd)
830
831         case OSWITCH, OSELECT:
832                 // These have been mostly rewritten by the front end into their Nbody fields.
833                 // Our main task is to correctly hook up any break statements.
834                 bEnd := s.f.NewBlock(ssa.BlockPlain)
835
836                 prevBreak := s.breakTo
837                 s.breakTo = bEnd
838                 lab := s.labeledNodes[n]
839                 if lab != nil {
840                         // labeled
841                         lab.breakTarget = bEnd
842                 }
843
844                 // generate body code
845                 s.stmtList(n.Nbody)
846
847                 s.breakTo = prevBreak
848                 if lab != nil {
849                         lab.breakTarget = nil
850                 }
851
852                 // OSWITCH never falls through (s.curBlock == nil here).
853                 // OSELECT does not fall through if we're calling selectgo.
854                 // OSELECT does fall through if we're calling selectnb{send,recv}[2].
855                 // In those latter cases, go to the code after the select.
856                 if b := s.endBlock(); b != nil {
857                         b.AddEdgeTo(bEnd)
858                 }
859                 s.startBlock(bEnd)
860
861         case OVARKILL:
862                 // Insert a varkill op to record that a variable is no longer live.
863                 // We only care about liveness info at call sites, so putting the
864                 // varkill in the store chain is enough to keep it correctly ordered
865                 // with respect to call ops.
866                 if !canSSA(n.Left) {
867                         s.vars[&memVar] = s.newValue1A(ssa.OpVarKill, ssa.TypeMem, n.Left, s.mem())
868                 }
869
870         case OVARLIVE:
871                 // Insert a varlive op to record that a variable is still live.
872                 if !n.Left.Addrtaken {
873                         s.Fatalf("VARLIVE variable %s must have Addrtaken set", n.Left)
874                 }
875                 s.vars[&memVar] = s.newValue1A(ssa.OpVarLive, ssa.TypeMem, n.Left, s.mem())
876
877         case OCHECKNIL:
878                 p := s.expr(n.Left)
879                 s.nilCheck(p)
880
881         default:
882                 s.Unimplementedf("unhandled stmt %s", opnames[n.Op])
883         }
884 }
885
886 type opAndType struct {
887         op    Op
888         etype EType
889 }
890
891 var opToSSA = map[opAndType]ssa.Op{
892         opAndType{OADD, TINT8}:    ssa.OpAdd8,
893         opAndType{OADD, TUINT8}:   ssa.OpAdd8,
894         opAndType{OADD, TINT16}:   ssa.OpAdd16,
895         opAndType{OADD, TUINT16}:  ssa.OpAdd16,
896         opAndType{OADD, TINT32}:   ssa.OpAdd32,
897         opAndType{OADD, TUINT32}:  ssa.OpAdd32,
898         opAndType{OADD, TPTR32}:   ssa.OpAdd32,
899         opAndType{OADD, TINT64}:   ssa.OpAdd64,
900         opAndType{OADD, TUINT64}:  ssa.OpAdd64,
901         opAndType{OADD, TPTR64}:   ssa.OpAdd64,
902         opAndType{OADD, TFLOAT32}: ssa.OpAdd32F,
903         opAndType{OADD, TFLOAT64}: ssa.OpAdd64F,
904
905         opAndType{OSUB, TINT8}:    ssa.OpSub8,
906         opAndType{OSUB, TUINT8}:   ssa.OpSub8,
907         opAndType{OSUB, TINT16}:   ssa.OpSub16,
908         opAndType{OSUB, TUINT16}:  ssa.OpSub16,
909         opAndType{OSUB, TINT32}:   ssa.OpSub32,
910         opAndType{OSUB, TUINT32}:  ssa.OpSub32,
911         opAndType{OSUB, TINT64}:   ssa.OpSub64,
912         opAndType{OSUB, TUINT64}:  ssa.OpSub64,
913         opAndType{OSUB, TFLOAT32}: ssa.OpSub32F,
914         opAndType{OSUB, TFLOAT64}: ssa.OpSub64F,
915
916         opAndType{ONOT, TBOOL}: ssa.OpNot,
917
918         opAndType{OMINUS, TINT8}:    ssa.OpNeg8,
919         opAndType{OMINUS, TUINT8}:   ssa.OpNeg8,
920         opAndType{OMINUS, TINT16}:   ssa.OpNeg16,
921         opAndType{OMINUS, TUINT16}:  ssa.OpNeg16,
922         opAndType{OMINUS, TINT32}:   ssa.OpNeg32,
923         opAndType{OMINUS, TUINT32}:  ssa.OpNeg32,
924         opAndType{OMINUS, TINT64}:   ssa.OpNeg64,
925         opAndType{OMINUS, TUINT64}:  ssa.OpNeg64,
926         opAndType{OMINUS, TFLOAT32}: ssa.OpNeg32F,
927         opAndType{OMINUS, TFLOAT64}: ssa.OpNeg64F,
928
929         opAndType{OCOM, TINT8}:   ssa.OpCom8,
930         opAndType{OCOM, TUINT8}:  ssa.OpCom8,
931         opAndType{OCOM, TINT16}:  ssa.OpCom16,
932         opAndType{OCOM, TUINT16}: ssa.OpCom16,
933         opAndType{OCOM, TINT32}:  ssa.OpCom32,
934         opAndType{OCOM, TUINT32}: ssa.OpCom32,
935         opAndType{OCOM, TINT64}:  ssa.OpCom64,
936         opAndType{OCOM, TUINT64}: ssa.OpCom64,
937
938         opAndType{OIMAG, TCOMPLEX64}:  ssa.OpComplexImag,
939         opAndType{OIMAG, TCOMPLEX128}: ssa.OpComplexImag,
940         opAndType{OREAL, TCOMPLEX64}:  ssa.OpComplexReal,
941         opAndType{OREAL, TCOMPLEX128}: ssa.OpComplexReal,
942
943         opAndType{OMUL, TINT8}:    ssa.OpMul8,
944         opAndType{OMUL, TUINT8}:   ssa.OpMul8,
945         opAndType{OMUL, TINT16}:   ssa.OpMul16,
946         opAndType{OMUL, TUINT16}:  ssa.OpMul16,
947         opAndType{OMUL, TINT32}:   ssa.OpMul32,
948         opAndType{OMUL, TUINT32}:  ssa.OpMul32,
949         opAndType{OMUL, TINT64}:   ssa.OpMul64,
950         opAndType{OMUL, TUINT64}:  ssa.OpMul64,
951         opAndType{OMUL, TFLOAT32}: ssa.OpMul32F,
952         opAndType{OMUL, TFLOAT64}: ssa.OpMul64F,
953
954         opAndType{ODIV, TFLOAT32}: ssa.OpDiv32F,
955         opAndType{ODIV, TFLOAT64}: ssa.OpDiv64F,
956
957         opAndType{OHMUL, TINT8}:   ssa.OpHmul8,
958         opAndType{OHMUL, TUINT8}:  ssa.OpHmul8u,
959         opAndType{OHMUL, TINT16}:  ssa.OpHmul16,
960         opAndType{OHMUL, TUINT16}: ssa.OpHmul16u,
961         opAndType{OHMUL, TINT32}:  ssa.OpHmul32,
962         opAndType{OHMUL, TUINT32}: ssa.OpHmul32u,
963
964         opAndType{ODIV, TINT8}:   ssa.OpDiv8,
965         opAndType{ODIV, TUINT8}:  ssa.OpDiv8u,
966         opAndType{ODIV, TINT16}:  ssa.OpDiv16,
967         opAndType{ODIV, TUINT16}: ssa.OpDiv16u,
968         opAndType{ODIV, TINT32}:  ssa.OpDiv32,
969         opAndType{ODIV, TUINT32}: ssa.OpDiv32u,
970         opAndType{ODIV, TINT64}:  ssa.OpDiv64,
971         opAndType{ODIV, TUINT64}: ssa.OpDiv64u,
972
973         opAndType{OMOD, TINT8}:   ssa.OpMod8,
974         opAndType{OMOD, TUINT8}:  ssa.OpMod8u,
975         opAndType{OMOD, TINT16}:  ssa.OpMod16,
976         opAndType{OMOD, TUINT16}: ssa.OpMod16u,
977         opAndType{OMOD, TINT32}:  ssa.OpMod32,
978         opAndType{OMOD, TUINT32}: ssa.OpMod32u,
979         opAndType{OMOD, TINT64}:  ssa.OpMod64,
980         opAndType{OMOD, TUINT64}: ssa.OpMod64u,
981
982         opAndType{OAND, TINT8}:   ssa.OpAnd8,
983         opAndType{OAND, TUINT8}:  ssa.OpAnd8,
984         opAndType{OAND, TINT16}:  ssa.OpAnd16,
985         opAndType{OAND, TUINT16}: ssa.OpAnd16,
986         opAndType{OAND, TINT32}:  ssa.OpAnd32,
987         opAndType{OAND, TUINT32}: ssa.OpAnd32,
988         opAndType{OAND, TINT64}:  ssa.OpAnd64,
989         opAndType{OAND, TUINT64}: ssa.OpAnd64,
990
991         opAndType{OOR, TINT8}:   ssa.OpOr8,
992         opAndType{OOR, TUINT8}:  ssa.OpOr8,
993         opAndType{OOR, TINT16}:  ssa.OpOr16,
994         opAndType{OOR, TUINT16}: ssa.OpOr16,
995         opAndType{OOR, TINT32}:  ssa.OpOr32,
996         opAndType{OOR, TUINT32}: ssa.OpOr32,
997         opAndType{OOR, TINT64}:  ssa.OpOr64,
998         opAndType{OOR, TUINT64}: ssa.OpOr64,
999
1000         opAndType{OXOR, TINT8}:   ssa.OpXor8,
1001         opAndType{OXOR, TUINT8}:  ssa.OpXor8,
1002         opAndType{OXOR, TINT16}:  ssa.OpXor16,
1003         opAndType{OXOR, TUINT16}: ssa.OpXor16,
1004         opAndType{OXOR, TINT32}:  ssa.OpXor32,
1005         opAndType{OXOR, TUINT32}: ssa.OpXor32,
1006         opAndType{OXOR, TINT64}:  ssa.OpXor64,
1007         opAndType{OXOR, TUINT64}: ssa.OpXor64,
1008
1009         opAndType{OEQ, TBOOL}:      ssa.OpEq8,
1010         opAndType{OEQ, TINT8}:      ssa.OpEq8,
1011         opAndType{OEQ, TUINT8}:     ssa.OpEq8,
1012         opAndType{OEQ, TINT16}:     ssa.OpEq16,
1013         opAndType{OEQ, TUINT16}:    ssa.OpEq16,
1014         opAndType{OEQ, TINT32}:     ssa.OpEq32,
1015         opAndType{OEQ, TUINT32}:    ssa.OpEq32,
1016         opAndType{OEQ, TINT64}:     ssa.OpEq64,
1017         opAndType{OEQ, TUINT64}:    ssa.OpEq64,
1018         opAndType{OEQ, TINTER}:     ssa.OpEqInter,
1019         opAndType{OEQ, TARRAY}:     ssa.OpEqSlice,
1020         opAndType{OEQ, TFUNC}:      ssa.OpEqPtr,
1021         opAndType{OEQ, TMAP}:       ssa.OpEqPtr,
1022         opAndType{OEQ, TCHAN}:      ssa.OpEqPtr,
1023         opAndType{OEQ, TPTR64}:     ssa.OpEqPtr,
1024         opAndType{OEQ, TUINTPTR}:   ssa.OpEqPtr,
1025         opAndType{OEQ, TUNSAFEPTR}: ssa.OpEqPtr,
1026         opAndType{OEQ, TFLOAT64}:   ssa.OpEq64F,
1027         opAndType{OEQ, TFLOAT32}:   ssa.OpEq32F,
1028
1029         opAndType{ONE, TBOOL}:      ssa.OpNeq8,
1030         opAndType{ONE, TINT8}:      ssa.OpNeq8,
1031         opAndType{ONE, TUINT8}:     ssa.OpNeq8,
1032         opAndType{ONE, TINT16}:     ssa.OpNeq16,
1033         opAndType{ONE, TUINT16}:    ssa.OpNeq16,
1034         opAndType{ONE, TINT32}:     ssa.OpNeq32,
1035         opAndType{ONE, TUINT32}:    ssa.OpNeq32,
1036         opAndType{ONE, TINT64}:     ssa.OpNeq64,
1037         opAndType{ONE, TUINT64}:    ssa.OpNeq64,
1038         opAndType{ONE, TINTER}:     ssa.OpNeqInter,
1039         opAndType{ONE, TARRAY}:     ssa.OpNeqSlice,
1040         opAndType{ONE, TFUNC}:      ssa.OpNeqPtr,
1041         opAndType{ONE, TMAP}:       ssa.OpNeqPtr,
1042         opAndType{ONE, TCHAN}:      ssa.OpNeqPtr,
1043         opAndType{ONE, TPTR64}:     ssa.OpNeqPtr,
1044         opAndType{ONE, TUINTPTR}:   ssa.OpNeqPtr,
1045         opAndType{ONE, TUNSAFEPTR}: ssa.OpNeqPtr,
1046         opAndType{ONE, TFLOAT64}:   ssa.OpNeq64F,
1047         opAndType{ONE, TFLOAT32}:   ssa.OpNeq32F,
1048
1049         opAndType{OLT, TINT8}:    ssa.OpLess8,
1050         opAndType{OLT, TUINT8}:   ssa.OpLess8U,
1051         opAndType{OLT, TINT16}:   ssa.OpLess16,
1052         opAndType{OLT, TUINT16}:  ssa.OpLess16U,
1053         opAndType{OLT, TINT32}:   ssa.OpLess32,
1054         opAndType{OLT, TUINT32}:  ssa.OpLess32U,
1055         opAndType{OLT, TINT64}:   ssa.OpLess64,
1056         opAndType{OLT, TUINT64}:  ssa.OpLess64U,
1057         opAndType{OLT, TFLOAT64}: ssa.OpLess64F,
1058         opAndType{OLT, TFLOAT32}: ssa.OpLess32F,
1059
1060         opAndType{OGT, TINT8}:    ssa.OpGreater8,
1061         opAndType{OGT, TUINT8}:   ssa.OpGreater8U,
1062         opAndType{OGT, TINT16}:   ssa.OpGreater16,
1063         opAndType{OGT, TUINT16}:  ssa.OpGreater16U,
1064         opAndType{OGT, TINT32}:   ssa.OpGreater32,
1065         opAndType{OGT, TUINT32}:  ssa.OpGreater32U,
1066         opAndType{OGT, TINT64}:   ssa.OpGreater64,
1067         opAndType{OGT, TUINT64}:  ssa.OpGreater64U,
1068         opAndType{OGT, TFLOAT64}: ssa.OpGreater64F,
1069         opAndType{OGT, TFLOAT32}: ssa.OpGreater32F,
1070
1071         opAndType{OLE, TINT8}:    ssa.OpLeq8,
1072         opAndType{OLE, TUINT8}:   ssa.OpLeq8U,
1073         opAndType{OLE, TINT16}:   ssa.OpLeq16,
1074         opAndType{OLE, TUINT16}:  ssa.OpLeq16U,
1075         opAndType{OLE, TINT32}:   ssa.OpLeq32,
1076         opAndType{OLE, TUINT32}:  ssa.OpLeq32U,
1077         opAndType{OLE, TINT64}:   ssa.OpLeq64,
1078         opAndType{OLE, TUINT64}:  ssa.OpLeq64U,
1079         opAndType{OLE, TFLOAT64}: ssa.OpLeq64F,
1080         opAndType{OLE, TFLOAT32}: ssa.OpLeq32F,
1081
1082         opAndType{OGE, TINT8}:    ssa.OpGeq8,
1083         opAndType{OGE, TUINT8}:   ssa.OpGeq8U,
1084         opAndType{OGE, TINT16}:   ssa.OpGeq16,
1085         opAndType{OGE, TUINT16}:  ssa.OpGeq16U,
1086         opAndType{OGE, TINT32}:   ssa.OpGeq32,
1087         opAndType{OGE, TUINT32}:  ssa.OpGeq32U,
1088         opAndType{OGE, TINT64}:   ssa.OpGeq64,
1089         opAndType{OGE, TUINT64}:  ssa.OpGeq64U,
1090         opAndType{OGE, TFLOAT64}: ssa.OpGeq64F,
1091         opAndType{OGE, TFLOAT32}: ssa.OpGeq32F,
1092
1093         opAndType{OLROT, TUINT8}:  ssa.OpLrot8,
1094         opAndType{OLROT, TUINT16}: ssa.OpLrot16,
1095         opAndType{OLROT, TUINT32}: ssa.OpLrot32,
1096         opAndType{OLROT, TUINT64}: ssa.OpLrot64,
1097
1098         opAndType{OSQRT, TFLOAT64}: ssa.OpSqrt,
1099 }
1100
1101 func (s *state) concreteEtype(t *Type) EType {
1102         e := t.Etype
1103         switch e {
1104         default:
1105                 return e
1106         case TINT:
1107                 if s.config.IntSize == 8 {
1108                         return TINT64
1109                 }
1110                 return TINT32
1111         case TUINT:
1112                 if s.config.IntSize == 8 {
1113                         return TUINT64
1114                 }
1115                 return TUINT32
1116         case TUINTPTR:
1117                 if s.config.PtrSize == 8 {
1118                         return TUINT64
1119                 }
1120                 return TUINT32
1121         }
1122 }
1123
1124 func (s *state) ssaOp(op Op, t *Type) ssa.Op {
1125         etype := s.concreteEtype(t)
1126         x, ok := opToSSA[opAndType{op, etype}]
1127         if !ok {
1128                 s.Unimplementedf("unhandled binary op %s %s", opnames[op], Econv(etype))
1129         }
1130         return x
1131 }
1132
1133 func floatForComplex(t *Type) *Type {
1134         if t.Size() == 8 {
1135                 return Types[TFLOAT32]
1136         } else {
1137                 return Types[TFLOAT64]
1138         }
1139 }
1140
1141 type opAndTwoTypes struct {
1142         op     Op
1143         etype1 EType
1144         etype2 EType
1145 }
1146
1147 type twoTypes struct {
1148         etype1 EType
1149         etype2 EType
1150 }
1151
1152 type twoOpsAndType struct {
1153         op1              ssa.Op
1154         op2              ssa.Op
1155         intermediateType EType
1156 }
1157
1158 var fpConvOpToSSA = map[twoTypes]twoOpsAndType{
1159
1160         twoTypes{TINT8, TFLOAT32}:  twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to32F, TINT32},
1161         twoTypes{TINT16, TFLOAT32}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to32F, TINT32},
1162         twoTypes{TINT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to32F, TINT32},
1163         twoTypes{TINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to32F, TINT64},
1164
1165         twoTypes{TINT8, TFLOAT64}:  twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to64F, TINT32},
1166         twoTypes{TINT16, TFLOAT64}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to64F, TINT32},
1167         twoTypes{TINT32, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to64F, TINT32},
1168         twoTypes{TINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to64F, TINT64},
1169
1170         twoTypes{TFLOAT32, TINT8}:  twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32},
1171         twoTypes{TFLOAT32, TINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32},
1172         twoTypes{TFLOAT32, TINT32}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpCopy, TINT32},
1173         twoTypes{TFLOAT32, TINT64}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpCopy, TINT64},
1174
1175         twoTypes{TFLOAT64, TINT8}:  twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32},
1176         twoTypes{TFLOAT64, TINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32},
1177         twoTypes{TFLOAT64, TINT32}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpCopy, TINT32},
1178         twoTypes{TFLOAT64, TINT64}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpCopy, TINT64},
1179         // unsigned
1180         twoTypes{TUINT8, TFLOAT32}:  twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to32F, TINT32},
1181         twoTypes{TUINT16, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to32F, TINT32},
1182         twoTypes{TUINT32, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to32F, TINT64}, // go wide to dodge unsigned
1183         twoTypes{TUINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64},            // Cvt64Uto32F, branchy code expansion instead
1184
1185         twoTypes{TUINT8, TFLOAT64}:  twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to64F, TINT32},
1186         twoTypes{TUINT16, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to64F, TINT32},
1187         twoTypes{TUINT32, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to64F, TINT64}, // go wide to dodge unsigned
1188         twoTypes{TUINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64},            // Cvt64Uto64F, branchy code expansion instead
1189
1190         twoTypes{TFLOAT32, TUINT8}:  twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32},
1191         twoTypes{TFLOAT32, TUINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32},
1192         twoTypes{TFLOAT32, TUINT32}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned
1193         twoTypes{TFLOAT32, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64},          // Cvt32Fto64U, branchy code expansion instead
1194
1195         twoTypes{TFLOAT64, TUINT8}:  twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32},
1196         twoTypes{TFLOAT64, TUINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32},
1197         twoTypes{TFLOAT64, TUINT32}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned
1198         twoTypes{TFLOAT64, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64},          // Cvt64Fto64U, branchy code expansion instead
1199
1200         // float
1201         twoTypes{TFLOAT64, TFLOAT32}: twoOpsAndType{ssa.OpCvt64Fto32F, ssa.OpCopy, TFLOAT32},
1202         twoTypes{TFLOAT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCopy, TFLOAT64},
1203         twoTypes{TFLOAT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCopy, TFLOAT32},
1204         twoTypes{TFLOAT32, TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, TFLOAT64},
1205 }
1206
1207 var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{
1208         opAndTwoTypes{OLSH, TINT8, TUINT8}:   ssa.OpLsh8x8,
1209         opAndTwoTypes{OLSH, TUINT8, TUINT8}:  ssa.OpLsh8x8,
1210         opAndTwoTypes{OLSH, TINT8, TUINT16}:  ssa.OpLsh8x16,
1211         opAndTwoTypes{OLSH, TUINT8, TUINT16}: ssa.OpLsh8x16,
1212         opAndTwoTypes{OLSH, TINT8, TUINT32}:  ssa.OpLsh8x32,
1213         opAndTwoTypes{OLSH, TUINT8, TUINT32}: ssa.OpLsh8x32,
1214         opAndTwoTypes{OLSH, TINT8, TUINT64}:  ssa.OpLsh8x64,
1215         opAndTwoTypes{OLSH, TUINT8, TUINT64}: ssa.OpLsh8x64,
1216
1217         opAndTwoTypes{OLSH, TINT16, TUINT8}:   ssa.OpLsh16x8,
1218         opAndTwoTypes{OLSH, TUINT16, TUINT8}:  ssa.OpLsh16x8,
1219         opAndTwoTypes{OLSH, TINT16, TUINT16}:  ssa.OpLsh16x16,
1220         opAndTwoTypes{OLSH, TUINT16, TUINT16}: ssa.OpLsh16x16,
1221         opAndTwoTypes{OLSH, TINT16, TUINT32}:  ssa.OpLsh16x32,
1222         opAndTwoTypes{OLSH, TUINT16, TUINT32}: ssa.OpLsh16x32,
1223         opAndTwoTypes{OLSH, TINT16, TUINT64}:  ssa.OpLsh16x64,
1224         opAndTwoTypes{OLSH, TUINT16, TUINT64}: ssa.OpLsh16x64,
1225
1226         opAndTwoTypes{OLSH, TINT32, TUINT8}:   ssa.OpLsh32x8,
1227         opAndTwoTypes{OLSH, TUINT32, TUINT8}:  ssa.OpLsh32x8,
1228         opAndTwoTypes{OLSH, TINT32, TUINT16}:  ssa.OpLsh32x16,
1229         opAndTwoTypes{OLSH, TUINT32, TUINT16}: ssa.OpLsh32x16,
1230         opAndTwoTypes{OLSH, TINT32, TUINT32}:  ssa.OpLsh32x32,
1231         opAndTwoTypes{OLSH, TUINT32, TUINT32}: ssa.OpLsh32x32,
1232         opAndTwoTypes{OLSH, TINT32, TUINT64}:  ssa.OpLsh32x64,
1233         opAndTwoTypes{OLSH, TUINT32, TUINT64}: ssa.OpLsh32x64,
1234
1235         opAndTwoTypes{OLSH, TINT64, TUINT8}:   ssa.OpLsh64x8,
1236         opAndTwoTypes{OLSH, TUINT64, TUINT8}:  ssa.OpLsh64x8,
1237         opAndTwoTypes{OLSH, TINT64, TUINT16}:  ssa.OpLsh64x16,
1238         opAndTwoTypes{OLSH, TUINT64, TUINT16}: ssa.OpLsh64x16,
1239         opAndTwoTypes{OLSH, TINT64, TUINT32}:  ssa.OpLsh64x32,
1240         opAndTwoTypes{OLSH, TUINT64, TUINT32}: ssa.OpLsh64x32,
1241         opAndTwoTypes{OLSH, TINT64, TUINT64}:  ssa.OpLsh64x64,
1242         opAndTwoTypes{OLSH, TUINT64, TUINT64}: ssa.OpLsh64x64,
1243
1244         opAndTwoTypes{ORSH, TINT8, TUINT8}:   ssa.OpRsh8x8,
1245         opAndTwoTypes{ORSH, TUINT8, TUINT8}:  ssa.OpRsh8Ux8,
1246         opAndTwoTypes{ORSH, TINT8, TUINT16}:  ssa.OpRsh8x16,
1247         opAndTwoTypes{ORSH, TUINT8, TUINT16}: ssa.OpRsh8Ux16,
1248         opAndTwoTypes{ORSH, TINT8, TUINT32}:  ssa.OpRsh8x32,
1249         opAndTwoTypes{ORSH, TUINT8, TUINT32}: ssa.OpRsh8Ux32,
1250         opAndTwoTypes{ORSH, TINT8, TUINT64}:  ssa.OpRsh8x64,
1251         opAndTwoTypes{ORSH, TUINT8, TUINT64}: ssa.OpRsh8Ux64,
1252
1253         opAndTwoTypes{ORSH, TINT16, TUINT8}:   ssa.OpRsh16x8,
1254         opAndTwoTypes{ORSH, TUINT16, TUINT8}:  ssa.OpRsh16Ux8,
1255         opAndTwoTypes{ORSH, TINT16, TUINT16}:  ssa.OpRsh16x16,
1256         opAndTwoTypes{ORSH, TUINT16, TUINT16}: ssa.OpRsh16Ux16,
1257         opAndTwoTypes{ORSH, TINT16, TUINT32}:  ssa.OpRsh16x32,
1258         opAndTwoTypes{ORSH, TUINT16, TUINT32}: ssa.OpRsh16Ux32,
1259         opAndTwoTypes{ORSH, TINT16, TUINT64}:  ssa.OpRsh16x64,
1260         opAndTwoTypes{ORSH, TUINT16, TUINT64}: ssa.OpRsh16Ux64,
1261
1262         opAndTwoTypes{ORSH, TINT32, TUINT8}:   ssa.OpRsh32x8,
1263         opAndTwoTypes{ORSH, TUINT32, TUINT8}:  ssa.OpRsh32Ux8,
1264         opAndTwoTypes{ORSH, TINT32, TUINT16}:  ssa.OpRsh32x16,
1265         opAndTwoTypes{ORSH, TUINT32, TUINT16}: ssa.OpRsh32Ux16,
1266         opAndTwoTypes{ORSH, TINT32, TUINT32}:  ssa.OpRsh32x32,
1267         opAndTwoTypes{ORSH, TUINT32, TUINT32}: ssa.OpRsh32Ux32,
1268         opAndTwoTypes{ORSH, TINT32, TUINT64}:  ssa.OpRsh32x64,
1269         opAndTwoTypes{ORSH, TUINT32, TUINT64}: ssa.OpRsh32Ux64,
1270
1271         opAndTwoTypes{ORSH, TINT64, TUINT8}:   ssa.OpRsh64x8,
1272         opAndTwoTypes{ORSH, TUINT64, TUINT8}:  ssa.OpRsh64Ux8,
1273         opAndTwoTypes{ORSH, TINT64, TUINT16}:  ssa.OpRsh64x16,
1274         opAndTwoTypes{ORSH, TUINT64, TUINT16}: ssa.OpRsh64Ux16,
1275         opAndTwoTypes{ORSH, TINT64, TUINT32}:  ssa.OpRsh64x32,
1276         opAndTwoTypes{ORSH, TUINT64, TUINT32}: ssa.OpRsh64Ux32,
1277         opAndTwoTypes{ORSH, TINT64, TUINT64}:  ssa.OpRsh64x64,
1278         opAndTwoTypes{ORSH, TUINT64, TUINT64}: ssa.OpRsh64Ux64,
1279 }
1280
1281 func (s *state) ssaShiftOp(op Op, t *Type, u *Type) ssa.Op {
1282         etype1 := s.concreteEtype(t)
1283         etype2 := s.concreteEtype(u)
1284         x, ok := shiftOpToSSA[opAndTwoTypes{op, etype1, etype2}]
1285         if !ok {
1286                 s.Unimplementedf("unhandled shift op %s etype=%s/%s", opnames[op], Econv(etype1), Econv(etype2))
1287         }
1288         return x
1289 }
1290
1291 func (s *state) ssaRotateOp(op Op, t *Type) ssa.Op {
1292         etype1 := s.concreteEtype(t)
1293         x, ok := opToSSA[opAndType{op, etype1}]
1294         if !ok {
1295                 s.Unimplementedf("unhandled rotate op %s etype=%s", opnames[op], Econv(etype1))
1296         }
1297         return x
1298 }
1299
1300 // expr converts the expression n to ssa, adds it to s and returns the ssa result.
1301 func (s *state) expr(n *Node) *ssa.Value {
1302         s.pushLine(n.Lineno)
1303         defer s.popLine()
1304
1305         s.stmtList(n.Ninit)
1306         switch n.Op {
1307         case OCFUNC:
1308                 aux := s.lookupSymbol(n, &ssa.ExternSymbol{n.Type, n.Left.Sym})
1309                 return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb)
1310         case OPARAM:
1311                 addr := s.addr(n, false)
1312                 return s.newValue2(ssa.OpLoad, n.Left.Type, addr, s.mem())
1313         case ONAME:
1314                 if n.Class == PFUNC {
1315                         // "value" of a function is the address of the function's closure
1316                         sym := funcsym(n.Sym)
1317                         aux := &ssa.ExternSymbol{n.Type, sym}
1318                         return s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sb)
1319                 }
1320                 if canSSA(n) {
1321                         return s.variable(n, n.Type)
1322                 }
1323                 addr := s.addr(n, false)
1324                 return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
1325         case OCLOSUREVAR:
1326                 addr := s.addr(n, false)
1327                 return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
1328         case OLITERAL:
1329                 switch n.Val().Ctype() {
1330                 case CTINT:
1331                         i := Mpgetfix(n.Val().U.(*Mpint))
1332                         switch n.Type.Size() {
1333                         case 1:
1334                                 return s.constInt8(n.Type, int8(i))
1335                         case 2:
1336                                 return s.constInt16(n.Type, int16(i))
1337                         case 4:
1338                                 return s.constInt32(n.Type, int32(i))
1339                         case 8:
1340                                 return s.constInt64(n.Type, i)
1341                         default:
1342                                 s.Fatalf("bad integer size %d", n.Type.Size())
1343                                 return nil
1344                         }
1345                 case CTSTR:
1346                         return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U)
1347                 case CTBOOL:
1348                         v := s.constBool(n.Val().U.(bool))
1349                         // For some reason the frontend gets the line numbers of
1350                         // CTBOOL literals totally wrong.  Fix it here by grabbing
1351                         // the line number of the enclosing AST node.
1352                         if len(s.line) >= 2 {
1353                                 v.Line = s.line[len(s.line)-2]
1354                         }
1355                         return v
1356                 case CTNIL:
1357                         t := n.Type
1358                         switch {
1359                         case t.IsSlice():
1360                                 return s.entryNewValue0(ssa.OpConstSlice, t)
1361                         case t.IsInterface():
1362                                 return s.entryNewValue0(ssa.OpConstInterface, t)
1363                         default:
1364                                 return s.entryNewValue0(ssa.OpConstNil, t)
1365                         }
1366                 case CTFLT:
1367                         f := n.Val().U.(*Mpflt)
1368                         switch n.Type.Size() {
1369                         case 4:
1370                                 return s.constFloat32(n.Type, mpgetflt32(f))
1371                         case 8:
1372                                 return s.constFloat64(n.Type, mpgetflt(f))
1373                         default:
1374                                 s.Fatalf("bad float size %d", n.Type.Size())
1375                                 return nil
1376                         }
1377                 case CTCPLX:
1378                         c := n.Val().U.(*Mpcplx)
1379                         r := &c.Real
1380                         i := &c.Imag
1381                         switch n.Type.Size() {
1382                         case 8:
1383                                 {
1384                                         pt := Types[TFLOAT32]
1385                                         return s.newValue2(ssa.OpComplexMake, n.Type,
1386                                                 s.constFloat32(pt, mpgetflt32(r)),
1387                                                 s.constFloat32(pt, mpgetflt32(i)))
1388                                 }
1389                         case 16:
1390                                 {
1391                                         pt := Types[TFLOAT64]
1392                                         return s.newValue2(ssa.OpComplexMake, n.Type,
1393                                                 s.constFloat64(pt, mpgetflt(r)),
1394                                                 s.constFloat64(pt, mpgetflt(i)))
1395                                 }
1396                         default:
1397                                 s.Fatalf("bad float size %d", n.Type.Size())
1398                                 return nil
1399                         }
1400
1401                 default:
1402                         s.Unimplementedf("unhandled OLITERAL %v", n.Val().Ctype())
1403                         return nil
1404                 }
1405         case OCONVNOP:
1406                 to := n.Type
1407                 from := n.Left.Type
1408
1409                 // Assume everything will work out, so set up our return value.
1410                 // Anything interesting that happens from here is a fatal.
1411                 x := s.expr(n.Left)
1412
1413                 // Special case for not confusing GC and liveness.
1414                 // We don't want pointers accidentally classified
1415                 // as not-pointers or vice-versa because of copy
1416                 // elision.
1417                 if to.IsPtr() != from.IsPtr() {
1418                         return s.newValue2(ssa.OpConvert, to, x, s.mem())
1419                 }
1420
1421                 v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type
1422
1423                 // CONVNOP closure
1424                 if to.Etype == TFUNC && from.IsPtr() {
1425                         return v
1426                 }
1427
1428                 // named <--> unnamed type or typed <--> untyped const
1429                 if from.Etype == to.Etype {
1430                         return v
1431                 }
1432
1433                 // unsafe.Pointer <--> *T
1434                 if to.Etype == TUNSAFEPTR && from.IsPtr() || from.Etype == TUNSAFEPTR && to.IsPtr() {
1435                         return v
1436                 }
1437
1438                 dowidth(from)
1439                 dowidth(to)
1440                 if from.Width != to.Width {
1441                         s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
1442                         return nil
1443                 }
1444                 if etypesign(from.Etype) != etypesign(to.Etype) {
1445                         s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, Econv(from.Etype), to, Econv(to.Etype))
1446                         return nil
1447                 }
1448
1449                 if flag_race != 0 {
1450                         // These appear to be fine, but they fail the
1451                         // integer constraint below, so okay them here.
1452                         // Sample non-integer conversion: map[string]string -> *uint8
1453                         return v
1454                 }
1455
1456                 if etypesign(from.Etype) == 0 {
1457                         s.Fatalf("CONVNOP unrecognized non-integer %v -> %v\n", from, to)
1458                         return nil
1459                 }
1460
1461                 // integer, same width, same sign
1462                 return v
1463
1464         case OCONV:
1465                 x := s.expr(n.Left)
1466                 ft := n.Left.Type // from type
1467                 tt := n.Type      // to type
1468                 if ft.IsInteger() && tt.IsInteger() {
1469                         var op ssa.Op
1470                         if tt.Size() == ft.Size() {
1471                                 op = ssa.OpCopy
1472                         } else if tt.Size() < ft.Size() {
1473                                 // truncation
1474                                 switch 10*ft.Size() + tt.Size() {
1475                                 case 21:
1476                                         op = ssa.OpTrunc16to8
1477                                 case 41:
1478                                         op = ssa.OpTrunc32to8
1479                                 case 42:
1480                                         op = ssa.OpTrunc32to16
1481                                 case 81:
1482                                         op = ssa.OpTrunc64to8
1483                                 case 82:
1484                                         op = ssa.OpTrunc64to16
1485                                 case 84:
1486                                         op = ssa.OpTrunc64to32
1487                                 default:
1488                                         s.Fatalf("weird integer truncation %s -> %s", ft, tt)
1489                                 }
1490                         } else if ft.IsSigned() {
1491                                 // sign extension
1492                                 switch 10*ft.Size() + tt.Size() {
1493                                 case 12:
1494                                         op = ssa.OpSignExt8to16
1495                                 case 14:
1496                                         op = ssa.OpSignExt8to32
1497                                 case 18:
1498                                         op = ssa.OpSignExt8to64
1499                                 case 24:
1500                                         op = ssa.OpSignExt16to32
1501                                 case 28:
1502                                         op = ssa.OpSignExt16to64
1503                                 case 48:
1504                                         op = ssa.OpSignExt32to64
1505                                 default:
1506                                         s.Fatalf("bad integer sign extension %s -> %s", ft, tt)
1507                                 }
1508                         } else {
1509                                 // zero extension
1510                                 switch 10*ft.Size() + tt.Size() {
1511                                 case 12:
1512                                         op = ssa.OpZeroExt8to16
1513                                 case 14:
1514                                         op = ssa.OpZeroExt8to32
1515                                 case 18:
1516                                         op = ssa.OpZeroExt8to64
1517                                 case 24:
1518                                         op = ssa.OpZeroExt16to32
1519                                 case 28:
1520                                         op = ssa.OpZeroExt16to64
1521                                 case 48:
1522                                         op = ssa.OpZeroExt32to64
1523                                 default:
1524                                         s.Fatalf("weird integer sign extension %s -> %s", ft, tt)
1525                                 }
1526                         }
1527                         return s.newValue1(op, n.Type, x)
1528                 }
1529
1530                 if ft.IsFloat() || tt.IsFloat() {
1531                         conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
1532                         if !ok {
1533                                 s.Fatalf("weird float conversion %s -> %s", ft, tt)
1534                         }
1535                         op1, op2, it := conv.op1, conv.op2, conv.intermediateType
1536
1537                         if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid {
1538                                 // normal case, not tripping over unsigned 64
1539                                 if op1 == ssa.OpCopy {
1540                                         if op2 == ssa.OpCopy {
1541                                                 return x
1542                                         }
1543                                         return s.newValue1(op2, n.Type, x)
1544                                 }
1545                                 if op2 == ssa.OpCopy {
1546                                         return s.newValue1(op1, n.Type, x)
1547                                 }
1548                                 return s.newValue1(op2, n.Type, s.newValue1(op1, Types[it], x))
1549                         }
1550                         // Tricky 64-bit unsigned cases.
1551                         if ft.IsInteger() {
1552                                 // therefore tt is float32 or float64, and ft is also unsigned
1553                                 if tt.Size() == 4 {
1554                                         return s.uint64Tofloat32(n, x, ft, tt)
1555                                 }
1556                                 if tt.Size() == 8 {
1557                                         return s.uint64Tofloat64(n, x, ft, tt)
1558                                 }
1559                                 s.Fatalf("weird unsigned integer to float conversion %s -> %s", ft, tt)
1560                         }
1561                         // therefore ft is float32 or float64, and tt is unsigned integer
1562                         if ft.Size() == 4 {
1563                                 return s.float32ToUint64(n, x, ft, tt)
1564                         }
1565                         if ft.Size() == 8 {
1566                                 return s.float64ToUint64(n, x, ft, tt)
1567                         }
1568                         s.Fatalf("weird float to unsigned integer conversion %s -> %s", ft, tt)
1569                         return nil
1570                 }
1571
1572                 if ft.IsComplex() && tt.IsComplex() {
1573                         var op ssa.Op
1574                         if ft.Size() == tt.Size() {
1575                                 op = ssa.OpCopy
1576                         } else if ft.Size() == 8 && tt.Size() == 16 {
1577                                 op = ssa.OpCvt32Fto64F
1578                         } else if ft.Size() == 16 && tt.Size() == 8 {
1579                                 op = ssa.OpCvt64Fto32F
1580                         } else {
1581                                 s.Fatalf("weird complex conversion %s -> %s", ft, tt)
1582                         }
1583                         ftp := floatForComplex(ft)
1584                         ttp := floatForComplex(tt)
1585                         return s.newValue2(ssa.OpComplexMake, tt,
1586                                 s.newValue1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, x)),
1587                                 s.newValue1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x)))
1588                 }
1589
1590                 s.Unimplementedf("unhandled OCONV %s -> %s", Econv(n.Left.Type.Etype), Econv(n.Type.Etype))
1591                 return nil
1592
1593         case ODOTTYPE:
1594                 res, _ := s.dottype(n, false)
1595                 return res
1596
1597         // binary ops
1598         case OLT, OEQ, ONE, OLE, OGE, OGT:
1599                 a := s.expr(n.Left)
1600                 b := s.expr(n.Right)
1601                 if n.Left.Type.IsComplex() {
1602                         pt := floatForComplex(n.Left.Type)
1603                         op := s.ssaOp(OEQ, pt)
1604                         r := s.newValue2(op, Types[TBOOL], s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b))
1605                         i := s.newValue2(op, Types[TBOOL], s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b))
1606                         c := s.newValue2(ssa.OpAnd8, Types[TBOOL], r, i)
1607                         switch n.Op {
1608                         case OEQ:
1609                                 return c
1610                         case ONE:
1611                                 return s.newValue1(ssa.OpNot, Types[TBOOL], c)
1612                         default:
1613                                 s.Fatalf("ordered complex compare %s", opnames[n.Op])
1614                         }
1615                 }
1616                 return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b)
1617         case OMUL:
1618                 a := s.expr(n.Left)
1619                 b := s.expr(n.Right)
1620                 if n.Type.IsComplex() {
1621                         mulop := ssa.OpMul64F
1622                         addop := ssa.OpAdd64F
1623                         subop := ssa.OpSub64F
1624                         pt := floatForComplex(n.Type) // Could be Float32 or Float64
1625                         wt := Types[TFLOAT64]         // Compute in Float64 to minimize cancellation error
1626
1627                         areal := s.newValue1(ssa.OpComplexReal, pt, a)
1628                         breal := s.newValue1(ssa.OpComplexReal, pt, b)
1629                         aimag := s.newValue1(ssa.OpComplexImag, pt, a)
1630                         bimag := s.newValue1(ssa.OpComplexImag, pt, b)
1631
1632                         if pt != wt { // Widen for calculation
1633                                 areal = s.newValue1(ssa.OpCvt32Fto64F, wt, areal)
1634                                 breal = s.newValue1(ssa.OpCvt32Fto64F, wt, breal)
1635                                 aimag = s.newValue1(ssa.OpCvt32Fto64F, wt, aimag)
1636                                 bimag = s.newValue1(ssa.OpCvt32Fto64F, wt, bimag)
1637                         }
1638
1639                         xreal := s.newValue2(subop, wt, s.newValue2(mulop, wt, areal, breal), s.newValue2(mulop, wt, aimag, bimag))
1640                         ximag := s.newValue2(addop, wt, s.newValue2(mulop, wt, areal, bimag), s.newValue2(mulop, wt, aimag, breal))
1641
1642                         if pt != wt { // Narrow to store back
1643                                 xreal = s.newValue1(ssa.OpCvt64Fto32F, pt, xreal)
1644                                 ximag = s.newValue1(ssa.OpCvt64Fto32F, pt, ximag)
1645                         }
1646
1647                         return s.newValue2(ssa.OpComplexMake, n.Type, xreal, ximag)
1648                 }
1649                 return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1650
1651         case ODIV:
1652                 a := s.expr(n.Left)
1653                 b := s.expr(n.Right)
1654                 if n.Type.IsComplex() {
1655                         // TODO this is not executed because the front-end substitutes a runtime call.
1656                         // That probably ought to change; with modest optimization the widen/narrow
1657                         // conversions could all be elided in larger expression trees.
1658                         mulop := ssa.OpMul64F
1659                         addop := ssa.OpAdd64F
1660                         subop := ssa.OpSub64F
1661                         divop := ssa.OpDiv64F
1662                         pt := floatForComplex(n.Type) // Could be Float32 or Float64
1663                         wt := Types[TFLOAT64]         // Compute in Float64 to minimize cancellation error
1664
1665                         areal := s.newValue1(ssa.OpComplexReal, pt, a)
1666                         breal := s.newValue1(ssa.OpComplexReal, pt, b)
1667                         aimag := s.newValue1(ssa.OpComplexImag, pt, a)
1668                         bimag := s.newValue1(ssa.OpComplexImag, pt, b)
1669
1670                         if pt != wt { // Widen for calculation
1671                                 areal = s.newValue1(ssa.OpCvt32Fto64F, wt, areal)
1672                                 breal = s.newValue1(ssa.OpCvt32Fto64F, wt, breal)
1673                                 aimag = s.newValue1(ssa.OpCvt32Fto64F, wt, aimag)
1674                                 bimag = s.newValue1(ssa.OpCvt32Fto64F, wt, bimag)
1675                         }
1676
1677                         denom := s.newValue2(addop, wt, s.newValue2(mulop, wt, breal, breal), s.newValue2(mulop, wt, bimag, bimag))
1678                         xreal := s.newValue2(addop, wt, s.newValue2(mulop, wt, areal, breal), s.newValue2(mulop, wt, aimag, bimag))
1679                         ximag := s.newValue2(subop, wt, s.newValue2(mulop, wt, aimag, breal), s.newValue2(mulop, wt, areal, bimag))
1680
1681                         // TODO not sure if this is best done in wide precision or narrow
1682                         // Double-rounding might be an issue.
1683                         // Note that the pre-SSA implementation does the entire calculation
1684                         // in wide format, so wide is compatible.
1685                         xreal = s.newValue2(divop, wt, xreal, denom)
1686                         ximag = s.newValue2(divop, wt, ximag, denom)
1687
1688                         if pt != wt { // Narrow to store back
1689                                 xreal = s.newValue1(ssa.OpCvt64Fto32F, pt, xreal)
1690                                 ximag = s.newValue1(ssa.OpCvt64Fto32F, pt, ximag)
1691                         }
1692                         return s.newValue2(ssa.OpComplexMake, n.Type, xreal, ximag)
1693                 }
1694                 if n.Type.IsFloat() {
1695                         return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1696                 } else {
1697                         // do a size-appropriate check for zero
1698                         cmp := s.newValue2(s.ssaOp(ONE, n.Type), Types[TBOOL], b, s.zeroVal(n.Type))
1699                         s.check(cmp, panicdivide)
1700                         return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1701                 }
1702         case OMOD:
1703                 a := s.expr(n.Left)
1704                 b := s.expr(n.Right)
1705                 // do a size-appropriate check for zero
1706                 cmp := s.newValue2(s.ssaOp(ONE, n.Type), Types[TBOOL], b, s.zeroVal(n.Type))
1707                 s.check(cmp, panicdivide)
1708                 return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1709         case OADD, OSUB:
1710                 a := s.expr(n.Left)
1711                 b := s.expr(n.Right)
1712                 if n.Type.IsComplex() {
1713                         pt := floatForComplex(n.Type)
1714                         op := s.ssaOp(n.Op, pt)
1715                         return s.newValue2(ssa.OpComplexMake, n.Type,
1716                                 s.newValue2(op, pt, s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)),
1717                                 s.newValue2(op, pt, s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b)))
1718                 }
1719                 return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1720         case OAND, OOR, OHMUL, OXOR:
1721                 a := s.expr(n.Left)
1722                 b := s.expr(n.Right)
1723                 return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
1724         case OLSH, ORSH:
1725                 a := s.expr(n.Left)
1726                 b := s.expr(n.Right)
1727                 return s.newValue2(s.ssaShiftOp(n.Op, n.Type, n.Right.Type), a.Type, a, b)
1728         case OLROT:
1729                 a := s.expr(n.Left)
1730                 i := n.Right.Int()
1731                 if i <= 0 || i >= n.Type.Size()*8 {
1732                         s.Fatalf("Wrong rotate distance for LROT, expected 1 through %d, saw %d", n.Type.Size()*8-1, i)
1733                 }
1734                 return s.newValue1I(s.ssaRotateOp(n.Op, n.Type), a.Type, i, a)
1735         case OANDAND, OOROR:
1736                 // To implement OANDAND (and OOROR), we introduce a
1737                 // new temporary variable to hold the result. The
1738                 // variable is associated with the OANDAND node in the
1739                 // s.vars table (normally variables are only
1740                 // associated with ONAME nodes). We convert
1741                 //     A && B
1742                 // to
1743                 //     var = A
1744                 //     if var {
1745                 //         var = B
1746                 //     }
1747                 // Using var in the subsequent block introduces the
1748                 // necessary phi variable.
1749                 el := s.expr(n.Left)
1750                 s.vars[n] = el
1751
1752                 b := s.endBlock()
1753                 b.Kind = ssa.BlockIf
1754                 b.Control = el
1755                 // In theory, we should set b.Likely here based on context.
1756                 // However, gc only gives us likeliness hints
1757                 // in a single place, for plain OIF statements,
1758                 // and passing around context is finnicky, so don't bother for now.
1759
1760                 bRight := s.f.NewBlock(ssa.BlockPlain)
1761                 bResult := s.f.NewBlock(ssa.BlockPlain)
1762                 if n.Op == OANDAND {
1763                         b.AddEdgeTo(bRight)
1764                         b.AddEdgeTo(bResult)
1765                 } else if n.Op == OOROR {
1766                         b.AddEdgeTo(bResult)
1767                         b.AddEdgeTo(bRight)
1768                 }
1769
1770                 s.startBlock(bRight)
1771                 er := s.expr(n.Right)
1772                 s.vars[n] = er
1773
1774                 b = s.endBlock()
1775                 b.AddEdgeTo(bResult)
1776
1777                 s.startBlock(bResult)
1778                 return s.variable(n, Types[TBOOL])
1779         case OCOMPLEX:
1780                 r := s.expr(n.Left)
1781                 i := s.expr(n.Right)
1782                 return s.newValue2(ssa.OpComplexMake, n.Type, r, i)
1783
1784         // unary ops
1785         case OMINUS:
1786                 a := s.expr(n.Left)
1787                 if n.Type.IsComplex() {
1788                         tp := floatForComplex(n.Type)
1789                         negop := s.ssaOp(n.Op, tp)
1790                         return s.newValue2(ssa.OpComplexMake, n.Type,
1791                                 s.newValue1(negop, tp, s.newValue1(ssa.OpComplexReal, tp, a)),
1792                                 s.newValue1(negop, tp, s.newValue1(ssa.OpComplexImag, tp, a)))
1793                 }
1794                 return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a)
1795         case ONOT, OCOM, OSQRT:
1796                 a := s.expr(n.Left)
1797                 return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a)
1798         case OIMAG, OREAL:
1799                 a := s.expr(n.Left)
1800                 return s.newValue1(s.ssaOp(n.Op, n.Left.Type), n.Type, a)
1801         case OPLUS:
1802                 return s.expr(n.Left)
1803
1804         case OADDR:
1805                 return s.addr(n.Left, n.Bounded)
1806
1807         case OINDREG:
1808                 if int(n.Reg) != Thearch.REGSP {
1809                         s.Unimplementedf("OINDREG of non-SP register %s in expr: %v", obj.Rconv(int(n.Reg)), n)
1810                         return nil
1811                 }
1812                 addr := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(n.Type), n.Xoffset, s.sp)
1813                 return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
1814
1815         case OIND:
1816                 p := s.expr(n.Left)
1817                 s.nilCheck(p)
1818                 return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
1819
1820         case ODOT:
1821                 t := n.Left.Type
1822                 if canSSAType(t) {
1823                         v := s.expr(n.Left)
1824                         return s.newValue1I(ssa.OpStructSelect, n.Type, fieldIdx(n), v)
1825                 }
1826                 p := s.addr(n, false)
1827                 return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
1828
1829         case ODOTPTR:
1830                 p := s.expr(n.Left)
1831                 s.nilCheck(p)
1832                 p = s.newValue2(ssa.OpAddPtr, p.Type, p, s.constInt(Types[TINT], n.Xoffset))
1833                 return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
1834
1835         case OINDEX:
1836                 switch {
1837                 case n.Left.Type.IsString():
1838                         a := s.expr(n.Left)
1839                         i := s.expr(n.Right)
1840                         i = s.extendIndex(i)
1841                         if !n.Bounded {
1842                                 len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
1843                                 s.boundsCheck(i, len)
1844                         }
1845                         ptrtyp := Ptrto(Types[TUINT8])
1846                         ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
1847                         ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
1848                         return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
1849                 case n.Left.Type.IsSlice():
1850                         p := s.addr(n, false)
1851                         return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
1852                 case n.Left.Type.IsArray():
1853                         // TODO: fix when we can SSA arrays of length 1.
1854                         p := s.addr(n, false)
1855                         return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
1856                 default:
1857                         s.Fatalf("bad type for index %v", n.Left.Type)
1858                         return nil
1859                 }
1860
1861         case OLEN, OCAP:
1862                 switch {
1863                 case n.Left.Type.IsSlice():
1864                         op := ssa.OpSliceLen
1865                         if n.Op == OCAP {
1866                                 op = ssa.OpSliceCap
1867                         }
1868                         return s.newValue1(op, Types[TINT], s.expr(n.Left))
1869                 case n.Left.Type.IsString(): // string; not reachable for OCAP
1870                         return s.newValue1(ssa.OpStringLen, Types[TINT], s.expr(n.Left))
1871                 case n.Left.Type.IsMap(), n.Left.Type.IsChan():
1872                         return s.referenceTypeBuiltin(n, s.expr(n.Left))
1873                 default: // array
1874                         return s.constInt(Types[TINT], n.Left.Type.Bound)
1875                 }
1876
1877         case OSPTR:
1878                 a := s.expr(n.Left)
1879                 if n.Left.Type.IsSlice() {
1880                         return s.newValue1(ssa.OpSlicePtr, n.Type, a)
1881                 } else {
1882                         return s.newValue1(ssa.OpStringPtr, n.Type, a)
1883                 }
1884
1885         case OITAB:
1886                 a := s.expr(n.Left)
1887                 return s.newValue1(ssa.OpITab, n.Type, a)
1888
1889         case OEFACE:
1890                 tab := s.expr(n.Left)
1891                 data := s.expr(n.Right)
1892                 // The frontend allows putting things like struct{*byte} in
1893                 // the data portion of an eface.  But we don't want struct{*byte}
1894                 // as a register type because (among other reasons) the liveness
1895                 // analysis is confused by the "fat" variables that result from
1896                 // such types being spilled.
1897                 // So here we ensure that we are selecting the underlying pointer
1898                 // when we build an eface.
1899                 // TODO: get rid of this now that structs can be SSA'd?
1900                 for !data.Type.IsPtr() {
1901                         switch {
1902                         case data.Type.IsArray():
1903                                 data = s.newValue2(ssa.OpArrayIndex, data.Type.Elem(), data, s.constInt(Types[TINT], 0))
1904                         case data.Type.IsStruct():
1905                                 for i := data.Type.NumFields() - 1; i >= 0; i-- {
1906                                         f := data.Type.FieldType(i)
1907                                         if f.Size() == 0 {
1908                                                 // eface type could also be struct{p *byte; q [0]int}
1909                                                 continue
1910                                         }
1911                                         data = s.newValue1I(ssa.OpStructSelect, f, i, data)
1912                                         break
1913                                 }
1914                         default:
1915                                 s.Fatalf("type being put into an eface isn't a pointer")
1916                         }
1917                 }
1918                 return s.newValue2(ssa.OpIMake, n.Type, tab, data)
1919
1920         case OSLICE, OSLICEARR:
1921                 v := s.expr(n.Left)
1922                 var i, j *ssa.Value
1923                 if n.Right.Left != nil {
1924                         i = s.extendIndex(s.expr(n.Right.Left))
1925                 }
1926                 if n.Right.Right != nil {
1927                         j = s.extendIndex(s.expr(n.Right.Right))
1928                 }
1929                 p, l, c := s.slice(n.Left.Type, v, i, j, nil)
1930                 return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
1931         case OSLICESTR:
1932                 v := s.expr(n.Left)
1933                 var i, j *ssa.Value
1934                 if n.Right.Left != nil {
1935                         i = s.extendIndex(s.expr(n.Right.Left))
1936                 }
1937                 if n.Right.Right != nil {
1938                         j = s.extendIndex(s.expr(n.Right.Right))
1939                 }
1940                 p, l, _ := s.slice(n.Left.Type, v, i, j, nil)
1941                 return s.newValue2(ssa.OpStringMake, n.Type, p, l)
1942         case OSLICE3, OSLICE3ARR:
1943                 v := s.expr(n.Left)
1944                 var i *ssa.Value
1945                 if n.Right.Left != nil {
1946                         i = s.extendIndex(s.expr(n.Right.Left))
1947                 }
1948                 j := s.extendIndex(s.expr(n.Right.Right.Left))
1949                 k := s.extendIndex(s.expr(n.Right.Right.Right))
1950                 p, l, c := s.slice(n.Left.Type, v, i, j, k)
1951                 return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
1952
1953         case OCALLFUNC, OCALLINTER, OCALLMETH:
1954                 a := s.call(n, callNormal)
1955                 return s.newValue2(ssa.OpLoad, n.Type, a, s.mem())
1956
1957         case OGETG:
1958                 return s.newValue1(ssa.OpGetG, n.Type, s.mem())
1959
1960         case OAPPEND:
1961                 // append(s, e1, e2, e3).  Compile like:
1962                 // ptr,len,cap := s
1963                 // newlen := len + 3
1964                 // if newlen > s.cap {
1965                 //     ptr,_,cap = growslice(s, newlen)
1966                 // }
1967                 // *(ptr+len) = e1
1968                 // *(ptr+len+1) = e2
1969                 // *(ptr+len+2) = e3
1970                 // makeslice(ptr,newlen,cap)
1971
1972                 et := n.Type.Type
1973                 pt := Ptrto(et)
1974
1975                 // Evaluate slice
1976                 slice := s.expr(n.List.N)
1977
1978                 // Allocate new blocks
1979                 grow := s.f.NewBlock(ssa.BlockPlain)
1980                 assign := s.f.NewBlock(ssa.BlockPlain)
1981
1982                 // Decide if we need to grow
1983                 nargs := int64(count(n.List) - 1)
1984                 p := s.newValue1(ssa.OpSlicePtr, pt, slice)
1985                 l := s.newValue1(ssa.OpSliceLen, Types[TINT], slice)
1986                 c := s.newValue1(ssa.OpSliceCap, Types[TINT], slice)
1987                 nl := s.newValue2(s.ssaOp(OADD, Types[TINT]), Types[TINT], l, s.constInt(Types[TINT], nargs))
1988                 cmp := s.newValue2(s.ssaOp(OGT, Types[TINT]), Types[TBOOL], nl, c)
1989                 s.vars[&ptrVar] = p
1990                 s.vars[&capVar] = c
1991                 b := s.endBlock()
1992                 b.Kind = ssa.BlockIf
1993                 b.Likely = ssa.BranchUnlikely
1994                 b.Control = cmp
1995                 b.AddEdgeTo(grow)
1996                 b.AddEdgeTo(assign)
1997
1998                 // Call growslice
1999                 s.startBlock(grow)
2000                 taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(n.Type)}, s.sb)
2001
2002                 r := s.rtcall(growslice, true, []*Type{pt, Types[TINT], Types[TINT]}, taddr, p, l, c, nl)
2003
2004                 s.vars[&ptrVar] = r[0]
2005                 // Note: we don't need to read r[1], the result's length.  It will be nl.
2006                 // (or maybe we should, we just have to spill/restore nl otherwise?)
2007                 s.vars[&capVar] = r[2]
2008                 b = s.endBlock()
2009                 b.AddEdgeTo(assign)
2010
2011                 // assign new elements to slots
2012                 s.startBlock(assign)
2013
2014                 // Evaluate args
2015                 args := make([]*ssa.Value, 0, nargs)
2016                 store := make([]bool, 0, nargs)
2017                 for l := n.List.Next; l != nil; l = l.Next {
2018                         if canSSAType(l.N.Type) {
2019                                 args = append(args, s.expr(l.N))
2020                                 store = append(store, true)
2021                         } else {
2022                                 args = append(args, s.addr(l.N, false))
2023                                 store = append(store, false)
2024                         }
2025                 }
2026
2027                 p = s.variable(&ptrVar, pt)          // generates phi for ptr
2028                 c = s.variable(&capVar, Types[TINT]) // generates phi for cap
2029                 p2 := s.newValue2(ssa.OpPtrIndex, pt, p, l)
2030                 // TODO: just one write barrier call for all of these writes?
2031                 // TODO: maybe just one writeBarrier.enabled check?
2032                 for i, arg := range args {
2033                         addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(Types[TINT], int64(i)))
2034                         if store[i] {
2035                                 if haspointers(et) {
2036                                         s.insertWBstore(et, addr, arg, n.Lineno)
2037                                 } else {
2038                                         s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg, s.mem())
2039                                 }
2040                         } else {
2041                                 if haspointers(et) {
2042                                         s.insertWBmove(et, addr, arg, n.Lineno)
2043                                 } else {
2044                                         s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, et.Size(), addr, arg, s.mem())
2045                                 }
2046                         }
2047                 }
2048
2049                 // make result
2050                 delete(s.vars, &ptrVar)
2051                 delete(s.vars, &capVar)
2052                 return s.newValue3(ssa.OpSliceMake, n.Type, p, nl, c)
2053
2054         default:
2055                 s.Unimplementedf("unhandled expr %s", opnames[n.Op])
2056                 return nil
2057         }
2058 }
2059
2060 // condBranch evaluates the boolean expression cond and branches to yes
2061 // if cond is true and no if cond is false.
2062 // This function is intended to handle && and || better than just calling
2063 // s.expr(cond) and branching on the result.
2064 func (s *state) condBranch(cond *Node, yes, no *ssa.Block, likely int8) {
2065         if cond.Op == OANDAND {
2066                 mid := s.f.NewBlock(ssa.BlockPlain)
2067                 s.stmtList(cond.Ninit)
2068                 s.condBranch(cond.Left, mid, no, max8(likely, 0))
2069                 s.startBlock(mid)
2070                 s.condBranch(cond.Right, yes, no, likely)
2071                 return
2072                 // Note: if likely==1, then both recursive calls pass 1.
2073                 // If likely==-1, then we don't have enough information to decide
2074                 // whether the first branch is likely or not.  So we pass 0 for
2075                 // the likeliness of the first branch.
2076                 // TODO: have the frontend give us branch prediction hints for
2077                 // OANDAND and OOROR nodes (if it ever has such info).
2078         }
2079         if cond.Op == OOROR {
2080                 mid := s.f.NewBlock(ssa.BlockPlain)
2081                 s.stmtList(cond.Ninit)
2082                 s.condBranch(cond.Left, yes, mid, min8(likely, 0))
2083                 s.startBlock(mid)
2084                 s.condBranch(cond.Right, yes, no, likely)
2085                 return
2086                 // Note: if likely==-1, then both recursive calls pass -1.
2087                 // If likely==1, then we don't have enough info to decide
2088                 // the likelihood of the first branch.
2089         }
2090         if cond.Op == ONOT {
2091                 s.stmtList(cond.Ninit)
2092                 s.condBranch(cond.Left, no, yes, -likely)
2093                 return
2094         }
2095         c := s.expr(cond)
2096         b := s.endBlock()
2097         b.Kind = ssa.BlockIf
2098         b.Control = c
2099         b.Likely = ssa.BranchPrediction(likely) // gc and ssa both use -1/0/+1 for likeliness
2100         b.AddEdgeTo(yes)
2101         b.AddEdgeTo(no)
2102 }
2103
2104 // assign does left = right.
2105 // Right has already been evaluated to ssa, left has not.
2106 // If deref is true, then we do left = *right instead (and right has already been nil-checked).
2107 // If deref is true and right == nil, just do left = 0.
2108 // Include a write barrier if wb is true.
2109 func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32) {
2110         if left.Op == ONAME && isblank(left) {
2111                 return
2112         }
2113         t := left.Type
2114         dowidth(t)
2115         if canSSA(left) {
2116                 if deref {
2117                         s.Fatalf("can SSA LHS %s but not RHS %s", left, right)
2118                 }
2119                 if left.Op == ODOT {
2120                         // We're assigning to a field of an ssa-able value.
2121                         // We need to build a new structure with the new value for the
2122                         // field we're assigning and the old values for the other fields.
2123                         // For instance:
2124                         //   type T struct {a, b, c int}
2125                         //   var T x
2126                         //   x.b = 5
2127                         // For the x.b = 5 assignment we want to generate x = T{x.a, 5, x.c}
2128
2129                         // Grab information about the structure type.
2130                         t := left.Left.Type
2131                         nf := t.NumFields()
2132                         idx := fieldIdx(left)
2133
2134                         // Grab old value of structure.
2135                         old := s.expr(left.Left)
2136
2137                         // Make new structure.
2138                         new := s.newValue0(ssa.StructMakeOp(t.NumFields()), t)
2139
2140                         // Add fields as args.
2141                         for i := int64(0); i < nf; i++ {
2142                                 if i == idx {
2143                                         new.AddArg(right)
2144                                 } else {
2145                                         new.AddArg(s.newValue1I(ssa.OpStructSelect, t.FieldType(i), i, old))
2146                                 }
2147                         }
2148
2149                         // Recursively assign the new value we've made to the base of the dot op.
2150                         s.assign(left.Left, new, false, false, line)
2151                         // TODO: do we need to update named values here?
2152                         return
2153                 }
2154                 // Update variable assignment.
2155                 s.vars[left] = right
2156                 s.addNamedValue(left, right)
2157                 return
2158         }
2159         // Left is not ssa-able.  Compute its address.
2160         addr := s.addr(left, false)
2161         if left.Op == ONAME {
2162                 s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem())
2163         }
2164         if deref {
2165                 // Treat as a mem->mem move.
2166                 if right == nil {
2167                         s.vars[&memVar] = s.newValue2I(ssa.OpZero, ssa.TypeMem, t.Size(), addr, s.mem())
2168                         return
2169                 }
2170                 if wb {
2171                         s.insertWBmove(t, addr, right, line)
2172                         return
2173                 }
2174                 s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, t.Size(), addr, right, s.mem())
2175                 return
2176         }
2177         // Treat as a store.
2178         if wb {
2179                 s.insertWBstore(t, addr, right, line)
2180                 return
2181         }
2182         s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem())
2183 }
2184
2185 // zeroVal returns the zero value for type t.
2186 func (s *state) zeroVal(t *Type) *ssa.Value {
2187         switch {
2188         case t.IsInteger():
2189                 switch t.Size() {
2190                 case 1:
2191                         return s.constInt8(t, 0)
2192                 case 2:
2193                         return s.constInt16(t, 0)
2194                 case 4:
2195                         return s.constInt32(t, 0)
2196                 case 8:
2197                         return s.constInt64(t, 0)
2198                 default:
2199                         s.Fatalf("bad sized integer type %s", t)
2200                 }
2201         case t.IsFloat():
2202                 switch t.Size() {
2203                 case 4:
2204                         return s.constFloat32(t, 0)
2205                 case 8:
2206                         return s.constFloat64(t, 0)
2207                 default:
2208                         s.Fatalf("bad sized float type %s", t)
2209                 }
2210         case t.IsComplex():
2211                 switch t.Size() {
2212                 case 8:
2213                         z := s.constFloat32(Types[TFLOAT32], 0)
2214                         return s.entryNewValue2(ssa.OpComplexMake, t, z, z)
2215                 case 16:
2216                         z := s.constFloat64(Types[TFLOAT64], 0)
2217                         return s.entryNewValue2(ssa.OpComplexMake, t, z, z)
2218                 default:
2219                         s.Fatalf("bad sized complex type %s", t)
2220                 }
2221
2222         case t.IsString():
2223                 return s.entryNewValue0A(ssa.OpConstString, t, "")
2224         case t.IsPtr():
2225                 return s.entryNewValue0(ssa.OpConstNil, t)
2226         case t.IsBoolean():
2227                 return s.constBool(false)
2228         case t.IsInterface():
2229                 return s.entryNewValue0(ssa.OpConstInterface, t)
2230         case t.IsSlice():
2231                 return s.entryNewValue0(ssa.OpConstSlice, t)
2232         case t.IsStruct():
2233                 n := t.NumFields()
2234                 v := s.entryNewValue0(ssa.StructMakeOp(t.NumFields()), t)
2235                 for i := int64(0); i < n; i++ {
2236                         v.AddArg(s.zeroVal(t.FieldType(i).(*Type)))
2237                 }
2238                 return v
2239         }
2240         s.Unimplementedf("zero for type %v not implemented", t)
2241         return nil
2242 }
2243
2244 type callKind int8
2245
2246 const (
2247         callNormal callKind = iota
2248         callDefer
2249         callGo
2250 )
2251
2252 // Calls the function n using the specified call type.
2253 // Returns the address of the return value (or nil if none).
2254 func (s *state) call(n *Node, k callKind) *ssa.Value {
2255         var sym *Sym           // target symbol (if static)
2256         var closure *ssa.Value // ptr to closure to run (if dynamic)
2257         var codeptr *ssa.Value // ptr to target code (if dynamic)
2258         var rcvr *ssa.Value    // receiver to set
2259         fn := n.Left
2260         switch n.Op {
2261         case OCALLFUNC:
2262                 if k == callNormal && fn.Op == ONAME && fn.Class == PFUNC {
2263                         sym = fn.Sym
2264                         break
2265                 }
2266                 closure = s.expr(fn)
2267         case OCALLMETH:
2268                 if fn.Op != ODOTMETH {
2269                         Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn)
2270                 }
2271                 if fn.Right.Op != ONAME {
2272                         Fatalf("OCALLMETH: n.Left.Right not a ONAME: %v", fn.Right)
2273                 }
2274                 if k == callNormal {
2275                         sym = fn.Right.Sym
2276                         break
2277                 }
2278                 n2 := *fn.Right
2279                 n2.Class = PFUNC
2280                 closure = s.expr(&n2)
2281                 // Note: receiver is already assigned in n.List, so we don't
2282                 // want to set it here.
2283         case OCALLINTER:
2284                 if fn.Op != ODOTINTER {
2285                         Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", Oconv(int(fn.Op), 0))
2286                 }
2287                 i := s.expr(fn.Left)
2288                 itab := s.newValue1(ssa.OpITab, Types[TUINTPTR], i)
2289                 itabidx := fn.Xoffset + 3*int64(Widthptr) + 8 // offset of fun field in runtime.itab
2290                 itab = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], itabidx, itab)
2291                 if k == callNormal {
2292                         codeptr = s.newValue2(ssa.OpLoad, Types[TUINTPTR], itab, s.mem())
2293                 } else {
2294                         closure = itab
2295                 }
2296                 rcvr = s.newValue1(ssa.OpIData, Types[TUINTPTR], i)
2297         }
2298         dowidth(fn.Type)
2299         stksize := fn.Type.Argwid // includes receiver
2300
2301         // Run all argument assignments.  The arg slots have already
2302         // been offset by the appropriate amount (+2*widthptr for go/defer,
2303         // +widthptr for interface calls).
2304         // For OCALLMETH, the receiver is set in these statements.
2305         s.stmtList(n.List)
2306
2307         // Set receiver (for interface calls)
2308         if rcvr != nil {
2309                 argStart := Ctxt.FixedFrameSize()
2310                 if k != callNormal {
2311                         argStart += int64(2 * Widthptr)
2312                 }
2313                 addr := s.entryNewValue1I(ssa.OpOffPtr, Types[TUINTPTR], argStart, s.sp)
2314                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, rcvr, s.mem())
2315         }
2316
2317         // Defer/go args
2318         if k != callNormal {
2319                 // Write argsize and closure (args to Newproc/Deferproc).
2320                 argsize := s.constInt32(Types[TUINT32], int32(stksize))
2321                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, 4, s.sp, argsize, s.mem())
2322                 addr := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(Types[TUINTPTR]), int64(Widthptr), s.sp)
2323                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, closure, s.mem())
2324                 stksize += 2 * int64(Widthptr)
2325         }
2326
2327         // call target
2328         bNext := s.f.NewBlock(ssa.BlockPlain)
2329         var call *ssa.Value
2330         switch {
2331         case k == callDefer:
2332                 call = s.newValue1(ssa.OpDeferCall, ssa.TypeMem, s.mem())
2333         case k == callGo:
2334                 call = s.newValue1(ssa.OpGoCall, ssa.TypeMem, s.mem())
2335         case closure != nil:
2336                 codeptr = s.newValue2(ssa.OpLoad, Types[TUINTPTR], closure, s.mem())
2337                 call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, codeptr, closure, s.mem())
2338         case codeptr != nil:
2339                 call = s.newValue2(ssa.OpInterCall, ssa.TypeMem, codeptr, s.mem())
2340         case sym != nil:
2341                 call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, sym, s.mem())
2342         default:
2343                 Fatalf("bad call type %s %v", opnames[n.Op], n)
2344         }
2345         call.AuxInt = stksize // Call operations carry the argsize of the callee along with them
2346
2347         // Finish call block
2348         s.vars[&memVar] = call
2349         b := s.endBlock()
2350         b.Kind = ssa.BlockCall
2351         b.Control = call
2352         b.AddEdgeTo(bNext)
2353
2354         // Start exit block, find address of result.
2355         s.startBlock(bNext)
2356         var titer Iter
2357         fp := Structfirst(&titer, Getoutarg(n.Left.Type))
2358         if fp == nil || k != callNormal {
2359                 // call has no return value. Continue with the next statement.
2360                 return nil
2361         }
2362         return s.entryNewValue1I(ssa.OpOffPtr, Ptrto(fp.Type), fp.Width, s.sp)
2363 }
2364
2365 // etypesign returns the signed-ness of e, for integer/pointer etypes.
2366 // -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer.
2367 func etypesign(e EType) int8 {
2368         switch e {
2369         case TINT8, TINT16, TINT32, TINT64, TINT:
2370                 return -1
2371         case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR, TUNSAFEPTR:
2372                 return +1
2373         }
2374         return 0
2375 }
2376
2377 // lookupSymbol is used to retrieve the symbol (Extern, Arg or Auto) used for a particular node.
2378 // This improves the effectiveness of cse by using the same Aux values for the
2379 // same symbols.
2380 func (s *state) lookupSymbol(n *Node, sym interface{}) interface{} {
2381         switch sym.(type) {
2382         default:
2383                 s.Fatalf("sym %v is of uknown type %T", sym, sym)
2384         case *ssa.ExternSymbol, *ssa.ArgSymbol, *ssa.AutoSymbol:
2385                 // these are the only valid types
2386         }
2387
2388         if lsym, ok := s.varsyms[n]; ok {
2389                 return lsym
2390         } else {
2391                 s.varsyms[n] = sym
2392                 return sym
2393         }
2394 }
2395
2396 // addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
2397 // The value that the returned Value represents is guaranteed to be non-nil.
2398 // If bounded is true then this address does not require a nil check for its operand
2399 // even if that would otherwise be implied.
2400 func (s *state) addr(n *Node, bounded bool) *ssa.Value {
2401         t := Ptrto(n.Type)
2402         switch n.Op {
2403         case ONAME:
2404                 switch n.Class {
2405                 case PEXTERN:
2406                         // global variable
2407                         aux := s.lookupSymbol(n, &ssa.ExternSymbol{n.Type, n.Sym})
2408                         v := s.entryNewValue1A(ssa.OpAddr, t, aux, s.sb)
2409                         // TODO: Make OpAddr use AuxInt as well as Aux.
2410                         if n.Xoffset != 0 {
2411                                 v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, n.Xoffset, v)
2412                         }
2413                         return v
2414                 case PPARAM:
2415                         // parameter slot
2416                         v := s.decladdrs[n]
2417                         if v != nil {
2418                                 return v
2419                         }
2420                         if n.String() == ".fp" {
2421                                 // Special arg that points to the frame pointer.
2422                                 // (Used by the race detector, others?)
2423                                 aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
2424                                 return s.entryNewValue1A(ssa.OpAddr, t, aux, s.sp)
2425                         }
2426                         s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
2427                         return nil
2428                 case PAUTO:
2429                         // We need to regenerate the address of autos
2430                         // at every use.  This prevents LEA instructions
2431                         // from occurring before the corresponding VarDef
2432                         // op and confusing the liveness analysis into thinking
2433                         // the variable is live at function entry.
2434                         // TODO: I'm not sure if this really works or we're just
2435                         // getting lucky.  We might need a real dependency edge
2436                         // between vardef and addr ops.
2437                         aux := &ssa.AutoSymbol{Typ: n.Type, Node: n}
2438                         return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
2439                 case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
2440                         // ensure that we reuse symbols for out parameters so
2441                         // that cse works on their addresses
2442                         aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
2443                         return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
2444                 case PAUTO | PHEAP, PPARAM | PHEAP, PPARAMOUT | PHEAP, PPARAMREF:
2445                         return s.expr(n.Name.Heapaddr)
2446                 default:
2447                         s.Unimplementedf("variable address class %v not implemented", n.Class)
2448                         return nil
2449                 }
2450         case OINDREG:
2451                 // indirect off a register
2452                 // used for storing/loading arguments/returns to/from callees
2453                 if int(n.Reg) != Thearch.REGSP {
2454                         s.Unimplementedf("OINDREG of non-SP register %s in addr: %v", obj.Rconv(int(n.Reg)), n)
2455                         return nil
2456                 }
2457                 return s.entryNewValue1I(ssa.OpOffPtr, t, n.Xoffset, s.sp)
2458         case OINDEX:
2459                 if n.Left.Type.IsSlice() {
2460                         a := s.expr(n.Left)
2461                         i := s.expr(n.Right)
2462                         i = s.extendIndex(i)
2463                         len := s.newValue1(ssa.OpSliceLen, Types[TINT], a)
2464                         if !n.Bounded {
2465                                 s.boundsCheck(i, len)
2466                         }
2467                         p := s.newValue1(ssa.OpSlicePtr, t, a)
2468                         return s.newValue2(ssa.OpPtrIndex, t, p, i)
2469                 } else { // array
2470                         a := s.addr(n.Left, bounded)
2471                         i := s.expr(n.Right)
2472                         i = s.extendIndex(i)
2473                         len := s.constInt(Types[TINT], n.Left.Type.Bound)
2474                         if !n.Bounded {
2475                                 s.boundsCheck(i, len)
2476                         }
2477                         return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i)
2478                 }
2479         case OIND:
2480                 p := s.expr(n.Left)
2481                 if !bounded {
2482                         s.nilCheck(p)
2483                 }
2484                 return p
2485         case ODOT:
2486                 p := s.addr(n.Left, bounded)
2487                 return s.newValue2(ssa.OpAddPtr, t, p, s.constInt(Types[TINT], n.Xoffset))
2488         case ODOTPTR:
2489                 p := s.expr(n.Left)
2490                 if !bounded {
2491                         s.nilCheck(p)
2492                 }
2493                 return s.newValue2(ssa.OpAddPtr, t, p, s.constInt(Types[TINT], n.Xoffset))
2494         case OCLOSUREVAR:
2495                 return s.newValue2(ssa.OpAddPtr, t,
2496                         s.entryNewValue0(ssa.OpGetClosurePtr, Ptrto(Types[TUINT8])),
2497                         s.constInt(Types[TINT], n.Xoffset))
2498         case OPARAM:
2499                 p := n.Left
2500                 if p.Op != ONAME || !(p.Class == PPARAM|PHEAP || p.Class == PPARAMOUT|PHEAP) {
2501                         s.Fatalf("OPARAM not of ONAME,{PPARAM,PPARAMOUT}|PHEAP, instead %s", nodedump(p, 0))
2502                 }
2503
2504                 // Recover original offset to address passed-in param value.
2505                 original_p := *p
2506                 original_p.Xoffset = n.Xoffset
2507                 aux := &ssa.ArgSymbol{Typ: n.Type, Node: &original_p}
2508                 return s.entryNewValue1A(ssa.OpAddr, t, aux, s.sp)
2509         case OCONVNOP:
2510                 addr := s.addr(n.Left, bounded)
2511                 return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
2512         case OCALLFUNC, OCALLINTER, OCALLMETH:
2513                 return s.call(n, callNormal)
2514
2515         default:
2516                 s.Unimplementedf("unhandled addr %v", Oconv(int(n.Op), 0))
2517                 return nil
2518         }
2519 }
2520
2521 // canSSA reports whether n is SSA-able.
2522 // n must be an ONAME (or an ODOT sequence with an ONAME base).
2523 func canSSA(n *Node) bool {
2524         for n.Op == ODOT {
2525                 n = n.Left
2526         }
2527         if n.Op != ONAME {
2528                 return false
2529         }
2530         if n.Addrtaken {
2531                 return false
2532         }
2533         if n.Class&PHEAP != 0 {
2534                 return false
2535         }
2536         switch n.Class {
2537         case PEXTERN, PPARAMOUT, PPARAMREF:
2538                 return false
2539         }
2540         if n.Class == PPARAM && n.String() == ".this" {
2541                 // wrappers generated by genwrapper need to update
2542                 // the .this pointer in place.
2543                 return false
2544         }
2545         return canSSAType(n.Type)
2546         // TODO: try to make more variables SSAable?
2547 }
2548
2549 // canSSA reports whether variables of type t are SSA-able.
2550 func canSSAType(t *Type) bool {
2551         dowidth(t)
2552         if t.Width > int64(4*Widthptr) {
2553                 // 4*Widthptr is an arbitrary constant.  We want it
2554                 // to be at least 3*Widthptr so slices can be registerized.
2555                 // Too big and we'll introduce too much register pressure.
2556                 return false
2557         }
2558         switch t.Etype {
2559         case TARRAY:
2560                 if Isslice(t) {
2561                         return true
2562                 }
2563                 // We can't do arrays because dynamic indexing is
2564                 // not supported on SSA variables.
2565                 // TODO: maybe allow if length is <=1?  All indexes
2566                 // are constant?  Might be good for the arrays
2567                 // introduced by the compiler for variadic functions.
2568                 return false
2569         case TSTRUCT:
2570                 if countfield(t) > ssa.MaxStruct {
2571                         return false
2572                 }
2573                 for t1 := t.Type; t1 != nil; t1 = t1.Down {
2574                         if !canSSAType(t1.Type) {
2575                                 return false
2576                         }
2577                 }
2578                 return true
2579         default:
2580                 return true
2581         }
2582 }
2583
2584 // nilCheck generates nil pointer checking code.
2585 // Starts a new block on return, unless nil checks are disabled.
2586 // Used only for automatically inserted nil checks,
2587 // not for user code like 'x != nil'.
2588 func (s *state) nilCheck(ptr *ssa.Value) {
2589         if Disable_checknil != 0 {
2590                 return
2591         }
2592         chk := s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem())
2593         b := s.endBlock()
2594         b.Kind = ssa.BlockCheck
2595         b.Control = chk
2596         bNext := s.f.NewBlock(ssa.BlockPlain)
2597         b.AddEdgeTo(bNext)
2598         s.startBlock(bNext)
2599 }
2600
2601 // boundsCheck generates bounds checking code.  Checks if 0 <= idx < len, branches to exit if not.
2602 // Starts a new block on return.
2603 func (s *state) boundsCheck(idx, len *ssa.Value) {
2604         if Debug['B'] != 0 {
2605                 return
2606         }
2607         // TODO: convert index to full width?
2608         // TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero.
2609
2610         // bounds check
2611         cmp := s.newValue2(ssa.OpIsInBounds, Types[TBOOL], idx, len)
2612         s.check(cmp, Panicindex)
2613 }
2614
2615 // sliceBoundsCheck generates slice bounds checking code.  Checks if 0 <= idx <= len, branches to exit if not.
2616 // Starts a new block on return.
2617 func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
2618         if Debug['B'] != 0 {
2619                 return
2620         }
2621         // TODO: convert index to full width?
2622         // TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero.
2623
2624         // bounds check
2625         cmp := s.newValue2(ssa.OpIsSliceInBounds, Types[TBOOL], idx, len)
2626         s.check(cmp, panicslice)
2627 }
2628
2629 // If cmp (a bool) is true, panic using the given function.
2630 func (s *state) check(cmp *ssa.Value, fn *Node) {
2631         b := s.endBlock()
2632         b.Kind = ssa.BlockIf
2633         b.Control = cmp
2634         b.Likely = ssa.BranchLikely
2635         bNext := s.f.NewBlock(ssa.BlockPlain)
2636         line := s.peekLine()
2637         bPanic := s.panics[funcLine{fn, line}]
2638         if bPanic == nil {
2639                 bPanic = s.f.NewBlock(ssa.BlockPlain)
2640                 s.panics[funcLine{fn, line}] = bPanic
2641                 s.startBlock(bPanic)
2642                 // The panic call takes/returns memory to ensure that the right
2643                 // memory state is observed if the panic happens.
2644                 s.rtcall(fn, false, nil)
2645         }
2646         b.AddEdgeTo(bNext)
2647         b.AddEdgeTo(bPanic)
2648         s.startBlock(bNext)
2649 }
2650
2651 // rtcall issues a call to the given runtime function fn with the listed args.
2652 // Returns a slice of results of the given result types.
2653 // The call is added to the end of the current block.
2654 // If returns is false, the block is marked as an exit block.
2655 // If returns is true, the block is marked as a call block.  A new block
2656 // is started to load the return values.
2657 func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Value) []*ssa.Value {
2658         // Write args to the stack
2659         var off int64 // TODO: arch-dependent starting offset?
2660         for _, arg := range args {
2661                 t := arg.Type
2662                 off = Rnd(off, t.Alignment())
2663                 ptr := s.sp
2664                 if off != 0 {
2665                         ptr = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], off, s.sp)
2666                 }
2667                 size := t.Size()
2668                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, size, ptr, arg, s.mem())
2669                 off += size
2670         }
2671         off = Rnd(off, int64(Widthptr))
2672
2673         // Issue call
2674         call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, fn.Sym, s.mem())
2675         s.vars[&memVar] = call
2676
2677         // Finish block
2678         b := s.endBlock()
2679         if !returns {
2680                 b.Kind = ssa.BlockExit
2681                 b.Control = call
2682                 call.AuxInt = off
2683                 if len(results) > 0 {
2684                         Fatalf("panic call can't have results")
2685                 }
2686                 return nil
2687         }
2688         b.Kind = ssa.BlockCall
2689         b.Control = call
2690         bNext := s.f.NewBlock(ssa.BlockPlain)
2691         b.AddEdgeTo(bNext)
2692         s.startBlock(bNext)
2693
2694         // Load results
2695         res := make([]*ssa.Value, len(results))
2696         for i, t := range results {
2697                 off = Rnd(off, t.Alignment())
2698                 ptr := s.sp
2699                 if off != 0 {
2700                         ptr = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], off, s.sp)
2701                 }
2702                 res[i] = s.newValue2(ssa.OpLoad, t, ptr, s.mem())
2703                 off += t.Size()
2704         }
2705         off = Rnd(off, int64(Widthptr))
2706
2707         // Remember how much callee stack space we needed.
2708         call.AuxInt = off
2709
2710         return res
2711 }
2712
2713 // insertWBmove inserts the assignment *left = *right including a write barrier.
2714 // t is the type being assigned.
2715 func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32) {
2716         // if writeBarrier.enabled {
2717         //   typedmemmove(&t, left, right)
2718         // } else {
2719         //   *left = *right
2720         // }
2721         bThen := s.f.NewBlock(ssa.BlockPlain)
2722         bElse := s.f.NewBlock(ssa.BlockPlain)
2723         bEnd := s.f.NewBlock(ssa.BlockPlain)
2724
2725         aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrier", 0).Sym}
2726         flagaddr := s.newValue1A(ssa.OpAddr, Ptrto(Types[TBOOL]), aux, s.sb)
2727         // TODO: select the .enabled field.  It is currently first, so not needed for now.
2728         flag := s.newValue2(ssa.OpLoad, Types[TBOOL], flagaddr, s.mem())
2729         b := s.endBlock()
2730         b.Kind = ssa.BlockIf
2731         b.Likely = ssa.BranchUnlikely
2732         b.Control = flag
2733         b.AddEdgeTo(bThen)
2734         b.AddEdgeTo(bElse)
2735
2736         s.startBlock(bThen)
2737         taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(t)}, s.sb)
2738         s.rtcall(typedmemmove, true, nil, taddr, left, right)
2739         s.endBlock().AddEdgeTo(bEnd)
2740
2741         s.startBlock(bElse)
2742         s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, t.Size(), left, right, s.mem())
2743         s.endBlock().AddEdgeTo(bEnd)
2744
2745         s.startBlock(bEnd)
2746
2747         if Debug_wb > 0 {
2748                 Warnl(int(line), "write barrier")
2749         }
2750 }
2751
2752 // insertWBstore inserts the assignment *left = right including a write barrier.
2753 // t is the type being assigned.
2754 func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line int32) {
2755         // store scalar fields
2756         // if writeBarrier.enabled {
2757         //   writebarrierptr for pointer fields
2758         // } else {
2759         //   store pointer fields
2760         // }
2761
2762         s.storeTypeScalars(t, left, right)
2763
2764         bThen := s.f.NewBlock(ssa.BlockPlain)
2765         bElse := s.f.NewBlock(ssa.BlockPlain)
2766         bEnd := s.f.NewBlock(ssa.BlockPlain)
2767
2768         aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrier", 0).Sym}
2769         flagaddr := s.newValue1A(ssa.OpAddr, Ptrto(Types[TBOOL]), aux, s.sb)
2770         // TODO: select the .enabled field.  It is currently first, so not needed for now.
2771         flag := s.newValue2(ssa.OpLoad, Types[TBOOL], flagaddr, s.mem())
2772         b := s.endBlock()
2773         b.Kind = ssa.BlockIf
2774         b.Likely = ssa.BranchUnlikely
2775         b.Control = flag
2776         b.AddEdgeTo(bThen)
2777         b.AddEdgeTo(bElse)
2778
2779         // Issue write barriers for pointer writes.
2780         s.startBlock(bThen)
2781         s.storeTypePtrsWB(t, left, right)
2782         s.endBlock().AddEdgeTo(bEnd)
2783
2784         // Issue regular stores for pointer writes.
2785         s.startBlock(bElse)
2786         s.storeTypePtrs(t, left, right)
2787         s.endBlock().AddEdgeTo(bEnd)
2788
2789         s.startBlock(bEnd)
2790
2791         if Debug_wb > 0 {
2792                 Warnl(int(line), "write barrier")
2793         }
2794 }
2795
2796 // do *left = right for all scalar (non-pointer) parts of t.
2797 func (s *state) storeTypeScalars(t *Type, left, right *ssa.Value) {
2798         switch {
2799         case t.IsBoolean() || t.IsInteger() || t.IsFloat() || t.IsComplex():
2800                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), left, right, s.mem())
2801         case t.IsPtr() || t.IsMap() || t.IsChan():
2802                 // no scalar fields.
2803         case t.IsString():
2804                 len := s.newValue1(ssa.OpStringLen, Types[TINT], right)
2805                 lenAddr := s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TINT]), s.config.IntSize, left)
2806                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
2807         case t.IsSlice():
2808                 len := s.newValue1(ssa.OpSliceLen, Types[TINT], right)
2809                 cap := s.newValue1(ssa.OpSliceCap, Types[TINT], right)
2810                 lenAddr := s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TINT]), s.config.IntSize, left)
2811                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, lenAddr, len, s.mem())
2812                 capAddr := s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TINT]), 2*s.config.IntSize, left)
2813                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, capAddr, cap, s.mem())
2814         case t.IsInterface():
2815                 // itab field doesn't need a write barrier (even though it is a pointer).
2816                 itab := s.newValue1(ssa.OpITab, Ptrto(Types[TUINT8]), right)
2817                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.IntSize, left, itab, s.mem())
2818         case t.IsStruct():
2819                 n := t.NumFields()
2820                 for i := int64(0); i < n; i++ {
2821                         ft := t.FieldType(i)
2822                         addr := s.newValue1I(ssa.OpOffPtr, ft.PtrTo(), t.FieldOff(i), left)
2823                         val := s.newValue1I(ssa.OpStructSelect, ft, i, right)
2824                         s.storeTypeScalars(ft.(*Type), addr, val)
2825                 }
2826         default:
2827                 s.Fatalf("bad write barrier type %s", t)
2828         }
2829 }
2830
2831 // do *left = right for all pointer parts of t.
2832 func (s *state) storeTypePtrs(t *Type, left, right *ssa.Value) {
2833         switch {
2834         case t.IsPtr() || t.IsMap() || t.IsChan():
2835                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
2836         case t.IsString():
2837                 ptr := s.newValue1(ssa.OpStringPtr, Ptrto(Types[TUINT8]), right)
2838                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
2839         case t.IsSlice():
2840                 ptr := s.newValue1(ssa.OpSlicePtr, Ptrto(Types[TUINT8]), right)
2841                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, left, ptr, s.mem())
2842         case t.IsInterface():
2843                 // itab field is treated as a scalar.
2844                 idata := s.newValue1(ssa.OpIData, Ptrto(Types[TUINT8]), right)
2845                 idataAddr := s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TUINT8]), s.config.PtrSize, left)
2846                 s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, s.config.PtrSize, idataAddr, idata, s.mem())
2847         case t.IsStruct():
2848                 n := t.NumFields()
2849                 for i := int64(0); i < n; i++ {
2850                         ft := t.FieldType(i)
2851                         if !haspointers(ft.(*Type)) {
2852                                 continue
2853                         }
2854                         addr := s.newValue1I(ssa.OpOffPtr, ft.PtrTo(), t.FieldOff(i), left)
2855                         val := s.newValue1I(ssa.OpStructSelect, ft, i, right)
2856                         s.storeTypePtrs(ft.(*Type), addr, val)
2857                 }
2858         default:
2859                 s.Fatalf("bad write barrier type %s", t)
2860         }
2861 }
2862
2863 // do *left = right with a write barrier for all pointer parts of t.
2864 func (s *state) storeTypePtrsWB(t *Type, left, right *ssa.Value) {
2865         switch {
2866         case t.IsPtr() || t.IsMap() || t.IsChan():
2867                 s.rtcall(writebarrierptr, true, nil, left, right)
2868         case t.IsString():
2869                 ptr := s.newValue1(ssa.OpStringPtr, Ptrto(Types[TUINT8]), right)
2870                 s.rtcall(writebarrierptr, true, nil, left, ptr)
2871         case t.IsSlice():
2872                 ptr := s.newValue1(ssa.OpSlicePtr, Ptrto(Types[TUINT8]), right)
2873                 s.rtcall(writebarrierptr, true, nil, left, ptr)
2874         case t.IsInterface():
2875                 idata := s.newValue1(ssa.OpIData, Ptrto(Types[TUINT8]), right)
2876                 idataAddr := s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TUINT8]), s.config.PtrSize, left)
2877                 s.rtcall(writebarrierptr, true, nil, idataAddr, idata)
2878         case t.IsStruct():
2879                 n := t.NumFields()
2880                 for i := int64(0); i < n; i++ {
2881                         ft := t.FieldType(i)
2882                         if !haspointers(ft.(*Type)) {
2883                                 continue
2884                         }
2885                         addr := s.newValue1I(ssa.OpOffPtr, ft.PtrTo(), t.FieldOff(i), left)
2886                         val := s.newValue1I(ssa.OpStructSelect, ft, i, right)
2887                         s.storeTypePtrsWB(ft.(*Type), addr, val)
2888                 }
2889         default:
2890                 s.Fatalf("bad write barrier type %s", t)
2891         }
2892 }
2893
2894 // slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
2895 // i,j,k may be nil, in which case they are set to their default value.
2896 // t is a slice, ptr to array, or string type.
2897 func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) {
2898         var elemtype *Type
2899         var ptrtype *Type
2900         var ptr *ssa.Value
2901         var len *ssa.Value
2902         var cap *ssa.Value
2903         zero := s.constInt(Types[TINT], 0)
2904         switch {
2905         case t.IsSlice():
2906                 elemtype = t.Type
2907                 ptrtype = Ptrto(elemtype)
2908                 ptr = s.newValue1(ssa.OpSlicePtr, ptrtype, v)
2909                 len = s.newValue1(ssa.OpSliceLen, Types[TINT], v)
2910                 cap = s.newValue1(ssa.OpSliceCap, Types[TINT], v)
2911         case t.IsString():
2912                 elemtype = Types[TUINT8]
2913                 ptrtype = Ptrto(elemtype)
2914                 ptr = s.newValue1(ssa.OpStringPtr, ptrtype, v)
2915                 len = s.newValue1(ssa.OpStringLen, Types[TINT], v)
2916                 cap = len
2917         case t.IsPtr():
2918                 if !t.Type.IsArray() {
2919                         s.Fatalf("bad ptr to array in slice %v\n", t)
2920                 }
2921                 elemtype = t.Type.Type
2922                 ptrtype = Ptrto(elemtype)
2923                 s.nilCheck(v)
2924                 ptr = v
2925                 len = s.constInt(Types[TINT], t.Type.Bound)
2926                 cap = len
2927         default:
2928                 s.Fatalf("bad type in slice %v\n", t)
2929         }
2930
2931         // Set default values
2932         if i == nil {
2933                 i = zero
2934         }
2935         if j == nil {
2936                 j = len
2937         }
2938         if k == nil {
2939                 k = cap
2940         }
2941
2942         // Panic if slice indices are not in bounds.
2943         s.sliceBoundsCheck(i, j)
2944         if j != k {
2945                 s.sliceBoundsCheck(j, k)
2946         }
2947         if k != cap {
2948                 s.sliceBoundsCheck(k, cap)
2949         }
2950
2951         // Generate the following code assuming that indexes are in bounds.
2952         // The conditional is to make sure that we don't generate a slice
2953         // that points to the next object in memory.
2954         // rlen = (Sub64 j i)
2955         // rcap = (Sub64 k i)
2956         // p = ptr
2957         // if rcap != 0 {
2958         //    p = (AddPtr ptr (Mul64 low (Const64 size)))
2959         // }
2960         // result = (SliceMake p size)
2961         subOp := s.ssaOp(OSUB, Types[TINT])
2962         neqOp := s.ssaOp(ONE, Types[TINT])
2963         mulOp := s.ssaOp(OMUL, Types[TINT])
2964         rlen := s.newValue2(subOp, Types[TINT], j, i)
2965         var rcap *ssa.Value
2966         switch {
2967         case t.IsString():
2968                 // Capacity of the result is unimportant.  However, we use
2969                 // rcap to test if we've generated a zero-length slice.
2970                 // Use length of strings for that.
2971                 rcap = rlen
2972         case j == k:
2973                 rcap = rlen
2974         default:
2975                 rcap = s.newValue2(subOp, Types[TINT], k, i)
2976         }
2977
2978         s.vars[&ptrVar] = ptr
2979
2980         // Generate code to test the resulting slice length.
2981         cmp := s.newValue2(neqOp, Types[TBOOL], rcap, s.constInt(Types[TINT], 0))
2982
2983         b := s.endBlock()
2984         b.Kind = ssa.BlockIf
2985         b.Likely = ssa.BranchLikely
2986         b.Control = cmp
2987
2988         // Generate code for non-zero length slice case.
2989         nz := s.f.NewBlock(ssa.BlockPlain)
2990         b.AddEdgeTo(nz)
2991         s.startBlock(nz)
2992         var inc *ssa.Value
2993         if elemtype.Width == 1 {
2994                 inc = i
2995         } else {
2996                 inc = s.newValue2(mulOp, Types[TINT], i, s.constInt(Types[TINT], elemtype.Width))
2997         }
2998         s.vars[&ptrVar] = s.newValue2(ssa.OpAddPtr, ptrtype, ptr, inc)
2999         s.endBlock()
3000
3001         // All done.
3002         merge := s.f.NewBlock(ssa.BlockPlain)
3003         b.AddEdgeTo(merge)
3004         nz.AddEdgeTo(merge)
3005         s.startBlock(merge)
3006         rptr := s.variable(&ptrVar, ptrtype)
3007         delete(s.vars, &ptrVar)
3008         return rptr, rlen, rcap
3009 }
3010
3011 type u2fcvtTab struct {
3012         geq, cvt2F, and, rsh, or, add ssa.Op
3013         one                           func(*state, ssa.Type, int64) *ssa.Value
3014 }
3015
3016 var u64_f64 u2fcvtTab = u2fcvtTab{
3017         geq:   ssa.OpGeq64,
3018         cvt2F: ssa.OpCvt64to64F,
3019         and:   ssa.OpAnd64,
3020         rsh:   ssa.OpRsh64Ux64,
3021         or:    ssa.OpOr64,
3022         add:   ssa.OpAdd64F,
3023         one:   (*state).constInt64,
3024 }
3025
3026 var u64_f32 u2fcvtTab = u2fcvtTab{
3027         geq:   ssa.OpGeq64,
3028         cvt2F: ssa.OpCvt64to32F,
3029         and:   ssa.OpAnd64,
3030         rsh:   ssa.OpRsh64Ux64,
3031         or:    ssa.OpOr64,
3032         add:   ssa.OpAdd32F,
3033         one:   (*state).constInt64,
3034 }
3035
3036 // Excess generality on a machine with 64-bit integer registers.
3037 // Not used on AMD64.
3038 var u32_f32 u2fcvtTab = u2fcvtTab{
3039         geq:   ssa.OpGeq32,
3040         cvt2F: ssa.OpCvt32to32F,
3041         and:   ssa.OpAnd32,
3042         rsh:   ssa.OpRsh32Ux32,
3043         or:    ssa.OpOr32,
3044         add:   ssa.OpAdd32F,
3045         one: func(s *state, t ssa.Type, x int64) *ssa.Value {
3046                 return s.constInt32(t, int32(x))
3047         },
3048 }
3049
3050 func (s *state) uint64Tofloat64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3051         return s.uintTofloat(&u64_f64, n, x, ft, tt)
3052 }
3053
3054 func (s *state) uint64Tofloat32(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3055         return s.uintTofloat(&u64_f32, n, x, ft, tt)
3056 }
3057
3058 func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3059         // if x >= 0 {
3060         //    result = (floatY) x
3061         // } else {
3062         //        y = uintX(x) ; y = x & 1
3063         //        z = uintX(x) ; z = z >> 1
3064         //        z = z >> 1
3065         //        z = z | y
3066         //        result = floatY(z)
3067         //        result = result + result
3068         // }
3069         //
3070         // Code borrowed from old code generator.
3071         // What's going on: large 64-bit "unsigned" looks like
3072         // negative number to hardware's integer-to-float
3073         // conversion.  However, because the mantissa is only
3074         // 63 bits, we don't need the LSB, so instead we do an
3075         // unsigned right shift (divide by two), convert, and
3076         // double.  However, before we do that, we need to be
3077         // sure that we do not lose a "1" if that made the
3078         // difference in the resulting rounding.  Therefore, we
3079         // preserve it, and OR (not ADD) it back in.  The case
3080         // that matters is when the eleven discarded bits are
3081         // equal to 10000000001; that rounds up, and the 1 cannot
3082         // be lost else it would round down if the LSB of the
3083         // candidate mantissa is 0.
3084         cmp := s.newValue2(cvttab.geq, Types[TBOOL], x, s.zeroVal(ft))
3085         b := s.endBlock()
3086         b.Kind = ssa.BlockIf
3087         b.Control = cmp
3088         b.Likely = ssa.BranchLikely
3089
3090         bThen := s.f.NewBlock(ssa.BlockPlain)
3091         bElse := s.f.NewBlock(ssa.BlockPlain)
3092         bAfter := s.f.NewBlock(ssa.BlockPlain)
3093
3094         b.AddEdgeTo(bThen)
3095         s.startBlock(bThen)
3096         a0 := s.newValue1(cvttab.cvt2F, tt, x)
3097         s.vars[n] = a0
3098         s.endBlock()
3099         bThen.AddEdgeTo(bAfter)
3100
3101         b.AddEdgeTo(bElse)
3102         s.startBlock(bElse)
3103         one := cvttab.one(s, ft, 1)
3104         y := s.newValue2(cvttab.and, ft, x, one)
3105         z := s.newValue2(cvttab.rsh, ft, x, one)
3106         z = s.newValue2(cvttab.or, ft, z, y)
3107         a := s.newValue1(cvttab.cvt2F, tt, z)
3108         a1 := s.newValue2(cvttab.add, tt, a, a)
3109         s.vars[n] = a1
3110         s.endBlock()
3111         bElse.AddEdgeTo(bAfter)
3112
3113         s.startBlock(bAfter)
3114         return s.variable(n, n.Type)
3115 }
3116
3117 // referenceTypeBuiltin generates code for the len/cap builtins for maps and channels.
3118 func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value {
3119         if !n.Left.Type.IsMap() && !n.Left.Type.IsChan() {
3120                 s.Fatalf("node must be a map or a channel")
3121         }
3122         // if n == nil {
3123         //   return 0
3124         // } else {
3125         //   // len
3126         //   return *((*int)n)
3127         //   // cap
3128         //   return *(((*int)n)+1)
3129         // }
3130         lenType := n.Type
3131         nilValue := s.newValue0(ssa.OpConstNil, Types[TUINTPTR])
3132         cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue)
3133         b := s.endBlock()
3134         b.Kind = ssa.BlockIf
3135         b.Control = cmp
3136         b.Likely = ssa.BranchUnlikely
3137
3138         bThen := s.f.NewBlock(ssa.BlockPlain)
3139         bElse := s.f.NewBlock(ssa.BlockPlain)
3140         bAfter := s.f.NewBlock(ssa.BlockPlain)
3141
3142         // length/capacity of a nil map/chan is zero
3143         b.AddEdgeTo(bThen)
3144         s.startBlock(bThen)
3145         s.vars[n] = s.zeroVal(lenType)
3146         s.endBlock()
3147         bThen.AddEdgeTo(bAfter)
3148
3149         b.AddEdgeTo(bElse)
3150         s.startBlock(bElse)
3151         if n.Op == OLEN {
3152                 // length is stored in the first word for map/chan
3153                 s.vars[n] = s.newValue2(ssa.OpLoad, lenType, x, s.mem())
3154         } else if n.Op == OCAP {
3155                 // capacity is stored in the second word for chan
3156                 sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Width, x)
3157                 s.vars[n] = s.newValue2(ssa.OpLoad, lenType, sw, s.mem())
3158         } else {
3159                 s.Fatalf("op must be OLEN or OCAP")
3160         }
3161         s.endBlock()
3162         bElse.AddEdgeTo(bAfter)
3163
3164         s.startBlock(bAfter)
3165         return s.variable(n, lenType)
3166 }
3167
3168 type f2uCvtTab struct {
3169         ltf, cvt2U, subf ssa.Op
3170         value            func(*state, ssa.Type, float64) *ssa.Value
3171 }
3172
3173 var f32_u64 f2uCvtTab = f2uCvtTab{
3174         ltf:   ssa.OpLess32F,
3175         cvt2U: ssa.OpCvt32Fto64,
3176         subf:  ssa.OpSub32F,
3177         value: (*state).constFloat32,
3178 }
3179
3180 var f64_u64 f2uCvtTab = f2uCvtTab{
3181         ltf:   ssa.OpLess64F,
3182         cvt2U: ssa.OpCvt64Fto64,
3183         subf:  ssa.OpSub64F,
3184         value: (*state).constFloat64,
3185 }
3186
3187 func (s *state) float32ToUint64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3188         return s.floatToUint(&f32_u64, n, x, ft, tt)
3189 }
3190 func (s *state) float64ToUint64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3191         return s.floatToUint(&f64_u64, n, x, ft, tt)
3192 }
3193
3194 func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value {
3195         // if x < 9223372036854775808.0 {
3196         //      result = uintY(x)
3197         // } else {
3198         //      y = x - 9223372036854775808.0
3199         //      z = uintY(y)
3200         //      result = z | -9223372036854775808
3201         // }
3202         twoToThe63 := cvttab.value(s, ft, 9223372036854775808.0)
3203         cmp := s.newValue2(cvttab.ltf, Types[TBOOL], x, twoToThe63)
3204         b := s.endBlock()
3205         b.Kind = ssa.BlockIf
3206         b.Control = cmp
3207         b.Likely = ssa.BranchLikely
3208
3209         bThen := s.f.NewBlock(ssa.BlockPlain)
3210         bElse := s.f.NewBlock(ssa.BlockPlain)
3211         bAfter := s.f.NewBlock(ssa.BlockPlain)
3212
3213         b.AddEdgeTo(bThen)
3214         s.startBlock(bThen)
3215         a0 := s.newValue1(cvttab.cvt2U, tt, x)
3216         s.vars[n] = a0
3217         s.endBlock()
3218         bThen.AddEdgeTo(bAfter)
3219
3220         b.AddEdgeTo(bElse)
3221         s.startBlock(bElse)
3222         y := s.newValue2(cvttab.subf, ft, x, twoToThe63)
3223         y = s.newValue1(cvttab.cvt2U, tt, y)
3224         z := s.constInt64(tt, -9223372036854775808)
3225         a1 := s.newValue2(ssa.OpOr64, tt, y, z)
3226         s.vars[n] = a1
3227         s.endBlock()
3228         bElse.AddEdgeTo(bAfter)
3229
3230         s.startBlock(bAfter)
3231         return s.variable(n, n.Type)
3232 }
3233
3234 // ifaceType returns the value for the word containing the type.
3235 // n is the node for the interface expression.
3236 // v is the corresponding value.
3237 func (s *state) ifaceType(n *Node, v *ssa.Value) *ssa.Value {
3238         byteptr := Ptrto(Types[TUINT8]) // type used in runtime prototypes for runtime type (*byte)
3239
3240         if isnilinter(n.Type) {
3241                 // Have *eface. The type is the first word in the struct.
3242                 return s.newValue1(ssa.OpITab, byteptr, v)
3243         }
3244
3245         // Have *iface.
3246         // The first word in the struct is the *itab.
3247         // If the *itab is nil, return 0.
3248         // Otherwise, the second word in the *itab is the type.
3249
3250         tab := s.newValue1(ssa.OpITab, byteptr, v)
3251         s.vars[&typVar] = tab
3252         isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.entryNewValue0(ssa.OpConstNil, byteptr))
3253         b := s.endBlock()
3254         b.Kind = ssa.BlockIf
3255         b.Control = isnonnil
3256         b.Likely = ssa.BranchLikely
3257
3258         bLoad := s.f.NewBlock(ssa.BlockPlain)
3259         bEnd := s.f.NewBlock(ssa.BlockPlain)
3260
3261         b.AddEdgeTo(bLoad)
3262         b.AddEdgeTo(bEnd)
3263         bLoad.AddEdgeTo(bEnd)
3264
3265         s.startBlock(bLoad)
3266         off := s.newValue1I(ssa.OpOffPtr, byteptr, int64(Widthptr), tab)
3267         s.vars[&typVar] = s.newValue2(ssa.OpLoad, byteptr, off, s.mem())
3268         s.endBlock()
3269
3270         s.startBlock(bEnd)
3271         typ := s.variable(&typVar, byteptr)
3272         delete(s.vars, &typVar)
3273         return typ
3274 }
3275
3276 // dottype generates SSA for a type assertion node.
3277 // commaok indicates whether to panic or return a bool.
3278 // If commaok is false, resok will be nil.
3279 func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
3280         iface := s.expr(n.Left)
3281         typ := s.ifaceType(n.Left, iface)  // actual concrete type
3282         target := s.expr(typename(n.Type)) // target type
3283         if !isdirectiface(n.Type) {
3284                 // walk rewrites ODOTTYPE/OAS2DOTTYPE into runtime calls except for this case.
3285                 Fatalf("dottype needs a direct iface type %s", n.Type)
3286         }
3287
3288         if Debug_typeassert > 0 {
3289                 Warnl(int(n.Lineno), "type assertion inlined")
3290         }
3291
3292         // TODO:  If we have a nonempty interface and its itab field is nil,
3293         // then this test is redundant and ifaceType should just branch directly to bFail.
3294         cond := s.newValue2(ssa.OpEqPtr, Types[TBOOL], typ, target)
3295         b := s.endBlock()
3296         b.Kind = ssa.BlockIf
3297         b.Control = cond
3298         b.Likely = ssa.BranchLikely
3299
3300         byteptr := Ptrto(Types[TUINT8])
3301
3302         bOk := s.f.NewBlock(ssa.BlockPlain)
3303         bFail := s.f.NewBlock(ssa.BlockPlain)
3304         b.AddEdgeTo(bOk)
3305         b.AddEdgeTo(bFail)
3306
3307         if !commaok {
3308                 // on failure, panic by calling panicdottype
3309                 s.startBlock(bFail)
3310                 taddr := s.newValue1A(ssa.OpAddr, byteptr, &ssa.ExternSymbol{byteptr, typenamesym(n.Left.Type)}, s.sb)
3311                 s.rtcall(panicdottype, false, nil, typ, target, taddr)
3312
3313                 // on success, return idata field
3314                 s.startBlock(bOk)
3315                 return s.newValue1(ssa.OpIData, n.Type, iface), nil
3316         }
3317
3318         // commaok is the more complicated case because we have
3319         // a control flow merge point.
3320         bEnd := s.f.NewBlock(ssa.BlockPlain)
3321
3322         // type assertion succeeded
3323         s.startBlock(bOk)
3324         s.vars[&idataVar] = s.newValue1(ssa.OpIData, n.Type, iface)
3325         s.vars[&okVar] = s.constBool(true)
3326         s.endBlock()
3327         bOk.AddEdgeTo(bEnd)
3328
3329         // type assertion failed
3330         s.startBlock(bFail)
3331         s.vars[&idataVar] = s.entryNewValue0(ssa.OpConstNil, byteptr)
3332         s.vars[&okVar] = s.constBool(false)
3333         s.endBlock()
3334         bFail.AddEdgeTo(bEnd)
3335
3336         // merge point
3337         s.startBlock(bEnd)
3338         res = s.variable(&idataVar, byteptr)
3339         resok = s.variable(&okVar, Types[TBOOL])
3340         delete(s.vars, &idataVar)
3341         delete(s.vars, &okVar)
3342         return res, resok
3343 }
3344
3345 // checkgoto checks that a goto from from to to does not
3346 // jump into a block or jump over variable declarations.
3347 // It is a copy of checkgoto in the pre-SSA backend,
3348 // modified only for line number handling.
3349 // TODO: document how this works and why it is designed the way it is.
3350 func (s *state) checkgoto(from *Node, to *Node) {
3351         if from.Sym == to.Sym {
3352                 return
3353         }
3354
3355         nf := 0
3356         for fs := from.Sym; fs != nil; fs = fs.Link {
3357                 nf++
3358         }
3359         nt := 0
3360         for fs := to.Sym; fs != nil; fs = fs.Link {
3361                 nt++
3362         }
3363         fs := from.Sym
3364         for ; nf > nt; nf-- {
3365                 fs = fs.Link
3366         }
3367         if fs != to.Sym {
3368                 // decide what to complain about.
3369                 // prefer to complain about 'into block' over declarations,
3370                 // so scan backward to find most recent block or else dcl.
3371                 var block *Sym
3372
3373                 var dcl *Sym
3374                 ts := to.Sym
3375                 for ; nt > nf; nt-- {
3376                         if ts.Pkg == nil {
3377                                 block = ts
3378                         } else {
3379                                 dcl = ts
3380                         }
3381                         ts = ts.Link
3382                 }
3383
3384                 for ts != fs {
3385                         if ts.Pkg == nil {
3386                                 block = ts
3387                         } else {
3388                                 dcl = ts
3389                         }
3390                         ts = ts.Link
3391                         fs = fs.Link
3392                 }
3393
3394                 lno := int(from.Left.Lineno)
3395                 if block != nil {
3396                         yyerrorl(lno, "goto %v jumps into block starting at %v", from.Left.Sym, Ctxt.Line(int(block.Lastlineno)))
3397                 } else {
3398                         yyerrorl(lno, "goto %v jumps over declaration of %v at %v", from.Left.Sym, dcl, Ctxt.Line(int(dcl.Lastlineno)))
3399                 }
3400         }
3401 }
3402
3403 // variable returns the value of a variable at the current location.
3404 func (s *state) variable(name *Node, t ssa.Type) *ssa.Value {
3405         v := s.vars[name]
3406         if v == nil {
3407                 v = s.newValue0A(ssa.OpFwdRef, t, name)
3408                 s.fwdRefs = append(s.fwdRefs, v)
3409                 s.vars[name] = v
3410                 s.addNamedValue(name, v)
3411         }
3412         return v
3413 }
3414
3415 func (s *state) mem() *ssa.Value {
3416         return s.variable(&memVar, ssa.TypeMem)
3417 }
3418
3419 func (s *state) linkForwardReferences() {
3420         // Build SSA graph.  Each variable on its first use in a basic block
3421         // leaves a FwdRef in that block representing the incoming value
3422         // of that variable.  This function links that ref up with possible definitions,
3423         // inserting Phi values as needed.  This is essentially the algorithm
3424         // described by Braun, Buchwald, Hack, Leißa, Mallon, and Zwinkau:
3425         // http://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf
3426         // Differences:
3427         //   - We use FwdRef nodes to postpone phi building until the CFG is
3428         //     completely built.  That way we can avoid the notion of "sealed"
3429         //     blocks.
3430         //   - Phi optimization is a separate pass (in ../ssa/phielim.go).
3431         for len(s.fwdRefs) > 0 {
3432                 v := s.fwdRefs[len(s.fwdRefs)-1]
3433                 s.fwdRefs = s.fwdRefs[:len(s.fwdRefs)-1]
3434                 s.resolveFwdRef(v)
3435         }
3436 }
3437
3438 // resolveFwdRef modifies v to be the variable's value at the start of its block.
3439 // v must be a FwdRef op.
3440 func (s *state) resolveFwdRef(v *ssa.Value) {
3441         b := v.Block
3442         name := v.Aux.(*Node)
3443         v.Aux = nil
3444         if b == s.f.Entry {
3445                 // Live variable at start of function.
3446                 if canSSA(name) {
3447                         v.Op = ssa.OpArg
3448                         v.Aux = name
3449                         return
3450                 }
3451                 // Not SSAable.  Load it.
3452                 addr := s.decladdrs[name]
3453                 if addr == nil {
3454                         // TODO: closure args reach here.
3455                         s.Unimplementedf("unhandled closure arg %s at entry to function %s", name, b.Func.Name)
3456                 }
3457                 if _, ok := addr.Aux.(*ssa.ArgSymbol); !ok {
3458                         s.Fatalf("variable live at start of function %s is not an argument %s", b.Func.Name, name)
3459                 }
3460                 v.Op = ssa.OpLoad
3461                 v.AddArgs(addr, s.startmem)
3462                 return
3463         }
3464         if len(b.Preds) == 0 {
3465                 // This block is dead; we have no predecessors and we're not the entry block.
3466                 // It doesn't matter what we use here as long as it is well-formed.
3467                 v.Op = ssa.OpUnknown
3468                 return
3469         }
3470         // Find variable value on each predecessor.
3471         var argstore [4]*ssa.Value
3472         args := argstore[:0]
3473         for _, p := range b.Preds {
3474                 args = append(args, s.lookupVarOutgoing(p, v.Type, name, v.Line))
3475         }
3476
3477         // Decide if we need a phi or not.  We need a phi if there
3478         // are two different args (which are both not v).
3479         var w *ssa.Value
3480         for _, a := range args {
3481                 if a == v {
3482                         continue // self-reference
3483                 }
3484                 if a == w {
3485                         continue // already have this witness
3486                 }
3487                 if w != nil {
3488                         // two witnesses, need a phi value
3489                         v.Op = ssa.OpPhi
3490                         v.AddArgs(args...)
3491                         return
3492                 }
3493                 w = a // save witness
3494         }
3495         if w == nil {
3496                 s.Fatalf("no witness for reachable phi %s", v)
3497         }
3498         // One witness.  Make v a copy of w.
3499         v.Op = ssa.OpCopy
3500         v.AddArg(w)
3501 }
3502
3503 // lookupVarOutgoing finds the variable's value at the end of block b.
3504 func (s *state) lookupVarOutgoing(b *ssa.Block, t ssa.Type, name *Node, line int32) *ssa.Value {
3505         m := s.defvars[b.ID]
3506         if v, ok := m[name]; ok {
3507                 return v
3508         }
3509         // The variable is not defined by b and we haven't
3510         // looked it up yet.  Generate a FwdRef for the variable and return that.
3511         v := b.NewValue0A(line, ssa.OpFwdRef, t, name)
3512         s.fwdRefs = append(s.fwdRefs, v)
3513         m[name] = v
3514         s.addNamedValue(name, v)
3515         return v
3516 }
3517
3518 func (s *state) addNamedValue(n *Node, v *ssa.Value) {
3519         if n.Class == Pxxx {
3520                 // Don't track our dummy nodes (&memVar etc.).
3521                 return
3522         }
3523         if strings.HasPrefix(n.Sym.Name, "autotmp_") {
3524                 // Don't track autotmp_ variables.
3525                 return
3526         }
3527         if n.Class == PAUTO && (v.Type.IsString() || v.Type.IsSlice() || v.Type.IsInterface()) {
3528                 // TODO: can't handle auto compound objects with pointers yet.
3529                 // The live variable analysis barfs because we don't put VARDEF
3530                 // pseudos in the right place when we spill to these nodes.
3531                 return
3532         }
3533         if n.Class == PAUTO && n.Xoffset != 0 {
3534                 s.Fatalf("AUTO var with offset %s %d", n, n.Xoffset)
3535         }
3536         loc := ssa.LocalSlot{N: n, Type: n.Type, Off: 0}
3537         values, ok := s.f.NamedValues[loc]
3538         if !ok {
3539                 s.f.Names = append(s.f.Names, loc)
3540         }
3541         s.f.NamedValues[loc] = append(values, v)
3542 }
3543
3544 // an unresolved branch
3545 type branch struct {
3546         p *obj.Prog  // branch instruction
3547         b *ssa.Block // target
3548 }
3549
3550 type genState struct {
3551         // branches remembers all the branch instructions we've seen
3552         // and where they would like to go.
3553         branches []branch
3554
3555         // bstart remembers where each block starts (indexed by block ID)
3556         bstart []*obj.Prog
3557
3558         // deferBranches remembers all the defer branches we've seen.
3559         deferBranches []*obj.Prog
3560
3561         // deferTarget remembers the (last) deferreturn call site.
3562         deferTarget *obj.Prog
3563 }
3564
3565 // genssa appends entries to ptxt for each instruction in f.
3566 // gcargs and gclocals are filled in with pointer maps for the frame.
3567 func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) {
3568         var s genState
3569
3570         e := f.Config.Frontend().(*ssaExport)
3571         // We're about to emit a bunch of Progs.
3572         // Since the only way to get here is to explicitly request it,
3573         // just fail on unimplemented instead of trying to unwind our mess.
3574         e.mustImplement = true
3575
3576         // Remember where each block starts.
3577         s.bstart = make([]*obj.Prog, f.NumBlocks())
3578
3579         var valueProgs map[*obj.Prog]*ssa.Value
3580         var blockProgs map[*obj.Prog]*ssa.Block
3581         const logProgs = true
3582         if logProgs {
3583                 valueProgs = make(map[*obj.Prog]*ssa.Value, f.NumValues())
3584                 blockProgs = make(map[*obj.Prog]*ssa.Block, f.NumBlocks())
3585                 f.Logf("genssa %s\n", f.Name)
3586                 blockProgs[Pc] = f.Blocks[0]
3587         }
3588
3589         // Emit basic blocks
3590         for i, b := range f.Blocks {
3591                 s.bstart[b.ID] = Pc
3592                 // Emit values in block
3593                 s.markMoves(b)
3594                 for _, v := range b.Values {
3595                         x := Pc
3596                         s.genValue(v)
3597                         if logProgs {
3598                                 for ; x != Pc; x = x.Link {
3599                                         valueProgs[x] = v
3600                                 }
3601                         }
3602                 }
3603                 // Emit control flow instructions for block
3604                 var next *ssa.Block
3605                 if i < len(f.Blocks)-1 && (Debug['N'] == 0 || b.Kind == ssa.BlockCall) {
3606                         // If -N, leave next==nil so every block with successors
3607                         // ends in a JMP (except call blocks - plive doesn't like
3608                         // select{send,recv} followed by a JMP call).  Helps keep
3609                         // line numbers for otherwise empty blocks.
3610                         next = f.Blocks[i+1]
3611                 }
3612                 x := Pc
3613                 s.genBlock(b, next)
3614                 if logProgs {
3615                         for ; x != Pc; x = x.Link {
3616                                 blockProgs[x] = b
3617                         }
3618                 }
3619         }
3620
3621         // Resolve branches
3622         for _, br := range s.branches {
3623                 br.p.To.Val = s.bstart[br.b.ID]
3624         }
3625         if s.deferBranches != nil && s.deferTarget == nil {
3626                 // This can happen when the function has a defer but
3627                 // no return (because it has an infinite loop).
3628                 s.deferReturn()
3629                 Prog(obj.ARET)
3630         }
3631         for _, p := range s.deferBranches {
3632                 p.To.Val = s.deferTarget
3633         }
3634
3635         if logProgs {
3636                 for p := ptxt; p != nil; p = p.Link {
3637                         var s string
3638                         if v, ok := valueProgs[p]; ok {
3639                                 s = v.String()
3640                         } else if b, ok := blockProgs[p]; ok {
3641                                 s = b.String()
3642                         } else {
3643                                 s = "   " // most value and branch strings are 2-3 characters long
3644                         }
3645                         f.Logf("%s\t%s\n", s, p)
3646                 }
3647                 if f.Config.HTML != nil {
3648                         saved := ptxt.Ctxt.LineHist.PrintFilenameOnly
3649                         ptxt.Ctxt.LineHist.PrintFilenameOnly = true
3650                         var buf bytes.Buffer
3651                         buf.WriteString("<code>")
3652                         buf.WriteString("<dl class=\"ssa-gen\">")
3653                         for p := ptxt; p != nil; p = p.Link {
3654                                 buf.WriteString("<dt class=\"ssa-prog-src\">")
3655                                 if v, ok := valueProgs[p]; ok {
3656                                         buf.WriteString(v.HTML())
3657                                 } else if b, ok := blockProgs[p]; ok {
3658                                         buf.WriteString(b.HTML())
3659                                 }
3660                                 buf.WriteString("</dt>")
3661                                 buf.WriteString("<dd class=\"ssa-prog\">")
3662                                 buf.WriteString(html.EscapeString(p.String()))
3663                                 buf.WriteString("</dd>")
3664                                 buf.WriteString("</li>")
3665                         }
3666                         buf.WriteString("</dl>")
3667                         buf.WriteString("</code>")
3668                         f.Config.HTML.WriteColumn("genssa", buf.String())
3669                         ptxt.Ctxt.LineHist.PrintFilenameOnly = saved
3670                 }
3671         }
3672
3673         // Emit static data
3674         if f.StaticData != nil {
3675                 for _, n := range f.StaticData.([]*Node) {
3676                         if !gen_as_init(n, false) {
3677                                 Fatalf("non-static data marked as static: %v\n\n", n, f)
3678                         }
3679                 }
3680         }
3681
3682         // Allocate stack frame
3683         allocauto(ptxt)
3684
3685         // Generate gc bitmaps.
3686         liveness(Curfn, ptxt, gcargs, gclocals)
3687         gcsymdup(gcargs)
3688         gcsymdup(gclocals)
3689
3690         // Add frame prologue.  Zero ambiguously live variables.
3691         Thearch.Defframe(ptxt)
3692         if Debug['f'] != 0 {
3693                 frame(0)
3694         }
3695
3696         // Remove leftover instrumentation from the instruction stream.
3697         removevardef(ptxt)
3698
3699         f.Config.HTML.Close()
3700 }
3701
3702 // opregreg emits instructions for
3703 //     dest := dest(To) op src(From)
3704 // and also returns the created obj.Prog so it
3705 // may be further adjusted (offset, scale, etc).
3706 func opregreg(op int, dest, src int16) *obj.Prog {
3707         p := Prog(op)
3708         p.From.Type = obj.TYPE_REG
3709         p.To.Type = obj.TYPE_REG
3710         p.To.Reg = dest
3711         p.From.Reg = src
3712         return p
3713 }
3714
3715 func (s *genState) genValue(v *ssa.Value) {
3716         lineno = v.Line
3717         switch v.Op {
3718         case ssa.OpAMD64ADDQ, ssa.OpAMD64ADDL, ssa.OpAMD64ADDW:
3719                 r := regnum(v)
3720                 r1 := regnum(v.Args[0])
3721                 r2 := regnum(v.Args[1])
3722                 switch {
3723                 case r == r1:
3724                         p := Prog(v.Op.Asm())
3725                         p.From.Type = obj.TYPE_REG
3726                         p.From.Reg = r2
3727                         p.To.Type = obj.TYPE_REG
3728                         p.To.Reg = r
3729                 case r == r2:
3730                         p := Prog(v.Op.Asm())
3731                         p.From.Type = obj.TYPE_REG
3732                         p.From.Reg = r1
3733                         p.To.Type = obj.TYPE_REG
3734                         p.To.Reg = r
3735                 default:
3736                         var asm int
3737                         switch v.Op {
3738                         case ssa.OpAMD64ADDQ:
3739                                 asm = x86.ALEAQ
3740                         case ssa.OpAMD64ADDL:
3741                                 asm = x86.ALEAL
3742                         case ssa.OpAMD64ADDW:
3743                                 asm = x86.ALEAW
3744                         }
3745                         p := Prog(asm)
3746                         p.From.Type = obj.TYPE_MEM
3747                         p.From.Reg = r1
3748                         p.From.Scale = 1
3749                         p.From.Index = r2
3750                         p.To.Type = obj.TYPE_REG
3751                         p.To.Reg = r
3752                 }
3753         // 2-address opcode arithmetic, symmetric
3754         case ssa.OpAMD64ADDB, ssa.OpAMD64ADDSS, ssa.OpAMD64ADDSD,
3755                 ssa.OpAMD64ANDQ, ssa.OpAMD64ANDL, ssa.OpAMD64ANDW, ssa.OpAMD64ANDB,
3756                 ssa.OpAMD64ORQ, ssa.OpAMD64ORL, ssa.OpAMD64ORW, ssa.OpAMD64ORB,
3757                 ssa.OpAMD64XORQ, ssa.OpAMD64XORL, ssa.OpAMD64XORW, ssa.OpAMD64XORB,
3758                 ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW, ssa.OpAMD64MULB,
3759                 ssa.OpAMD64MULSS, ssa.OpAMD64MULSD, ssa.OpAMD64PXOR:
3760                 r := regnum(v)
3761                 x := regnum(v.Args[0])
3762                 y := regnum(v.Args[1])
3763                 if x != r && y != r {
3764                         opregreg(moveByType(v.Type), r, x)
3765                         x = r
3766                 }
3767                 p := Prog(v.Op.Asm())
3768                 p.From.Type = obj.TYPE_REG
3769                 p.To.Type = obj.TYPE_REG
3770                 p.To.Reg = r
3771                 if x == r {
3772                         p.From.Reg = y
3773                 } else {
3774                         p.From.Reg = x
3775                 }
3776         // 2-address opcode arithmetic, not symmetric
3777         case ssa.OpAMD64SUBQ, ssa.OpAMD64SUBL, ssa.OpAMD64SUBW, ssa.OpAMD64SUBB:
3778                 r := regnum(v)
3779                 x := regnum(v.Args[0])
3780                 y := regnum(v.Args[1])
3781                 var neg bool
3782                 if y == r {
3783                         // compute -(y-x) instead
3784                         x, y = y, x
3785                         neg = true
3786                 }
3787                 if x != r {
3788                         opregreg(moveByType(v.Type), r, x)
3789                 }
3790                 opregreg(v.Op.Asm(), r, y)
3791
3792                 if neg {
3793                         p := Prog(x86.ANEGQ) // TODO: use correct size?  This is mostly a hack until regalloc does 2-address correctly
3794                         p.To.Type = obj.TYPE_REG
3795                         p.To.Reg = r
3796                 }
3797         case ssa.OpAMD64SUBSS, ssa.OpAMD64SUBSD, ssa.OpAMD64DIVSS, ssa.OpAMD64DIVSD:
3798                 r := regnum(v)
3799                 x := regnum(v.Args[0])
3800                 y := regnum(v.Args[1])
3801                 if y == r && x != r {
3802                         // r/y := x op r/y, need to preserve x and rewrite to
3803                         // r/y := r/y op x15
3804                         x15 := int16(x86.REG_X15)
3805                         // register move y to x15
3806                         // register move x to y
3807                         // rename y with x15
3808                         opregreg(moveByType(v.Type), x15, y)
3809                         opregreg(moveByType(v.Type), r, x)
3810                         y = x15
3811                 } else if x != r {
3812                         opregreg(moveByType(v.Type), r, x)
3813                 }
3814                 opregreg(v.Op.Asm(), r, y)
3815
3816         case ssa.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW,
3817                 ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU,
3818                 ssa.OpAMD64MODQ, ssa.OpAMD64MODL, ssa.OpAMD64MODW,
3819                 ssa.OpAMD64MODQU, ssa.OpAMD64MODLU, ssa.OpAMD64MODWU:
3820
3821                 // Arg[0] is already in AX as it's the only register we allow
3822                 // and AX is the only output
3823                 x := regnum(v.Args[1])
3824
3825                 // CPU faults upon signed overflow, which occurs when most
3826                 // negative int is divided by -1.
3827                 var j *obj.Prog
3828                 if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL ||
3829                         v.Op == ssa.OpAMD64DIVW || v.Op == ssa.OpAMD64MODQ ||
3830                         v.Op == ssa.OpAMD64MODL || v.Op == ssa.OpAMD64MODW {
3831
3832                         var c *obj.Prog
3833                         switch v.Op {
3834                         case ssa.OpAMD64DIVQ, ssa.OpAMD64MODQ:
3835                                 c = Prog(x86.ACMPQ)
3836                                 j = Prog(x86.AJEQ)
3837                                 // go ahead and sign extend to save doing it later
3838                                 Prog(x86.ACQO)
3839
3840                         case ssa.OpAMD64DIVL, ssa.OpAMD64MODL:
3841                                 c = Prog(x86.ACMPL)
3842                                 j = Prog(x86.AJEQ)
3843                                 Prog(x86.ACDQ)
3844
3845                         case ssa.OpAMD64DIVW, ssa.OpAMD64MODW:
3846                                 c = Prog(x86.ACMPW)
3847                                 j = Prog(x86.AJEQ)
3848                                 Prog(x86.ACWD)
3849                         }
3850                         c.From.Type = obj.TYPE_REG
3851                         c.From.Reg = x
3852                         c.To.Type = obj.TYPE_CONST
3853                         c.To.Offset = -1
3854
3855                         j.To.Type = obj.TYPE_BRANCH
3856
3857                 }
3858
3859                 // for unsigned ints, we sign extend by setting DX = 0
3860                 // signed ints were sign extended above
3861                 if v.Op == ssa.OpAMD64DIVQU || v.Op == ssa.OpAMD64MODQU ||
3862                         v.Op == ssa.OpAMD64DIVLU || v.Op == ssa.OpAMD64MODLU ||
3863                         v.Op == ssa.OpAMD64DIVWU || v.Op == ssa.OpAMD64MODWU {
3864                         c := Prog(x86.AXORQ)
3865                         c.From.Type = obj.TYPE_REG
3866                         c.From.Reg = x86.REG_DX
3867                         c.To.Type = obj.TYPE_REG
3868                         c.To.Reg = x86.REG_DX
3869                 }
3870
3871                 p := Prog(v.Op.Asm())
3872                 p.From.Type = obj.TYPE_REG
3873                 p.From.Reg = x
3874
3875                 // signed division, rest of the check for -1 case
3876                 if j != nil {
3877                         j2 := Prog(obj.AJMP)
3878                         j2.To.Type = obj.TYPE_BRANCH
3879
3880                         var n *obj.Prog
3881                         if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL ||
3882                                 v.Op == ssa.OpAMD64DIVW {
3883                                 // n * -1 = -n
3884                                 n = Prog(x86.ANEGQ)
3885                                 n.To.Type = obj.TYPE_REG
3886                                 n.To.Reg = x86.REG_AX
3887                         } else {
3888                                 // n % -1 == 0
3889                                 n = Prog(x86.AXORQ)
3890                                 n.From.Type = obj.TYPE_REG
3891                                 n.From.Reg = x86.REG_DX
3892                                 n.To.Type = obj.TYPE_REG
3893                                 n.To.Reg = x86.REG_DX
3894                         }
3895
3896                         j.To.Val = n
3897                         j2.To.Val = Pc
3898                 }
3899
3900         case ssa.OpAMD64HMULQ, ssa.OpAMD64HMULL, ssa.OpAMD64HMULW, ssa.OpAMD64HMULB,
3901                 ssa.OpAMD64HMULQU, ssa.OpAMD64HMULLU, ssa.OpAMD64HMULWU, ssa.OpAMD64HMULBU:
3902                 // the frontend rewrites constant division by 8/16/32 bit integers into
3903                 // HMUL by a constant
3904                 // SSA rewrites generate the 64 bit versions
3905
3906                 // Arg[0] is already in AX as it's the only register we allow
3907                 // and DX is the only output we care about (the high bits)
3908                 p := Prog(v.Op.Asm())
3909                 p.From.Type = obj.TYPE_REG
3910                 p.From.Reg = regnum(v.Args[1])
3911
3912                 // IMULB puts the high portion in AH instead of DL,
3913                 // so move it to DL for consistency
3914                 if v.Type.Size() == 1 {
3915                         m := Prog(x86.AMOVB)
3916                         m.From.Type = obj.TYPE_REG
3917                         m.From.Reg = x86.REG_AH
3918                         m.To.Type = obj.TYPE_REG
3919                         m.To.Reg = x86.REG_DX
3920                 }
3921
3922         case ssa.OpAMD64AVGQU:
3923                 // compute (x+y)/2 unsigned.
3924                 // Do a 64-bit add, the overflow goes into the carry.
3925                 // Shift right once and pull the carry back into the 63rd bit.
3926                 r := regnum(v)
3927                 x := regnum(v.Args[0])
3928                 y := regnum(v.Args[1])
3929                 if x != r && y != r {
3930                         opregreg(moveByType(v.Type), r, x)
3931                         x = r
3932                 }
3933                 p := Prog(x86.AADDQ)
3934                 p.From.Type = obj.TYPE_REG
3935                 p.To.Type = obj.TYPE_REG
3936                 p.To.Reg = r
3937                 if x == r {
3938                         p.From.Reg = y
3939                 } else {
3940                         p.From.Reg = x
3941                 }
3942                 p = Prog(x86.ARCRQ)
3943                 p.From.Type = obj.TYPE_CONST
3944                 p.From.Offset = 1
3945                 p.To.Type = obj.TYPE_REG
3946                 p.To.Reg = r
3947
3948         case ssa.OpAMD64SHLQ, ssa.OpAMD64SHLL, ssa.OpAMD64SHLW, ssa.OpAMD64SHLB,
3949                 ssa.OpAMD64SHRQ, ssa.OpAMD64SHRL, ssa.OpAMD64SHRW, ssa.OpAMD64SHRB,
3950                 ssa.OpAMD64SARQ, ssa.OpAMD64SARL, ssa.OpAMD64SARW, ssa.OpAMD64SARB:
3951                 x := regnum(v.Args[0])
3952                 r := regnum(v)
3953                 if x != r {
3954                         if r == x86.REG_CX {
3955                                 v.Fatalf("can't implement %s, target and shift both in CX", v.LongString())
3956                         }
3957                         p := Prog(moveByType(v.Type))
3958                         p.From.Type = obj.TYPE_REG
3959                         p.From.Reg = x
3960                         p.To.Type = obj.TYPE_REG
3961                         p.To.Reg = r
3962                 }
3963                 p := Prog(v.Op.Asm())
3964                 p.From.Type = obj.TYPE_REG
3965                 p.From.Reg = regnum(v.Args[1]) // should be CX
3966                 p.To.Type = obj.TYPE_REG
3967                 p.To.Reg = r
3968         case ssa.OpAMD64ADDQconst, ssa.OpAMD64ADDLconst, ssa.OpAMD64ADDWconst:
3969                 r := regnum(v)
3970                 a := regnum(v.Args[0])
3971                 if r == a {
3972                         if v.AuxInt2Int64() == 1 {
3973                                 var asm int
3974                                 switch v.Op {
3975                                 // Software optimization manual recommends add $1,reg.
3976                                 // But inc/dec is 1 byte smaller. ICC always uses inc
3977                                 // Clang/GCC choose depending on flags, but prefer add.
3978                                 // Experiments show that inc/dec is both a little faster
3979                                 // and make a binary a little smaller.
3980                                 case ssa.OpAMD64ADDQconst:
3981                                         asm = x86.AINCQ
3982                                 case ssa.OpAMD64ADDLconst:
3983                                         asm = x86.AINCL
3984                                 case ssa.OpAMD64ADDWconst:
3985                                         asm = x86.AINCW
3986                                 }
3987                                 p := Prog(asm)
3988                                 p.To.Type = obj.TYPE_REG
3989                                 p.To.Reg = r
3990                                 return
3991                         } else if v.AuxInt2Int64() == -1 {
3992                                 var asm int
3993                                 switch v.Op {
3994                                 case ssa.OpAMD64ADDQconst:
3995                                         asm = x86.ADECQ
3996                                 case ssa.OpAMD64ADDLconst:
3997                                         asm = x86.ADECL
3998                                 case ssa.OpAMD64ADDWconst:
3999                                         asm = x86.ADECW
4000                                 }
4001                                 p := Prog(asm)
4002                                 p.To.Type = obj.TYPE_REG
4003                                 p.To.Reg = r
4004                                 return
4005                         } else {
4006                                 p := Prog(v.Op.Asm())
4007                                 p.From.Type = obj.TYPE_CONST
4008                                 p.From.Offset = v.AuxInt2Int64()
4009                                 p.To.Type = obj.TYPE_REG
4010                                 p.To.Reg = r
4011                                 return
4012                         }
4013                 }
4014                 var asm int
4015                 switch v.Op {
4016                 case ssa.OpAMD64ADDQconst:
4017                         asm = x86.ALEAQ
4018                 case ssa.OpAMD64ADDLconst:
4019                         asm = x86.ALEAL
4020                 case ssa.OpAMD64ADDWconst:
4021                         asm = x86.ALEAW
4022                 }
4023                 p := Prog(asm)
4024                 p.From.Type = obj.TYPE_MEM
4025                 p.From.Reg = a
4026                 p.From.Offset = v.AuxInt2Int64()
4027                 p.To.Type = obj.TYPE_REG
4028                 p.To.Reg = r
4029         case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst, ssa.OpAMD64MULWconst, ssa.OpAMD64MULBconst:
4030                 r := regnum(v)
4031                 x := regnum(v.Args[0])
4032                 if r != x {
4033                         p := Prog(moveByType(v.Type))
4034                         p.From.Type = obj.TYPE_REG
4035                         p.From.Reg = x
4036                         p.To.Type = obj.TYPE_REG
4037                         p.To.Reg = r
4038                 }
4039                 p := Prog(v.Op.Asm())
4040                 p.From.Type = obj.TYPE_CONST
4041                 p.From.Offset = v.AuxInt2Int64()
4042                 p.To.Type = obj.TYPE_REG
4043                 p.To.Reg = r
4044                 // TODO: Teach doasm to compile the three-address multiply imul $c, r1, r2
4045                 // instead of using the MOVQ above.
4046                 //p.From3 = new(obj.Addr)
4047                 //p.From3.Type = obj.TYPE_REG
4048                 //p.From3.Reg = regnum(v.Args[0])
4049         case ssa.OpAMD64SUBQconst, ssa.OpAMD64SUBLconst, ssa.OpAMD64SUBWconst:
4050                 x := regnum(v.Args[0])
4051                 r := regnum(v)
4052                 // We have 3-op add (lea), so transforming a = b - const into
4053                 // a = b + (- const), saves us 1 instruction. We can't fit
4054                 // - (-1 << 31) into  4 bytes offset in lea.
4055                 // We handle 2-address just fine below.
4056                 if v.AuxInt2Int64() == -1<<31 || x == r {
4057                         if x != r {
4058                                 // This code compensates for the fact that the register allocator
4059                                 // doesn't understand 2-address instructions yet.  TODO: fix that.
4060                                 p := Prog(moveByType(v.Type))
4061                                 p.From.Type = obj.TYPE_REG
4062                                 p.From.Reg = x
4063                                 p.To.Type = obj.TYPE_REG
4064                                 p.To.Reg = r
4065                         }
4066                         p := Prog(v.Op.Asm())
4067                         p.From.Type = obj.TYPE_CONST
4068                         p.From.Offset = v.AuxInt2Int64()
4069                         p.To.Type = obj.TYPE_REG
4070                         p.To.Reg = r
4071                 } else if x == r && v.AuxInt2Int64() == -1 {
4072                         var asm int
4073                         // x = x - (-1) is the same as x++
4074                         // See OpAMD64ADDQconst comments about inc vs add $1,reg
4075                         switch v.Op {
4076                         case ssa.OpAMD64SUBQconst:
4077                                 asm = x86.AINCQ
4078                         case ssa.OpAMD64SUBLconst:
4079                                 asm = x86.AINCL
4080                         case ssa.OpAMD64SUBWconst:
4081                                 asm = x86.AINCW
4082                         }
4083                         p := Prog(asm)
4084                         p.To.Type = obj.TYPE_REG
4085                         p.To.Reg = r
4086                 } else if x == r && v.AuxInt2Int64() == 1 {
4087                         var asm int
4088                         switch v.Op {
4089                         case ssa.OpAMD64SUBQconst:
4090                                 asm = x86.ADECQ
4091                         case ssa.OpAMD64SUBLconst:
4092                                 asm = x86.ADECL
4093                         case ssa.OpAMD64SUBWconst:
4094                                 asm = x86.ADECW
4095                         }
4096                         p := Prog(asm)
4097                         p.To.Type = obj.TYPE_REG
4098                         p.To.Reg = r
4099                 } else {
4100                         var asm int
4101                         switch v.Op {
4102                         case ssa.OpAMD64SUBQconst:
4103                                 asm = x86.ALEAQ
4104                         case ssa.OpAMD64SUBLconst:
4105                                 asm = x86.ALEAL
4106                         case ssa.OpAMD64SUBWconst:
4107                                 asm = x86.ALEAW
4108                         }
4109                         p := Prog(asm)
4110                         p.From.Type = obj.TYPE_MEM
4111                         p.From.Reg = x
4112                         p.From.Offset = -v.AuxInt2Int64()
4113                         p.To.Type = obj.TYPE_REG
4114                         p.To.Reg = r
4115                 }
4116
4117         case ssa.OpAMD64ADDBconst,
4118                 ssa.OpAMD64ANDQconst, ssa.OpAMD64ANDLconst, ssa.OpAMD64ANDWconst, ssa.OpAMD64ANDBconst,
4119                 ssa.OpAMD64ORQconst, ssa.OpAMD64ORLconst, ssa.OpAMD64ORWconst, ssa.OpAMD64ORBconst,
4120                 ssa.OpAMD64XORQconst, ssa.OpAMD64XORLconst, ssa.OpAMD64XORWconst, ssa.OpAMD64XORBconst,
4121                 ssa.OpAMD64SUBBconst, ssa.OpAMD64SHLQconst, ssa.OpAMD64SHLLconst, ssa.OpAMD64SHLWconst,
4122                 ssa.OpAMD64SHLBconst, ssa.OpAMD64SHRQconst, ssa.OpAMD64SHRLconst, ssa.OpAMD64SHRWconst,
4123                 ssa.OpAMD64SHRBconst, ssa.OpAMD64SARQconst, ssa.OpAMD64SARLconst, ssa.OpAMD64SARWconst,
4124                 ssa.OpAMD64SARBconst, ssa.OpAMD64ROLQconst, ssa.OpAMD64ROLLconst, ssa.OpAMD64ROLWconst,
4125                 ssa.OpAMD64ROLBconst:
4126                 // This code compensates for the fact that the register allocator
4127                 // doesn't understand 2-address instructions yet.  TODO: fix that.
4128                 x := regnum(v.Args[0])
4129                 r := regnum(v)
4130                 if x != r {
4131                         p := Prog(moveByType(v.Type))
4132                         p.From.Type = obj.TYPE_REG
4133                         p.From.Reg = x
4134                         p.To.Type = obj.TYPE_REG
4135                         p.To.Reg = r
4136                 }
4137                 p := Prog(v.Op.Asm())
4138                 p.From.Type = obj.TYPE_CONST
4139                 p.From.Offset = v.AuxInt2Int64()
4140                 p.To.Type = obj.TYPE_REG
4141                 p.To.Reg = r
4142         case ssa.OpAMD64SBBQcarrymask, ssa.OpAMD64SBBLcarrymask:
4143                 r := regnum(v)
4144                 p := Prog(v.Op.Asm())
4145                 p.From.Type = obj.TYPE_REG
4146                 p.From.Reg = r
4147                 p.To.Type = obj.TYPE_REG
4148                 p.To.Reg = r
4149         case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8:
4150                 p := Prog(x86.ALEAQ)
4151                 p.From.Type = obj.TYPE_MEM
4152                 p.From.Reg = regnum(v.Args[0])
4153                 switch v.Op {
4154                 case ssa.OpAMD64LEAQ1:
4155                         p.From.Scale = 1
4156                 case ssa.OpAMD64LEAQ2:
4157                         p.From.Scale = 2
4158                 case ssa.OpAMD64LEAQ4:
4159                         p.From.Scale = 4
4160                 case ssa.OpAMD64LEAQ8:
4161                         p.From.Scale = 8
4162                 }
4163                 p.From.Index = regnum(v.Args[1])
4164                 addAux(&p.From, v)
4165                 p.To.Type = obj.TYPE_REG
4166                 p.To.Reg = regnum(v)
4167         case ssa.OpAMD64LEAQ:
4168                 p := Prog(x86.ALEAQ)
4169                 p.From.Type = obj.TYPE_MEM
4170                 p.From.Reg = regnum(v.Args[0])
4171                 addAux(&p.From, v)
4172                 p.To.Type = obj.TYPE_REG
4173                 p.To.Reg = regnum(v)
4174         case ssa.OpAMD64CMPQ, ssa.OpAMD64CMPL, ssa.OpAMD64CMPW, ssa.OpAMD64CMPB,
4175                 ssa.OpAMD64TESTQ, ssa.OpAMD64TESTL, ssa.OpAMD64TESTW, ssa.OpAMD64TESTB:
4176                 opregreg(v.Op.Asm(), regnum(v.Args[1]), regnum(v.Args[0]))
4177         case ssa.OpAMD64UCOMISS, ssa.OpAMD64UCOMISD:
4178                 // Go assembler has swapped operands for UCOMISx relative to CMP,
4179                 // must account for that right here.
4180                 opregreg(v.Op.Asm(), regnum(v.Args[0]), regnum(v.Args[1]))
4181         case ssa.OpAMD64CMPQconst, ssa.OpAMD64CMPLconst, ssa.OpAMD64CMPWconst, ssa.OpAMD64CMPBconst:
4182                 p := Prog(v.Op.Asm())
4183                 p.From.Type = obj.TYPE_REG
4184                 p.From.Reg = regnum(v.Args[0])
4185                 p.To.Type = obj.TYPE_CONST
4186                 p.To.Offset = v.AuxInt2Int64()
4187         case ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst:
4188                 p := Prog(v.Op.Asm())
4189                 p.From.Type = obj.TYPE_CONST
4190                 p.From.Offset = v.AuxInt2Int64()
4191                 p.To.Type = obj.TYPE_REG
4192                 p.To.Reg = regnum(v.Args[0])
4193         case ssa.OpAMD64MOVBconst, ssa.OpAMD64MOVWconst, ssa.OpAMD64MOVLconst, ssa.OpAMD64MOVQconst:
4194                 x := regnum(v)
4195                 p := Prog(v.Op.Asm())
4196                 p.From.Type = obj.TYPE_CONST
4197                 p.From.Offset = v.AuxInt2Int64()
4198                 p.To.Type = obj.TYPE_REG
4199                 p.To.Reg = x
4200                 // If flags are live at this instruction, suppress the
4201                 // MOV $0,AX -> XOR AX,AX optimization.
4202                 if v.Aux != nil {
4203                         p.Mark |= x86.PRESERVEFLAGS
4204                 }
4205         case ssa.OpAMD64MOVSSconst, ssa.OpAMD64MOVSDconst:
4206                 x := regnum(v)
4207                 p := Prog(v.Op.Asm())
4208                 p.From.Type = obj.TYPE_FCONST
4209                 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
4210                 p.To.Type = obj.TYPE_REG
4211                 p.To.Reg = x
4212         case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVWQZXload, ssa.OpAMD64MOVLQSXload, ssa.OpAMD64MOVLQZXload, ssa.OpAMD64MOVOload:
4213                 p := Prog(v.Op.Asm())
4214                 p.From.Type = obj.TYPE_MEM
4215                 p.From.Reg = regnum(v.Args[0])
4216                 addAux(&p.From, v)
4217                 p.To.Type = obj.TYPE_REG
4218                 p.To.Reg = regnum(v)
4219         case ssa.OpAMD64MOVQloadidx8, ssa.OpAMD64MOVSDloadidx8:
4220                 p := Prog(v.Op.Asm())
4221                 p.From.Type = obj.TYPE_MEM
4222                 p.From.Reg = regnum(v.Args[0])
4223                 addAux(&p.From, v)
4224                 p.From.Scale = 8
4225                 p.From.Index = regnum(v.Args[1])
4226                 p.To.Type = obj.TYPE_REG
4227                 p.To.Reg = regnum(v)
4228         case ssa.OpAMD64MOVLloadidx4, ssa.OpAMD64MOVSSloadidx4:
4229                 p := Prog(v.Op.Asm())
4230                 p.From.Type = obj.TYPE_MEM
4231                 p.From.Reg = regnum(v.Args[0])
4232                 addAux(&p.From, v)
4233                 p.From.Scale = 4
4234                 p.From.Index = regnum(v.Args[1])
4235                 p.To.Type = obj.TYPE_REG
4236                 p.To.Reg = regnum(v)
4237         case ssa.OpAMD64MOVWloadidx2:
4238                 p := Prog(v.Op.Asm())
4239                 p.From.Type = obj.TYPE_MEM
4240                 p.From.Reg = regnum(v.Args[0])
4241                 addAux(&p.From, v)
4242                 p.From.Scale = 2
4243                 p.From.Index = regnum(v.Args[1])
4244                 p.To.Type = obj.TYPE_REG
4245                 p.To.Reg = regnum(v)
4246         case ssa.OpAMD64MOVBloadidx1:
4247                 p := Prog(v.Op.Asm())
4248                 p.From.Type = obj.TYPE_MEM
4249                 p.From.Reg = regnum(v.Args[0])
4250                 addAux(&p.From, v)
4251                 p.From.Scale = 1
4252                 p.From.Index = regnum(v.Args[1])
4253                 p.To.Type = obj.TYPE_REG
4254                 p.To.Reg = regnum(v)
4255         case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore:
4256                 p := Prog(v.Op.Asm())
4257                 p.From.Type = obj.TYPE_REG
4258                 p.From.Reg = regnum(v.Args[1])
4259                 p.To.Type = obj.TYPE_MEM
4260                 p.To.Reg = regnum(v.Args[0])
4261                 addAux(&p.To, v)
4262         case ssa.OpAMD64MOVQstoreidx8, ssa.OpAMD64MOVSDstoreidx8:
4263                 p := Prog(v.Op.Asm())
4264                 p.From.Type = obj.TYPE_REG
4265                 p.From.Reg = regnum(v.Args[2])
4266                 p.To.Type = obj.TYPE_MEM
4267                 p.To.Reg = regnum(v.Args[0])
4268                 p.To.Scale = 8
4269                 p.To.Index = regnum(v.Args[1])
4270                 addAux(&p.To, v)
4271         case ssa.OpAMD64MOVSSstoreidx4, ssa.OpAMD64MOVLstoreidx4:
4272                 p := Prog(v.Op.Asm())
4273                 p.From.Type = obj.TYPE_REG
4274                 p.From.Reg = regnum(v.Args[2])
4275                 p.To.Type = obj.TYPE_MEM
4276                 p.To.Reg = regnum(v.Args[0])
4277                 p.To.Scale = 4
4278                 p.To.Index = regnum(v.Args[1])
4279                 addAux(&p.To, v)
4280         case ssa.OpAMD64MOVWstoreidx2:
4281                 p := Prog(v.Op.Asm())
4282                 p.From.Type = obj.TYPE_REG
4283                 p.From.Reg = regnum(v.Args[2])
4284                 p.To.Type = obj.TYPE_MEM
4285                 p.To.Reg = regnum(v.Args[0])
4286                 p.To.Scale = 2
4287                 p.To.Index = regnum(v.Args[1])
4288                 addAux(&p.To, v)
4289         case ssa.OpAMD64MOVBstoreidx1:
4290                 p := Prog(v.Op.Asm())
4291                 p.From.Type = obj.TYPE_REG
4292                 p.From.Reg = regnum(v.Args[2])
4293                 p.To.Type = obj.TYPE_MEM
4294                 p.To.Reg = regnum(v.Args[0])
4295                 p.To.Scale = 1
4296                 p.To.Index = regnum(v.Args[1])
4297                 addAux(&p.To, v)
4298         case ssa.OpAMD64MOVQstoreconst, ssa.OpAMD64MOVLstoreconst, ssa.OpAMD64MOVWstoreconst, ssa.OpAMD64MOVBstoreconst:
4299                 p := Prog(v.Op.Asm())
4300                 p.From.Type = obj.TYPE_CONST
4301                 sc := v.AuxValAndOff()
4302                 i := sc.Val()
4303                 switch v.Op {
4304                 case ssa.OpAMD64MOVBstoreconst:
4305                         i = int64(int8(i))
4306                 case ssa.OpAMD64MOVWstoreconst:
4307                         i = int64(int16(i))
4308                 case ssa.OpAMD64MOVLstoreconst:
4309                         i = int64(int32(i))
4310                 case ssa.OpAMD64MOVQstoreconst:
4311                 }
4312                 p.From.Offset = i
4313                 p.To.Type = obj.TYPE_MEM
4314                 p.To.Reg = regnum(v.Args[0])
4315                 addAux2(&p.To, v, sc.Off())
4316         case ssa.OpAMD64MOVQstoreconstidx8, ssa.OpAMD64MOVLstoreconstidx4, ssa.OpAMD64MOVWstoreconstidx2, ssa.OpAMD64MOVBstoreconstidx1:
4317                 p := Prog(v.Op.Asm())
4318                 p.From.Type = obj.TYPE_CONST
4319                 sc := v.AuxValAndOff()
4320                 switch v.Op {
4321                 case ssa.OpAMD64MOVBstoreconstidx1:
4322                         p.From.Offset = int64(int8(sc.Val()))
4323                         p.To.Scale = 1
4324                 case ssa.OpAMD64MOVWstoreconstidx2:
4325                         p.From.Offset = int64(int16(sc.Val()))
4326                         p.To.Scale = 2
4327                 case ssa.OpAMD64MOVLstoreconstidx4:
4328                         p.From.Offset = int64(int32(sc.Val()))
4329                         p.To.Scale = 4
4330                 case ssa.OpAMD64MOVQstoreconstidx8:
4331                         p.From.Offset = sc.Val()
4332                         p.To.Scale = 8
4333                 }
4334                 p.To.Type = obj.TYPE_MEM
4335                 p.To.Reg = regnum(v.Args[0])
4336                 p.To.Index = regnum(v.Args[1])
4337                 addAux2(&p.To, v, sc.Off())
4338         case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX,
4339                 ssa.OpAMD64CVTSL2SS, ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSQ2SD,
4340                 ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ,
4341                 ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS:
4342                 opregreg(v.Op.Asm(), regnum(v), regnum(v.Args[0]))
4343         case ssa.OpAMD64DUFFZERO:
4344                 p := Prog(obj.ADUFFZERO)
4345                 p.To.Type = obj.TYPE_ADDR
4346                 p.To.Sym = Linksym(Pkglookup("duffzero", Runtimepkg))
4347                 p.To.Offset = v.AuxInt
4348         case ssa.OpAMD64MOVOconst:
4349                 if v.AuxInt != 0 {
4350                         v.Unimplementedf("MOVOconst can only do constant=0")
4351                 }
4352                 r := regnum(v)
4353                 opregreg(x86.AXORPS, r, r)
4354         case ssa.OpAMD64DUFFCOPY:
4355                 p := Prog(obj.ADUFFCOPY)
4356                 p.To.Type = obj.TYPE_ADDR
4357                 p.To.Sym = Linksym(Pkglookup("duffcopy", Runtimepkg))
4358                 p.To.Offset = v.AuxInt
4359
4360         case ssa.OpCopy, ssa.OpAMD64MOVQconvert: // TODO: use MOVQreg for reg->reg copies instead of OpCopy?
4361                 if v.Type.IsMemory() {
4362                         return
4363                 }
4364                 x := regnum(v.Args[0])
4365                 y := regnum(v)
4366                 if x != y {
4367                         opregreg(moveByType(v.Type), y, x)
4368                 }
4369         case ssa.OpLoadReg:
4370                 if v.Type.IsFlags() {
4371                         v.Unimplementedf("load flags not implemented: %v", v.LongString())
4372                         return
4373                 }
4374                 p := Prog(loadByType(v.Type))
4375                 n, off := autoVar(v.Args[0])
4376                 p.From.Type = obj.TYPE_MEM
4377                 p.From.Node = n
4378                 p.From.Sym = Linksym(n.Sym)
4379                 p.From.Offset = off
4380                 if n.Class == PPARAM {
4381                         p.From.Name = obj.NAME_PARAM
4382                         p.From.Offset += n.Xoffset
4383                 } else {
4384                         p.From.Name = obj.NAME_AUTO
4385                 }
4386                 p.To.Type = obj.TYPE_REG
4387                 p.To.Reg = regnum(v)
4388
4389         case ssa.OpStoreReg:
4390                 if v.Type.IsFlags() {
4391                         v.Unimplementedf("store flags not implemented: %v", v.LongString())
4392                         return
4393                 }
4394                 p := Prog(storeByType(v.Type))
4395                 p.From.Type = obj.TYPE_REG
4396                 p.From.Reg = regnum(v.Args[0])
4397                 n, off := autoVar(v)
4398                 p.To.Type = obj.TYPE_MEM
4399                 p.To.Node = n
4400                 p.To.Sym = Linksym(n.Sym)
4401                 p.To.Offset = off
4402                 if n.Class == PPARAM {
4403                         p.To.Name = obj.NAME_PARAM
4404                         p.To.Offset += n.Xoffset
4405                 } else {
4406                         p.To.Name = obj.NAME_AUTO
4407                 }
4408         case ssa.OpPhi:
4409                 // just check to make sure regalloc and stackalloc did it right
4410                 if v.Type.IsMemory() {
4411                         return
4412                 }
4413                 f := v.Block.Func
4414                 loc := f.RegAlloc[v.ID]
4415                 for _, a := range v.Args {
4416                         if aloc := f.RegAlloc[a.ID]; aloc != loc { // TODO: .Equal() instead?
4417                                 v.Fatalf("phi arg at different location than phi: %v @ %v, but arg %v @ %v\n%s\n", v, loc, a, aloc, v.Block.Func)
4418                         }
4419                 }
4420         case ssa.OpInitMem:
4421                 // memory arg needs no code
4422         case ssa.OpArg:
4423                 // input args need no code
4424         case ssa.OpAMD64LoweredGetClosurePtr:
4425                 // Output is hardwired to DX only,
4426                 // and DX contains the closure pointer on
4427                 // closure entry, and this "instruction"
4428                 // is scheduled to the very beginning
4429                 // of the entry block.
4430         case ssa.OpAMD64LoweredGetG:
4431                 r := regnum(v)
4432                 // See the comments in cmd/internal/obj/x86/obj6.go
4433                 // near CanUse1InsnTLS for a detailed explanation of these instructions.
4434                 if x86.CanUse1InsnTLS(Ctxt) {
4435                         // MOVQ (TLS), r
4436                         p := Prog(x86.AMOVQ)
4437                         p.From.Type = obj.TYPE_MEM
4438                         p.From.Reg = x86.REG_TLS
4439                         p.To.Type = obj.TYPE_REG
4440                         p.To.Reg = r
4441                 } else {
4442                         // MOVQ TLS, r
4443                         // MOVQ (r)(TLS*1), r
4444                         p := Prog(x86.AMOVQ)
4445                         p.From.Type = obj.TYPE_REG
4446                         p.From.Reg = x86.REG_TLS
4447                         p.To.Type = obj.TYPE_REG
4448                         p.To.Reg = r
4449                         q := Prog(x86.AMOVQ)
4450                         q.From.Type = obj.TYPE_MEM
4451                         q.From.Reg = r
4452                         q.From.Index = x86.REG_TLS
4453                         q.From.Scale = 1
4454                         q.To.Type = obj.TYPE_REG
4455                         q.To.Reg = r
4456                 }
4457         case ssa.OpAMD64CALLstatic:
4458                 p := Prog(obj.ACALL)
4459                 p.To.Type = obj.TYPE_MEM
4460                 p.To.Name = obj.NAME_EXTERN
4461                 p.To.Sym = Linksym(v.Aux.(*Sym))
4462                 if Maxarg < v.AuxInt {
4463                         Maxarg = v.AuxInt
4464                 }
4465         case ssa.OpAMD64CALLclosure:
4466                 p := Prog(obj.ACALL)
4467                 p.To.Type = obj.TYPE_REG
4468                 p.To.Reg = regnum(v.Args[0])
4469                 if Maxarg < v.AuxInt {
4470                         Maxarg = v.AuxInt
4471                 }
4472         case ssa.OpAMD64CALLdefer:
4473                 p := Prog(obj.ACALL)
4474                 p.To.Type = obj.TYPE_MEM
4475                 p.To.Name = obj.NAME_EXTERN
4476                 p.To.Sym = Linksym(Deferproc.Sym)
4477                 if Maxarg < v.AuxInt {
4478                         Maxarg = v.AuxInt
4479                 }
4480                 // defer returns in rax:
4481                 // 0 if we should continue executing
4482                 // 1 if we should jump to deferreturn call
4483                 p = Prog(x86.ATESTL)
4484                 p.From.Type = obj.TYPE_REG
4485                 p.From.Reg = x86.REG_AX
4486                 p.To.Type = obj.TYPE_REG
4487                 p.To.Reg = x86.REG_AX
4488                 p = Prog(x86.AJNE)
4489                 p.To.Type = obj.TYPE_BRANCH
4490                 s.deferBranches = append(s.deferBranches, p)
4491         case ssa.OpAMD64CALLgo:
4492                 p := Prog(obj.ACALL)
4493                 p.To.Type = obj.TYPE_MEM
4494                 p.To.Name = obj.NAME_EXTERN
4495                 p.To.Sym = Linksym(Newproc.Sym)
4496                 if Maxarg < v.AuxInt {
4497                         Maxarg = v.AuxInt
4498                 }
4499         case ssa.OpAMD64CALLinter:
4500                 p := Prog(obj.ACALL)
4501                 p.To.Type = obj.TYPE_REG
4502                 p.To.Reg = regnum(v.Args[0])
4503                 if Maxarg < v.AuxInt {
4504                         Maxarg = v.AuxInt
4505                 }
4506         case ssa.OpAMD64NEGQ, ssa.OpAMD64NEGL, ssa.OpAMD64NEGW, ssa.OpAMD64NEGB,
4507                 ssa.OpAMD64NOTQ, ssa.OpAMD64NOTL, ssa.OpAMD64NOTW, ssa.OpAMD64NOTB:
4508                 x := regnum(v.Args[0])
4509                 r := regnum(v)
4510                 if x != r {
4511                         p := Prog(moveByType(v.Type))
4512                         p.From.Type = obj.TYPE_REG
4513                         p.From.Reg = x
4514                         p.To.Type = obj.TYPE_REG
4515                         p.To.Reg = r
4516                 }
4517                 p := Prog(v.Op.Asm())
4518                 p.To.Type = obj.TYPE_REG
4519                 p.To.Reg = r
4520         case ssa.OpAMD64SQRTSD:
4521                 p := Prog(v.Op.Asm())
4522                 p.From.Type = obj.TYPE_REG
4523                 p.From.Reg = regnum(v.Args[0])
4524                 p.To.Type = obj.TYPE_REG
4525                 p.To.Reg = regnum(v)
4526         case ssa.OpSP, ssa.OpSB:
4527                 // nothing to do
4528         case ssa.OpAMD64SETEQ, ssa.OpAMD64SETNE,
4529                 ssa.OpAMD64SETL, ssa.OpAMD64SETLE,
4530                 ssa.OpAMD64SETG, ssa.OpAMD64SETGE,
4531                 ssa.OpAMD64SETGF, ssa.OpAMD64SETGEF,
4532                 ssa.OpAMD64SETB, ssa.OpAMD64SETBE,
4533                 ssa.OpAMD64SETORD, ssa.OpAMD64SETNAN,
4534                 ssa.OpAMD64SETA, ssa.OpAMD64SETAE:
4535                 p := Prog(v.Op.Asm())
4536                 p.To.Type = obj.TYPE_REG
4537                 p.To.Reg = regnum(v)
4538
4539         case ssa.OpAMD64SETNEF:
4540                 p := Prog(v.Op.Asm())
4541                 p.To.Type = obj.TYPE_REG
4542                 p.To.Reg = regnum(v)
4543                 q := Prog(x86.ASETPS)
4544                 q.To.Type = obj.TYPE_REG
4545                 q.To.Reg = x86.REG_AX
4546                 // TODO AORQ copied from old code generator, why not AORB?
4547                 opregreg(x86.AORQ, regnum(v), x86.REG_AX)
4548
4549         case ssa.OpAMD64SETEQF:
4550                 p := Prog(v.Op.Asm())
4551                 p.To.Type = obj.TYPE_REG
4552                 p.To.Reg = regnum(v)
4553                 q := Prog(x86.ASETPC)
4554                 q.To.Type = obj.TYPE_REG
4555                 q.To.Reg = x86.REG_AX
4556                 // TODO AANDQ copied from old code generator, why not AANDB?
4557                 opregreg(x86.AANDQ, regnum(v), x86.REG_AX)
4558
4559         case ssa.OpAMD64InvertFlags:
4560                 v.Fatalf("InvertFlags should never make it to codegen %v", v)
4561         case ssa.OpAMD64FlagEQ, ssa.OpAMD64FlagLT_ULT, ssa.OpAMD64FlagLT_UGT, ssa.OpAMD64FlagGT_ULT, ssa.OpAMD64FlagGT_UGT:
4562                 v.Fatalf("Flag* ops should never make it to codegen %v", v)
4563         case ssa.OpAMD64REPSTOSQ:
4564                 Prog(x86.AREP)
4565                 Prog(x86.ASTOSQ)
4566         case ssa.OpAMD64REPMOVSQ:
4567                 Prog(x86.AREP)
4568                 Prog(x86.AMOVSQ)
4569         case ssa.OpVarDef:
4570                 Gvardef(v.Aux.(*Node))
4571         case ssa.OpVarKill:
4572                 gvarkill(v.Aux.(*Node))
4573         case ssa.OpVarLive:
4574                 gvarlive(v.Aux.(*Node))
4575         case ssa.OpAMD64LoweredNilCheck:
4576                 // Optimization - if the subsequent block has a load or store
4577                 // at the same address, we don't need to issue this instruction.
4578                 mem := v.Args[1]
4579                 for _, w := range v.Block.Succs[0].Values {
4580                         if w.Op == ssa.OpPhi {
4581                                 if w.Type.IsMemory() {
4582                                         mem = w
4583                                 }
4584                                 continue
4585                         }
4586                         if len(w.Args) == 0 || !w.Args[len(w.Args)-1].Type.IsMemory() {
4587                                 // w doesn't use a store - can't be a memory op.
4588                                 continue
4589                         }
4590                         if w.Args[len(w.Args)-1] != mem {
4591                                 v.Fatalf("wrong store after nilcheck v=%s w=%s", v, w)
4592                         }
4593                         switch w.Op {
4594                         case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload,
4595                                 ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore,
4596                                 ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload, ssa.OpAMD64MOVWQSXload,
4597                                 ssa.OpAMD64MOVWQZXload, ssa.OpAMD64MOVLQSXload, ssa.OpAMD64MOVLQZXload,
4598                                 ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVOload,
4599                                 ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVOstore:
4600                                 if w.Args[0] == v.Args[0] && w.Aux == nil && w.AuxInt >= 0 && w.AuxInt < minZeroPage {
4601                                         if Debug_checknil != 0 && int(v.Line) > 1 {
4602                                                 Warnl(int(v.Line), "removed nil check")
4603                                         }
4604                                         return
4605                                 }
4606                         case ssa.OpAMD64MOVQstoreconst, ssa.OpAMD64MOVLstoreconst, ssa.OpAMD64MOVWstoreconst, ssa.OpAMD64MOVBstoreconst:
4607                                 off := ssa.ValAndOff(v.AuxInt).Off()
4608                                 if w.Args[0] == v.Args[0] && w.Aux == nil && off >= 0 && off < minZeroPage {
4609                                         if Debug_checknil != 0 && int(v.Line) > 1 {
4610                                                 Warnl(int(v.Line), "removed nil check")
4611                                         }
4612                                         return
4613                                 }
4614                         }
4615                         if w.Type.IsMemory() {
4616                                 if w.Op == ssa.OpVarDef || w.Op == ssa.OpVarKill || w.Op == ssa.OpVarLive {
4617                                         // these ops are OK
4618                                         mem = w
4619                                         continue
4620                                 }
4621                                 // We can't delay the nil check past the next store.
4622                                 break
4623                         }
4624                 }
4625                 // Issue a load which will fault if the input is nil.
4626                 // TODO: We currently use the 2-byte instruction TESTB AX, (reg).
4627                 // Should we use the 3-byte TESTB $0, (reg) instead?  It is larger
4628                 // but it doesn't have false dependency on AX.
4629                 // Or maybe allocate an output register and use MOVL (reg),reg2 ?
4630                 // That trades clobbering flags for clobbering a register.
4631                 p := Prog(x86.ATESTB)
4632                 p.From.Type = obj.TYPE_REG
4633                 p.From.Reg = x86.REG_AX
4634                 p.To.Type = obj.TYPE_MEM
4635                 p.To.Reg = regnum(v.Args[0])
4636                 addAux(&p.To, v)
4637                 if Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers
4638                         Warnl(int(v.Line), "generated nil check")
4639                 }
4640         default:
4641                 v.Unimplementedf("genValue not implemented: %s", v.LongString())
4642         }
4643 }
4644
4645 // markMoves marks any MOVXconst ops that need to avoid clobbering flags.
4646 func (s *genState) markMoves(b *ssa.Block) {
4647         flive := b.FlagsLiveAtEnd
4648         if b.Control != nil && b.Control.Type.IsFlags() {
4649                 flive = true
4650         }
4651         for i := len(b.Values) - 1; i >= 0; i-- {
4652                 v := b.Values[i]
4653                 if flive && (v.Op == ssa.OpAMD64MOVBconst || v.Op == ssa.OpAMD64MOVWconst || v.Op == ssa.OpAMD64MOVLconst || v.Op == ssa.OpAMD64MOVQconst) {
4654                         // The "mark" is any non-nil Aux value.
4655                         v.Aux = v
4656                 }
4657                 if v.Type.IsFlags() {
4658                         flive = false
4659                 }
4660                 for _, a := range v.Args {
4661                         if a.Type.IsFlags() {
4662                                 flive = true
4663                         }
4664                 }
4665         }
4666 }
4667
4668 // movZero generates a register indirect move with a 0 immediate and keeps track of bytes left and next offset
4669 func movZero(as int, width int64, nbytes int64, offset int64, regnum int16) (nleft int64, noff int64) {
4670         p := Prog(as)
4671         // TODO: use zero register on archs that support it.
4672         p.From.Type = obj.TYPE_CONST
4673         p.From.Offset = 0
4674         p.To.Type = obj.TYPE_MEM
4675         p.To.Reg = regnum
4676         p.To.Offset = offset
4677         offset += width
4678         nleft = nbytes - width
4679         return nleft, offset
4680 }
4681
4682 var blockJump = [...]struct {
4683         asm, invasm int
4684 }{
4685         ssa.BlockAMD64EQ:  {x86.AJEQ, x86.AJNE},
4686         ssa.BlockAMD64NE:  {x86.AJNE, x86.AJEQ},
4687         ssa.BlockAMD64LT:  {x86.AJLT, x86.AJGE},
4688         ssa.BlockAMD64GE:  {x86.AJGE, x86.AJLT},
4689         ssa.BlockAMD64LE:  {x86.AJLE, x86.AJGT},
4690         ssa.BlockAMD64GT:  {x86.AJGT, x86.AJLE},
4691         ssa.BlockAMD64ULT: {x86.AJCS, x86.AJCC},
4692         ssa.BlockAMD64UGE: {x86.AJCC, x86.AJCS},
4693         ssa.BlockAMD64UGT: {x86.AJHI, x86.AJLS},
4694         ssa.BlockAMD64ULE: {x86.AJLS, x86.AJHI},
4695         ssa.BlockAMD64ORD: {x86.AJPC, x86.AJPS},
4696         ssa.BlockAMD64NAN: {x86.AJPS, x86.AJPC},
4697 }
4698
4699 type floatingEQNEJump struct {
4700         jump, index int
4701 }
4702
4703 var eqfJumps = [2][2]floatingEQNEJump{
4704         {{x86.AJNE, 1}, {x86.AJPS, 1}}, // next == b.Succs[0]
4705         {{x86.AJNE, 1}, {x86.AJPC, 0}}, // next == b.Succs[1]
4706 }
4707 var nefJumps = [2][2]floatingEQNEJump{
4708         {{x86.AJNE, 0}, {x86.AJPC, 1}}, // next == b.Succs[0]
4709         {{x86.AJNE, 0}, {x86.AJPS, 0}}, // next == b.Succs[1]
4710 }
4711
4712 func oneFPJump(b *ssa.Block, jumps *floatingEQNEJump, likely ssa.BranchPrediction, branches []branch) []branch {
4713         p := Prog(jumps.jump)
4714         p.To.Type = obj.TYPE_BRANCH
4715         to := jumps.index
4716         branches = append(branches, branch{p, b.Succs[to]})
4717         if to == 1 {
4718                 likely = -likely
4719         }
4720         // liblink reorders the instruction stream as it sees fit.
4721         // Pass along what we know so liblink can make use of it.
4722         // TODO: Once we've fully switched to SSA,
4723         // make liblink leave our output alone.
4724         switch likely {
4725         case ssa.BranchUnlikely:
4726                 p.From.Type = obj.TYPE_CONST
4727                 p.From.Offset = 0
4728         case ssa.BranchLikely:
4729                 p.From.Type = obj.TYPE_CONST
4730                 p.From.Offset = 1
4731         }
4732         return branches
4733 }
4734
4735 func genFPJump(s *genState, b, next *ssa.Block, jumps *[2][2]floatingEQNEJump) {
4736         likely := b.Likely
4737         switch next {
4738         case b.Succs[0]:
4739                 s.branches = oneFPJump(b, &jumps[0][0], likely, s.branches)
4740                 s.branches = oneFPJump(b, &jumps[0][1], likely, s.branches)
4741         case b.Succs[1]:
4742                 s.branches = oneFPJump(b, &jumps[1][0], likely, s.branches)
4743                 s.branches = oneFPJump(b, &jumps[1][1], likely, s.branches)
4744         default:
4745                 s.branches = oneFPJump(b, &jumps[1][0], likely, s.branches)
4746                 s.branches = oneFPJump(b, &jumps[1][1], likely, s.branches)
4747                 q := Prog(obj.AJMP)
4748                 q.To.Type = obj.TYPE_BRANCH
4749                 s.branches = append(s.branches, branch{q, b.Succs[1]})
4750         }
4751 }
4752
4753 func (s *genState) genBlock(b, next *ssa.Block) {
4754         lineno = b.Line
4755
4756         switch b.Kind {
4757         case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
4758                 if b.Succs[0] != next {
4759                         p := Prog(obj.AJMP)
4760                         p.To.Type = obj.TYPE_BRANCH
4761                         s.branches = append(s.branches, branch{p, b.Succs[0]})
4762                 }
4763         case ssa.BlockExit:
4764                 Prog(obj.AUNDEF) // tell plive.go that we never reach here
4765         case ssa.BlockRet:
4766                 if hasdefer {
4767                         s.deferReturn()
4768                 }
4769                 Prog(obj.ARET)
4770         case ssa.BlockRetJmp:
4771                 p := Prog(obj.AJMP)
4772                 p.To.Type = obj.TYPE_MEM
4773                 p.To.Name = obj.NAME_EXTERN
4774                 p.To.Sym = Linksym(b.Aux.(*Sym))
4775
4776         case ssa.BlockAMD64EQF:
4777                 genFPJump(s, b, next, &eqfJumps)
4778
4779         case ssa.BlockAMD64NEF:
4780                 genFPJump(s, b, next, &nefJumps)
4781
4782         case ssa.BlockAMD64EQ, ssa.BlockAMD64NE,
4783                 ssa.BlockAMD64LT, ssa.BlockAMD64GE,
4784                 ssa.BlockAMD64LE, ssa.BlockAMD64GT,
4785                 ssa.BlockAMD64ULT, ssa.BlockAMD64UGT,
4786                 ssa.BlockAMD64ULE, ssa.BlockAMD64UGE:
4787                 jmp := blockJump[b.Kind]
4788                 likely := b.Likely
4789                 var p *obj.Prog
4790                 switch next {
4791                 case b.Succs[0]:
4792                         p = Prog(jmp.invasm)
4793                         likely *= -1
4794                         p.To.Type = obj.TYPE_BRANCH
4795                         s.branches = append(s.branches, branch{p, b.Succs[1]})
4796                 case b.Succs[1]:
4797                         p = Prog(jmp.asm)
4798                         p.To.Type = obj.TYPE_BRANCH
4799                         s.branches = append(s.branches, branch{p, b.Succs[0]})
4800                 default:
4801                         p = Prog(jmp.asm)
4802                         p.To.Type = obj.TYPE_BRANCH
4803                         s.branches = append(s.branches, branch{p, b.Succs[0]})
4804                         q := Prog(obj.AJMP)
4805                         q.To.Type = obj.TYPE_BRANCH
4806                         s.branches = append(s.branches, branch{q, b.Succs[1]})
4807                 }
4808
4809                 // liblink reorders the instruction stream as it sees fit.
4810                 // Pass along what we know so liblink can make use of it.
4811                 // TODO: Once we've fully switched to SSA,
4812                 // make liblink leave our output alone.
4813                 switch likely {
4814                 case ssa.BranchUnlikely:
4815                         p.From.Type = obj.TYPE_CONST
4816                         p.From.Offset = 0
4817                 case ssa.BranchLikely:
4818                         p.From.Type = obj.TYPE_CONST
4819                         p.From.Offset = 1
4820                 }
4821
4822         default:
4823                 b.Unimplementedf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
4824         }
4825 }
4826
4827 func (s *genState) deferReturn() {
4828         // Deferred calls will appear to be returning to
4829         // the CALL deferreturn(SB) that we are about to emit.
4830         // However, the stack trace code will show the line
4831         // of the instruction byte before the return PC.
4832         // To avoid that being an unrelated instruction,
4833         // insert an actual hardware NOP that will have the right line number.
4834         // This is different from obj.ANOP, which is a virtual no-op
4835         // that doesn't make it into the instruction stream.
4836         s.deferTarget = Pc
4837         Thearch.Ginsnop()
4838         p := Prog(obj.ACALL)
4839         p.To.Type = obj.TYPE_MEM
4840         p.To.Name = obj.NAME_EXTERN
4841         p.To.Sym = Linksym(Deferreturn.Sym)
4842 }
4843
4844 // addAux adds the offset in the aux fields (AuxInt and Aux) of v to a.
4845 func addAux(a *obj.Addr, v *ssa.Value) {
4846         addAux2(a, v, v.AuxInt)
4847 }
4848 func addAux2(a *obj.Addr, v *ssa.Value, offset int64) {
4849         if a.Type != obj.TYPE_MEM {
4850                 v.Fatalf("bad addAux addr %s", a)
4851         }
4852         // add integer offset
4853         a.Offset += offset
4854
4855         // If no additional symbol offset, we're done.
4856         if v.Aux == nil {
4857                 return
4858         }
4859         // Add symbol's offset from its base register.
4860         switch sym := v.Aux.(type) {
4861         case *ssa.ExternSymbol:
4862                 a.Name = obj.NAME_EXTERN
4863                 a.Sym = Linksym(sym.Sym.(*Sym))
4864         case *ssa.ArgSymbol:
4865                 n := sym.Node.(*Node)
4866                 a.Name = obj.NAME_PARAM
4867                 a.Node = n
4868                 a.Sym = Linksym(n.Orig.Sym)
4869                 a.Offset += n.Xoffset // TODO: why do I have to add this here?  I don't for auto variables.
4870         case *ssa.AutoSymbol:
4871                 n := sym.Node.(*Node)
4872                 a.Name = obj.NAME_AUTO
4873                 a.Node = n
4874                 a.Sym = Linksym(n.Sym)
4875         default:
4876                 v.Fatalf("aux in %s not implemented %#v", v, v.Aux)
4877         }
4878 }
4879
4880 // extendIndex extends v to a full int width.
4881 func (s *state) extendIndex(v *ssa.Value) *ssa.Value {
4882         size := v.Type.Size()
4883         if size == s.config.IntSize {
4884                 return v
4885         }
4886         if size > s.config.IntSize {
4887                 // TODO: truncate 64-bit indexes on 32-bit pointer archs.  We'd need to test
4888                 // the high word and branch to out-of-bounds failure if it is not 0.
4889                 s.Unimplementedf("64->32 index truncation not implemented")
4890                 return v
4891         }
4892
4893         // Extend value to the required size
4894         var op ssa.Op
4895         if v.Type.IsSigned() {
4896                 switch 10*size + s.config.IntSize {
4897                 case 14:
4898                         op = ssa.OpSignExt8to32
4899                 case 18:
4900                         op = ssa.OpSignExt8to64
4901                 case 24:
4902                         op = ssa.OpSignExt16to32
4903                 case 28:
4904                         op = ssa.OpSignExt16to64
4905                 case 48:
4906                         op = ssa.OpSignExt32to64
4907                 default:
4908                         s.Fatalf("bad signed index extension %s", v.Type)
4909                 }
4910         } else {
4911                 switch 10*size + s.config.IntSize {
4912                 case 14:
4913                         op = ssa.OpZeroExt8to32
4914                 case 18:
4915                         op = ssa.OpZeroExt8to64
4916                 case 24:
4917                         op = ssa.OpZeroExt16to32
4918                 case 28:
4919                         op = ssa.OpZeroExt16to64
4920                 case 48:
4921                         op = ssa.OpZeroExt32to64
4922                 default:
4923                         s.Fatalf("bad unsigned index extension %s", v.Type)
4924                 }
4925         }
4926         return s.newValue1(op, Types[TINT], v)
4927 }
4928
4929 // ssaRegToReg maps ssa register numbers to obj register numbers.
4930 var ssaRegToReg = [...]int16{
4931         x86.REG_AX,
4932         x86.REG_CX,
4933         x86.REG_DX,
4934         x86.REG_BX,
4935         x86.REG_SP,
4936         x86.REG_BP,
4937         x86.REG_SI,
4938         x86.REG_DI,
4939         x86.REG_R8,
4940         x86.REG_R9,
4941         x86.REG_R10,
4942         x86.REG_R11,
4943         x86.REG_R12,
4944         x86.REG_R13,
4945         x86.REG_R14,
4946         x86.REG_R15,
4947         x86.REG_X0,
4948         x86.REG_X1,
4949         x86.REG_X2,
4950         x86.REG_X3,
4951         x86.REG_X4,
4952         x86.REG_X5,
4953         x86.REG_X6,
4954         x86.REG_X7,
4955         x86.REG_X8,
4956         x86.REG_X9,
4957         x86.REG_X10,
4958         x86.REG_X11,
4959         x86.REG_X12,
4960         x86.REG_X13,
4961         x86.REG_X14,
4962         x86.REG_X15,
4963         0, // SB isn't a real register.  We fill an Addr.Reg field with 0 in this case.
4964         // TODO: arch-dependent
4965 }
4966
4967 // loadByType returns the load instruction of the given type.
4968 func loadByType(t ssa.Type) int {
4969         // For x86, there's no difference between load and store opcodes.
4970         return storeByType(t)
4971 }
4972
4973 // storeByType returns the store instruction of the given type.
4974 func storeByType(t ssa.Type) int {
4975         width := t.Size()
4976         if t.IsFloat() {
4977                 switch width {
4978                 case 4:
4979                         return x86.AMOVSS
4980                 case 8:
4981                         return x86.AMOVSD
4982                 }
4983         } else {
4984                 switch width {
4985                 case 1:
4986                         return x86.AMOVB
4987                 case 2:
4988                         return x86.AMOVW
4989                 case 4:
4990                         return x86.AMOVL
4991                 case 8:
4992                         return x86.AMOVQ
4993                 }
4994         }
4995         panic("bad store type")
4996 }
4997
4998 // moveByType returns the reg->reg move instruction of the given type.
4999 func moveByType(t ssa.Type) int {
5000         if t.IsFloat() {
5001                 // Moving the whole sse2 register is faster
5002                 // than moving just the correct low portion of it.
5003                 return x86.AMOVAPD
5004         } else {
5005                 switch t.Size() {
5006                 case 1:
5007                         return x86.AMOVB
5008                 case 2:
5009                         return x86.AMOVW
5010                 case 4:
5011                         return x86.AMOVL
5012                 case 8:
5013                         return x86.AMOVQ
5014                 default:
5015                         panic("bad int register width")
5016                 }
5017         }
5018         panic("bad register type")
5019 }
5020
5021 // regnum returns the register (in cmd/internal/obj numbering) to
5022 // which v has been allocated.  Panics if v is not assigned to a
5023 // register.
5024 // TODO: Make this panic again once it stops happening routinely.
5025 func regnum(v *ssa.Value) int16 {
5026         reg := v.Block.Func.RegAlloc[v.ID]
5027         if reg == nil {
5028                 v.Unimplementedf("nil regnum for value: %s\n%s\n", v.LongString(), v.Block.Func)
5029                 return 0
5030         }
5031         return ssaRegToReg[reg.(*ssa.Register).Num]
5032 }
5033
5034 // autoVar returns a *Node and int64 representing the auto variable and offset within it
5035 // where v should be spilled.
5036 func autoVar(v *ssa.Value) (*Node, int64) {
5037         loc := v.Block.Func.RegAlloc[v.ID].(ssa.LocalSlot)
5038         if v.Type.Size() > loc.Type.Size() {
5039                 v.Fatalf("spill/restore type %s doesn't fit in slot type %s", v.Type, loc.Type)
5040         }
5041         return loc.N.(*Node), loc.Off
5042 }
5043
5044 // fieldIdx finds the index of the field referred to by the ODOT node n.
5045 func fieldIdx(n *Node) int64 {
5046         t := n.Left.Type
5047         f := n.Right
5048         if t.Etype != TSTRUCT {
5049                 panic("ODOT's LHS is not a struct")
5050         }
5051
5052         var i int64
5053         for t1 := t.Type; t1 != nil; t1 = t1.Down {
5054                 if t1.Etype != TFIELD {
5055                         panic("non-TFIELD in TSTRUCT")
5056                 }
5057                 if t1.Sym != f.Sym {
5058                         i++
5059                         continue
5060                 }
5061                 if t1.Width != n.Xoffset {
5062                         panic("field offset doesn't match")
5063                 }
5064                 return i
5065         }
5066         panic(fmt.Sprintf("can't find field in expr %s\n", n))
5067
5068         // TODO: keep the result of this fucntion somewhere in the ODOT Node
5069         // so we don't have to recompute it each time we need it.
5070 }
5071
5072 // ssaExport exports a bunch of compiler services for the ssa backend.
5073 type ssaExport struct {
5074         log           bool
5075         unimplemented bool
5076         mustImplement bool
5077 }
5078
5079 func (s *ssaExport) TypeBool() ssa.Type    { return Types[TBOOL] }
5080 func (s *ssaExport) TypeInt8() ssa.Type    { return Types[TINT8] }
5081 func (s *ssaExport) TypeInt16() ssa.Type   { return Types[TINT16] }
5082 func (s *ssaExport) TypeInt32() ssa.Type   { return Types[TINT32] }
5083 func (s *ssaExport) TypeInt64() ssa.Type   { return Types[TINT64] }
5084 func (s *ssaExport) TypeUInt8() ssa.Type   { return Types[TUINT8] }
5085 func (s *ssaExport) TypeUInt16() ssa.Type  { return Types[TUINT16] }
5086 func (s *ssaExport) TypeUInt32() ssa.Type  { return Types[TUINT32] }
5087 func (s *ssaExport) TypeUInt64() ssa.Type  { return Types[TUINT64] }
5088 func (s *ssaExport) TypeFloat32() ssa.Type { return Types[TFLOAT32] }
5089 func (s *ssaExport) TypeFloat64() ssa.Type { return Types[TFLOAT64] }
5090 func (s *ssaExport) TypeInt() ssa.Type     { return Types[TINT] }
5091 func (s *ssaExport) TypeUintptr() ssa.Type { return Types[TUINTPTR] }
5092 func (s *ssaExport) TypeString() ssa.Type  { return Types[TSTRING] }
5093 func (s *ssaExport) TypeBytePtr() ssa.Type { return Ptrto(Types[TUINT8]) }
5094
5095 // StringData returns a symbol (a *Sym wrapped in an interface) which
5096 // is the data component of a global string constant containing s.
5097 func (*ssaExport) StringData(s string) interface{} {
5098         // TODO: is idealstring correct?  It might not matter...
5099         _, data := stringsym(s)
5100         return &ssa.ExternSymbol{Typ: idealstring, Sym: data}
5101 }
5102
5103 func (e *ssaExport) Auto(t ssa.Type) ssa.GCNode {
5104         n := temp(t.(*Type))   // Note: adds new auto to Curfn.Func.Dcl list
5105         e.mustImplement = true // This modifies the input to SSA, so we want to make sure we succeed from here!
5106         return n
5107 }
5108
5109 func (e *ssaExport) CanSSA(t ssa.Type) bool {
5110         return canSSAType(t.(*Type))
5111 }
5112
5113 func (e *ssaExport) Line(line int32) string {
5114         return Ctxt.Line(int(line))
5115 }
5116
5117 // Log logs a message from the compiler.
5118 func (e *ssaExport) Logf(msg string, args ...interface{}) {
5119         // If e was marked as unimplemented, anything could happen. Ignore.
5120         if e.log && !e.unimplemented {
5121                 fmt.Printf(msg, args...)
5122         }
5123 }
5124
5125 func (e *ssaExport) Log() bool {
5126         return e.log
5127 }
5128
5129 // Fatal reports a compiler error and exits.
5130 func (e *ssaExport) Fatalf(line int32, msg string, args ...interface{}) {
5131         // If e was marked as unimplemented, anything could happen. Ignore.
5132         if !e.unimplemented {
5133                 lineno = line
5134                 Fatalf(msg, args...)
5135         }
5136 }
5137
5138 // Unimplemented reports that the function cannot be compiled.
5139 // It will be removed once SSA work is complete.
5140 func (e *ssaExport) Unimplementedf(line int32, msg string, args ...interface{}) {
5141         if e.mustImplement {
5142                 lineno = line
5143                 Fatalf(msg, args...)
5144         }
5145         const alwaysLog = false // enable to calculate top unimplemented features
5146         if !e.unimplemented && (e.log || alwaysLog) {
5147                 // first implementation failure, print explanation
5148                 fmt.Printf("SSA unimplemented: "+msg+"\n", args...)
5149         }
5150         e.unimplemented = true
5151 }
5152
5153 // Warnl reports a "warning", which is usually flag-triggered
5154 // logging output for the benefit of tests.
5155 func (e *ssaExport) Warnl(line int, fmt_ string, args ...interface{}) {
5156         Warnl(line, fmt_, args...)
5157 }
5158
5159 func (e *ssaExport) Debug_checknil() bool {
5160         return Debug_checknil != 0
5161 }
5162
5163 func (n *Node) Typ() ssa.Type {
5164         return n.Type
5165 }