ssa_builder.mx raw
1 package main
2
3 import (
4 "go/constant"
5 "go/token"
6 )
7
8 // CreatePackage builds the SSA Package from type-checked syntax files.
9 func (prog *SSAProgram) CreatePackage(pkg *TCPackage, files []*File, info *Info) *SSAPackage {
10 p := &SSAPackage{
11 Prog: prog,
12 Pkg: pkg,
13 Members: map[string]SSAMember{},
14 }
15 prog.packages[pkg] = p
16 prog.imported[pkg.Path()] = p
17
18 pb := &ssaPkgBuilder{pkg: p, info: info, prog: prog}
19
20 for _, f := range files {
21 pb.registerFile(f)
22 }
23 for _, f := range files {
24 pb.buildFile(f)
25 }
26 return p
27 }
28
29 // ssaPkgBuilder builds one SSAPackage.
30 type ssaPkgBuilder struct {
31 pkg *SSAPackage
32 info *Info
33 prog *SSAProgram
34 }
35
36 func (pb *ssaPkgBuilder) registerFile(f *File) {
37 for _, d := range f.DeclList {
38 switch d := d.(type) {
39 case *FuncDecl:
40 pb.registerFunc(d)
41 case *VarDecl:
42 pb.registerVar(d)
43 case *TypeDecl:
44 pb.registerType(d)
45 case *ConstDecl:
46 pb.registerConst(d)
47 }
48 }
49 }
50
51 func (pb *ssaPkgBuilder) registerFunc(d *FuncDecl) {
52 if d.Recv != nil {
53 pb.registerMethod(d)
54 return
55 }
56 if d.Name.Value == "init" {
57 return
58 }
59 var obj *TCFunc
60 if o := pb.pkg.Pkg.Scope().Lookup(d.Name.Value); o != nil {
61 obj, _ = o.(*TCFunc)
62 }
63 var sig *Signature
64 if obj != nil {
65 sig, _ = obj.Type().(*Signature)
66 }
67 fn := &SSAFunction{
68 name: d.Name.Value,
69 object: obj,
70 Signature: sig,
71 pos: 0,
72 Pkg: pb.pkg,
73 Prog: pb.prog,
74 }
75 pb.pkg.Members[fn.name] = fn
76 }
77
78 func (pb *ssaPkgBuilder) registerMethod(d *FuncDecl) {
79 recvTypeName := ssaRecvTypeName(d.Recv)
80 if recvTypeName == "" {
81 return
82 }
83 mangledName := recvTypeName | "." | d.Name.Value
84 var obj *TCFunc
85 obj = pb.findMethod(recvTypeName, d.Name.Value)
86 var sig *Signature
87 if obj != nil {
88 sig, _ = obj.Type().(*Signature)
89 }
90 fn := &SSAFunction{
91 name: mangledName,
92 object: obj,
93 Signature: sig,
94 pos: 0,
95 Pkg: pb.pkg,
96 Prog: pb.prog,
97 }
98 pb.pkg.Members[mangledName] = fn
99 }
100
101 func ssaRecvTypeName(recv *Field) string {
102 if recv == nil {
103 return ""
104 }
105 switch t := recv.Type.(type) {
106 case *Name:
107 return t.Value
108 case *Operation:
109 if t.Y == nil && t.Op == Mul {
110 if n, ok := t.X.(*Name); ok {
111 return n.Value
112 }
113 }
114 }
115 return ""
116 }
117
118 func (pb *ssaPkgBuilder) findMethod(typeName string, methodName string) *TCFunc {
119 obj := pb.pkg.Pkg.Scope().Lookup(typeName)
120 if obj == nil {
121 return nil
122 }
123 tn, ok := obj.(*TypeName)
124 if !ok {
125 return nil
126 }
127 named, ok := tn.Type().(*Named)
128 if !ok {
129 return nil
130 }
131 for i := 0; i < named.NumMethods(); i++ {
132 m := named.Method(i)
133 if m.Name() == methodName {
134 return m
135 }
136 }
137 return nil
138 }
139
140 func (pb *ssaPkgBuilder) registerVar(d *VarDecl) {
141 for _, name := range d.NameList {
142 var obj *TCVar
143 if o := pb.pkg.Pkg.Scope().Lookup(name.Value); o != nil {
144 obj, _ = o.(*TCVar)
145 }
146 var typ Type
147 if obj != nil {
148 typ = obj.Type()
149 }
150 g := &SSAGlobal{
151 name: name.Value,
152 object: obj,
153 typ: NewPointer(typ),
154 pos: 0,
155 pkg: pb.pkg,
156 }
157 pb.pkg.Members[name.Value] = g
158 }
159 }
160
161 func (pb *ssaPkgBuilder) registerType(d *TypeDecl) {
162 var obj *TypeName
163 if o := pb.pkg.Pkg.Scope().Lookup(d.Name.Value); o != nil {
164 obj, _ = o.(*TypeName)
165 }
166 if obj == nil {
167 return
168 }
169 t := &SSAType_{object: obj, pkg: pb.pkg}
170 pb.pkg.Members[d.Name.Value] = t
171 }
172
173 func (pb *ssaPkgBuilder) registerConst(d *ConstDecl) {
174 for _, name := range d.NameList {
175 var obj *TCConst
176 if o := pb.pkg.Pkg.Scope().Lookup(name.Value); o != nil {
177 obj, _ = o.(*TCConst)
178 }
179 if obj == nil {
180 continue
181 }
182 c := &SSANamedConst{
183 object: obj,
184 Value: &SSAConst{typ: obj.Type(), val: obj.Val()},
185 pkg: pb.pkg,
186 }
187 pb.pkg.Members[name.Value] = c
188 }
189 }
190
191 func (pb *ssaPkgBuilder) buildFile(f *File) {
192 for _, d := range f.DeclList {
193 if fd, ok := d.(*FuncDecl); ok {
194 pb.buildFunc(fd)
195 }
196 }
197 }
198
199 func (pb *ssaPkgBuilder) buildFunc(d *FuncDecl) {
200 if d.Body == nil {
201 return
202 }
203 name := d.Name.Value
204 if d.Recv != nil {
205 rtn := ssaRecvTypeName(d.Recv)
206 if rtn != "" {
207 name = rtn | "." | d.Name.Value
208 }
209 }
210 fn, _ := pb.pkg.Members[name].(*SSAFunction)
211 if fn == nil {
212 return
213 }
214 fb := newSSAFuncBuilder(fn, pb.info)
215 fb.buildBody(d)
216 }
217
218 // ssaFuncBuilder builds one SSAFunction body.
219 type ssaFuncBuilder struct {
220 fn *SSAFunction
221 info *Info
222 parent *ssaFuncBuilder
223 currentBlock *SSABasicBlock
224 vars map[Object]*SSAAlloc
225 namedResults []*SSAAlloc
226 counter int
227
228 loops []ssaLoopState
229 deferred int
230 }
231
232 type ssaLoopState struct {
233 body *SSABasicBlock
234 post *SSABasicBlock
235 done *SSABasicBlock
236 }
237
238 func newSSAFuncBuilder(fn *SSAFunction, info *Info) *ssaFuncBuilder {
239 return &ssaFuncBuilder{
240 fn: fn,
241 info: info,
242 vars: map[Object]*SSAAlloc{},
243 }
244 }
245
246 func (fb *ssaFuncBuilder) newBlock(comment string) *SSABasicBlock {
247 return NewSSABasicBlock(fb.fn, comment)
248 }
249
250 func (fb *ssaFuncBuilder) emit(instr SSAInstruction) {
251 if fb.currentBlock == nil {
252 return
253 }
254 instr.setBlock(fb.currentBlock)
255 fb.currentBlock.Instrs = append(fb.currentBlock.Instrs, instr)
256 }
257
258 func (fb *ssaFuncBuilder) nextName() string {
259 fb.counter++
260 return "t" | ssaItoa(fb.counter)
261 }
262
263 func (fb *ssaFuncBuilder) buildBody(d *FuncDecl) {
264 entry := fb.newBlock("entry")
265 fb.currentBlock = entry
266
267 sig := fb.fn.Signature
268 if sig == nil {
269 return
270 }
271
272 params := sig.Params()
273 if d.Recv != nil {
274 recv := sig.Recv()
275 if recv != nil {
276 recvName := recv.Name()
277 if recvName == "" && d.Recv.Name != nil {
278 recvName = d.Recv.Name.Value
279 }
280 p := &SSAParameter{
281 name: recvName,
282 typ: recv.Type(),
283 pos: 0,
284 parent: fb.fn,
285 }
286 fb.fn.Params = append(fb.fn.Params, p)
287 if recvName != "" && recvName != "_" {
288 recvObj := NewTCVar(fb.fn.Pkg.Pkg, recvName, recv.Type())
289 p.object = recvObj
290 alloc := fb.emitAlloc(recv.Type(), 0)
291 fb.vars[recvObj] = alloc
292 fb.emitStore(alloc, p)
293 }
294 }
295 }
296 if params != nil {
297 for i := 0; i < params.Len(); i++ {
298 pvar := params.At(i)
299 p := &SSAParameter{
300 name: pvar.Name(),
301 typ: pvar.Type(),
302 pos: fb.fn.pos,
303 parent: fb.fn,
304 }
305 fb.fn.Params = append(fb.fn.Params, p)
306 if pvar.Name() != "" && pvar.Name() != "_" {
307 obj := NewTCVar(fb.fn.Pkg.Pkg, pvar.Name(), pvar.Type())
308 alloc := fb.emitAlloc(pvar.Type(), p.pos)
309 fb.vars[obj] = alloc
310 fb.emitStore(alloc, p)
311 }
312 }
313 }
314
315 if sig.Results() != nil {
316 for i := 0; i < sig.Results().Len(); i++ {
317 r := sig.Results().At(i)
318 if r.Name() != "" && r.Name() != "_" {
319 alloc := fb.emitAlloc(r.Type(), fb.fn.pos)
320 fb.namedResults = append(fb.namedResults, alloc)
321 fb.fn.Locals = append(fb.fn.Locals, alloc)
322 }
323 }
324 }
325
326 if d.Body != nil {
327 fb.buildBlock(d.Body)
328 }
329
330 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
331 fb.emitReturn(nil, 0)
332 }
333 }
334
335 func (fb *ssaFuncBuilder) emitAlloc(typ Type, pos int32) *SSAAlloc {
336 a := &SSAAlloc{Heap: true}
337 a.typ = NewPointer(typ)
338 a.pos = pos
339 a.name = fb.nextName()
340 fb.emit(a)
341 fb.fn.Locals = append(fb.fn.Locals, a)
342 return a
343 }
344
345 func (fb *ssaFuncBuilder) emitStore(addr SSAValue, val SSAValue) {
346 fb.emit(&SSAStore{Addr: addr, Val: val})
347 }
348
349 func (fb *ssaFuncBuilder) emitLoad(addr SSAValue, typ Type) SSAValue {
350 u := &SSAUnOp{Op: OpMul, X: addr}
351 u.typ = typ
352 u.name = fb.nextName()
353 fb.emit(u)
354 return u
355 }
356
357 func (fb *ssaFuncBuilder) emitReturn(vals []SSAValue, pos int32) {
358 fb.emit(&SSAReturn{Results: vals, pos: pos})
359 fb.currentBlock = nil
360 }
361
362 func (fb *ssaFuncBuilder) blockTerminated(b *SSABasicBlock) bool {
363 if len(b.Instrs) == 0 {
364 return false
365 }
366 switch b.Instrs[len(b.Instrs)-1].(type) {
367 case *SSAReturn, *SSAJump, *SSAIf, *SSAPanic:
368 return true
369 }
370 return false
371 }
372
373 // Statement builders.
374
375 func (fb *ssaFuncBuilder) buildBlock(b *BlockStmt) {
376 if b == nil {
377 return
378 }
379 for _, s := range b.List {
380 fb.buildStmt(s)
381 if fb.currentBlock == nil {
382 return
383 }
384 }
385 }
386
387 func (fb *ssaFuncBuilder) buildStmt(s Stmt) {
388 if s == nil || fb.currentBlock == nil {
389 return
390 }
391 switch s := s.(type) {
392 case *EmptyStmt:
393 // nothing
394 case *ExprStmt:
395 fb.buildExpr(s.X)
396 case *AssignStmt:
397 fb.buildAssign(s)
398 case *BlockStmt:
399 fb.buildBlock(s)
400 case *DeclStmt:
401 for _, d := range s.DeclList {
402 fb.buildLocalDecl(d)
403 }
404 case *IfStmt:
405 fb.buildIf(s)
406 case *ForStmt:
407 fb.buildFor(s)
408 case *SwitchStmt:
409 fb.buildSwitch(s)
410 case *SelectStmt:
411 fb.buildSelect(s)
412 case *ReturnStmt:
413 fb.buildReturn(s)
414 case *BranchStmt:
415 fb.buildBranch(s)
416 case *LabeledStmt:
417 fb.buildStmt(s.Stmt)
418 case *SendStmt:
419 ch := fb.buildExpr(s.Chan)
420 val := fb.buildExpr(s.Value)
421 if ch != nil && val != nil {
422 fb.emit(&SSASend{Chan: ch, X: val})
423 }
424 case *CallStmt:
425 call, _ := s.Call.(*CallExpr)
426 switch s.Tok {
427 case Go:
428 if call != nil {
429 fb.buildGoStmt(call)
430 }
431 case Defer:
432 if call != nil {
433 fb.buildDeferStmt(call)
434 }
435 default:
436 fb.buildExpr(s.Call)
437 }
438 }
439 }
440
441 func (fb *ssaFuncBuilder) buildAssign(s *AssignStmt) {
442 if s.Rhs == nil {
443 lv := fb.buildExpr(s.Lhs)
444 if lv == nil {
445 return
446 }
447 one := &SSAConst{typ: lv.SSAType(), val: constant.MakeInt64(1)}
448 op := OpAdd
449 if s.Op == Sub {
450 op = OpSub
451 }
452 bin := &SSABinOp{Op: op, X: lv, Y: one}
453 bin.typ = lv.SSAType()
454 bin.name = fb.nextName()
455 fb.emit(bin)
456 fb.buildStore(s.Lhs, bin)
457 return
458 }
459 if s.Op == Def {
460 fb.buildShortVarDecl(s)
461 return
462 }
463 if s.Op != 0 {
464 lv := fb.buildExpr(s.Lhs)
465 rv := fb.buildExpr(s.Rhs)
466 if lv == nil || rv == nil {
467 return
468 }
469 op := compoundOp(s.Op)
470 bin := &SSABinOp{Op: op, X: lv, Y: rv}
471 bin.typ = lv.SSAType()
472 bin.name = fb.nextName()
473 fb.emit(bin)
474 fb.buildStore(s.Lhs, bin)
475 return
476 }
477 lhsList, lhsIsList := s.Lhs.(*ListExpr)
478 rhsList, rhsIsList := s.Rhs.(*ListExpr)
479 if lhsIsList && rhsIsList && len(lhsList.ElemList) == len(rhsList.ElemList) {
480 vals := []SSAValue{:len(rhsList.ElemList)}
481 for i, re := range rhsList.ElemList {
482 vals[i] = fb.buildExpr(re)
483 }
484 for i, le := range lhsList.ElemList {
485 if vals[i] != nil {
486 fb.buildStore(le, vals[i])
487 }
488 }
489 return
490 }
491 rhs := fb.buildExpr(s.Rhs)
492 if rhs == nil {
493 return
494 }
495 fb.buildStore(s.Lhs, rhs)
496 }
497
498 func (fb *ssaFuncBuilder) coerceToInterface(val SSAValue, targetType Type) SSAValue {
499 if targetType == nil || val == nil || val.SSAType() == nil {
500 return val
501 }
502 if _, isIface := safeUnderlying(targetType).(*TCInterface); isIface {
503 if _, alreadyIface := safeUnderlying(val.SSAType()).(*TCInterface); !alreadyIface {
504 mi := &SSAMakeInterface{X: val}
505 mi.typ = targetType
506 mi.name = fb.nextName()
507 fb.emit(mi)
508 return mi
509 }
510 }
511 return val
512 }
513
514 func (fb *ssaFuncBuilder) buildStore(lhs Expr, val SSAValue) {
515 switch lhs := lhs.(type) {
516 case *Name:
517 if lhs.Value == "_" {
518 return
519 }
520 obj := fb.lookupObject(lhs.Value)
521 if obj == nil {
522 return
523 }
524 if alloc, ok := fb.vars[obj]; ok {
525 val = fb.coerceToInterface(val, obj.Type())
526 fb.emitStore(alloc, val)
527 } else if g, ok := fb.fn.Pkg.Members[lhs.Value].(*SSAGlobal); ok {
528 fb.emitStore(g, val)
529 }
530 case *Operation:
531 if lhs.Y == nil && lhs.Op == Mul {
532 ptr := fb.buildExpr(lhs.X)
533 if ptr != nil {
534 fb.emitStore(ptr, val)
535 }
536 }
537 case *SelectorExpr:
538 addr := fb.buildSelectorAddr(lhs)
539 if addr == nil {
540 return
541 }
542 fb.emitStore(addr, val)
543 case *IndexExpr:
544 base := fb.buildExpr(lhs.X)
545 idx := fb.buildExpr(lhs.Index)
546 if base == nil || idx == nil {
547 return
548 }
549 if m, isMap := safeUnderlying(base.SSAType()).(*TCMap); isMap {
550 idx = fb.coerceToInterface(idx, m.Key())
551 val = fb.coerceToInterface(val, m.Elem())
552 fb.emit(&SSAMapUpdate{Map: base, Key: idx, Value: val})
553 return
554 }
555 ia := &SSAIndexAddr{X: base, Index: idx}
556 ia.typ = NewPointer(ssaElemType(base.SSAType()))
557 ia.name = fb.nextName()
558 fb.emit(ia)
559 fb.emitStore(ia, val)
560 case *ListExpr:
561 for i, e := range lhs.ElemList {
562 ext := &SSAExtract{Tuple: val, Index: i}
563 ext.typ = ssaTupleElemType(val.SSAType(), i)
564 ext.name = fb.nextName()
565 fb.emit(ext)
566 fb.buildStore(e, ext)
567 }
568 }
569 }
570
571 func (fb *ssaFuncBuilder) buildShortVarDecl(s *AssignStmt) {
572 names := ssaExprNames(s.Lhs)
573 if len(names) == 2 {
574 if ae, ok := s.Rhs.(*AssertExpr); ok {
575 x := fb.buildExpr(ae.X)
576 assertedType := fb.resolveType(ae.Type)
577 if x != nil && assertedType != nil {
578 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: true}
579 ta.typ = NewTuple(
580 NewTCVar(nil, "val", assertedType),
581 NewTCVar(nil, "ok", Typ[Bool]),
582 )
583 ta.name = fb.nextName()
584 fb.emit(ta)
585 for i, name := range names {
586 if name.Value == "_" {
587 continue
588 }
589 ext := &SSAExtract{Tuple: ta, Index: i}
590 ext.typ = ssaTupleElemType(ta.typ, i)
591 ext.name = fb.nextName()
592 fb.emit(ext)
593 fb.removeVar(name.Value)
594 obj := NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
595 alloc := fb.emitAlloc(ext.typ, 0)
596 fb.vars[obj] = alloc
597 fb.emitStore(alloc, ext)
598 }
599 return
600 }
601 }
602 if ie, ok := s.Rhs.(*IndexExpr); ok {
603 x := fb.buildExpr(ie.X)
604 idx := fb.buildExpr(ie.Index)
605 if x != nil && idx != nil {
606 if mt, ok2 := safeUnderlying(x.SSAType()).(*TCMap); ok2 {
607 idx = fb.coerceToInterface(idx, mt.Key())
608 l := &SSALookup{X: x, Index: idx, CommaOk: true}
609 l.typ = NewTuple(
610 NewTCVar(nil, "v", mt.Elem()),
611 NewTCVar(nil, "ok", Typ[Bool]),
612 )
613 l.name = fb.nextName()
614 fb.emit(l)
615 for i, name := range names {
616 if name.Value == "_" {
617 continue
618 }
619 ext := &SSAExtract{Tuple: l, Index: i}
620 ext.typ = ssaTupleElemType(l.typ, i)
621 ext.name = fb.nextName()
622 fb.emit(ext)
623 fb.removeVar(name.Value)
624 var obj Object
625 if fb.info != nil {
626 obj = fb.info.Defs[name]
627 }
628 if obj == nil {
629 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
630 }
631 alloc := fb.emitAlloc(ext.typ, 0)
632 fb.vars[obj] = alloc
633 fb.emitStore(alloc, ext)
634 }
635 return
636 }
637 }
638 }
639 }
640 if rhsList, ok := s.Rhs.(*ListExpr); ok && len(rhsList.ElemList) == len(names) {
641 vals := []SSAValue{:len(rhsList.ElemList)}
642 for i, re := range rhsList.ElemList {
643 vals[i] = fb.buildExpr(re)
644 }
645 for i, name := range names {
646 if name.Value == "_" {
647 continue
648 }
649 var typ Type
650 if vals[i] != nil {
651 typ = vals[i].SSAType()
652 }
653 fb.removeVar(name.Value)
654 var obj Object
655 if fb.info != nil {
656 obj = fb.info.Defs[name]
657 }
658 if obj == nil {
659 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
660 }
661 alloc := fb.emitAlloc(typ, 0)
662 fb.vars[obj] = alloc
663 if vals[i] != nil {
664 fb.emitStore(alloc, vals[i])
665 }
666 }
667 return
668 }
669
670 rhs := fb.buildExpr(s.Rhs)
671
672 isTuple := false
673 var tup *Tuple
674 if rhs != nil {
675 tup, isTuple = rhs.SSAType().(*Tuple)
676 }
677 for i, name := range names {
678 if name.Value == "_" {
679 continue
680 }
681 var typ Type
682 if rhs != nil {
683 if isTuple && i < tup.Len() {
684 typ = tup.At(i).Type()
685 } else if i == 0 {
686 typ = rhs.SSAType()
687 }
688 }
689 if typ == nil {
690 typ = Typ[Int32]
691 }
692 fb.removeVar(name.Value)
693 var obj Object
694 if fb.info != nil {
695 obj = fb.info.Defs[name]
696 }
697 if obj == nil {
698 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
699 }
700 alloc := fb.emitAlloc(typ, 0)
701 fb.vars[obj] = alloc
702 var initVal SSAValue
703 if rhs != nil {
704 if isTuple {
705 ext := &SSAExtract{Tuple: rhs, Index: i}
706 ext.typ = typ
707 ext.name = fb.nextName()
708 fb.emit(ext)
709 initVal = ext
710 } else if i == 0 {
711 initVal = rhs
712 }
713 }
714 if initVal != nil {
715 fb.emitStore(alloc, initVal)
716 }
717 }
718 }
719
720 func (fb *ssaFuncBuilder) buildLocalDecl(d Decl) {
721 switch d := d.(type) {
722 case *VarDecl:
723 var typ Type
724 if fb.info != nil && len(d.NameList) > 0 {
725 if obj := fb.info.Defs[d.NameList[0]]; obj != nil {
726 typ = obj.Type()
727 }
728 }
729 if typ == nil && d.Type != nil {
730 typ = fb.resolveType(d.Type)
731 }
732 initVal := fb.buildExpr(d.Values)
733 for _, name := range d.NameList {
734 if name.Value == "_" {
735 continue
736 }
737 var obj Object
738 if fb.info != nil {
739 obj = fb.info.Defs[name]
740 }
741 if obj == nil {
742 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
743 }
744 alloc := fb.emitAlloc(obj.Type(), 0)
745 fb.vars[obj] = alloc
746 fb.fn.Locals = append(fb.fn.Locals, alloc)
747 if initVal != nil {
748 fb.emitStore(alloc, initVal)
749 }
750 }
751 case *ConstDecl:
752 // inlined as constants
753 case *TypeDecl:
754 // no code generated
755 }
756 }
757
758 func (fb *ssaFuncBuilder) buildIf(s *IfStmt) {
759 if s.Init != nil {
760 fb.buildStmt(s.Init)
761 }
762 if fb.currentBlock == nil {
763 return
764 }
765 cond := fb.buildExpr(s.Cond)
766 if cond == nil {
767 return
768 }
769
770 thenBlock := fb.newBlock("if.then")
771 var elseBlock *SSABasicBlock
772 doneBlock := fb.newBlock("if.done")
773
774 if s.Else != nil {
775 elseBlock = fb.newBlock("if.else")
776 } else {
777 elseBlock = doneBlock
778 }
779
780 fb.emit(&SSAIf{Cond: cond})
781 fb.currentBlock.Succs = append(fb.currentBlock.Succs, thenBlock, elseBlock)
782 thenBlock.Preds = append(thenBlock.Preds, fb.currentBlock)
783 elseBlock.Preds = append(elseBlock.Preds, fb.currentBlock)
784
785 fb.currentBlock = thenBlock
786 fb.buildBlock(s.Then)
787 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
788 fb.emit(&SSAJump{Comment: "if.done"})
789 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
790 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
791 }
792
793 if s.Else != nil {
794 fb.currentBlock = elseBlock
795 fb.buildStmt(s.Else)
796 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
797 fb.emit(&SSAJump{Comment: "if.done"})
798 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
799 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
800 }
801 }
802
803 fb.currentBlock = doneBlock
804 }
805
806 func (fb *ssaFuncBuilder) buildFor(s *ForStmt) {
807 if s.Init != nil {
808 if rc, ok := s.Init.(*RangeClause); ok {
809 fb.buildRangeLoop(s, rc)
810 return
811 }
812 fb.buildStmt(s.Init)
813 }
814
815 condBlock := fb.newBlock("for.cond")
816 bodyBlock := fb.newBlock("for.body")
817 postBlock := fb.newBlock("for.post")
818 doneBlock := fb.newBlock("for.done")
819
820 fb.emit(&SSAJump{Comment: "for.cond"})
821 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
822 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
823
824 fb.loops = append(fb.loops, ssaLoopState{body: bodyBlock, post: postBlock, done: doneBlock})
825
826 fb.currentBlock = condBlock
827 if s.Cond != nil {
828 cond := fb.buildExpr(s.Cond)
829 if cond != nil {
830 fb.emit(&SSAIf{Cond: cond})
831 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock, doneBlock)
832 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
833 doneBlock.Preds = append(doneBlock.Preds, condBlock)
834 }
835 } else {
836 fb.emit(&SSAJump{Comment: "for.body"})
837 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock)
838 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
839 }
840
841 fb.currentBlock = bodyBlock
842 fb.buildBlock(s.Body)
843 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
844 fb.emit(&SSAJump{Comment: "for.post"})
845 fb.currentBlock.Succs = append(fb.currentBlock.Succs, postBlock)
846 postBlock.Preds = append(postBlock.Preds, fb.currentBlock)
847 }
848
849 fb.currentBlock = postBlock
850 if s.Post != nil {
851 fb.buildStmt(s.Post)
852 }
853 if fb.currentBlock != nil {
854 fb.emit(&SSAJump{Comment: "for.cond"})
855 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
856 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
857 }
858
859 fb.loops = fb.loops[:len(fb.loops)-1]
860 fb.currentBlock = doneBlock
861 }
862
863 func (fb *ssaFuncBuilder) buildRangeLoop(s *ForStmt, rc *RangeClause) {
864 iterExpr := fb.buildExpr(rc.X)
865 if iterExpr == nil {
866 return
867 }
868
869 r := &SSARange{X: iterExpr}
870 r.typ = Typ[Invalid]
871 r.name = fb.nextName()
872 fb.emit(r)
873
874 bodyBlock := fb.newBlock("range.body")
875 doneBlock := fb.newBlock("range.done")
876
877 fb.loops = append(fb.loops, ssaLoopState{body: bodyBlock, done: doneBlock})
878
879 condBlock := fb.newBlock("range.cond")
880 fb.emit(&SSAJump{Comment: "range.cond"})
881 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
882 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
883
884 fb.currentBlock = condBlock
885 nxt := &SSANext{Iter: r, IsString: ssaIsStringType(iterExpr.SSAType())}
886 keyTyp := Type(Typ[Int32])
887 valTyp := Type(Typ[Invalid])
888 if sl, ok := safeUnderlying(iterExpr.SSAType()).(*Slice); ok {
889 valTyp = sl.Elem()
890 } else if mt, ok := safeUnderlying(iterExpr.SSAType()).(*TCMap); ok {
891 keyTyp = mt.Key()
892 valTyp = mt.Elem()
893 }
894 nxt.typ = NewTuple(
895 NewTCVar(nil, "ok", Typ[Bool]),
896 NewTCVar(nil, "k", keyTyp),
897 NewTCVar(nil, "v", valTyp),
898 )
899 nxt.name = fb.nextName()
900 fb.emit(nxt)
901
902 okExt := &SSAExtract{Tuple: nxt, Index: 0}
903 okExt.typ = Typ[Bool]
904 okExt.name = fb.nextName()
905 fb.emit(okExt)
906
907 fb.emit(&SSAIf{Cond: okExt})
908 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock, doneBlock)
909 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
910 doneBlock.Preds = append(doneBlock.Preds, condBlock)
911
912 fb.currentBlock = bodyBlock
913 if rc.Lhs != nil && rc.Def {
914 names := ssaExprNames(rc.Lhs)
915 for i, name := range names {
916 if name.Value == "_" {
917 continue
918 }
919 ext := &SSAExtract{Tuple: nxt, Index: i + 1}
920 ext.typ = ssaTupleElemType(nxt.typ, i+1)
921 ext.name = fb.nextName()
922 fb.emit(ext)
923 var obj Object
924 if fb.info != nil {
925 obj = fb.info.Defs[name]
926 }
927 if obj == nil {
928 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
929 }
930 alloc := fb.emitAlloc(ext.typ, 0)
931 fb.vars[obj] = alloc
932 fb.emitStore(alloc, ext)
933 }
934 }
935 fb.buildBlock(s.Body)
936 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
937 fb.emit(&SSAJump{Comment: "range.cond"})
938 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
939 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
940 }
941
942 fb.loops = fb.loops[:len(fb.loops)-1]
943 fb.currentBlock = doneBlock
944 }
945
946 func (fb *ssaFuncBuilder) buildSwitch(s *SwitchStmt) {
947 if s.Init != nil {
948 fb.buildStmt(s.Init)
949 }
950 if fb.currentBlock == nil {
951 return
952 }
953
954 doneBlock := fb.newBlock("switch.done")
955 savedLoops := fb.loops
956 fb.loops = append(fb.loops, ssaLoopState{done: doneBlock})
957
958 if s.Tag != nil {
959 if tsg, ok := s.Tag.(*TypeSwitchGuard); ok {
960 fb.buildTypeSwitch(s, tsg, doneBlock)
961 fb.loops = savedLoops
962 fb.currentBlock = doneBlock
963 return
964 }
965 }
966
967 var tag SSAValue
968 if s.Tag != nil {
969 tag = fb.buildExpr(s.Tag)
970 }
971
972 for _, clause := range s.Body {
973 caseBlock := fb.newBlock("switch.case")
974 nextBlock := fb.newBlock("switch.next")
975
976 if clause.Cases != nil && tag != nil {
977 var cond SSAValue
978 caseExprs := []Expr{clause.Cases}
979 if list, ok := clause.Cases.(*ListExpr); ok {
980 caseExprs = list.ElemList
981 }
982 for _, ce := range caseExprs {
983 caseVal := fb.buildExpr(ce)
984 cmp := &SSABinOp{Op: OpEql, X: tag, Y: caseVal}
985 cmp.typ = Typ[Bool]
986 cmp.name = fb.nextName()
987 fb.emit(cmp)
988 if cond == nil {
989 cond = cmp
990 } else {
991 orOp := &SSABinOp{Op: OpLor, X: cond, Y: cmp}
992 orOp.typ = Typ[Bool]
993 orOp.name = fb.nextName()
994 fb.emit(orOp)
995 cond = orOp
996 }
997 }
998 fb.emit(&SSAIf{Cond: cond})
999 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1000 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1001 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1002 } else if clause.Cases != nil && tag == nil {
1003 cond := fb.buildExpr(clause.Cases)
1004 fb.emit(&SSAIf{Cond: cond})
1005 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1006 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1007 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1008 } else {
1009 fb.emit(&SSAJump{Comment: "switch.case"})
1010 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock)
1011 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1012 }
1013
1014 fb.currentBlock = caseBlock
1015 for _, stmt := range clause.Body {
1016 fb.buildStmt(stmt)
1017 if fb.currentBlock == nil {
1018 break
1019 }
1020 }
1021 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1022 fb.emit(&SSAJump{Comment: "switch.done"})
1023 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1024 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1025 }
1026 fb.currentBlock = nextBlock
1027 }
1028
1029 if fb.currentBlock != nil {
1030 fb.emit(&SSAJump{Comment: "switch.done"})
1031 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1032 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1033 }
1034
1035 fb.loops = savedLoops
1036 fb.currentBlock = doneBlock
1037 }
1038
1039 func (fb *ssaFuncBuilder) buildTypeSwitch(s *SwitchStmt, tsg *TypeSwitchGuard, doneBlock *SSABasicBlock) {
1040 x := fb.buildExpr(tsg.X)
1041 for _, clause := range s.Body {
1042 caseBlock := fb.newBlock("typeswitch.case")
1043 nextBlock := fb.newBlock("typeswitch.next")
1044
1045 if clause.Cases != nil {
1046 var assertedType Type
1047 if fb.info != nil {
1048 tv := fb.info.Types[clause.Cases]
1049 assertedType = tv.Type
1050 }
1051 if assertedType == nil {
1052 assertedType = fb.resolveType(clause.Cases)
1053 }
1054 if assertedType == nil {
1055 assertedType = Typ[Invalid]
1056 }
1057 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: true}
1058 ta.typ = NewTuple(
1059 NewTCVar(nil, "val", assertedType),
1060 NewTCVar(nil, "ok", Typ[Bool]),
1061 )
1062 ta.name = fb.nextName()
1063 fb.emit(ta)
1064 okExt := &SSAExtract{Tuple: ta, Index: 1}
1065 okExt.typ = Typ[Bool]
1066 okExt.name = fb.nextName()
1067 fb.emit(okExt)
1068 fb.emit(&SSAIf{Cond: okExt})
1069 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1070 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1071 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1072
1073 fb.currentBlock = caseBlock
1074 if tsg.Lhs != nil {
1075 guardVal := &SSAExtract{Tuple: ta, Index: 0}
1076 guardVal.typ = assertedType
1077 guardVal.name = fb.nextName()
1078 fb.emit(guardVal)
1079 for old := range fb.vars {
1080 if old.Name() == tsg.Lhs.Value {
1081 delete(fb.vars, old)
1082 break
1083 }
1084 }
1085 obj := NewTCVar(fb.fn.Pkg.Pkg, tsg.Lhs.Value, assertedType)
1086 alloc := fb.emitAlloc(assertedType, 0)
1087 fb.vars[obj] = alloc
1088 fb.emitStore(alloc, guardVal)
1089 }
1090 } else {
1091 fb.emit(&SSAJump{Comment: "typeswitch.case"})
1092 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock)
1093 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1094 fb.currentBlock = caseBlock
1095 }
1096
1097 for _, stmt := range clause.Body {
1098 fb.buildStmt(stmt)
1099 if fb.currentBlock == nil {
1100 break
1101 }
1102 }
1103 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1104 fb.emit(&SSAJump{Comment: "switch.done"})
1105 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1106 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1107 }
1108 fb.currentBlock = nextBlock
1109 }
1110 if fb.currentBlock != nil {
1111 fb.emit(&SSAJump{Comment: "switch.done"})
1112 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1113 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1114 }
1115 }
1116
1117 func (fb *ssaFuncBuilder) buildSelect(s *SelectStmt) {
1118 doneBlock := fb.newBlock("select.done")
1119
1120 var states []*SSASelectState
1121 caseBlocks := [](*SSABasicBlock){:0:len(s.Body)}
1122 for i, clause := range s.Body {
1123 cb := fb.newBlock("select.case")
1124 caseBlocks = append(caseBlocks, cb)
1125 state := &SSASelectState{}
1126 if clause.Comm != nil {
1127 switch comm := clause.Comm.(type) {
1128 case *SendStmt:
1129 state.Dir = token.ARROW
1130 state.Chan = fb.buildExpr(comm.Chan)
1131 state.Send = fb.buildExpr(comm.Value)
1132 case *AssignStmt:
1133 var chanExpr Expr
1134 if op, ok2 := comm.Rhs.(*Operation); ok2 && op.Y == nil && op.Op == Recv {
1135 chanExpr = op.X
1136 }
1137 if chanExpr != nil {
1138 state.Dir = token.ILLEGAL
1139 state.Chan = fb.buildExpr(chanExpr)
1140 }
1141 case *ExprStmt:
1142 if op, ok2 := comm.X.(*Operation); ok2 && op.Y == nil && op.Op == Recv {
1143 state.Dir = token.ILLEGAL
1144 state.Chan = fb.buildExpr(op.X)
1145 }
1146 }
1147 }
1148 states = append(states, state)
1149 _ = i
1150 }
1151
1152 sel := &SSASelect{States: states, Blocking: true}
1153 sel.typ = NewTuple(
1154 NewTCVar(nil, "index", Typ[Int32]),
1155 NewTCVar(nil, "recvOk", Typ[Bool]),
1156 )
1157 sel.name = fb.nextName()
1158 fb.emit(sel)
1159
1160 for i, clause := range s.Body {
1161 fb.currentBlock = caseBlocks[i]
1162 for _, stmt := range clause.Body {
1163 fb.buildStmt(stmt)
1164 if fb.currentBlock == nil {
1165 break
1166 }
1167 }
1168 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1169 fb.emit(&SSAJump{Comment: "select.done"})
1170 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1171 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1172 }
1173 }
1174
1175 fb.currentBlock = doneBlock
1176 }
1177
1178 func (fb *ssaFuncBuilder) buildReturn(s *ReturnStmt) {
1179 var vals []SSAValue
1180 if s.Results != nil {
1181 if list, ok := s.Results.(*ListExpr); ok {
1182 for _, el := range list.ElemList {
1183 v := fb.buildExpr(el)
1184 if v != nil {
1185 vals = append(vals, v)
1186 }
1187 }
1188 } else {
1189 v := fb.buildExpr(s.Results)
1190 if v != nil {
1191 vals = append(vals, v)
1192 }
1193 }
1194 }
1195 if fb.fn.Signature != nil && fb.fn.Signature.Results() != nil {
1196 for i, v := range vals {
1197 if i < fb.fn.Signature.Results().Len() {
1198 retType := fb.fn.Signature.Results().At(i).Type()
1199 vals[i] = fb.coerceToInterface(v, retType)
1200 }
1201 }
1202 }
1203 fb.emitReturn(vals, 0)
1204 }
1205
1206 func (fb *ssaFuncBuilder) buildBranch(s *BranchStmt) {
1207 if fb.currentBlock == nil {
1208 return
1209 }
1210 switch s.Tok {
1211 case Break:
1212 if len(fb.loops) > 0 {
1213 doneBlock := fb.loops[len(fb.loops)-1].done
1214 fb.emit(&SSAJump{Comment: "break"})
1215 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1216 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1217 fb.currentBlock = nil
1218 }
1219 case Continue:
1220 for i := len(fb.loops) - 1; i >= 0; i-- {
1221 postBlock := fb.loops[i].post
1222 if postBlock == nil {
1223 postBlock = fb.loops[i].body
1224 }
1225 if postBlock == nil {
1226 continue
1227 }
1228 fb.emit(&SSAJump{Comment: "continue"})
1229 fb.currentBlock.Succs = append(fb.currentBlock.Succs, postBlock)
1230 postBlock.Preds = append(postBlock.Preds, fb.currentBlock)
1231 fb.currentBlock = nil
1232 break
1233 }
1234 case Return:
1235 fb.emitReturn(nil, 0)
1236 }
1237 }
1238
1239 func (fb *ssaFuncBuilder) buildGoStmt(call *CallExpr) {
1240 fn := fb.buildExpr(call.Fun)
1241 if fn == nil {
1242 return
1243 }
1244 args := fb.buildArgs(call.ArgList)
1245 g := &SSAGo{Call: SSACallCommon{Value: fn, Args: args}}
1246 fb.emit(g)
1247 }
1248
1249 func (fb *ssaFuncBuilder) buildDeferStmt(call *CallExpr) {
1250 fn := fb.buildExpr(call.Fun)
1251 if fn == nil {
1252 return
1253 }
1254 args := fb.buildArgs(call.ArgList)
1255 d := &SSADefer{Call: SSACallCommon{Value: fn, Args: args}}
1256 fb.emit(d)
1257 fb.deferred++
1258 }
1259
1260 // Expression builders.
1261
1262 func (fb *ssaFuncBuilder) buildExpr(e Expr) SSAValue {
1263 if e == nil || fb.currentBlock == nil {
1264 return nil
1265 }
1266 switch e := e.(type) {
1267 case *Name:
1268 return fb.buildIdent(e)
1269 case *BasicLit:
1270 return fb.buildLit(e)
1271 case *Operation:
1272 return fb.buildOperation(e)
1273 case *CallExpr:
1274 return fb.buildCall(e)
1275 case *SelectorExpr:
1276 return fb.buildSelector(e)
1277 case *IndexExpr:
1278 return fb.buildIndex(e)
1279 case *SliceExpr:
1280 return fb.buildSlice(e)
1281 case *AssertExpr:
1282 return fb.buildAssert(e)
1283 case *CompositeLit:
1284 return fb.buildCompositeLit(e)
1285 case *FuncLit:
1286 return fb.buildFuncLit(e)
1287 case *ParenExpr:
1288 return fb.buildExpr(e.X)
1289 case *ListExpr:
1290 var last SSAValue
1291 for _, el := range e.ElemList {
1292 last = fb.buildExpr(el)
1293 }
1294 return last
1295 case *KeyValueExpr:
1296 return fb.buildExpr(e.Value)
1297 }
1298 return nil
1299 }
1300
1301 func (fb *ssaFuncBuilder) buildIdent(e *Name) SSAValue {
1302 if e.Value == "_" || e.Value == "nil" {
1303 return &SSAConst{typ: nil, val: nil}
1304 }
1305 obj := fb.lookupObject(e.Value)
1306 if obj == nil {
1307 return fb.builtinValue(e.Value)
1308 }
1309 switch obj := obj.(type) {
1310 case *TCVar:
1311 if alloc, ok := fb.vars[obj]; ok {
1312 return fb.emitLoad(alloc, obj.Type())
1313 }
1314 if fb.parent != nil {
1315 if _, ok := fb.parent.vars[obj]; ok {
1316 return fb.getOrCreateFreeVar(e.Value, obj.Type())
1317 }
1318 }
1319 if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
1320 return fb.emitLoad(g, obj.Type())
1321 }
1322 return &SSAConst{typ: obj.Type(), val: nil}
1323 case *TCConst:
1324 return &SSAConst{typ: obj.Type(), val: obj.Val()}
1325 case *TCFunc:
1326 fn, _ := fb.fn.Pkg.Members[e.Value].(*SSAFunction)
1327 if fn != nil {
1328 return fn
1329 }
1330 return &SSAConst{typ: obj.Type(), val: nil}
1331 case *TypeName:
1332 return nil
1333 case *Builtin:
1334 return &SSABuiltin{id: obj.ID(), name: obj.Name()}
1335 }
1336 return nil
1337 }
1338
1339 func (fb *ssaFuncBuilder) builtinValue(name string) SSAValue {
1340 id, ok := ssaBuiltinID(name)
1341 if !ok {
1342 return nil
1343 }
1344 return &SSABuiltin{id: id, name: name}
1345 }
1346
1347 func (fb *ssaFuncBuilder) buildLit(e *BasicLit) SSAValue {
1348 switch e.Kind {
1349 case IntLit:
1350 cv := constant.MakeFromLiteral(e.Value, token.INT, 0)
1351 return &SSAConst{typ: Typ[UntypedInt], val: cv}
1352 case FloatLit:
1353 cv := constant.MakeFromLiteral(e.Value, token.FLOAT, 0)
1354 return &SSAConst{typ: Typ[UntypedFloat], val: cv}
1355 case StringLit:
1356 s := e.Value
1357 if len(s) >= 2 {
1358 s = s[1 : len(s)-1]
1359 }
1360 return &SSAConst{typ: Typ[UntypedString], val: constant.MakeString(s)}
1361 case RuneLit:
1362 cv := constant.MakeFromLiteral(e.Value, token.CHAR, 0)
1363 return &SSAConst{typ: Typ[UntypedRune], val: cv}
1364 }
1365 return nil
1366 }
1367
1368 func (fb *ssaFuncBuilder) buildOperation(e *Operation) SSAValue {
1369 if e.Y == nil {
1370 if e.Op == Add {
1371 return fb.buildExpr(e.X)
1372 }
1373 x := fb.buildExpr(e.X)
1374 if x == nil {
1375 return nil
1376 }
1377 op := syntaxOpToSSAOp(e.Op, true)
1378 if op == OpArrow {
1379 u := &SSAUnOp{Op: OpArrow, X: x}
1380 u.typ = ssaChanElemType(x.SSAType())
1381 u.name = fb.nextName()
1382 fb.emit(u)
1383 return u
1384 }
1385 if op == OpAnd {
1386 if name, ok := e.X.(*Name); ok {
1387 obj := fb.lookupObject(name.Value)
1388 if obj != nil {
1389 if alloc, ok2 := fb.vars[obj]; ok2 {
1390 return alloc
1391 }
1392 if g, ok2 := fb.fn.Pkg.Members[name.Value].(*SSAGlobal); ok2 {
1393 return g
1394 }
1395 }
1396 }
1397 inner := x
1398 a := &SSAAlloc{Heap: true}
1399 a.typ = NewPointer(inner.SSAType())
1400 a.name = fb.nextName()
1401 fb.emit(a)
1402 fb.emitStore(a, inner)
1403 return a
1404 }
1405 u := &SSAUnOp{Op: op, X: x}
1406 if op == OpMul {
1407 if p, ok := x.SSAType().(*Pointer); ok {
1408 u.typ = p.Elem()
1409 } else {
1410 u.typ = x.SSAType()
1411 }
1412 } else {
1413 u.typ = x.SSAType()
1414 }
1415 u.name = fb.nextName()
1416 fb.emit(u)
1417 return u
1418 }
1419 x := fb.buildExpr(e.X)
1420 y := fb.buildExpr(e.Y)
1421 if x == nil || y == nil {
1422 return nil
1423 }
1424 op := syntaxOpToSSAOp(e.Op, false)
1425 b := &SSABinOp{Op: op, X: x, Y: y}
1426 b.name = fb.nextName()
1427 switch op {
1428 case OpEql, OpNeq, OpLss, OpLeq, OpGtr, OpGeq, OpLand, OpLor:
1429 b.typ = Typ[Bool]
1430 default:
1431 xT := x.SSAType()
1432 yT := y.SSAType()
1433 xUntyped := false
1434 if xB, ok := safeUnderlying(xT).(*Basic); ok && xB.Info()&IsUntyped != 0 {
1435 xUntyped = true
1436 }
1437 if xT != nil && !xUntyped {
1438 b.typ = xT
1439 } else if yT != nil {
1440 b.typ = yT
1441 } else {
1442 b.typ = xT
1443 }
1444 }
1445 fb.emit(b)
1446 return b
1447 }
1448
1449 func (fb *ssaFuncBuilder) buildCall(e *CallExpr) SSAValue {
1450 if name, ok := e.Fun.(*Name); ok {
1451 obj := fb.lookupObject(name.Value)
1452 if tn, ok2 := obj.(*TypeName); ok2 {
1453 args := fb.buildArgs(e.ArgList)
1454 if len(args) == 1 && args[0] != nil {
1455 conv := &SSAConvert{X: args[0]}
1456 conv.typ = tn.Type()
1457 conv.name = fb.nextName()
1458 fb.emit(conv)
1459 return conv
1460 }
1461 return nil
1462 }
1463 }
1464 if convType := fb.resolveTypeAST(e.Fun); convType != nil {
1465 args := fb.buildArgs(e.ArgList)
1466 if len(args) == 1 && args[0] != nil {
1467 conv := &SSAConvert{X: args[0]}
1468 conv.typ = convType
1469 conv.name = fb.nextName()
1470 fb.emit(conv)
1471 return conv
1472 }
1473 return nil
1474 }
1475 if sel, ok := e.Fun.(*SelectorExpr); ok {
1476 if name, ok2 := sel.X.(*Name); ok2 {
1477 obj := fb.lookupObject(name.Value)
1478 if pn, ok3 := obj.(*PkgName); ok3 {
1479 return fb.buildPkgCall(pn, sel.Sel.Value, e.ArgList)
1480 }
1481 }
1482 recv := fb.buildExpr(sel.X)
1483 if recv != nil && recv.SSAType() != nil {
1484 if fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv); fn != nil {
1485 args := fb.buildArgs(e.ArgList)
1486 if fn.Signature != nil {
1487 args = fb.coerceArgsToInterface(args, fn.Signature)
1488 }
1489 allArgs := []SSAValue{:0:len(args) + 1}
1490 allArgs = append(allArgs, fixedRecv)
1491 allArgs = append(allArgs, args...)
1492 var retType Type
1493 if fn.Signature != nil {
1494 if fn.Signature.Results() != nil && fn.Signature.Results().Len() == 1 {
1495 retType = fn.Signature.Results().At(0).Type()
1496 } else if fn.Signature.Results() != nil && fn.Signature.Results().Len() > 1 {
1497 retType = fn.Signature.Results()
1498 }
1499 }
1500 call := &SSACall{Call: SSACallCommon{Value: fn, Args: allArgs}}
1501 call.typ = retType
1502 call.name = fb.nextName()
1503 fb.emit(call)
1504 if retType == nil {
1505 return nil
1506 }
1507 return call
1508 }
1509 if inv := fb.buildIfaceMethodCall(sel, recv, e.ArgList); inv != nil {
1510 return inv
1511 }
1512 }
1513 }
1514 fn := fb.buildExpr(e.Fun)
1515 args := fb.buildArgs(e.ArgList)
1516
1517 if fn == nil {
1518 return nil
1519 }
1520 if bi, ok := fn.(*SSABuiltin); ok {
1521 return fb.buildBuiltinCall(e, bi, args)
1522 }
1523
1524 var retType Type
1525 if fn.SSAType() != nil {
1526 if sig, ok := safeUnderlying(fn.SSAType()).(*Signature); ok {
1527 if sig.Results() != nil && sig.Results().Len() == 1 {
1528 retType = sig.Results().At(0).Type()
1529 } else if sig.Results() != nil && sig.Results().Len() > 1 {
1530 retType = sig.Results()
1531 }
1532 }
1533 }
1534
1535 if fn.SSAType() != nil {
1536 if sig, ok := safeUnderlying(fn.SSAType()).(*Signature); ok {
1537 if sig.Variadic() && !e.HasDots {
1538 args = fb.wrapVariadicArgs(args, sig)
1539 }
1540 args = fb.coerceArgsToInterface(args, sig)
1541 }
1542 }
1543
1544 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
1545 call.typ = retType
1546 call.name = fb.nextName()
1547 fb.emit(call)
1548
1549 if retType == nil {
1550 return nil
1551 }
1552 return call
1553 }
1554
1555 func (fb *ssaFuncBuilder) coerceArgsToInterface(args []SSAValue, sig *Signature) []SSAValue {
1556 if sig.Params() == nil {
1557 return args
1558 }
1559 for i := 0; i < len(args) && i < sig.Params().Len(); i++ {
1560 paramType := sig.Params().At(i).Type()
1561 if paramType == nil || args[i] == nil || args[i].SSAType() == nil {
1562 continue
1563 }
1564 _, isIface := safeUnderlying(paramType).(*TCInterface)
1565 if !isIface {
1566 continue
1567 }
1568 _, argIsIface := safeUnderlying(args[i].SSAType()).(*TCInterface)
1569 if argIsIface {
1570 continue
1571 }
1572 mi := &SSAMakeInterface{X: args[i], IType: paramType}
1573 mi.typ = paramType
1574 mi.name = fb.nextName()
1575 fb.emit(mi)
1576 args[i] = mi
1577 }
1578 return args
1579 }
1580
1581 func (fb *ssaFuncBuilder) wrapVariadicArgs(args []SSAValue, sig *Signature) []SSAValue {
1582 nFixed := sig.Params().Len() - 1
1583 if nFixed < 0 {
1584 nFixed = 0
1585 }
1586 nVariadic := len(args) - nFixed
1587 if nVariadic <= 0 {
1588 nilSlice := NewSSAConst(constNil{}, sig.Params().At(sig.Params().Len()-1).Type())
1589 result := args[:nFixed]
1590 return append(result, nilSlice)
1591 }
1592 sliceType := sig.Params().At(sig.Params().Len() - 1).Type()
1593 var elemType Type
1594 if sl, ok := safeUnderlying(sliceType).(*Slice); ok {
1595 elemType = sl.Elem()
1596 }
1597 lenVal := NewSSAConst(constInt{int64(nVariadic)}, Typ[Int32])
1598 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal}
1599 ms.typ = sliceType
1600 ms.name = fb.nextName()
1601 fb.emit(ms)
1602 for i := 0; i < nVariadic; i++ {
1603 idx := NewSSAConst(constInt{int64(i)}, Typ[Int32])
1604 ia := &SSAIndexAddr{X: ms, Index: idx}
1605 ia.typ = NewPointer(elemType)
1606 ia.name = fb.nextName()
1607 fb.emit(ia)
1608 fb.emitStore(ia, args[nFixed+i])
1609 }
1610 result := args[:nFixed]
1611 return append(result, ms)
1612 }
1613
1614 func (fb *ssaFuncBuilder) buildArgs(argList []Expr) []SSAValue {
1615 args := []SSAValue{:0:len(argList)}
1616 for _, a := range argList {
1617 v := fb.buildExpr(a)
1618 if v != nil {
1619 args = append(args, v)
1620 }
1621 }
1622 return args
1623 }
1624
1625 func (fb *ssaFuncBuilder) buildBuiltinCall(e *CallExpr, b *SSABuiltin, args []SSAValue) SSAValue {
1626 switch b.id {
1627 case BuiltinLen, BuiltinCap:
1628 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1629 call.typ = Typ[Int32]
1630 call.name = fb.nextName()
1631 fb.emit(call)
1632 return call
1633 case BuiltinAppend:
1634 if len(args) > 1 {
1635 if sl, ok := safeUnderlying(args[0].SSAType()).(*Slice); ok {
1636 if _, isIface := safeUnderlying(sl.Elem()).(*TCInterface); isIface {
1637 for i := 1; i < len(args); i++ {
1638 if args[i] == nil || args[i].SSAType() == nil {
1639 continue
1640 }
1641 if _, argIface := safeUnderlying(args[i].SSAType()).(*TCInterface); argIface {
1642 continue
1643 }
1644 mi := &SSAMakeInterface{X: args[i], IType: sl.Elem()}
1645 mi.typ = sl.Elem()
1646 mi.name = fb.nextName()
1647 fb.emit(mi)
1648 args[i] = mi
1649 }
1650 }
1651 }
1652 }
1653 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1654 if len(args) > 0 {
1655 call.typ = args[0].SSAType()
1656 }
1657 call.name = fb.nextName()
1658 fb.emit(call)
1659 return call
1660 case BuiltinMake:
1661 if len(e.ArgList) == 0 {
1662 return nil
1663 }
1664 typ := fb.resolveType(e.ArgList[0])
1665 return fb.emitMake(typ, args)
1666 case BuiltinNew:
1667 if len(e.ArgList) == 0 {
1668 return nil
1669 }
1670 typ := fb.resolveType(e.ArgList[0])
1671 a := &SSAAlloc{Heap: true}
1672 a.typ = NewPointer(typ)
1673 a.name = fb.nextName()
1674 fb.emit(a)
1675 return a
1676 case BuiltinPanic:
1677 if len(args) > 0 {
1678 fb.emit(&SSAPanic{X: args[0]})
1679 fb.currentBlock = nil
1680 }
1681 return nil
1682 case BuiltinClose, BuiltinDelete, BuiltinClear, BuiltinPrint, BuiltinPrintln:
1683 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1684 call.name = fb.nextName()
1685 fb.emit(call)
1686 return nil
1687 case BuiltinCopy:
1688 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1689 call.typ = Typ[Int32]
1690 call.name = fb.nextName()
1691 fb.emit(call)
1692 return call
1693 case BuiltinRecover:
1694 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1695 call.typ = Typ[TCString]
1696 call.name = fb.nextName()
1697 fb.emit(call)
1698 return call
1699 }
1700 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1701 call.name = fb.nextName()
1702 fb.emit(call)
1703 return call
1704 }
1705
1706 func (fb *ssaFuncBuilder) emitMake(typ Type, sizeArgs []SSAValue) SSAValue {
1707 if typ == nil {
1708 return nil
1709 }
1710 switch safeUnderlying(typ).(type) {
1711 case *Slice:
1712 ms := &SSAMakeSlice{}
1713 ms.typ = typ
1714 ms.name = fb.nextName()
1715 if len(sizeArgs) > 0 {
1716 ms.Len = sizeArgs[0]
1717 }
1718 if len(sizeArgs) > 1 {
1719 ms.Cap = sizeArgs[1]
1720 }
1721 fb.emit(ms)
1722 return ms
1723 case *TCMap:
1724 mm := &SSAMakeMap{}
1725 mm.typ = typ
1726 mm.name = fb.nextName()
1727 if len(sizeArgs) > 0 {
1728 mm.Reserve = sizeArgs[0]
1729 }
1730 fb.emit(mm)
1731 return mm
1732 case *TCChan:
1733 mc := &SSAMakeChan{}
1734 mc.typ = typ
1735 mc.name = fb.nextName()
1736 if len(sizeArgs) > 0 {
1737 mc.Size = sizeArgs[0]
1738 }
1739 fb.emit(mc)
1740 return mc
1741 }
1742 return nil
1743 }
1744
1745 func (fb *ssaFuncBuilder) buildSelector(e *SelectorExpr) SSAValue {
1746 if name, ok := e.X.(*Name); ok {
1747 obj := fb.lookupObject(name.Value)
1748 if pn, ok2 := obj.(*PkgName); ok2 {
1749 return fb.buildPkgMember(pn, e.Sel.Value)
1750 }
1751 }
1752 fa := fb.buildSelectorAddr(e)
1753 if fa == nil {
1754 return nil
1755 }
1756 elemType := fa.SSAType()
1757 if p, ok := safeUnderlying(elemType).(*Pointer); ok {
1758 elemType = p.Elem()
1759 }
1760 return fb.emitLoad(fa, elemType)
1761 }
1762
1763 func (fb *ssaFuncBuilder) ensureImportedSSAPackage(imported *TCPackage) *SSAPackage {
1764 impPkg := fb.fn.Prog.ImportedPackage(imported.Path())
1765 if impPkg == nil {
1766 impPkg = &SSAPackage{
1767 Prog: fb.fn.Prog,
1768 Pkg: imported,
1769 Members: map[string]SSAMember{},
1770 }
1771 fb.fn.Prog.imported[imported.Path()] = impPkg
1772 fb.fn.Prog.packages[imported] = impPkg
1773 }
1774 return impPkg
1775 }
1776
1777 func (fb *ssaFuncBuilder) buildPkgMember(pn *PkgName, memberName string) SSAValue {
1778 imported := pn.Imported()
1779 if imported == nil {
1780 return nil
1781 }
1782 obj := imported.Scope().Lookup(memberName)
1783 if obj == nil {
1784 return nil
1785 }
1786 switch obj := obj.(type) {
1787 case *TCConst:
1788 return &SSAConst{typ: obj.Type(), val: obj.Val()}
1789 case *TCVar:
1790 impPkg := fb.ensureImportedSSAPackage(imported)
1791 g, ok := impPkg.Members[memberName].(*SSAGlobal)
1792 if !ok {
1793 g = &SSAGlobal{
1794 name: memberName,
1795 typ: NewPointer(obj.Type()),
1796 pkg: impPkg,
1797 }
1798 impPkg.Members[memberName] = g
1799 }
1800 return fb.emitLoad(g, obj.Type())
1801 case *TCFunc:
1802 impPkg := fb.ensureImportedSSAPackage(imported)
1803 fn := impPkg.Func(memberName)
1804 if fn != nil {
1805 return fn
1806 }
1807 return nil
1808 }
1809 return nil
1810 }
1811
1812 func (fb *ssaFuncBuilder) buildSelectorAddr(e *SelectorExpr) SSAValue {
1813 var addr SSAValue
1814 var structType Type
1815 if inner, ok := e.X.(*SelectorExpr); ok {
1816 addr = fb.buildSelectorAddr(inner)
1817 if addr == nil {
1818 return nil
1819 }
1820 structType = addr.SSAType()
1821 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1822 structType = p.Elem()
1823 }
1824 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1825 ld := &SSAUnOp{Op: OpMul, X: addr}
1826 ld.typ = structType
1827 ld.name = fb.nextName()
1828 fb.emit(ld)
1829 addr = ld
1830 structType = p.Elem()
1831 }
1832 } else if ie, ok := e.X.(*IndexExpr); ok {
1833 x := fb.buildExpr(ie.X)
1834 idx := fb.buildExpr(ie.Index)
1835 if x == nil || idx == nil {
1836 return nil
1837 }
1838 ia := &SSAIndexAddr{X: x, Index: idx}
1839 ia.typ = NewPointer(ssaElemType(x.SSAType()))
1840 ia.name = fb.nextName()
1841 fb.emit(ia)
1842 addr = ia
1843 structType = ssaElemType(x.SSAType())
1844 } else {
1845 x := fb.buildExpr(e.X)
1846 if x == nil || x.SSAType() == nil {
1847 if name, ok := e.X.(*Name); ok {
1848 obj := fb.lookupObject(name.Value)
1849 if pn, ok := obj.(*PkgName); ok {
1850 return fb.buildPkgMemberAddr(pn, e.Sel.Value)
1851 }
1852 }
1853 return nil
1854 }
1855 baseType := x.SSAType()
1856 addr = x
1857 if _, ok := safeUnderlying(baseType).(*Pointer); !ok {
1858 if name, ok := e.X.(*Name); ok {
1859 obj := fb.lookupObject(name.Value)
1860 if obj != nil {
1861 if alloc, ok2 := fb.vars[obj]; ok2 {
1862 addr = alloc
1863 baseType = NewPointer(baseType)
1864 }
1865 }
1866 }
1867 }
1868 structType = baseType
1869 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1870 structType = p.Elem()
1871 }
1872 }
1873 fieldIdx := fb.fieldIndex(structType, e.Sel.Value)
1874 if fieldIdx >= 0 {
1875 fa := &SSAFieldAddr{X: addr, Field: fieldIdx}
1876 fa.typ = NewPointer(fb.fieldType(structType, fieldIdx))
1877 fa.name = fb.nextName()
1878 fb.emit(fa)
1879 return fa
1880 }
1881 embedIdx, innerIdx := fb.findEmbeddedField(structType, e.Sel.Value)
1882 if embedIdx >= 0 {
1883 embedAddr := &SSAFieldAddr{X: addr, Field: embedIdx}
1884 embedAddr.typ = NewPointer(fb.fieldType(structType, embedIdx))
1885 embedAddr.name = fb.nextName()
1886 fb.emit(embedAddr)
1887 embedType := fb.fieldType(structType, embedIdx)
1888 innerFA := &SSAFieldAddr{X: embedAddr, Field: innerIdx}
1889 innerFA.typ = NewPointer(fb.fieldType(embedType, innerIdx))
1890 innerFA.name = fb.nextName()
1891 fb.emit(innerFA)
1892 return innerFA
1893 }
1894 return nil
1895 }
1896
1897 func (fb *ssaFuncBuilder) buildIndex(e *IndexExpr) SSAValue {
1898 x := fb.buildExpr(e.X)
1899 idx := fb.buildExpr(e.Index)
1900 if x == nil || idx == nil {
1901 return nil
1902 }
1903 if x.SSAType() == nil {
1904 return nil
1905 }
1906 switch t := safeUnderlying(x.SSAType()).(type) {
1907 case *TCMap:
1908 idx = fb.coerceToInterface(idx, t.Key())
1909 l := &SSALookup{X: x, Index: idx}
1910 l.typ = t.Elem()
1911 l.name = fb.nextName()
1912 fb.emit(l)
1913 return l
1914 default:
1915 ia := &SSAIndexAddr{X: x, Index: idx}
1916 ia.typ = NewPointer(ssaElemType(x.SSAType()))
1917 ia.name = fb.nextName()
1918 fb.emit(ia)
1919 return fb.emitLoad(ia, ssaElemType(x.SSAType()))
1920 }
1921 }
1922
1923 func (fb *ssaFuncBuilder) buildSlice(e *SliceExpr) SSAValue {
1924 x := fb.buildExpr(e.X)
1925 if x == nil {
1926 return nil
1927 }
1928 sl := &SSASlice{X: x}
1929 if len(e.Index) > 0 && e.Index[0] != nil {
1930 sl.Low = fb.buildExpr(e.Index[0])
1931 }
1932 if len(e.Index) > 1 && e.Index[1] != nil {
1933 sl.High = fb.buildExpr(e.Index[1])
1934 }
1935 if len(e.Index) > 2 && e.Index[2] != nil {
1936 sl.Max = fb.buildExpr(e.Index[2])
1937 }
1938 sl.typ = ssaSliceOf(x.SSAType())
1939 sl.name = fb.nextName()
1940 fb.emit(sl)
1941 return sl
1942 }
1943
1944 func (fb *ssaFuncBuilder) buildAssert(e *AssertExpr) SSAValue {
1945 x := fb.buildExpr(e.X)
1946 assertedType := fb.resolveType(e.Type)
1947 if x == nil {
1948 return nil
1949 }
1950 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: false}
1951 ta.typ = assertedType
1952 ta.name = fb.nextName()
1953 fb.emit(ta)
1954 return ta
1955 }
1956
1957 func (fb *ssaFuncBuilder) buildCompositeLit(e *CompositeLit) SSAValue {
1958 var typ Type
1959 if e.Type != nil {
1960 typ = fb.resolveType(e.Type)
1961 }
1962 if typ == nil {
1963 return nil
1964 }
1965
1966 if sl, ok := safeUnderlying(typ).(*Slice); ok {
1967 return fb.buildSliceLit(e, typ, sl)
1968 }
1969
1970 if mt, isMap := safeUnderlying(typ).(*TCMap); isMap {
1971 mm := &SSAMakeMap{}
1972 mm.typ = typ
1973 mm.name = fb.nextName()
1974 fb.emit(mm)
1975 for _, el := range e.ElemList {
1976 if kv, ok := el.(*KeyValueExpr); ok {
1977 k := fb.buildExpr(kv.Key)
1978 v := fb.buildExpr(kv.Value)
1979 if k != nil && v != nil {
1980 k = fb.coerceToInterface(k, mt.Key())
1981 v = fb.coerceToInterface(v, mt.Elem())
1982 fb.emit(&SSAMapUpdate{Map: mm, Key: k, Value: v})
1983 }
1984 }
1985 }
1986 return mm
1987 }
1988
1989 alloc := fb.emitAlloc(typ, 0)
1990 posIdx := 0
1991 for _, el := range e.ElemList {
1992 if kv, ok := el.(*KeyValueExpr); ok {
1993 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
1994 idx := fb.fieldIndex(typ, kv.Key.(*Name).Value)
1995 if idx >= 0 {
1996 fa := &SSAFieldAddr{X: alloc, Field: idx}
1997 fa.typ = NewPointer(fb.fieldType(typ, idx))
1998 fa.name = fb.nextName()
1999 fb.emit(fa)
2000 v := fb.buildExpr(kv.Value)
2001 if v != nil {
2002 fb.emitStore(fa, v)
2003 }
2004 }
2005 }
2006 } else {
2007 v := fb.buildExpr(el)
2008 if v != nil {
2009 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2010 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
2011 fa.typ = NewPointer(fb.fieldType(typ, posIdx))
2012 fa.name = fb.nextName()
2013 fb.emit(fa)
2014 fb.emitStore(fa, v)
2015 }
2016 }
2017 posIdx++
2018 }
2019 }
2020 return fb.emitLoad(alloc, typ)
2021 }
2022
2023 func (fb *ssaFuncBuilder) buildSliceLit(e *CompositeLit, typ Type, sl *Slice) SSAValue {
2024 n := len(e.ElemList)
2025 nVal := &SSAConst{typ: Typ[Int32], val: constant.MakeInt64(int64(n))}
2026 ms := &SSAMakeSlice{}
2027 ms.typ = typ
2028 ms.name = fb.nextName()
2029 ms.Len = nVal
2030 ms.Cap = nVal
2031 fb.emit(ms)
2032
2033 for i, el := range e.ElemList {
2034 var v SSAValue
2035 if kv, ok := el.(*KeyValueExpr); ok {
2036 v = fb.buildExpr(kv.Value)
2037 } else {
2038 v = fb.buildExpr(el)
2039 }
2040 if v == nil {
2041 continue
2042 }
2043 idx := &SSAConst{typ: Typ[Int32], val: constant.MakeInt64(int64(i))}
2044 ia := &SSAIndexAddr{X: ms, Index: idx}
2045 ia.typ = NewPointer(sl.Elem())
2046 ia.name = fb.nextName()
2047 fb.emit(ia)
2048 v = fb.coerceToInterface(v, sl.Elem())
2049 fb.emitStore(ia, v)
2050 }
2051 return ms
2052 }
2053
2054 func (fb *ssaFuncBuilder) buildFuncLit(e *FuncLit) SSAValue {
2055 var sig *Signature
2056 if fb.info != nil {
2057 if tv, ok := fb.info.Types[e]; ok {
2058 sig, _ = tv.Type.(*Signature)
2059 }
2060 }
2061 if sig == nil && e.Type != nil {
2062 sig = tcResolveFuncInline(e.Type)
2063 }
2064 name := fb.fn.name | "$" | ssaItoa(len(fb.fn.AnonFuncs)+1)
2065 anon := &SSAFunction{
2066 name: name,
2067 Signature: sig,
2068 pos: 0,
2069 Pkg: fb.fn.Pkg,
2070 Prog: fb.fn.Prog,
2071 parent: fb.fn,
2072 }
2073 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, anon)
2074
2075 ab := newSSAFuncBuilder(anon, fb.info)
2076 ab.parent = fb
2077 d := &FuncDecl{
2078 Name: &Name{Value: name},
2079 Type: e.Type,
2080 Body: e.Body,
2081 }
2082 ab.buildBody(d)
2083
2084 if len(anon.FreeVars) == 0 {
2085 return anon
2086 }
2087 bindings := []SSAValue{:0:len(anon.FreeVars)}
2088 for _, fv := range anon.FreeVars {
2089 obj := fb.lookupObject(fv.name)
2090 if obj != nil {
2091 if alloc, ok := fb.vars[obj]; ok {
2092 loaded := fb.emitLoad(alloc, fv.typ)
2093 bindings = append(bindings, loaded)
2094 }
2095 }
2096 }
2097 mc := &SSAMakeClosure{Fn: anon, Bindings: bindings}
2098 mc.typ = sig
2099 mc.name = fb.nextName()
2100 fb.emit(mc)
2101 return mc
2102 }
2103
2104 func (fb *ssaFuncBuilder) removeVar(name string) {
2105 for o := range fb.vars {
2106 if o.Name() == name {
2107 delete(fb.vars, o)
2108 return
2109 }
2110 }
2111 }
2112
2113 func (fb *ssaFuncBuilder) buildPkgMemberAddr(pn *PkgName, memberName string) SSAValue {
2114 imported := pn.Imported()
2115 if imported == nil {
2116 return nil
2117 }
2118 obj := imported.Scope().Lookup(memberName)
2119 if obj == nil {
2120 return nil
2121 }
2122 switch obj := obj.(type) {
2123 case *TCConst:
2124 return nil
2125 case *TCVar:
2126 impPkg := fb.ensureImportedSSAPackage(imported)
2127 g, ok := impPkg.Members[memberName].(*SSAGlobal)
2128 if !ok {
2129 g = &SSAGlobal{
2130 name: memberName,
2131 typ: NewPointer(obj.Type()),
2132 pkg: impPkg,
2133 }
2134 impPkg.Members[memberName] = g
2135 }
2136 return g
2137 }
2138 return nil
2139 }
2140
2141 func (fb *ssaFuncBuilder) buildPkgCall(pn *PkgName, funcName string, argList []Expr) SSAValue {
2142 imported := pn.Imported()
2143 if imported == nil {
2144 return nil
2145 }
2146 obj := imported.Scope().Lookup(funcName)
2147 if obj == nil {
2148 return nil
2149 }
2150 fn, ok := obj.(*TCFunc)
2151 if !ok {
2152 return nil
2153 }
2154 impPkg := fb.ensureImportedSSAPackage(imported)
2155 ssaFn := impPkg.Func(funcName)
2156 if ssaFn == nil {
2157 ssaFn = &SSAFunction{
2158 name: funcName,
2159 object: fn,
2160 Signature: fn.Type().(*Signature),
2161 Pkg: impPkg,
2162 Prog: fb.fn.Prog,
2163 }
2164 impPkg.Members[funcName] = ssaFn
2165 }
2166 args := fb.buildArgs(argList)
2167 var retType Type
2168 if ssaFn.Signature != nil {
2169 if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() == 1 {
2170 retType = ssaFn.Signature.Results().At(0).Type()
2171 } else if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() > 1 {
2172 retType = ssaFn.Signature.Results()
2173 }
2174 }
2175 call := &SSACall{Call: SSACallCommon{Value: ssaFn, Args: args}}
2176 call.typ = retType
2177 call.name = fb.nextName()
2178 fb.emit(call)
2179 if retType == nil {
2180 return nil
2181 }
2182 return call
2183 }
2184
2185 // Helpers.
2186
2187 func (fb *ssaFuncBuilder) lookupObject(name string) Object {
2188 for obj := range fb.vars {
2189 if obj.Name() == name {
2190 return obj
2191 }
2192 }
2193 if fb.parent != nil {
2194 for obj := range fb.parent.vars {
2195 if obj.Name() == name {
2196 return obj
2197 }
2198 }
2199 }
2200 if fb.fn.Pkg != nil {
2201 if _, obj := fb.fn.Pkg.Pkg.Scope().LookupParent(name); obj != nil {
2202 return obj
2203 }
2204 }
2205 return nil
2206 }
2207
2208 func (fb *ssaFuncBuilder) getOrCreateFreeVar(name string, typ Type) SSAValue {
2209 for _, fv := range fb.fn.FreeVars {
2210 if fv.name == name {
2211 return fv
2212 }
2213 }
2214 fv := &SSAFreeVar{
2215 name: name,
2216 typ: typ,
2217 parent: fb.fn,
2218 }
2219 fb.fn.FreeVars = append(fb.fn.FreeVars, fv)
2220 return fv
2221 }
2222
2223 func (fb *ssaFuncBuilder) lookupVar(name string) *TCVar {
2224 obj := fb.lookupObject(name)
2225 v, _ := obj.(*TCVar)
2226 return v
2227 }
2228
2229 func (fb *ssaFuncBuilder) resolveMethodCallWithRecv(sel *SelectorExpr, recv SSAValue) (*SSAFunction, SSAValue) {
2230 typ := recv.SSAType()
2231 isPtr := false
2232 if p, ok := safeUnderlying(typ).(*Pointer); ok {
2233 typ = p.Elem()
2234 isPtr = true
2235 }
2236 if _, ok := safeUnderlying(typ).(*TCInterface); ok {
2237 return nil, nil
2238 }
2239 named, ok := typ.(*Named)
2240 if !ok {
2241 return nil, nil
2242 }
2243 typeName := ""
2244 if named.Obj() != nil {
2245 typeName = named.Obj().Name()
2246 }
2247 if typeName == "" {
2248 return nil, nil
2249 }
2250 mangledName := typeName | "." | sel.Sel.Value
2251 fn, _ := fb.fn.Pkg.Members[mangledName].(*SSAFunction)
2252 if fn != nil {
2253 if fn.Signature != nil && fn.Signature.Recv() != nil {
2254 recvParam := fn.Signature.Recv()
2255 _, recvIsPtr := safeUnderlying(recvParam.Type()).(*Pointer)
2256 if recvIsPtr && !isPtr {
2257 if nameExpr, ok2 := sel.X.(*Name); ok2 {
2258 obj := fb.lookupObject(nameExpr.Value)
2259 if obj != nil {
2260 if alloc, ok3 := fb.vars[obj]; ok3 {
2261 recv = alloc
2262 }
2263 }
2264 }
2265 }
2266 }
2267 return fn, recv
2268 }
2269 st, ok2 := safeUnderlying(named).(*TCStruct)
2270 if !ok2 {
2271 return nil, nil
2272 }
2273 for i := 0; i < st.NumFields(); i++ {
2274 f := st.Field(i)
2275 if !f.Anonymous() {
2276 continue
2277 }
2278 embedType := f.Type()
2279 embedNamed, ok3 := embedType.(*Named)
2280 if !ok3 {
2281 if p, ok4 := embedType.(*Pointer); ok4 {
2282 embedNamed, ok3 = p.Elem().(*Named)
2283 }
2284 }
2285 if !ok3 || embedNamed.Obj() == nil {
2286 continue
2287 }
2288 embedName := embedNamed.Obj().Name()
2289 embedMangledName := embedName | "." | sel.Sel.Value
2290 embedFn, _ := fb.fn.Pkg.Members[embedMangledName].(*SSAFunction)
2291 if embedFn != nil {
2292 fieldAddr := &SSAFieldAddr{
2293 X: recv,
2294 Field: i,
2295 }
2296 fieldAddr.typ = NewPointer(embedType)
2297 fieldAddr.name = fb.nextName()
2298 fb.emit(fieldAddr)
2299 return embedFn, fieldAddr
2300 }
2301 embedSt, ok5 := safeUnderlying(embedNamed).(*TCStruct)
2302 if !ok5 {
2303 continue
2304 }
2305 for j := 0; j < embedSt.NumFields(); j++ {
2306 f2 := embedSt.Field(j)
2307 if !f2.Anonymous() {
2308 continue
2309 }
2310 embed2Type := f2.Type()
2311 embed2Named, ok6 := embed2Type.(*Named)
2312 if !ok6 {
2313 if p2, ok7 := embed2Type.(*Pointer); ok7 {
2314 embed2Named, ok6 = p2.Elem().(*Named)
2315 }
2316 }
2317 if !ok6 || embed2Named.Obj() == nil {
2318 continue
2319 }
2320 embed2Name := embed2Named.Obj().Name()
2321 embed2Mangled := embed2Name | "." | sel.Sel.Value
2322 embed2Fn, _ := fb.fn.Pkg.Members[embed2Mangled].(*SSAFunction)
2323 if embed2Fn == nil {
2324 continue
2325 }
2326 fieldAddr1 := &SSAFieldAddr{X: recv, Field: i}
2327 fieldAddr1.typ = NewPointer(embedType)
2328 fieldAddr1.name = fb.nextName()
2329 fb.emit(fieldAddr1)
2330 fieldAddr2 := &SSAFieldAddr{X: fieldAddr1, Field: j}
2331 fieldAddr2.typ = NewPointer(embed2Type)
2332 fieldAddr2.name = fb.nextName()
2333 fb.emit(fieldAddr2)
2334 return embed2Fn, fieldAddr2
2335 }
2336 }
2337 return nil, nil
2338 }
2339
2340 func (fb *ssaFuncBuilder) buildIfaceMethodCall(sel *SelectorExpr, recv SSAValue, argExprs []Expr) SSAValue {
2341 typ := recv.SSAType()
2342 if p, ok := safeUnderlying(typ).(*Pointer); ok {
2343 typ = p.Elem()
2344 }
2345 iface, ok := safeUnderlying(typ).(*TCInterface)
2346 if !ok {
2347 return nil
2348 }
2349 var methodSig *Signature
2350 for i := 0; i < iface.NumMethods(); i++ {
2351 if iface.Method(i).Name() == sel.Sel.Value {
2352 methodSig = iface.Method(i).Sig()
2353 break
2354 }
2355 }
2356 var retType Type
2357 if methodSig != nil && methodSig.Results() != nil {
2358 if methodSig.Results().Len() == 1 {
2359 retType = methodSig.Results().At(0).Type()
2360 } else if methodSig.Results().Len() > 1 {
2361 retType = methodSig.Results()
2362 }
2363 }
2364 args := fb.buildArgs(argExprs)
2365 inv := &SSAInvoke{
2366 X: recv,
2367 MethodName: sel.Sel.Value,
2368 IfaceType: iface,
2369 Args: args,
2370 }
2371 inv.typ = retType
2372 inv.name = fb.nextName()
2373 fb.emit(inv)
2374 if retType == nil {
2375 return nil
2376 }
2377 return inv
2378 }
2379
2380 func (fb *ssaFuncBuilder) resolveType(e Expr) Type {
2381 if fb.info != nil {
2382 if tv, ok := fb.info.Types[e]; ok && tv.Type != nil {
2383 return tv.Type
2384 }
2385 }
2386 return fb.resolveTypeAST(e)
2387 }
2388
2389 func (fb *ssaFuncBuilder) resolveTypeAST(e Expr) Type {
2390 if e == nil {
2391 return nil
2392 }
2393 switch e := e.(type) {
2394 case *Name:
2395 obj := fb.lookupObject(e.Value)
2396 if tn, ok := obj.(*TypeName); ok {
2397 return tn.Type()
2398 }
2399 case *Operation:
2400 if e.Y == nil && e.Op == Mul {
2401 base := fb.resolveTypeAST(e.X)
2402 if base != nil {
2403 return NewPointer(base)
2404 }
2405 }
2406 case *SliceType:
2407 elem := fb.resolveTypeAST(e.Elem)
2408 if elem != nil {
2409 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
2410 return Typ[TCString]
2411 }
2412 return NewSlice(elem)
2413 }
2414 case *ArrayType:
2415 elem := fb.resolveTypeAST(e.Elem)
2416 if elem != nil {
2417 n := int64(-1)
2418 if lit, ok := e.Len.(*BasicLit); ok {
2419 n = ssaParseInt64(lit.Value)
2420 }
2421 return NewArray(elem, n)
2422 }
2423 case *MapType:
2424 key := fb.resolveTypeAST(e.Key)
2425 val := fb.resolveTypeAST(e.Value)
2426 if key != nil && val != nil {
2427 return NewTCMap(key, val)
2428 }
2429 case *InterfaceType:
2430 return fb.resolveInterfaceTypeAST(e)
2431 }
2432 return nil
2433 }
2434
2435 func (fb *ssaFuncBuilder) resolveInterfaceTypeAST(e *InterfaceType) *TCInterface {
2436 var methods []*IfaceMethod
2437 for _, f := range e.MethodList {
2438 if f.Name == nil {
2439 continue
2440 }
2441 ft, ok := f.Type.(*FuncType)
2442 if !ok {
2443 continue
2444 }
2445 sig := fb.resolveFuncTypeAST(ft)
2446 if sig != nil {
2447 methods = append(methods, NewTCIfaceMethod(f.Name.Value, sig))
2448 }
2449 }
2450 iface := NewTCInterface(methods, nil)
2451 iface.Complete()
2452 return iface
2453 }
2454
2455 func (fb *ssaFuncBuilder) resolveFuncTypeAST(ft *FuncType) *Signature {
2456 if ft == nil {
2457 return nil
2458 }
2459 var params []*TCVar
2460 for _, p := range ft.ParamList {
2461 typ := fb.resolveTypeAST(p.Type)
2462 pname := ""
2463 if p.Name != nil {
2464 pname = p.Name.Value
2465 }
2466 params = append(params, NewTCVar(nil, pname, typ))
2467 }
2468 var results []*TCVar
2469 for _, r := range ft.ResultList {
2470 typ := fb.resolveTypeAST(r.Type)
2471 rname := ""
2472 if r.Name != nil {
2473 rname = r.Name.Value
2474 }
2475 results = append(results, NewTCVar(nil, rname, typ))
2476 }
2477 var pTuple, rTuple *Tuple
2478 if len(params) > 0 {
2479 pTuple = NewTuple(params...)
2480 }
2481 if len(results) > 0 {
2482 rTuple = NewTuple(results...)
2483 }
2484 return NewSignature(nil, pTuple, rTuple, false)
2485 }
2486
2487 func (fb *ssaFuncBuilder) fieldIndex(t Type, name string) int {
2488 if t == nil {
2489 return -1
2490 }
2491 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2492 t = pt.Elem()
2493 }
2494 if st, ok := safeUnderlying(t).(*TCStruct); ok {
2495 for i := 0; i < st.NumFields(); i++ {
2496 if st.Field(i).Name() == name {
2497 return i
2498 }
2499 }
2500 }
2501 return -1
2502 }
2503
2504 func (fb *ssaFuncBuilder) findEmbeddedField(t Type, name string) (embedIdx int, innerIdx int) {
2505 if t == nil {
2506 return -1, -1
2507 }
2508 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2509 t = pt.Elem()
2510 }
2511 st, ok := safeUnderlying(t).(*TCStruct)
2512 if !ok {
2513 return -1, -1
2514 }
2515 for i := 0; i < st.NumFields(); i++ {
2516 f := st.Field(i)
2517 if !f.Anonymous() {
2518 continue
2519 }
2520 embedType := f.Type()
2521 if pt, ok := safeUnderlying(embedType).(*Pointer); ok {
2522 embedType = pt.Elem()
2523 }
2524 inner := fb.fieldIndex(embedType, name)
2525 if inner >= 0 {
2526 return i, inner
2527 }
2528 }
2529 return -1, -1
2530 }
2531
2532 func (fb *ssaFuncBuilder) fieldType(t Type, idx int) Type {
2533 if t == nil {
2534 return nil
2535 }
2536 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2537 t = pt.Elem()
2538 }
2539 if st, ok := safeUnderlying(t).(*TCStruct); ok {
2540 if idx >= 0 && idx < st.NumFields() {
2541 return st.Field(idx).Type()
2542 }
2543 }
2544 return nil
2545 }
2546
2547 func ssaExprNames(e Expr) []*Name {
2548 if e == nil {
2549 return nil
2550 }
2551 if n, ok := e.(*Name); ok {
2552 return []*Name{n}
2553 }
2554 if l, ok := e.(*ListExpr); ok {
2555 var names []*Name
2556 for _, el := range l.ElemList {
2557 if n, ok := el.(*Name); ok {
2558 names = append(names, n)
2559 }
2560 }
2561 return names
2562 }
2563 return nil
2564 }
2565