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