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: false}
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 case BuiltinMin, BuiltinMax:
1700 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1701 if len(args) > 0 && args[0] != nil {
1702 call.typ = args[0].SSAType()
1703 } else {
1704 call.typ = Typ[Int32]
1705 }
1706 call.name = fb.nextName()
1707 fb.emit(call)
1708 return call
1709 }
1710 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
1711 call.name = fb.nextName()
1712 fb.emit(call)
1713 return call
1714 }
1715
1716 func (fb *ssaFuncBuilder) emitMake(typ Type, sizeArgs []SSAValue) SSAValue {
1717 if typ == nil {
1718 return nil
1719 }
1720 switch safeUnderlying(typ).(type) {
1721 case *Slice:
1722 ms := &SSAMakeSlice{}
1723 ms.typ = typ
1724 ms.name = fb.nextName()
1725 if len(sizeArgs) > 0 {
1726 ms.Len = sizeArgs[0]
1727 }
1728 if len(sizeArgs) > 1 {
1729 ms.Cap = sizeArgs[1]
1730 }
1731 fb.emit(ms)
1732 return ms
1733 case *TCMap:
1734 mm := &SSAMakeMap{}
1735 mm.typ = typ
1736 mm.name = fb.nextName()
1737 if len(sizeArgs) > 0 {
1738 mm.Reserve = sizeArgs[0]
1739 }
1740 fb.emit(mm)
1741 return mm
1742 case *TCChan:
1743 mc := &SSAMakeChan{}
1744 mc.typ = typ
1745 mc.name = fb.nextName()
1746 if len(sizeArgs) > 0 {
1747 mc.Size = sizeArgs[0]
1748 }
1749 fb.emit(mc)
1750 return mc
1751 }
1752 return nil
1753 }
1754
1755 func (fb *ssaFuncBuilder) buildSelector(e *SelectorExpr) SSAValue {
1756 if name, ok := e.X.(*Name); ok {
1757 obj := fb.lookupObject(name.Value)
1758 if pn, ok2 := obj.(*PkgName); ok2 {
1759 return fb.buildPkgMember(pn, e.Sel.Value)
1760 }
1761 }
1762 fa := fb.buildSelectorAddr(e)
1763 if fa == nil {
1764 return nil
1765 }
1766 elemType := fa.SSAType()
1767 if p, ok := safeUnderlying(elemType).(*Pointer); ok {
1768 elemType = p.Elem()
1769 }
1770 return fb.emitLoad(fa, elemType)
1771 }
1772
1773 func (fb *ssaFuncBuilder) ensureImportedSSAPackage(imported *TCPackage) *SSAPackage {
1774 impPkg := fb.fn.Prog.ImportedPackage(imported.Path())
1775 if impPkg == nil {
1776 impPkg = &SSAPackage{
1777 Prog: fb.fn.Prog,
1778 Pkg: imported,
1779 Members: map[string]SSAMember{},
1780 }
1781 fb.fn.Prog.imported[imported.Path()] = impPkg
1782 fb.fn.Prog.packages[imported] = impPkg
1783 }
1784 return impPkg
1785 }
1786
1787 func (fb *ssaFuncBuilder) buildPkgMember(pn *PkgName, memberName string) SSAValue {
1788 imported := pn.Imported()
1789 if imported == nil {
1790 return nil
1791 }
1792 obj := imported.Scope().Lookup(memberName)
1793 if obj == nil {
1794 return nil
1795 }
1796 switch obj := obj.(type) {
1797 case *TCConst:
1798 return &SSAConst{typ: obj.Type(), val: obj.Val()}
1799 case *TCVar:
1800 impPkg := fb.ensureImportedSSAPackage(imported)
1801 g, ok := impPkg.Members[memberName].(*SSAGlobal)
1802 if !ok {
1803 g = &SSAGlobal{
1804 name: memberName,
1805 typ: NewPointer(obj.Type()),
1806 pkg: impPkg,
1807 }
1808 impPkg.Members[memberName] = g
1809 }
1810 return fb.emitLoad(g, obj.Type())
1811 case *TCFunc:
1812 impPkg := fb.ensureImportedSSAPackage(imported)
1813 fn := impPkg.Func(memberName)
1814 if fn != nil {
1815 return fn
1816 }
1817 return nil
1818 }
1819 return nil
1820 }
1821
1822 func (fb *ssaFuncBuilder) buildSelectorAddr(e *SelectorExpr) SSAValue {
1823 var addr SSAValue
1824 var structType Type
1825 if inner, ok := e.X.(*SelectorExpr); ok {
1826 addr = fb.buildSelectorAddr(inner)
1827 if addr == nil {
1828 return nil
1829 }
1830 structType = addr.SSAType()
1831 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1832 structType = p.Elem()
1833 }
1834 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1835 ld := &SSAUnOp{Op: OpMul, X: addr}
1836 ld.typ = structType
1837 ld.name = fb.nextName()
1838 fb.emit(ld)
1839 addr = ld
1840 structType = p.Elem()
1841 }
1842 } else if ie, ok := e.X.(*IndexExpr); ok {
1843 x := fb.buildExpr(ie.X)
1844 idx := fb.buildExpr(ie.Index)
1845 if x == nil || idx == nil {
1846 return nil
1847 }
1848 ia := &SSAIndexAddr{X: x, Index: idx}
1849 ia.typ = NewPointer(ssaElemType(x.SSAType()))
1850 ia.name = fb.nextName()
1851 fb.emit(ia)
1852 addr = ia
1853 structType = ssaElemType(x.SSAType())
1854 } else {
1855 x := fb.buildExpr(e.X)
1856 if x == nil || x.SSAType() == nil {
1857 if name, ok := e.X.(*Name); ok {
1858 obj := fb.lookupObject(name.Value)
1859 if pn, ok := obj.(*PkgName); ok {
1860 return fb.buildPkgMemberAddr(pn, e.Sel.Value)
1861 }
1862 }
1863 return nil
1864 }
1865 baseType := x.SSAType()
1866 addr = x
1867 if _, ok := safeUnderlying(baseType).(*Pointer); !ok {
1868 if name, ok := e.X.(*Name); ok {
1869 obj := fb.lookupObject(name.Value)
1870 if obj != nil {
1871 if alloc, ok2 := fb.vars[obj]; ok2 {
1872 addr = alloc
1873 baseType = NewPointer(baseType)
1874 }
1875 }
1876 }
1877 }
1878 structType = baseType
1879 if p, ok := safeUnderlying(structType).(*Pointer); ok {
1880 structType = p.Elem()
1881 }
1882 }
1883 fieldIdx := fb.fieldIndex(structType, e.Sel.Value)
1884 if fieldIdx >= 0 {
1885 fa := &SSAFieldAddr{X: addr, Field: fieldIdx}
1886 fa.typ = NewPointer(fb.fieldType(structType, fieldIdx))
1887 fa.name = fb.nextName()
1888 fb.emit(fa)
1889 return fa
1890 }
1891 embedIdx, innerIdx := fb.findEmbeddedField(structType, e.Sel.Value)
1892 if embedIdx >= 0 {
1893 embedAddr := &SSAFieldAddr{X: addr, Field: embedIdx}
1894 embedAddr.typ = NewPointer(fb.fieldType(structType, embedIdx))
1895 embedAddr.name = fb.nextName()
1896 fb.emit(embedAddr)
1897 embedType := fb.fieldType(structType, embedIdx)
1898 innerFA := &SSAFieldAddr{X: embedAddr, Field: innerIdx}
1899 innerFA.typ = NewPointer(fb.fieldType(embedType, innerIdx))
1900 innerFA.name = fb.nextName()
1901 fb.emit(innerFA)
1902 return innerFA
1903 }
1904 return nil
1905 }
1906
1907 func (fb *ssaFuncBuilder) buildIndex(e *IndexExpr) SSAValue {
1908 x := fb.buildExpr(e.X)
1909 idx := fb.buildExpr(e.Index)
1910 if x == nil || idx == nil {
1911 return nil
1912 }
1913 if x.SSAType() == nil {
1914 return nil
1915 }
1916 switch t := safeUnderlying(x.SSAType()).(type) {
1917 case *TCMap:
1918 idx = fb.coerceToInterface(idx, t.Key())
1919 l := &SSALookup{X: x, Index: idx}
1920 l.typ = t.Elem()
1921 l.name = fb.nextName()
1922 fb.emit(l)
1923 return l
1924 default:
1925 ia := &SSAIndexAddr{X: x, Index: idx}
1926 ia.typ = NewPointer(ssaElemType(x.SSAType()))
1927 ia.name = fb.nextName()
1928 fb.emit(ia)
1929 return fb.emitLoad(ia, ssaElemType(x.SSAType()))
1930 }
1931 }
1932
1933 func (fb *ssaFuncBuilder) buildSlice(e *SliceExpr) SSAValue {
1934 x := fb.buildExpr(e.X)
1935 if x == nil {
1936 return nil
1937 }
1938 sl := &SSASlice{X: x}
1939 if len(e.Index) > 0 && e.Index[0] != nil {
1940 sl.Low = fb.buildExpr(e.Index[0])
1941 }
1942 if len(e.Index) > 1 && e.Index[1] != nil {
1943 sl.High = fb.buildExpr(e.Index[1])
1944 }
1945 if len(e.Index) > 2 && e.Index[2] != nil {
1946 sl.Max = fb.buildExpr(e.Index[2])
1947 }
1948 sl.typ = ssaSliceOf(x.SSAType())
1949 sl.name = fb.nextName()
1950 fb.emit(sl)
1951 return sl
1952 }
1953
1954 func (fb *ssaFuncBuilder) buildAssert(e *AssertExpr) SSAValue {
1955 x := fb.buildExpr(e.X)
1956 assertedType := fb.resolveType(e.Type)
1957 if x == nil {
1958 return nil
1959 }
1960 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: false}
1961 ta.typ = assertedType
1962 ta.name = fb.nextName()
1963 fb.emit(ta)
1964 return ta
1965 }
1966
1967 func (fb *ssaFuncBuilder) buildCompositeLit(e *CompositeLit) SSAValue {
1968 var typ Type
1969 if e.Type != nil {
1970 typ = fb.resolveType(e.Type)
1971 }
1972 if typ == nil {
1973 return nil
1974 }
1975
1976 if sl, ok := safeUnderlying(typ).(*Slice); ok {
1977 return fb.buildSliceLit(e, typ, sl)
1978 }
1979
1980 if mt, isMap := safeUnderlying(typ).(*TCMap); isMap {
1981 mm := &SSAMakeMap{}
1982 mm.typ = typ
1983 mm.name = fb.nextName()
1984 fb.emit(mm)
1985 for _, el := range e.ElemList {
1986 if kv, ok := el.(*KeyValueExpr); ok {
1987 k := fb.buildExpr(kv.Key)
1988 v := fb.buildExpr(kv.Value)
1989 if k != nil && v != nil {
1990 k = fb.coerceToInterface(k, mt.Key())
1991 v = fb.coerceToInterface(v, mt.Elem())
1992 fb.emit(&SSAMapUpdate{Map: mm, Key: k, Value: v})
1993 }
1994 }
1995 }
1996 return mm
1997 }
1998
1999 alloc := fb.emitAlloc(typ, 0)
2000 posIdx := 0
2001 for _, el := range e.ElemList {
2002 if kv, ok := el.(*KeyValueExpr); ok {
2003 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2004 idx := fb.fieldIndex(typ, kv.Key.(*Name).Value)
2005 if idx >= 0 {
2006 fa := &SSAFieldAddr{X: alloc, Field: idx}
2007 fa.typ = NewPointer(fb.fieldType(typ, idx))
2008 fa.name = fb.nextName()
2009 fb.emit(fa)
2010 v := fb.buildExpr(kv.Value)
2011 if v != nil {
2012 fb.emitStore(fa, v)
2013 }
2014 }
2015 }
2016 } else {
2017 v := fb.buildExpr(el)
2018 if v != nil {
2019 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2020 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
2021 fa.typ = NewPointer(fb.fieldType(typ, posIdx))
2022 fa.name = fb.nextName()
2023 fb.emit(fa)
2024 fb.emitStore(fa, v)
2025 }
2026 }
2027 posIdx++
2028 }
2029 }
2030 return fb.emitLoad(alloc, typ)
2031 }
2032
2033 func (fb *ssaFuncBuilder) buildSliceLit(e *CompositeLit, typ Type, sl *Slice) SSAValue {
2034 n := len(e.ElemList)
2035 nVal := &SSAConst{typ: Typ[Int32], val: constant.MakeInt64(int64(n))}
2036 ms := &SSAMakeSlice{}
2037 ms.typ = typ
2038 ms.name = fb.nextName()
2039 ms.Len = nVal
2040 ms.Cap = nVal
2041 fb.emit(ms)
2042
2043 for i, el := range e.ElemList {
2044 var v SSAValue
2045 if kv, ok := el.(*KeyValueExpr); ok {
2046 v = fb.buildExpr(kv.Value)
2047 } else {
2048 v = fb.buildExpr(el)
2049 }
2050 if v == nil {
2051 continue
2052 }
2053 idx := &SSAConst{typ: Typ[Int32], val: constant.MakeInt64(int64(i))}
2054 ia := &SSAIndexAddr{X: ms, Index: idx}
2055 ia.typ = NewPointer(sl.Elem())
2056 ia.name = fb.nextName()
2057 fb.emit(ia)
2058 v = fb.coerceToInterface(v, sl.Elem())
2059 fb.emitStore(ia, v)
2060 }
2061 return ms
2062 }
2063
2064 func (fb *ssaFuncBuilder) buildFuncLit(e *FuncLit) SSAValue {
2065 var sig *Signature
2066 if fb.info != nil {
2067 if tv, ok := fb.info.Types[e]; ok {
2068 sig, _ = tv.Type.(*Signature)
2069 }
2070 }
2071 if sig == nil && e.Type != nil {
2072 sig = tcResolveFuncInline(e.Type, fb.fn.Pkg.Pkg.Scope())
2073 }
2074 name := fb.fn.name | "$" | ssaItoa(len(fb.fn.AnonFuncs)+1)
2075 anon := &SSAFunction{
2076 name: name,
2077 Signature: sig,
2078 pos: 0,
2079 Pkg: fb.fn.Pkg,
2080 Prog: fb.fn.Prog,
2081 parent: fb.fn,
2082 }
2083 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, anon)
2084
2085 ab := newSSAFuncBuilder(anon, fb.info)
2086 ab.parent = fb
2087 d := &FuncDecl{
2088 Name: &Name{Value: name},
2089 Type: e.Type,
2090 Body: e.Body,
2091 }
2092 ab.buildBody(d)
2093
2094 if len(anon.FreeVars) == 0 {
2095 return anon
2096 }
2097 bindings := []SSAValue{:0:len(anon.FreeVars)}
2098 for _, fv := range anon.FreeVars {
2099 obj := fb.lookupObject(fv.name)
2100 if obj != nil {
2101 if alloc, ok := fb.vars[obj]; ok {
2102 loaded := fb.emitLoad(alloc, fv.typ)
2103 bindings = append(bindings, loaded)
2104 }
2105 }
2106 }
2107 mc := &SSAMakeClosure{Fn: anon, Bindings: bindings}
2108 mc.typ = sig
2109 mc.name = fb.nextName()
2110 fb.emit(mc)
2111 return mc
2112 }
2113
2114 func (fb *ssaFuncBuilder) removeVar(name string) {
2115 for o := range fb.vars {
2116 if o.Name() == name {
2117 delete(fb.vars, o)
2118 return
2119 }
2120 }
2121 }
2122
2123 func (fb *ssaFuncBuilder) buildPkgMemberAddr(pn *PkgName, memberName string) SSAValue {
2124 imported := pn.Imported()
2125 if imported == nil {
2126 return nil
2127 }
2128 obj := imported.Scope().Lookup(memberName)
2129 if obj == nil {
2130 return nil
2131 }
2132 switch obj := obj.(type) {
2133 case *TCConst:
2134 return nil
2135 case *TCVar:
2136 impPkg := fb.ensureImportedSSAPackage(imported)
2137 g, ok := impPkg.Members[memberName].(*SSAGlobal)
2138 if !ok {
2139 g = &SSAGlobal{
2140 name: memberName,
2141 typ: NewPointer(obj.Type()),
2142 pkg: impPkg,
2143 }
2144 impPkg.Members[memberName] = g
2145 }
2146 return g
2147 }
2148 return nil
2149 }
2150
2151 func (fb *ssaFuncBuilder) buildPkgCall(pn *PkgName, funcName string, argList []Expr) SSAValue {
2152 imported := pn.Imported()
2153 if imported == nil {
2154 return nil
2155 }
2156 if imported.Path() == "unsafe" && funcName == "Slice" {
2157 return fb.buildUnsafeSlice(argList)
2158 }
2159 obj := imported.Scope().Lookup(funcName)
2160 if obj == nil {
2161 return nil
2162 }
2163 fn, ok := obj.(*TCFunc)
2164 if !ok {
2165 return nil
2166 }
2167 impPkg := fb.ensureImportedSSAPackage(imported)
2168 ssaFn := impPkg.Func(funcName)
2169 if ssaFn == nil {
2170 ssaFn = &SSAFunction{
2171 name: funcName,
2172 object: fn,
2173 Signature: fn.Type().(*Signature),
2174 Pkg: impPkg,
2175 Prog: fb.fn.Prog,
2176 }
2177 impPkg.Members[funcName] = ssaFn
2178 }
2179 args := fb.buildArgs(argList)
2180 var retType Type
2181 if ssaFn.Signature != nil {
2182 if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() == 1 {
2183 retType = ssaFn.Signature.Results().At(0).Type()
2184 } else if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() > 1 {
2185 retType = ssaFn.Signature.Results()
2186 }
2187 }
2188 call := &SSACall{Call: SSACallCommon{Value: ssaFn, Args: args}}
2189 call.typ = retType
2190 call.name = fb.nextName()
2191 fb.emit(call)
2192 if retType == nil {
2193 return nil
2194 }
2195 return call
2196 }
2197
2198 func (fb *ssaFuncBuilder) buildUnsafeSlice(argList []Expr) SSAValue {
2199 if len(argList) < 2 {
2200 return nil
2201 }
2202 ptrVal := fb.buildExpr(argList[0])
2203 lenVal := fb.buildExpr(argList[1])
2204 if ptrVal == nil || lenVal == nil {
2205 return nil
2206 }
2207 var elemType Type
2208 if pt, ok := safeUnderlying(ptrVal.SSAType()).(*Pointer); ok {
2209 elemType = pt.Elem()
2210 }
2211 if elemType == nil {
2212 elemType = Typ[Uint8]
2213 }
2214 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal, Data: ptrVal}
2215 if b, ok := elemType.(*Basic); ok && b.kind == Uint8 {
2216 ms.typ = Typ[TCString]
2217 } else {
2218 ms.typ = NewSlice(elemType)
2219 }
2220 ms.name = fb.nextName()
2221 fb.emit(ms)
2222 return ms
2223 }
2224
2225 // Helpers.
2226
2227 func (fb *ssaFuncBuilder) lookupObject(name string) Object {
2228 for obj := range fb.vars {
2229 if obj.Name() == name {
2230 return obj
2231 }
2232 }
2233 if fb.parent != nil {
2234 for obj := range fb.parent.vars {
2235 if obj.Name() == name {
2236 return obj
2237 }
2238 }
2239 }
2240 if fb.fn.Pkg != nil {
2241 if _, obj := fb.fn.Pkg.Pkg.Scope().LookupParent(name); obj != nil {
2242 return obj
2243 }
2244 }
2245 return nil
2246 }
2247
2248 func (fb *ssaFuncBuilder) getOrCreateFreeVar(name string, typ Type) SSAValue {
2249 for _, fv := range fb.fn.FreeVars {
2250 if fv.name == name {
2251 return fv
2252 }
2253 }
2254 fv := &SSAFreeVar{
2255 name: name,
2256 typ: typ,
2257 parent: fb.fn,
2258 }
2259 fb.fn.FreeVars = append(fb.fn.FreeVars, fv)
2260 return fv
2261 }
2262
2263 func (fb *ssaFuncBuilder) lookupVar(name string) *TCVar {
2264 obj := fb.lookupObject(name)
2265 v, _ := obj.(*TCVar)
2266 return v
2267 }
2268
2269 func (fb *ssaFuncBuilder) resolveMethodCallWithRecv(sel *SelectorExpr, recv SSAValue) (*SSAFunction, SSAValue) {
2270 typ := recv.SSAType()
2271 isPtr := false
2272 if p, ok := safeUnderlying(typ).(*Pointer); ok {
2273 typ = p.Elem()
2274 isPtr = true
2275 }
2276 if _, ok := safeUnderlying(typ).(*TCInterface); ok {
2277 return nil, nil
2278 }
2279 named, ok := typ.(*Named)
2280 if !ok {
2281 return nil, nil
2282 }
2283 typeName := ""
2284 if named.Obj() != nil {
2285 typeName = named.Obj().Name()
2286 }
2287 if typeName == "" {
2288 return nil, nil
2289 }
2290 mangledName := typeName | "." | sel.Sel.Value
2291 fn, _ := fb.fn.Pkg.Members[mangledName].(*SSAFunction)
2292 if fn != nil {
2293 if fn.Signature != nil && fn.Signature.Recv() != nil {
2294 recvParam := fn.Signature.Recv()
2295 _, recvIsPtr := safeUnderlying(recvParam.Type()).(*Pointer)
2296 if recvIsPtr && !isPtr {
2297 if nameExpr, ok2 := sel.X.(*Name); ok2 {
2298 obj := fb.lookupObject(nameExpr.Value)
2299 if obj != nil {
2300 if alloc, ok3 := fb.vars[obj]; ok3 {
2301 recv = alloc
2302 }
2303 }
2304 }
2305 }
2306 }
2307 return fn, recv
2308 }
2309 st, ok2 := safeUnderlying(named).(*TCStruct)
2310 if !ok2 {
2311 return nil, nil
2312 }
2313 for i := 0; i < st.NumFields(); i++ {
2314 f := st.Field(i)
2315 if !f.Anonymous() {
2316 continue
2317 }
2318 embedType := f.Type()
2319 embedNamed, ok3 := embedType.(*Named)
2320 if !ok3 {
2321 if p, ok4 := embedType.(*Pointer); ok4 {
2322 embedNamed, ok3 = p.Elem().(*Named)
2323 }
2324 }
2325 if !ok3 || embedNamed.Obj() == nil {
2326 continue
2327 }
2328 embedName := embedNamed.Obj().Name()
2329 embedMangledName := embedName | "." | sel.Sel.Value
2330 embedFn, _ := fb.fn.Pkg.Members[embedMangledName].(*SSAFunction)
2331 if embedFn != nil {
2332 fieldAddr := &SSAFieldAddr{
2333 X: recv,
2334 Field: i,
2335 }
2336 fieldAddr.typ = NewPointer(embedType)
2337 fieldAddr.name = fb.nextName()
2338 fb.emit(fieldAddr)
2339 return embedFn, fieldAddr
2340 }
2341 embedSt, ok5 := safeUnderlying(embedNamed).(*TCStruct)
2342 if !ok5 {
2343 continue
2344 }
2345 for j := 0; j < embedSt.NumFields(); j++ {
2346 f2 := embedSt.Field(j)
2347 if !f2.Anonymous() {
2348 continue
2349 }
2350 embed2Type := f2.Type()
2351 embed2Named, ok6 := embed2Type.(*Named)
2352 if !ok6 {
2353 if p2, ok7 := embed2Type.(*Pointer); ok7 {
2354 embed2Named, ok6 = p2.Elem().(*Named)
2355 }
2356 }
2357 if !ok6 || embed2Named.Obj() == nil {
2358 continue
2359 }
2360 embed2Name := embed2Named.Obj().Name()
2361 embed2Mangled := embed2Name | "." | sel.Sel.Value
2362 embed2Fn, _ := fb.fn.Pkg.Members[embed2Mangled].(*SSAFunction)
2363 if embed2Fn == nil {
2364 continue
2365 }
2366 fieldAddr1 := &SSAFieldAddr{X: recv, Field: i}
2367 fieldAddr1.typ = NewPointer(embedType)
2368 fieldAddr1.name = fb.nextName()
2369 fb.emit(fieldAddr1)
2370 fieldAddr2 := &SSAFieldAddr{X: fieldAddr1, Field: j}
2371 fieldAddr2.typ = NewPointer(embed2Type)
2372 fieldAddr2.name = fb.nextName()
2373 fb.emit(fieldAddr2)
2374 return embed2Fn, fieldAddr2
2375 }
2376 }
2377 return nil, nil
2378 }
2379
2380 func (fb *ssaFuncBuilder) buildIfaceMethodCall(sel *SelectorExpr, recv SSAValue, argExprs []Expr) SSAValue {
2381 typ := recv.SSAType()
2382 if p, ok := safeUnderlying(typ).(*Pointer); ok {
2383 typ = p.Elem()
2384 }
2385 iface, ok := safeUnderlying(typ).(*TCInterface)
2386 if !ok {
2387 return nil
2388 }
2389 var methodSig *Signature
2390 for i := 0; i < iface.NumMethods(); i++ {
2391 if iface.Method(i).Name() == sel.Sel.Value {
2392 methodSig = iface.Method(i).Sig()
2393 break
2394 }
2395 }
2396 var retType Type
2397 if methodSig != nil && methodSig.Results() != nil {
2398 if methodSig.Results().Len() == 1 {
2399 retType = methodSig.Results().At(0).Type()
2400 } else if methodSig.Results().Len() > 1 {
2401 retType = methodSig.Results()
2402 }
2403 }
2404 args := fb.buildArgs(argExprs)
2405 inv := &SSAInvoke{
2406 X: recv,
2407 MethodName: sel.Sel.Value,
2408 IfaceType: iface,
2409 Args: args,
2410 }
2411 inv.typ = retType
2412 inv.name = fb.nextName()
2413 fb.emit(inv)
2414 if retType == nil {
2415 return nil
2416 }
2417 return inv
2418 }
2419
2420 func (fb *ssaFuncBuilder) resolveType(e Expr) Type {
2421 if fb.info != nil {
2422 if tv, ok := fb.info.Types[e]; ok && tv.Type != nil {
2423 return tv.Type
2424 }
2425 }
2426 return fb.resolveTypeAST(e)
2427 }
2428
2429 func (fb *ssaFuncBuilder) resolveTypeAST(e Expr) Type {
2430 if e == nil {
2431 return nil
2432 }
2433 switch e := e.(type) {
2434 case *Name:
2435 obj := fb.lookupObject(e.Value)
2436 if tn, ok := obj.(*TypeName); ok {
2437 return tn.Type()
2438 }
2439 case *Operation:
2440 if e.Y == nil && e.Op == Mul {
2441 base := fb.resolveTypeAST(e.X)
2442 if base != nil {
2443 return NewPointer(base)
2444 }
2445 }
2446 case *SliceType:
2447 elem := fb.resolveTypeAST(e.Elem)
2448 if elem != nil {
2449 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
2450 return Typ[TCString]
2451 }
2452 return NewSlice(elem)
2453 }
2454 case *ArrayType:
2455 elem := fb.resolveTypeAST(e.Elem)
2456 if elem != nil {
2457 n := int64(-1)
2458 if lit, ok := e.Len.(*BasicLit); ok {
2459 n = ssaParseInt64(lit.Value)
2460 }
2461 return NewArray(elem, n)
2462 }
2463 case *MapType:
2464 key := fb.resolveTypeAST(e.Key)
2465 val := fb.resolveTypeAST(e.Value)
2466 if key != nil && val != nil {
2467 return NewTCMap(key, val)
2468 }
2469 case *InterfaceType:
2470 return fb.resolveInterfaceTypeAST(e)
2471 case *ParenExpr:
2472 return fb.resolveTypeAST(e.X)
2473 }
2474 return nil
2475 }
2476
2477 func (fb *ssaFuncBuilder) resolveInterfaceTypeAST(e *InterfaceType) *TCInterface {
2478 var methods []*IfaceMethod
2479 for _, f := range e.MethodList {
2480 if f.Name == nil {
2481 continue
2482 }
2483 ft, ok := f.Type.(*FuncType)
2484 if !ok {
2485 continue
2486 }
2487 sig := fb.resolveFuncTypeAST(ft)
2488 if sig != nil {
2489 methods = append(methods, NewTCIfaceMethod(f.Name.Value, sig))
2490 }
2491 }
2492 iface := NewTCInterface(methods, nil)
2493 iface.Complete()
2494 return iface
2495 }
2496
2497 func (fb *ssaFuncBuilder) resolveFuncTypeAST(ft *FuncType) *Signature {
2498 if ft == nil {
2499 return nil
2500 }
2501 var params []*TCVar
2502 for _, p := range ft.ParamList {
2503 typ := fb.resolveTypeAST(p.Type)
2504 pname := ""
2505 if p.Name != nil {
2506 pname = p.Name.Value
2507 }
2508 params = append(params, NewTCVar(nil, pname, typ))
2509 }
2510 var results []*TCVar
2511 for _, r := range ft.ResultList {
2512 typ := fb.resolveTypeAST(r.Type)
2513 rname := ""
2514 if r.Name != nil {
2515 rname = r.Name.Value
2516 }
2517 results = append(results, NewTCVar(nil, rname, typ))
2518 }
2519 var pTuple, rTuple *Tuple
2520 if len(params) > 0 {
2521 pTuple = NewTuple(params...)
2522 }
2523 if len(results) > 0 {
2524 rTuple = NewTuple(results...)
2525 }
2526 return NewSignature(nil, pTuple, rTuple, false)
2527 }
2528
2529 func (fb *ssaFuncBuilder) fieldIndex(t Type, name string) int {
2530 if t == nil {
2531 return -1
2532 }
2533 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2534 t = pt.Elem()
2535 }
2536 if st, ok := safeUnderlying(t).(*TCStruct); ok {
2537 for i := 0; i < st.NumFields(); i++ {
2538 if st.Field(i).Name() == name {
2539 return i
2540 }
2541 }
2542 }
2543 return -1
2544 }
2545
2546 func (fb *ssaFuncBuilder) findEmbeddedField(t Type, name string) (embedIdx int, innerIdx int) {
2547 if t == nil {
2548 return -1, -1
2549 }
2550 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2551 t = pt.Elem()
2552 }
2553 st, ok := safeUnderlying(t).(*TCStruct)
2554 if !ok {
2555 return -1, -1
2556 }
2557 for i := 0; i < st.NumFields(); i++ {
2558 f := st.Field(i)
2559 if !f.Anonymous() {
2560 continue
2561 }
2562 embedType := f.Type()
2563 if pt, ok := safeUnderlying(embedType).(*Pointer); ok {
2564 embedType = pt.Elem()
2565 }
2566 inner := fb.fieldIndex(embedType, name)
2567 if inner >= 0 {
2568 return i, inner
2569 }
2570 }
2571 return -1, -1
2572 }
2573
2574 func (fb *ssaFuncBuilder) fieldType(t Type, idx int) Type {
2575 if t == nil {
2576 return nil
2577 }
2578 if pt, ok := safeUnderlying(t).(*Pointer); ok {
2579 t = pt.Elem()
2580 }
2581 if st, ok := safeUnderlying(t).(*TCStruct); ok {
2582 if idx >= 0 && idx < st.NumFields() {
2583 return st.Field(idx).Type()
2584 }
2585 }
2586 return nil
2587 }
2588
2589 func ssaExprNames(e Expr) []*Name {
2590 if e == nil {
2591 return nil
2592 }
2593 if n, ok := e.(*Name); ok {
2594 return []*Name{n}
2595 }
2596 if l, ok := e.(*ListExpr); ok {
2597 var names []*Name
2598 for _, el := range l.ElemList {
2599 if n, ok := el.(*Name); ok {
2600 names = append(names, n)
2601 }
2602 }
2603 return names
2604 }
2605 return nil
2606 }
2607