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