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