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