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