ssa_builder.mx raw
1 package main
2
3 func asType(t Type) Type { return t }
4
5 // CreatePackage builds the SSA Package from type-checked syntax files.
6 func (prog *SSAProgram) CreatePackage(pkg *TCPackage, files []*File, info *Info) *SSAPackage {
7 p := &SSAPackage{
8 Prog: prog,
9 Pkg: pkg,
10 Members: map[string]SSAMember{},
11 }
12 prog.packages[pkg] = p
13 prog.imported[pkg.Path()] = p
14
15 pb := &ssaPkgBuilder{pkg: p, info: info, prog: prog}
16
17 for _, f := range files {
18 pb.registerImportsAndTypes(f)
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) registerImportsAndTypes(f *File) {
37 for _, d := range f.DeclList {
38 switch d := d.(type) {
39 case *ImportDecl:
40 pb.registerImport(d)
41 case *TypeDecl:
42 pb.registerType(d)
43 }
44 }
45 }
46
47 func (pb *ssaPkgBuilder) registerFile(f *File) {
48 for _, d := range f.DeclList {
49 switch d := d.(type) {
50 case *FuncDecl:
51 pb.registerFunc(d)
52 case *VarDecl:
53 pb.registerVar(d)
54 case *ConstDecl:
55 pb.registerConst(d)
56 }
57 }
58 }
59
60 func (pb *ssaPkgBuilder) registerImport(d *ImportDecl) {
61 if d.Path == nil {
62 return
63 }
64 path := d.Path.Value
65 if len(path) >= 2 && path[0] == '"' {
66 path = path[1 : len(path)-1]
67 }
68 localName := ""
69 if d.LocalPkgName != nil {
70 localName = d.LocalPkgName.Value
71 }
72 if localName == "" {
73 for i := len(path) - 1; i >= 0; i-- {
74 if path[i] == '/' {
75 localName = path[i+1:]
76 break
77 }
78 }
79 if localName == "" {
80 localName = path
81 }
82 }
83 if localName == "." || localName == "_" {
84 return
85 }
86 existing := pb.pkg.Pkg.Scope().Lookup(localName)
87 if existing != nil {
88 return
89 }
90 impPkg := pb.prog.ImportedPackage(path)
91 if impPkg != nil && impPkg.Pkg != nil {
92 pn := NewPkgName(nil, localName, impPkg.Pkg)
93 pb.pkg.Pkg.Scope().Insert(pn)
94 } else {
95 ensureImportRegistry()
96 regPkg := importRegistry[path]
97 if regPkg != nil {
98 pn := NewPkgName(nil, localName, regPkg)
99 pb.pkg.Pkg.Scope().Insert(pn)
100 }
101 }
102 }
103
104 func pkgResolveTypeAST(pkg *SSAPackage, e Expr) Type {
105 if e == nil {
106 return nil
107 }
108 switch e := e.(type) {
109 case *Name:
110 if _, obj := Universe.LookupParent(e.Value); obj != nil {
111 if tn, ok := obj.(*TypeName); ok {
112 return tn.Type()
113 }
114 }
115 if pkg != nil {
116 obj := pkg.Pkg.Scope().Lookup(e.Value)
117 if tn, ok := obj.(*TypeName); ok {
118 return tn.Type()
119 }
120 }
121 case *Operation:
122 if e.Y == nil && e.Op == Mul {
123 base := pkgResolveTypeAST(pkg, e.X)
124 if base != nil {
125 return NewPointer(base)
126 }
127 }
128 case *SliceType:
129 elem := pkgResolveTypeAST(pkg, e.Elem)
130 if elem != nil {
131 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
132 return Typ[TCString]
133 }
134 return NewSlice(elem)
135 }
136 case *MapType:
137 key := pkgResolveTypeAST(pkg, e.Key)
138 val := pkgResolveTypeAST(pkg, e.Value)
139 if key != nil && val != nil {
140 return NewTCMap(key, val)
141 }
142 case *FuncType:
143 return pkgResolveSigAST(pkg, e)
144 case *SelectorExpr:
145 if x, ok := e.X.(*Name); ok {
146 var pn *PkgName
147 if okv, okok := pkg.Pkg.Scope().Lookup(x.Value).(*PkgName); okok {
148 pn = okv
149 }
150 if pn != nil && pn.Imported() != nil {
151 sel := pn.Imported().Scope().Lookup(e.Sel.Value)
152 if tn, ok2 := sel.(*TypeName); ok2 {
153 return tn.Type()
154 }
155 }
156 }
157 case *InterfaceType:
158 return NewTCInterface(nil, nil)
159 }
160 return nil
161 }
162
163 func pkgResolveSigAST(pkg *SSAPackage, ft *FuncType) *Signature {
164 if ft == nil {
165 return nil
166 }
167 var params []*TCVar
168 for _, p := range ft.ParamList {
169 typ := pkgResolveTypeAST(pkg, p.Type)
170 pname := ""
171 if p.Name != nil {
172 pname = p.Name.Value
173 }
174 params = append(params, NewTCVar(nil, pname, typ))
175 }
176 var results []*TCVar
177 for _, r := range ft.ResultList {
178 typ := pkgResolveTypeAST(pkg, r.Type)
179 rname := ""
180 if r.Name != nil {
181 rname = r.Name.Value
182 }
183 results = append(results, NewTCVar(nil, rname, typ))
184 }
185 var pTuple, rTuple *Tuple
186 if len(params) > 0 {
187 pTuple = NewTuple(params...)
188 }
189 if len(results) > 0 {
190 rTuple = NewTuple(results...)
191 }
192 return NewSignature(nil, pTuple, rTuple, false)
193 }
194
195 func (pb *ssaPkgBuilder) registerFunc(d *FuncDecl) {
196 if len(d.TParamList) > 0 {
197 return
198 }
199 if d.Recv != nil {
200 pb.registerMethod(d)
201 return
202 }
203 if d.Name.Value == "init" {
204 writeStr(2, "compile error: init() is not allowed; use main() for package initialization\n")
205 return
206 }
207 var obj *TCFunc
208 if o := pb.pkg.Pkg.Scope().Lookup(d.Name.Value); o != nil {
209 if okv, okok := o.(*TCFunc); okok {
210 obj = okv
211 }
212 }
213 var sig *Signature
214 if obj != nil {
215 if okv, okok := obj.Type().(*Signature); okok {
216 sig = okv
217 }
218 }
219 if sig == nil && d.Type != nil {
220 sig = pkgResolveSigAST(pb.pkg, d.Type)
221 }
222 fn := &SSAFunction{
223 name: d.Name.Value,
224 object: obj,
225 Signature: sig,
226 pos: 0,
227 Pkg: pb.pkg,
228 Prog: pb.prog,
229 }
230 if compileExportMap != nil {
231 if ename, ok := compileExportMap[d.Name.Value]; ok {
232 fn.externalSymbol = ename
233 fn.isExternC = true
234 }
235 }
236 if d.Body == nil && isNoContextExtern(pb.pkg.Pkg.Path(), d.Name.Value) {
237 fn.isExternC = true
238 }
239 pb.pkg.Members[fn.name] = fn
240 }
241
242 func checkInitBody(body *BlockStmt) string {
243 for _, s := range body.List {
244 if err := checkInitStmt(s); err != "" {
245 return err
246 }
247 }
248 return ""
249 }
250
251 func checkInitStmt(s Stmt) string {
252 switch s := s.(type) {
253 case *SelectStmt:
254 return "select{} not allowed in init()"
255 case *BlockStmt:
256 for _, sub := range s.List {
257 if err := checkInitStmt(sub); err != "" {
258 return err
259 }
260 }
261 case *IfStmt:
262 if s.Then != nil {
263 if err := checkInitStmt(s.Then); err != "" {
264 return err
265 }
266 }
267 if s.Else != nil {
268 if err := checkInitStmt(s.Else); err != "" {
269 return err
270 }
271 }
272 case *ForStmt:
273 if s.Body != nil {
274 if err := checkInitStmt(s.Body); err != "" {
275 return err
276 }
277 }
278 case *SwitchStmt:
279 for _, cc := range s.Body {
280 for _, sub := range cc.Body {
281 if err := checkInitStmt(sub); err != "" {
282 return err
283 }
284 }
285 }
286 case *ExprStmt:
287 if err := checkInitExpr(s.X); err != "" {
288 return err
289 }
290 }
291 return ""
292 }
293
294 func checkInitExpr(x Expr) string {
295 if x == nil {
296 return ""
297 }
298 if c, ok := x.(*CallExpr); ok {
299 if n, ok2 := c.Fun.(*Name); ok2 && n.Value == "spawn" {
300 return "spawn() not allowed in init()"
301 }
302 }
303 return ""
304 }
305
306 func isNoContextExtern(pkg, name string) bool {
307 if pkg == "internal/runtime/syscall" && name == "Syscall6" {
308 return true
309 }
310 if pkg == "syscall" {
311 switch name {
312 case "runtime_entersyscall", "runtime_exitsyscall",
313 "Exit", "Getpagesize", "gettimeofday",
314 "runtime_BeforeExec", "runtime_AfterExec",
315 "runtime_BeforeFork", "runtime_AfterFork", "runtime_AfterForkInChild":
316 return true
317 }
318 }
319 if pkg == "os" {
320 switch name {
321 case "putchar", "getchar", "buffered", "gosched", "runtime_args":
322 return true
323 }
324 }
325 return false
326 }
327
328 func (pb *ssaPkgBuilder) registerMethod(d *FuncDecl) {
329 recvTypeName := ssaRecvTypeName(d.Recv)
330 if recvTypeName == "" {
331 return
332 }
333 mangledName := recvTypeName | "." | d.Name.Value
334 var obj *TCFunc
335 obj = pb.findMethod(recvTypeName, d.Name.Value)
336 var sig *Signature
337 if obj != nil {
338 if okv, okok := obj.Type().(*Signature); okok {
339 sig = okv
340 }
341 }
342 if sig == nil && d.Type != nil {
343 sig = pkgResolveSigAST(pb.pkg, d.Type)
344 }
345 fn := &SSAFunction{
346 name: mangledName,
347 object: obj,
348 Signature: sig,
349 pos: 0,
350 Pkg: pb.pkg,
351 Prog: pb.prog,
352 }
353 pb.pkg.Members[mangledName] = fn
354 }
355
356 func ssaRecvTypeName(recv *Field) string {
357 if recv == nil {
358 return ""
359 }
360 switch t := recv.Type.(type) {
361 case *Name:
362 return t.Value
363 case *Operation:
364 if t.Y == nil && t.Op == Mul {
365 if n, ok := t.X.(*Name); ok {
366 return n.Value
367 }
368 }
369 }
370 return ""
371 }
372
373 func (pb *ssaPkgBuilder) findMethod(typeName string, methodName string) *TCFunc {
374 obj := pb.pkg.Pkg.Scope().Lookup(typeName)
375 if obj == nil {
376 return nil
377 }
378 tn, ok := obj.(*TypeName)
379 if !ok {
380 return nil
381 }
382 named, ok := tn.Type().(*Named)
383 if !ok {
384 return nil
385 }
386 for i := 0; i < named.NumMethods(); i++ {
387 m := named.Method(i)
388 if m.Name() == methodName {
389 return m
390 }
391 }
392 return nil
393 }
394
395 func (pb *ssaPkgBuilder) registerVar(d *VarDecl) {
396 for _, name := range d.NameList {
397 var obj *TCVar
398 if o := pb.pkg.Pkg.Scope().Lookup(name.Value); o != nil {
399 if okv, okok := o.(*TCVar); okok {
400 obj = okv
401 }
402 }
403 var typ Type
404 if obj != nil {
405 typ = obj.Type()
406 }
407 if typ == nil && d.Type != nil {
408 typ = pkgResolveTypeAST(pb.pkg, d.Type)
409 }
410 g := &SSAGlobal{
411 name: name.Value,
412 object: obj,
413 typ: NewPointer(typ),
414 pos: 0,
415 pkg: pb.pkg,
416 }
417 if obj != nil && obj.initVal != nil {
418 g.initConst = obj.initVal
419 g.initType = typ
420 }
421 pb.pkg.Members[name.Value] = g
422 }
423 }
424
425 func (pb *ssaPkgBuilder) registerType(d *TypeDecl) {
426 var obj *TypeName
427 if o := pb.pkg.Pkg.Scope().Lookup(d.Name.Value); o != nil {
428 if okv, okok := o.(*TypeName); okok {
429 obj = okv
430 }
431 }
432 if obj == nil {
433 underlying := pkgResolveTypeAST(pb.pkg, d.Type)
434 if underlying == nil {
435 underlying = &TCStruct{}
436 }
437 named := NewNamed(NewTypeName(pb.pkg.Pkg, d.Name.Value, nil), underlying)
438 named.obj.typ = named
439 pb.pkg.Pkg.Scope().Insert(named.obj)
440 obj = named.obj
441 }
442 t := &SSAType_{object: obj, pkg: pb.pkg}
443 pb.pkg.Members[d.Name.Value] = t
444 }
445
446 func (pb *ssaPkgBuilder) registerConst(d *ConstDecl) {
447 for _, name := range d.NameList {
448 var obj *TCConst
449 if o := pb.pkg.Pkg.Scope().Lookup(name.Value); o != nil {
450 if okv, okok := o.(*TCConst); okok {
451 obj = okv
452 }
453 }
454 if obj == nil {
455 continue
456 }
457 c := &SSANamedConst{
458 object: obj,
459 Value: &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())},
460 pkg: pb.pkg,
461 }
462 pb.pkg.Members[name.Value] = c
463 }
464 }
465
466 func (pb *ssaPkgBuilder) buildFile(f *File) {
467 for _, d := range f.DeclList {
468 if fd, ok := d.(*FuncDecl); ok {
469 pb.buildFunc(fd)
470 }
471 }
472 }
473
474 func (pb *ssaPkgBuilder) buildFunc(d *FuncDecl) {
475 if len(d.TParamList) > 0 {
476 return
477 }
478 if d.Body == nil {
479 return
480 }
481 name := d.Name.Value
482 if d.Recv != nil {
483 rtn := ssaRecvTypeName(d.Recv)
484 if rtn != "" {
485 name = rtn | "." | d.Name.Value
486 }
487 }
488 var fn *SSAFunction
489 if okv, okok := pb.pkg.Members[name].(*SSAFunction); okok {
490 fn = okv
491 }
492 if fn == nil {
493 return
494 }
495 fb := newSSAFuncBuilder(fn, pb.info)
496 fb.buildBody(d)
497 }
498
499 // ssaFuncBuilder builds one SSAFunction body.
500 type ssaFuncBuilder struct {
501 fn *SSAFunction
502 info *Info
503 parent *ssaFuncBuilder
504 currentBlock *SSABasicBlock
505 vars map[Object]*SSAAlloc
506 localTypes map[string]Type
507 localConsts map[string]*SSAConst
508 freeVarPtrs map[string]*SSAFreeVar
509 namedResults []*SSAAlloc
510 paramAllocas []*SSAAlloc
511 tailBlock *SSABasicBlock
512 counter int32
513
514 loops []ssaLoopState
515 pendingLabel string
516 labels map[string]*SSABasicBlock
517 deferred int32
518 typeSubst map[string]Type
519 srcScope *Scope
520 }
521
522 type ssaLoopState struct {
523 label string
524 body *SSABasicBlock
525 post *SSABasicBlock
526 done *SSABasicBlock
527 }
528
529 func newSSAFuncBuilder(fn *SSAFunction, info *Info) *ssaFuncBuilder {
530 return &ssaFuncBuilder{
531 fn: fn,
532 info: info,
533 vars: map[Object]*SSAAlloc{},
534 localTypes: map[string]Type{},
535 }
536 }
537
538 func (fb *ssaFuncBuilder) newBlock(comment string) *SSABasicBlock {
539 return NewSSABasicBlock(fb.fn, comment)
540 }
541
542 func (fb *ssaFuncBuilder) labelBlock(name string) *SSABasicBlock {
543 if fb.labels == nil {
544 fb.labels = map[string]*SSABasicBlock{}
545 }
546 if b := fb.labels[name]; b != nil {
547 return b
548 }
549 b := fb.newBlock("label." + name)
550 fb.labels[name] = b
551 return b
552 }
553
554 func (fb *ssaFuncBuilder) emit(instr SSAInstruction) {
555 if fb.currentBlock == nil {
556 return
557 }
558 instr.setBlock(fb.currentBlock)
559 fb.currentBlock.Instrs = append(fb.currentBlock.Instrs, instr)
560 }
561
562 func (fb *ssaFuncBuilder) nextName() string {
563 fb.counter++
564 return "t" | ssaItoa(fb.counter)
565 }
566
567 func (fb *ssaFuncBuilder) buildBody(d *FuncDecl) {
568 entry := fb.newBlock("entry")
569 fb.currentBlock = entry
570
571 sig := fb.fn.Signature
572 if sig == nil {
573 return
574 }
575 params := sig.Params()
576 if d.Recv != nil {
577 recv := sig.Recv()
578 if recv != nil {
579 recvName := recv.Name()
580 if recvName == "" && d.Recv.Name != nil {
581 recvName = d.Recv.Name.Value
582 }
583 p := &SSAParameter{
584 name: recvName,
585 typ: recv.Type(),
586 pos: 0,
587 parent: fb.fn,
588 }
589 fb.fn.Params = append(fb.fn.Params, p)
590 if recvName != "" && recvName != "_" {
591 recvObj := NewTCVar(fb.fn.Pkg.Pkg, recvName, recv.Type())
592 p.object = recvObj
593 alloc := fb.emitAlloc(recv.Type(), 0)
594 fb.vars[recvObj] = alloc
595 fb.paramAllocas = append(fb.paramAllocas, alloc)
596 fb.emitStore(alloc, p)
597 }
598 }
599 }
600 if params != nil {
601 for i := 0; i < params.Len(); i++ {
602 pvar := params.At(i)
603 p := &SSAParameter{
604 name: pvar.Name(),
605 typ: pvar.Type(),
606 pos: fb.fn.pos,
607 parent: fb.fn,
608 }
609 fb.fn.Params = append(fb.fn.Params, p)
610 if pvar.Name() != "" && pvar.Name() != "_" {
611 obj := NewTCVar(fb.fn.Pkg.Pkg, pvar.Name(), pvar.Type())
612 alloc := fb.emitAlloc(pvar.Type(), p.pos)
613 fb.vars[obj] = alloc
614 fb.paramAllocas = append(fb.paramAllocas, alloc)
615 fb.emitStore(alloc, p)
616 }
617 }
618 }
619
620 if sig.Results() != nil {
621 for i := 0; i < sig.Results().Len(); i++ {
622 r := sig.Results().At(i)
623 if r.Name() != "" && r.Name() != "_" {
624 alloc := fb.emitAlloc(r.Type(), fb.fn.pos)
625 fb.namedResults = append(fb.namedResults, alloc)
626 fb.fn.Locals = append(fb.fn.Locals, alloc)
627 fb.vars[r] = alloc
628 }
629 }
630 }
631
632 if len(fb.paramAllocas) > 0 {
633 fb.tailBlock = fb.newBlock("tailcall")
634 fb.emit(&SSAJump{Comment: "enter.body"})
635 fb.currentBlock.Succs = append(fb.currentBlock.Succs, fb.tailBlock)
636 fb.tailBlock.Preds = append(fb.tailBlock.Preds, fb.currentBlock)
637 fb.currentBlock = fb.tailBlock
638 }
639
640 if d.Body != nil {
641 fb.buildBlock(d.Body)
642 }
643
644 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
645 if len(fb.namedResults) > 0 {
646 var vals []SSAValue
647 for _, nr := range fb.namedResults {
648 elemType := nr.SSAType()
649 if p, ok := elemType.(*Pointer); ok {
650 elemType = p.Elem()
651 }
652 vals = append(vals, fb.emitLoad(nr, elemType))
653 }
654 fb.emitReturn(vals, 0)
655 } else {
656 fb.emitReturn(nil, 0)
657 }
658 }
659 fb.fn.NamedResults = fb.namedResults
660 }
661
662 func (fb *ssaFuncBuilder) emitAlloc(typ Type, pos int32) *SSAAlloc {
663 a := &SSAAlloc{Heap: false}
664 a.typ = NewPointer(typ)
665 a.pos = pos
666 a.name = fb.nextName()
667 fb.emit(a)
668 fb.fn.Locals = append(fb.fn.Locals, a)
669 return a
670 }
671
672 func (fb *ssaFuncBuilder) emitStore(addr SSAValue, val SSAValue) {
673 fb.emit(&SSAStore{Addr: addr, Val: val})
674 }
675
676 func (fb *ssaFuncBuilder) emitLoad(addr SSAValue, typ Type) SSAValue {
677 u := &SSAUnOp{Op: OpMul, X: addr}
678 u.typ = typ
679 u.name = fb.nextName()
680 fb.emit(u)
681 return u
682 }
683
684 func (fb *ssaFuncBuilder) emitReturn(vals []SSAValue, pos int32) {
685 fb.emit(&SSAReturn{Results: vals, pos: pos})
686 fb.currentBlock = nil
687 }
688
689 func (fb *ssaFuncBuilder) blockTerminated(b *SSABasicBlock) bool {
690 if len(b.Instrs) == 0 {
691 return false
692 }
693 switch b.Instrs[len(b.Instrs)-1].(type) {
694 case *SSAReturn, *SSAJump, *SSAIf, *SSAPanic:
695 return true
696 }
697 return false
698 }
699
700 // Statement builders.
701
702 func (fb *ssaFuncBuilder) buildBlock(b *BlockStmt) {
703 if b == nil {
704 return
705 }
706 for _, s := range b.List {
707 fb.buildStmt(s)
708 }
709 }
710
711 func (fb *ssaFuncBuilder) buildStmt(s Stmt) {
712 if s == nil {
713 return
714 }
715 if ls, ok := s.(*LabeledStmt); ok {
716 if ls.Label != nil {
717 fb.pendingLabel = ls.Label.Value
718 lblBlock := fb.labelBlock(ls.Label.Value)
719 if fb.currentBlock != nil {
720 fb.emit(&SSAJump{Comment: "goto.label." + ls.Label.Value})
721 fb.currentBlock.Succs = append(fb.currentBlock.Succs, lblBlock)
722 lblBlock.Preds = append(lblBlock.Preds, fb.currentBlock)
723 }
724 fb.currentBlock = lblBlock
725 }
726 fb.buildStmt(ls.Stmt)
727 fb.pendingLabel = ""
728 return
729 }
730 if fb.currentBlock == nil {
731 return
732 }
733 switch s := s.(type) {
734 case *EmptyStmt:
735 // nothing
736 case *ExprStmt:
737 fb.buildExpr(s.X)
738 case *AssignStmt:
739 fb.buildAssign(s)
740 case *BlockStmt:
741 fb.buildBlock(s)
742 case *DeclStmt:
743 for _, d := range s.DeclList {
744 fb.buildLocalDecl(d)
745 }
746 case *IfStmt:
747 fb.buildIf(s)
748 case *ForStmt:
749 fb.buildFor(s)
750 case *SwitchStmt:
751 fb.buildSwitch(s)
752 case *SelectStmt:
753 fb.buildSelect(s)
754 case *ReturnStmt:
755 fb.buildReturn(s)
756 case *BranchStmt:
757 fb.buildBranch(s)
758 case *SendStmt:
759 ch := fb.buildExpr(s.Chan)
760 val := fb.buildExpr(s.Value)
761 if ch != nil && val != nil {
762 fb.emit(&SSASend{Chan: ch, X: val})
763 }
764 case *CallStmt:
765 var call *CallExpr
766 if okv, okok := s.Call.(*CallExpr); okok {
767 call = okv
768 }
769 switch s.Tok {
770 case Go:
771 if call != nil {
772 fb.buildGoStmt(call)
773 }
774 case Defer:
775 if call != nil {
776 fb.buildDeferStmt(call)
777 }
778 default:
779 fb.buildExpr(s.Call)
780 }
781 }
782 }
783
784 func (fb *ssaFuncBuilder) buildAssign(s *AssignStmt) {
785 if s.Rhs == nil {
786 lv := fb.buildExpr(s.Lhs)
787 if lv == nil {
788 return
789 }
790 one := &SSAConst{typ: lv.SSAType(), val: constInt{1}}
791 op := OpAdd
792 if s.Op == Sub {
793 op = OpSub
794 }
795 bin := &SSABinOp{Op: op, X: lv, Y: one}
796 bin.typ = lv.SSAType()
797 bin.name = fb.nextName()
798 fb.emit(bin)
799 fb.buildStore(s.Lhs, bin)
800 return
801 }
802 if s.Op == Def {
803 fb.buildShortVarDecl(s)
804 return
805 }
806 if s.Op != 0 {
807 lv := fb.buildExpr(s.Lhs)
808 rv := fb.buildExpr(s.Rhs)
809 if lv == nil || rv == nil {
810 return
811 }
812 op := compoundOp(s.Op)
813 bin := &SSABinOp{Op: op, X: lv, Y: rv}
814 bin.typ = lv.SSAType()
815 bin.name = fb.nextName()
816 fb.emit(bin)
817 fb.buildStore(s.Lhs, bin)
818 return
819 }
820 lhsList, lhsIsList := s.Lhs.(*ListExpr)
821 rhsList, rhsIsList := s.Rhs.(*ListExpr)
822 if lhsIsList && rhsIsList && len(lhsList.ElemList) == len(rhsList.ElemList) {
823 vals := []SSAValue{:len(rhsList.ElemList)}
824 for i, re := range rhsList.ElemList {
825 vals[i] = fb.buildExpr(re)
826 }
827 for i, le := range lhsList.ElemList {
828 if vals[i] != nil {
829 fb.buildStore(le, vals[i])
830 }
831 }
832 return
833 }
834 if lhsIsList && len(lhsList.ElemList) == 2 {
835 if ae, ok := s.Rhs.(*AssertExpr); ok {
836 x := fb.buildExpr(ae.X)
837 assertedType := fb.resolveType(ae.Type)
838 if x != nil && assertedType != nil {
839 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: true}
840 ta.typ = NewTuple(
841 NewTCVar(nil, "val", assertedType),
842 NewTCVar(nil, "ok", Typ[Bool]),
843 )
844 ta.name = fb.nextName()
845 fb.emit(ta)
846 for i, le := range lhsList.ElemList {
847 if n, ok := le.(*Name); ok && n.Value == "_" {
848 continue
849 }
850 ext := &SSAExtract{Tuple: ta, Index: i}
851 ext.typ = ssaTupleElemType(ta.typ, i)
852 ext.name = fb.nextName()
853 fb.emit(ext)
854 fb.buildStore(le, ext)
855 }
856 return
857 }
858 }
859 if ie, ok := s.Rhs.(*IndexExpr); ok {
860 x := fb.buildExpr(ie.X)
861 idx := fb.buildExpr(ie.Index)
862 if x != nil && idx != nil {
863 if mt, ok2 := safeUnderlying(x.SSAType()).(*TCMap); ok2 {
864 idx = fb.coerceToInterface(idx, mt.Key())
865 l := &SSALookup{X: x, Index: idx, CommaOk: true}
866 l.typ = NewTuple(
867 NewTCVar(nil, "v", mt.Elem()),
868 NewTCVar(nil, "ok", Typ[Bool]),
869 )
870 l.name = fb.nextName()
871 fb.emit(l)
872 for i, le := range lhsList.ElemList {
873 if n, ok := le.(*Name); ok && n.Value == "_" {
874 continue
875 }
876 ext := &SSAExtract{Tuple: l, Index: i}
877 ext.typ = ssaTupleElemType(l.typ, i)
878 ext.name = fb.nextName()
879 fb.emit(ext)
880 fb.buildStore(le, ext)
881 }
882 return
883 }
884 }
885 }
886 }
887 rhs := fb.buildExpr(s.Rhs)
888 if rhs == nil {
889 return
890 }
891 fb.buildStore(s.Lhs, rhs)
892 }
893
894 func (fb *ssaFuncBuilder) coerceToInterface(val SSAValue, targetType Type) SSAValue {
895 if targetType == nil || val == nil || val.SSAType() == nil {
896 return val
897 }
898 if _, isIface := safeUnderlying(targetType).(*TCInterface); isIface {
899 if _, alreadyIface := safeUnderlying(val.SSAType()).(*TCInterface); !alreadyIface {
900 mi := &SSAMakeInterface{X: val}
901 mi.typ = targetType
902 mi.name = fb.nextName()
903 fb.emit(mi)
904 return mi
905 }
906 }
907 return val
908 }
909
910 func (fb *ssaFuncBuilder) buildStore(lhs Expr, val SSAValue) {
911 if lhs == nil {
912 panic("buildStore: nil lhs")
913 }
914 switch lhs := lhs.(type) {
915 case *Name:
916 if lhs == nil {
917 panic("buildStore: nil *Name after type switch")
918 }
919 if lhs.Value == "_" {
920 return
921 }
922 obj := fb.lookupObject(lhs.Value)
923 if obj == nil {
924 return
925 }
926 if alloc, ok := fb.vars[obj]; ok {
927 val = fb.coerceToInterface(val, obj.Type())
928 fb.emitStore(alloc, val)
929 } else if fv, ok := fb.freeVarPtrs[lhs.Value]; ok {
930 val = fb.coerceToInterface(val, obj.Type())
931 fb.emitStore(fv, val)
932 } else if g, ok := fb.fn.Pkg.Members[lhs.Value].(*SSAGlobal); ok {
933 if p, ok2 := g.SSAType().(*Pointer); ok2 && p.Elem() != nil {
934 val = fb.coerceToInterface(val, p.Elem())
935 }
936 fb.emitStore(g, val)
937 }
938 case *Operation:
939 if lhs.Y == nil && lhs.Op == Mul {
940 ptr := fb.buildExpr(lhs.X)
941 if ptr != nil {
942 if p, ok2 := ptr.SSAType().(*Pointer); ok2 && p.Elem() != nil {
943 val = fb.coerceToInterface(val, p.Elem())
944 }
945 fb.emitStore(ptr, val)
946 }
947 }
948 case *SelectorExpr:
949 addr := fb.buildSelectorAddr(lhs)
950 if addr == nil {
951 return
952 }
953 if p, ok2 := addr.SSAType().(*Pointer); ok2 && p.Elem() != nil {
954 val = fb.coerceToInterface(val, p.Elem())
955 }
956 fb.emitStore(addr, val)
957 case *IndexExpr:
958 base := fb.buildExpr(lhs.X)
959 idx := fb.buildExpr(lhs.Index)
960 if base == nil || idx == nil {
961 return
962 }
963 if m, isMap := safeUnderlying(base.SSAType()).(*TCMap); isMap {
964 idx = fb.coerceToInterface(idx, m.Key())
965 val = fb.coerceToInterface(val, m.Elem())
966 fb.emit(&SSAMapUpdate{Map: base, Key: idx, Value: val})
967 return
968 }
969 // For array LHS assignment, resolve the address of the base directly
970 // so SSAIndexAddr GEPs into the original, not a stack copy.
971 var baseAddr SSAValue
972 if n, ok := lhs.X.(*Name); ok {
973 obj := fb.lookupObject(n.Value)
974 if obj != nil {
975 if alloc, ok2 := fb.vars[obj]; ok2 {
976 baseAddr = alloc
977 } else if g, ok2 := fb.fn.Pkg.Members[n.Value].(*SSAGlobal); ok2 {
978 baseAddr = g
979 }
980 }
981 } else if sel, ok := lhs.X.(*SelectorExpr); ok {
982 baseAddr = fb.buildSelectorAddr(sel)
983 }
984 if baseAddr != nil {
985 if _, isArr := safeUnderlying(base.SSAType()).(*Array); isArr {
986 ia := &SSAIndexAddr{X: baseAddr, Index: idx}
987 ia.typ = NewPointer(ssaElemType(base.SSAType()))
988 ia.name = fb.nextName()
989 fb.emit(ia)
990 if p, ok2 := ia.SSAType().(*Pointer); ok2 && p.Elem() != nil {
991 val = fb.coerceToInterface(val, p.Elem())
992 }
993 fb.emitStore(ia, val)
994 return
995 }
996 }
997 ia := &SSAIndexAddr{X: base, Index: idx}
998 ia.typ = NewPointer(ssaElemType(base.SSAType()))
999 ia.name = fb.nextName()
1000 fb.emit(ia)
1001 if p, ok2 := ia.SSAType().(*Pointer); ok2 && p.Elem() != nil {
1002 val = fb.coerceToInterface(val, p.Elem())
1003 }
1004 fb.emitStore(ia, val)
1005 case *ListExpr:
1006 for i, e := range lhs.ElemList {
1007 ext := &SSAExtract{Tuple: val, Index: i}
1008 ext.typ = ssaTupleElemType(val.SSAType(), i)
1009 ext.name = fb.nextName()
1010 fb.emit(ext)
1011 fb.buildStore(e, ext)
1012 }
1013 }
1014 }
1015
1016 func (fb *ssaFuncBuilder) buildShortVarDecl(s *AssignStmt) {
1017 names := ssaExprNames(s.Lhs)
1018 if len(names) == 2 {
1019 if ae, ok := s.Rhs.(*AssertExpr); ok {
1020 x := fb.buildExpr(ae.X)
1021 assertedType := fb.resolveType(ae.Type)
1022 if x != nil && assertedType != nil {
1023 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: true}
1024 ta.typ = NewTuple(
1025 NewTCVar(nil, "val", assertedType),
1026 NewTCVar(nil, "ok", Typ[Bool]),
1027 )
1028 ta.name = fb.nextName()
1029 fb.emit(ta)
1030 for i, name := range names {
1031 if name.Value == "_" {
1032 continue
1033 }
1034 ext := &SSAExtract{Tuple: ta, Index: i}
1035 ext.typ = ssaTupleElemType(ta.typ, i)
1036 ext.name = fb.nextName()
1037 fb.emit(ext)
1038 fb.removeVar(name.Value)
1039 obj := NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
1040 alloc := fb.emitAlloc(ext.typ, 0)
1041 fb.vars[obj] = alloc
1042 fb.emitStore(alloc, ext)
1043 }
1044 return
1045 }
1046 }
1047 if ie, ok := s.Rhs.(*IndexExpr); ok {
1048 x := fb.buildExpr(ie.X)
1049 idx := fb.buildExpr(ie.Index)
1050 if x != nil && idx != nil {
1051 if mt, ok2 := safeUnderlying(x.SSAType()).(*TCMap); ok2 {
1052 idx = fb.coerceToInterface(idx, mt.Key())
1053 l := &SSALookup{X: x, Index: idx, CommaOk: true}
1054 l.typ = NewTuple(
1055 NewTCVar(nil, "v", mt.Elem()),
1056 NewTCVar(nil, "ok", Typ[Bool]),
1057 )
1058 l.name = fb.nextName()
1059 fb.emit(l)
1060 for i, name := range names {
1061 if name.Value == "_" {
1062 continue
1063 }
1064 ext := &SSAExtract{Tuple: l, Index: i}
1065 ext.typ = ssaTupleElemType(l.typ, i)
1066 ext.name = fb.nextName()
1067 fb.emit(ext)
1068 fb.removeVar(name.Value)
1069 var obj Object
1070 if fb.info != nil {
1071 obj = fb.info.Defs[name]
1072 }
1073 if obj == nil {
1074 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
1075 }
1076 alloc := fb.emitAlloc(ext.typ, 0)
1077 fb.vars[obj] = alloc
1078 fb.emitStore(alloc, ext)
1079 }
1080 return
1081 }
1082 }
1083 }
1084 }
1085 if rhsList, ok := s.Rhs.(*ListExpr); ok && len(rhsList.ElemList) == len(names) {
1086 vals := []SSAValue{:len(rhsList.ElemList)}
1087 for i, re := range rhsList.ElemList {
1088 vals[i] = fb.buildExpr(re)
1089 }
1090 for i, name := range names {
1091 if name.Value == "_" {
1092 continue
1093 }
1094 var typ Type
1095 if vals[i] != nil {
1096 typ = vals[i].SSAType()
1097 }
1098 fb.removeVar(name.Value)
1099 var obj Object
1100 if fb.info != nil {
1101 obj = fb.info.Defs[name]
1102 }
1103 if obj == nil {
1104 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
1105 }
1106 alloc := fb.emitAlloc(typ, 0)
1107 fb.vars[obj] = alloc
1108 if vals[i] != nil {
1109 fb.emitStore(alloc, vals[i])
1110 }
1111 }
1112 return
1113 }
1114
1115 rhs := fb.buildExpr(s.Rhs)
1116
1117 isTuple := false
1118 var tup *Tuple
1119 if rhs != nil {
1120 tup, isTuple = rhs.SSAType().(*Tuple)
1121 }
1122 for i, name := range names {
1123 if name.Value == "_" {
1124 continue
1125 }
1126 var typ Type
1127 if rhs != nil {
1128 if isTuple && i < tup.Len() {
1129 typ = tup.At(i).Type()
1130 } else if i == 0 {
1131 typ = rhs.SSAType()
1132 }
1133 }
1134 if typ == nil {
1135 typ = Typ[Int32]
1136 }
1137 fb.removeVar(name.Value)
1138 var obj Object
1139 if fb.info != nil {
1140 obj = fb.info.Defs[name]
1141 }
1142 if obj == nil {
1143 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
1144 }
1145 alloc := fb.emitAlloc(typ, 0)
1146 fb.vars[obj] = alloc
1147 var initVal SSAValue
1148 if rhs != nil {
1149 if isTuple {
1150 ext := &SSAExtract{Tuple: rhs, Index: i}
1151 ext.typ = typ
1152 ext.name = fb.nextName()
1153 fb.emit(ext)
1154 initVal = ext
1155 } else if i == 0 {
1156 initVal = rhs
1157 }
1158 }
1159 if initVal != nil {
1160 fb.emitStore(alloc, initVal)
1161 }
1162 }
1163 }
1164
1165 func (fb *ssaFuncBuilder) buildLocalDecl(d Decl) {
1166 switch d := d.(type) {
1167 case *VarDecl:
1168 var typ Type
1169 if fb.info != nil && len(d.NameList) > 0 {
1170 if obj := fb.info.Defs[d.NameList[0]]; obj != nil {
1171 typ = obj.Type()
1172 }
1173 }
1174 if typ == nil && d.Type != nil {
1175 typ = fb.resolveType(d.Type)
1176 }
1177 initVal := fb.buildExpr(d.Values)
1178 for _, name := range d.NameList {
1179 if name.Value == "_" {
1180 continue
1181 }
1182 fb.removeVar(name.Value)
1183 var obj Object
1184 if fb.info != nil {
1185 obj = fb.info.Defs[name]
1186 }
1187 if obj == nil {
1188 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, typ)
1189 }
1190 alloc := fb.emitAlloc(obj.Type(), 0)
1191 fb.vars[obj] = alloc
1192 fb.fn.Locals = append(fb.fn.Locals, alloc)
1193 if initVal != nil {
1194 initVal = fb.coerceToInterface(initVal, obj.Type())
1195 fb.emitStore(alloc, initVal)
1196 } else {
1197 fb.emitStore(alloc, &SSAConst{typ: obj.Type(), val: nil})
1198 }
1199 }
1200 case *ConstDecl:
1201 if d.Values != nil && len(d.NameList) > 0 {
1202 if fb.localConsts == nil {
1203 fb.localConsts = map[string]*SSAConst{}
1204 }
1205 if list, ok := d.Values.(*ListExpr); ok {
1206 for i, name := range d.NameList {
1207 if i < len(list.ElemList) {
1208 if v := fb.buildExpr(list.ElemList[i]); v != nil {
1209 if c, ok2 := v.(*SSAConst); ok2 {
1210 fb.localConsts[name.Value] = c
1211 }
1212 }
1213 }
1214 }
1215 } else if len(d.NameList) == 1 {
1216 if v := fb.buildExpr(d.Values); v != nil {
1217 if c, ok2 := v.(*SSAConst); ok2 {
1218 fb.localConsts[d.NameList[0].Value] = c
1219 }
1220 }
1221 }
1222 }
1223 case *TypeDecl:
1224 if d.Name != nil {
1225 resolved := fb.resolveTypeAST(d.Type)
1226 if resolved != nil {
1227 fb.localTypes[d.Name.Value] = resolved
1228 }
1229 }
1230 }
1231 }
1232
1233 func (fb *ssaFuncBuilder) buildIf(s *IfStmt) {
1234 var savedVars map[Object]*SSAAlloc
1235 if s.Init != nil {
1236 savedVars = fb.saveVars()
1237 fb.buildStmt(s.Init)
1238 }
1239 if fb.currentBlock == nil {
1240 if savedVars != nil {
1241 fb.vars = savedVars
1242 }
1243 return
1244 }
1245 cond := fb.buildExpr(s.Cond)
1246 if cond == nil {
1247 if savedVars != nil {
1248 fb.vars = savedVars
1249 }
1250 return
1251 }
1252
1253 thenBlock := fb.newBlock("if.then")
1254 var elseBlock *SSABasicBlock
1255 doneBlock := fb.newBlock("if.done")
1256
1257 if s.Else != nil {
1258 elseBlock = fb.newBlock("if.else")
1259 } else {
1260 elseBlock = doneBlock
1261 }
1262
1263 fb.emit(&SSAIf{Cond: cond})
1264 fb.currentBlock.Succs = append(fb.currentBlock.Succs, thenBlock, elseBlock)
1265 thenBlock.Preds = append(thenBlock.Preds, fb.currentBlock)
1266 elseBlock.Preds = append(elseBlock.Preds, fb.currentBlock)
1267
1268 fb.currentBlock = thenBlock
1269 fb.buildBlock(s.Then)
1270 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1271 fb.emit(&SSAJump{Comment: "if.done"})
1272 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1273 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1274 }
1275
1276 if s.Else != nil {
1277 fb.currentBlock = elseBlock
1278 fb.buildStmt(s.Else)
1279 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1280 fb.emit(&SSAJump{Comment: "if.done"})
1281 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1282 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1283 }
1284 }
1285
1286 fb.currentBlock = doneBlock
1287 if savedVars != nil {
1288 fb.vars = savedVars
1289 }
1290 }
1291
1292 func (fb *ssaFuncBuilder) buildFor(s *ForStmt) {
1293 var savedVars map[Object]*SSAAlloc
1294 if s.Init != nil {
1295 if rc, ok := s.Init.(*RangeClause); ok {
1296 fb.buildRangeLoop(s, rc)
1297 return
1298 }
1299 savedVars = fb.saveVars()
1300 fb.buildStmt(s.Init)
1301 }
1302
1303 condBlock := fb.newBlock("for.cond")
1304 bodyBlock := fb.newBlock("for.body")
1305 postBlock := fb.newBlock("for.post")
1306 doneBlock := fb.newBlock("for.done")
1307
1308 fb.emit(&SSAJump{Comment: "for.cond"})
1309 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
1310 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
1311
1312 fb.loops = append(fb.loops, ssaLoopState{label: fb.pendingLabel, body: bodyBlock, post: postBlock, done: doneBlock})
1313 fb.pendingLabel = ""
1314
1315 fb.currentBlock = condBlock
1316 if s.Cond != nil {
1317 cond := fb.buildExpr(s.Cond)
1318 if cond != nil {
1319 fb.emit(&SSAIf{Cond: cond})
1320 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock, doneBlock)
1321 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
1322 doneBlock.Preds = append(doneBlock.Preds, condBlock)
1323 }
1324 } else {
1325 fb.emit(&SSAJump{Comment: "for.body"})
1326 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock)
1327 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
1328 }
1329
1330 fb.currentBlock = bodyBlock
1331 fb.buildBlock(s.Body)
1332 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1333 fb.emit(&SSAJump{Comment: "for.post"})
1334 fb.currentBlock.Succs = append(fb.currentBlock.Succs, postBlock)
1335 postBlock.Preds = append(postBlock.Preds, fb.currentBlock)
1336 }
1337
1338 fb.currentBlock = postBlock
1339 if s.Post != nil {
1340 fb.buildStmt(s.Post)
1341 }
1342 if fb.currentBlock != nil {
1343 fb.emit(&SSAJump{Comment: "for.cond"})
1344 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
1345 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
1346 }
1347
1348 fb.loops = fb.loops[:len(fb.loops)-1]
1349 fb.currentBlock = doneBlock
1350 if savedVars != nil {
1351 fb.vars = savedVars
1352 }
1353 }
1354
1355 func (fb *ssaFuncBuilder) buildRangeLoop(s *ForStmt, rc *RangeClause) {
1356 iterExpr := fb.buildExpr(rc.X)
1357 if iterExpr == nil {
1358 return
1359 }
1360
1361 r := &SSARange{X: iterExpr}
1362 r.typ = Typ[Invalid]
1363 r.name = fb.nextName()
1364 fb.emit(r)
1365
1366 bodyBlock := fb.newBlock("range.body")
1367 doneBlock := fb.newBlock("range.done")
1368
1369 condBlock := fb.newBlock("range.cond")
1370
1371 fb.loops = append(fb.loops, ssaLoopState{label: fb.pendingLabel, body: bodyBlock, post: condBlock, done: doneBlock})
1372 fb.pendingLabel = ""
1373 fb.emit(&SSAJump{Comment: "range.cond"})
1374 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
1375 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
1376
1377 fb.currentBlock = condBlock
1378 iterSSAType := iterExpr.SSAType()
1379 nxt := &SSANext{Iter: r, IsString: ssaIsStringType(iterSSAType)}
1380 keyTyp := asType(Typ[Int32])
1381 valTyp := asType(Typ[Invalid])
1382 iterT := iterExpr.SSAType()
1383 iterU := safeUnderlying(iterT)
1384 if sl, ok := iterU.(*Slice); ok {
1385 valTyp = sl.Elem()
1386 } else if sl, ok := iterT.(*Slice); ok {
1387 valTyp = sl.Elem()
1388 } else if mt, ok := iterU.(*TCMap); ok {
1389 keyTyp = mt.Key()
1390 valTyp = mt.Elem()
1391 } else if mt, ok := iterT.(*TCMap); ok {
1392 keyTyp = mt.Key()
1393 valTyp = mt.Elem()
1394 } else if ar, ok := iterU.(*Array); ok {
1395 valTyp = ar.Elem()
1396 } else if ar, ok := iterT.(*Array); ok {
1397 valTyp = ar.Elem()
1398 }
1399 nxt.typ = NewTuple(
1400 NewTCVar(nil, "ok", Typ[Bool]),
1401 NewTCVar(nil, "k", keyTyp),
1402 NewTCVar(nil, "v", valTyp),
1403 )
1404 nxt.name = fb.nextName()
1405 fb.emit(nxt)
1406
1407 okExt := &SSAExtract{Tuple: nxt, Index: 0}
1408 okExt.typ = Typ[Bool]
1409 okExt.name = fb.nextName()
1410 fb.emit(okExt)
1411
1412 fb.emit(&SSAIf{Cond: okExt})
1413 fb.currentBlock.Succs = append(fb.currentBlock.Succs, bodyBlock, doneBlock)
1414 bodyBlock.Preds = append(bodyBlock.Preds, condBlock)
1415 doneBlock.Preds = append(doneBlock.Preds, condBlock)
1416
1417 fb.currentBlock = bodyBlock
1418 if rc.Lhs != nil && rc.Def {
1419 names := ssaExprNames(rc.Lhs)
1420 for i, name := range names {
1421 if name.Value == "_" {
1422 continue
1423 }
1424 ext := &SSAExtract{Tuple: nxt, Index: i + 1}
1425 ext.typ = ssaTupleElemType(nxt.typ, i+1)
1426 ext.name = fb.nextName()
1427 fb.emit(ext)
1428 var obj Object
1429 if fb.info != nil {
1430 obj = fb.info.Defs[name]
1431 }
1432 if obj == nil {
1433 obj = NewTCVar(fb.fn.Pkg.Pkg, name.Value, ext.typ)
1434 }
1435 fb.removeVar(name.Value)
1436 alloc := fb.emitAlloc(ext.typ, 0)
1437 fb.vars[obj] = alloc
1438 fb.emitStore(alloc, ext)
1439 }
1440 }
1441 fb.buildBlock(s.Body)
1442 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1443 fb.emit(&SSAJump{Comment: "range.cond"})
1444 fb.currentBlock.Succs = append(fb.currentBlock.Succs, condBlock)
1445 condBlock.Preds = append(condBlock.Preds, fb.currentBlock)
1446 }
1447
1448 fb.loops = fb.loops[:len(fb.loops)-1]
1449 fb.currentBlock = doneBlock
1450 }
1451
1452 func (fb *ssaFuncBuilder) buildSwitch(s *SwitchStmt) {
1453 var savedVars map[Object]*SSAAlloc
1454 if s.Init != nil {
1455 savedVars = fb.saveVars()
1456 fb.buildStmt(s.Init)
1457 }
1458 if fb.currentBlock == nil {
1459 if savedVars != nil {
1460 fb.vars = savedVars
1461 }
1462 return
1463 }
1464
1465 doneBlock := fb.newBlock("switch.done")
1466 savedLoops := fb.loops
1467 fb.loops = append(fb.loops, ssaLoopState{label: fb.pendingLabel, done: doneBlock})
1468 fb.pendingLabel = ""
1469
1470 if s.Tag != nil {
1471 if tsg, ok := s.Tag.(*TypeSwitchGuard); ok {
1472 fb.buildTypeSwitch(s, tsg, doneBlock)
1473 fb.loops = savedLoops
1474 fb.currentBlock = doneBlock
1475 if savedVars != nil {
1476 fb.vars = savedVars
1477 }
1478 return
1479 }
1480 }
1481
1482 var tag SSAValue
1483 if s.Tag != nil {
1484 tag = fb.buildExpr(s.Tag)
1485 }
1486
1487 for _, clause := range s.Body {
1488 caseBlock := fb.newBlock("switch.case")
1489 nextBlock := fb.newBlock("switch.next")
1490
1491 if clause.Cases != nil && tag != nil {
1492 var cond SSAValue
1493 caseExprs := []Expr{clause.Cases}
1494 if list, ok := clause.Cases.(*ListExpr); ok {
1495 caseExprs = list.ElemList
1496 }
1497 for _, ce := range caseExprs {
1498 caseVal := fb.buildExpr(ce)
1499 cmp := &SSABinOp{Op: OpEql, X: tag, Y: caseVal}
1500 cmp.typ = Typ[Bool]
1501 cmp.name = fb.nextName()
1502 fb.emit(cmp)
1503 if cond == nil {
1504 cond = cmp
1505 } else {
1506 orOp := &SSABinOp{Op: OpLor, X: cond, Y: cmp}
1507 orOp.typ = Typ[Bool]
1508 orOp.name = fb.nextName()
1509 fb.emit(orOp)
1510 cond = orOp
1511 }
1512 }
1513 fb.emit(&SSAIf{Cond: cond})
1514 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1515 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1516 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1517 } else if clause.Cases != nil && tag == nil {
1518 cond := fb.buildExpr(clause.Cases)
1519 fb.emit(&SSAIf{Cond: cond})
1520 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1521 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1522 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1523 } else {
1524 fb.emit(&SSAJump{Comment: "switch.case"})
1525 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock)
1526 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1527 }
1528
1529 fb.currentBlock = caseBlock
1530 for _, stmt := range clause.Body {
1531 fb.buildStmt(stmt)
1532 if fb.currentBlock == nil {
1533 break
1534 }
1535 }
1536 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1537 fb.emit(&SSAJump{Comment: "switch.done"})
1538 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1539 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1540 }
1541 fb.currentBlock = nextBlock
1542 }
1543
1544 if fb.currentBlock != nil {
1545 fb.emit(&SSAJump{Comment: "switch.done"})
1546 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1547 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1548 }
1549
1550 fb.loops = savedLoops
1551 fb.currentBlock = doneBlock
1552 if savedVars != nil {
1553 fb.vars = savedVars
1554 }
1555 }
1556
1557 func (fb *ssaFuncBuilder) buildTypeSwitch(s *SwitchStmt, tsg *TypeSwitchGuard, doneBlock *SSABasicBlock) {
1558 x := fb.buildExpr(tsg.X)
1559 for _, clause := range s.Body {
1560 caseBlock := fb.newBlock("typeswitch.case")
1561 nextBlock := fb.newBlock("typeswitch.next")
1562
1563 if clause.Cases != nil {
1564 caseExprs := []Expr{clause.Cases}
1565 if list, ok := clause.Cases.(*ListExpr); ok {
1566 caseExprs = list.ElemList
1567 }
1568
1569 var cond SSAValue
1570 var firstTA *SSATypeAssert
1571 var firstType Type
1572 for _, ce := range caseExprs {
1573 if n, isName := ce.(*Name); isName && n.Value == "nil" {
1574 nilType := x.SSAType()
1575 if nilType == nil {
1576 nilType = NewTCInterface(nil, nil)
1577 }
1578 nilCheck := &SSABinOp{Op: OpEql, X: x, Y: &SSAConst{typ: nilType, val: nil}}
1579 nilCheck.typ = Typ[Bool]
1580 nilCheck.name = fb.nextName()
1581 fb.emit(nilCheck)
1582 if cond == nil {
1583 cond = nilCheck
1584 } else {
1585 orOp := &SSABinOp{Op: OpLor, X: cond, Y: nilCheck}
1586 orOp.typ = Typ[Bool]
1587 orOp.name = fb.nextName()
1588 fb.emit(orOp)
1589 cond = orOp
1590 }
1591 continue
1592 }
1593 var assertedType Type
1594 if fb.info != nil {
1595 tv := fb.info.Types[ce]
1596 assertedType = tv.Type
1597 }
1598 if assertedType == nil {
1599 assertedType = fb.resolveType(ce)
1600 }
1601 if assertedType == nil {
1602 assertedType = Typ[Invalid]
1603 }
1604 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: true}
1605 ta.typ = NewTuple(
1606 NewTCVar(nil, "val", assertedType),
1607 NewTCVar(nil, "ok", Typ[Bool]),
1608 )
1609 ta.name = fb.nextName()
1610 fb.emit(ta)
1611 okExt := &SSAExtract{Tuple: ta, Index: 1}
1612 okExt.typ = Typ[Bool]
1613 okExt.name = fb.nextName()
1614 fb.emit(okExt)
1615 if firstTA == nil {
1616 firstTA = ta
1617 firstType = assertedType
1618 }
1619 if cond == nil {
1620 cond = okExt
1621 } else {
1622 orOp := &SSABinOp{Op: OpLor, X: cond, Y: okExt}
1623 orOp.typ = Typ[Bool]
1624 orOp.name = fb.nextName()
1625 fb.emit(orOp)
1626 cond = orOp
1627 }
1628 }
1629 fb.emit(&SSAIf{Cond: cond})
1630 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock, nextBlock)
1631 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1632 nextBlock.Preds = append(nextBlock.Preds, fb.currentBlock)
1633
1634 fb.currentBlock = caseBlock
1635 if tsg.Lhs != nil {
1636 var guardVal SSAValue
1637 var guardType Type
1638 if firstTA != nil {
1639 ext := &SSAExtract{Tuple: firstTA, Index: 0}
1640 ext.typ = firstType
1641 ext.name = fb.nextName()
1642 fb.emit(ext)
1643 guardVal = ext
1644 guardType = firstType
1645 } else {
1646 guardType = x.SSAType()
1647 if guardType == nil {
1648 guardType = NewTCInterface(nil, nil)
1649 }
1650 guardVal = &SSAConst{typ: guardType, val: nil}
1651 }
1652 for old := range fb.vars {
1653 if old.Name() == tsg.Lhs.Value {
1654 delete(fb.vars, old)
1655 break
1656 }
1657 }
1658 obj := NewTCVar(fb.fn.Pkg.Pkg, tsg.Lhs.Value, guardType)
1659 alloc := fb.emitAlloc(guardType, 0)
1660 fb.vars[obj] = alloc
1661 fb.emitStore(alloc, guardVal)
1662 }
1663 } else {
1664 fb.emit(&SSAJump{Comment: "typeswitch.case"})
1665 fb.currentBlock.Succs = append(fb.currentBlock.Succs, caseBlock)
1666 caseBlock.Preds = append(caseBlock.Preds, fb.currentBlock)
1667 fb.currentBlock = caseBlock
1668 }
1669
1670 for _, stmt := range clause.Body {
1671 fb.buildStmt(stmt)
1672 if fb.currentBlock == nil {
1673 break
1674 }
1675 }
1676 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1677 fb.emit(&SSAJump{Comment: "switch.done"})
1678 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1679 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1680 }
1681 fb.currentBlock = nextBlock
1682 }
1683 if fb.currentBlock != nil {
1684 fb.emit(&SSAJump{Comment: "switch.done"})
1685 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1686 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1687 }
1688 }
1689
1690 func (fb *ssaFuncBuilder) buildSelect(s *SelectStmt) {
1691 doneBlock := fb.newBlock("select.done")
1692
1693 var states []*SSASelectState
1694 caseBlocks := [](*SSABasicBlock){:0:len(s.Body)}
1695 for i, clause := range s.Body {
1696 cb := fb.newBlock("select.case")
1697 caseBlocks = append(caseBlocks, cb)
1698 state := &SSASelectState{}
1699 if clause.Comm != nil {
1700 switch comm := clause.Comm.(type) {
1701 case *SendStmt:
1702 state.Dir = SelectDirSend
1703 state.Chan = fb.buildExpr(comm.Chan)
1704 state.Send = fb.buildExpr(comm.Value)
1705 case *AssignStmt:
1706 var chanExpr Expr
1707 if op, ok2 := comm.Rhs.(*Operation); ok2 && op.Y == nil && op.Op == Recv {
1708 chanExpr = op.X
1709 }
1710 if chanExpr != nil {
1711 state.Dir = SelectDirRecv
1712 state.Chan = fb.buildExpr(chanExpr)
1713 }
1714 case *ExprStmt:
1715 if op, ok2 := comm.X.(*Operation); ok2 && op.Y == nil && op.Op == Recv {
1716 state.Dir = SelectDirRecv
1717 state.Chan = fb.buildExpr(op.X)
1718 }
1719 }
1720 }
1721 states = append(states, state)
1722 _ = i
1723 }
1724
1725 sel := &SSASelect{States: states, Blocking: true}
1726 sel.typ = NewTuple(
1727 NewTCVar(nil, "index", Typ[Int32]),
1728 NewTCVar(nil, "recvOk", Typ[Bool]),
1729 )
1730 sel.name = fb.nextName()
1731 fb.emit(sel)
1732
1733 for i, clause := range s.Body {
1734 fb.currentBlock = caseBlocks[i]
1735 for _, stmt := range clause.Body {
1736 fb.buildStmt(stmt)
1737 if fb.currentBlock == nil {
1738 break
1739 }
1740 }
1741 if fb.currentBlock != nil && !fb.blockTerminated(fb.currentBlock) {
1742 fb.emit(&SSAJump{Comment: "select.done"})
1743 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1744 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1745 }
1746 }
1747
1748 fb.currentBlock = doneBlock
1749 }
1750
1751 func (fb *ssaFuncBuilder) isSelfTailCall(e Expr) (*CallExpr, bool) {
1752 call, ok := e.(*CallExpr)
1753 if !ok || fb.tailBlock == nil || fb.deferred > 0 {
1754 return nil, false
1755 }
1756 name, ok := call.Fun.(*Name)
1757 if !ok {
1758 return nil, false
1759 }
1760 obj := fb.lookupObject(name.Value)
1761 if obj == nil {
1762 return nil, false
1763 }
1764 tc, ok := obj.(*TCFunc)
1765 if !ok || tc == nil {
1766 return nil, false
1767 }
1768 var fn *SSAFunction
1769 if okv, okok := fb.fn.Pkg.Members[name.Value].(*SSAFunction); okok {
1770 fn = okv
1771 }
1772 if fn != fb.fn {
1773 return nil, false
1774 }
1775 return call, true
1776 }
1777
1778 func (fb *ssaFuncBuilder) buildReturn(s *ReturnStmt) {
1779 if s.Results != nil {
1780 if call, ok := fb.isSelfTailCall(s.Results); ok {
1781 args := fb.buildArgs(call.ArgList)
1782 if len(args) == len(fb.paramAllocas) {
1783 for i, arg := range args {
1784 fb.emitStore(fb.paramAllocas[i], arg)
1785 }
1786 fb.emit(&SSAJump{Comment: "tailcall"})
1787 fb.currentBlock.Succs = append(fb.currentBlock.Succs, fb.tailBlock)
1788 fb.tailBlock.Preds = append(fb.tailBlock.Preds, fb.currentBlock)
1789 fb.currentBlock = nil
1790 return
1791 }
1792 }
1793 }
1794 var vals []SSAValue
1795 if s.Results != nil {
1796 if list, ok := s.Results.(*ListExpr); ok {
1797 for _, el := range list.ElemList {
1798 v := fb.buildExpr(el)
1799 if v != nil {
1800 vals = append(vals, v)
1801 }
1802 }
1803 } else {
1804 v := fb.buildExpr(s.Results)
1805 if v != nil {
1806 if v.SSAType() == nil {
1807 vals = append(vals, v)
1808 } else if tup, ok := v.SSAType().(*Tuple); ok && tup.Len() > 1 {
1809 for i := 0; i < tup.Len(); i++ {
1810 ext := &SSAExtract{Tuple: v, Index: i}
1811 ext.typ = tup.At(i).Type()
1812 ext.name = fb.nextName()
1813 fb.emit(ext)
1814 vals = append(vals, ext)
1815 }
1816 } else {
1817 vals = append(vals, v)
1818 }
1819 }
1820 }
1821 } else if len(fb.namedResults) > 0 {
1822 for _, nr := range fb.namedResults {
1823 elemType := nr.SSAType()
1824 if p, ok := elemType.(*Pointer); ok {
1825 elemType = p.Elem()
1826 }
1827 vals = append(vals, fb.emitLoad(nr, elemType))
1828 }
1829 }
1830 if fb.fn.Signature != nil && fb.fn.Signature.Results() != nil {
1831 for i, v := range vals {
1832 if i < fb.fn.Signature.Results().Len() {
1833 retType := fb.fn.Signature.Results().At(i).Type()
1834 vals[i] = fb.coerceToInterface(v, retType)
1835 }
1836 }
1837 }
1838 fb.emitReturn(vals, 0)
1839 }
1840
1841 func (fb *ssaFuncBuilder) buildBranch(s *BranchStmt) {
1842 if fb.currentBlock == nil {
1843 return
1844 }
1845 switch s.Tok {
1846 case Break:
1847 if len(fb.loops) > 0 {
1848 var doneBlock *SSABasicBlock
1849 if s.Label != nil {
1850 for i := len(fb.loops) - 1; i >= 0; i-- {
1851 if fb.loops[i].label == s.Label.Value {
1852 doneBlock = fb.loops[i].done
1853 break
1854 }
1855 }
1856 }
1857 if doneBlock == nil {
1858 doneBlock = fb.loops[len(fb.loops)-1].done
1859 }
1860 fb.emit(&SSAJump{Comment: "break"})
1861 fb.currentBlock.Succs = append(fb.currentBlock.Succs, doneBlock)
1862 doneBlock.Preds = append(doneBlock.Preds, fb.currentBlock)
1863 fb.currentBlock = nil
1864 }
1865 case Continue:
1866 for i := len(fb.loops) - 1; i >= 0; i-- {
1867 postBlock := fb.loops[i].post
1868 if postBlock == nil {
1869 postBlock = fb.loops[i].body
1870 }
1871 if postBlock == nil {
1872 continue
1873 }
1874 fb.emit(&SSAJump{Comment: "continue"})
1875 fb.currentBlock.Succs = append(fb.currentBlock.Succs, postBlock)
1876 postBlock.Preds = append(postBlock.Preds, fb.currentBlock)
1877 fb.currentBlock = nil
1878 break
1879 }
1880 case Goto:
1881 if s.Label != nil {
1882 target := fb.labelBlock(s.Label.Value)
1883 fb.emit(&SSAJump{Comment: "goto." + s.Label.Value})
1884 fb.currentBlock.Succs = append(fb.currentBlock.Succs, target)
1885 target.Preds = append(target.Preds, fb.currentBlock)
1886 fb.currentBlock = nil
1887 }
1888 case Return:
1889 fb.emitReturn(nil, 0)
1890 }
1891 }
1892
1893 func (fb *ssaFuncBuilder) buildGoStmt(call *CallExpr) {
1894 fn := fb.buildExpr(call.Fun)
1895 if fn == nil {
1896 return
1897 }
1898 args := fb.buildArgs(call.ArgList)
1899 g := &SSAGo{Call: SSACallCommon{Value: fn, Args: args}}
1900 fb.emit(g)
1901 }
1902
1903 func (fb *ssaFuncBuilder) buildDeferStmt(call *CallExpr) {
1904 fn := fb.buildExpr(call.Fun)
1905 if fn == nil {
1906 return
1907 }
1908 args := fb.buildArgs(call.ArgList)
1909 d := &SSADefer{Call: SSACallCommon{Value: fn, Args: args}}
1910 fb.emit(d)
1911 fb.deferred++
1912 }
1913
1914 // Expression builders.
1915
1916 func (fb *ssaFuncBuilder) buildExpr(e Expr) SSAValue {
1917 if e == nil || fb.currentBlock == nil {
1918 return nil
1919 }
1920 switch e := e.(type) {
1921 case *Name:
1922 return fb.buildIdent(e)
1923 case *BasicLit:
1924 return fb.buildLit(e)
1925 case *Operation:
1926 return fb.buildOperation(e)
1927 case *CallExpr:
1928 return fb.buildCall(e)
1929 case *SelectorExpr:
1930 return fb.buildSelector(e)
1931 case *IndexExpr:
1932 return fb.buildIndex(e)
1933 case *SliceExpr:
1934 return fb.buildSlice(e)
1935 case *AssertExpr:
1936 return fb.buildAssert(e)
1937 case *CompositeLit:
1938 return fb.buildCompositeLit(e)
1939 case *FuncLit:
1940 return fb.buildFuncLit(e)
1941 case *ParenExpr:
1942 return fb.buildExpr(e.X)
1943 case *ListExpr:
1944 var last SSAValue
1945 for _, el := range e.ElemList {
1946 last = fb.buildExpr(el)
1947 }
1948 return last
1949 case *KeyValueExpr:
1950 return fb.buildExpr(e.Value)
1951 }
1952 return nil
1953 }
1954
1955 func (fb *ssaFuncBuilder) buildIdent(e *Name) SSAValue {
1956 if e.Value == "_" || e.Value == "nil" {
1957 return &SSAConst{typ: nil, val: nil}
1958 }
1959 if fb.localConsts != nil {
1960 if c, ok := fb.localConsts[e.Value]; ok {
1961 return c
1962 }
1963 }
1964 obj := fb.lookupObject(e.Value)
1965 if obj == nil && fb.info != nil {
1966 obj = fb.info.Uses[e]
1967 }
1968 if obj == nil {
1969 if fb.fn.Pkg != nil {
1970 if fn, ok := fb.fn.Pkg.Members[e.Value].(*SSAFunction); ok {
1971 return fn
1972 }
1973 if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
1974 return fb.emitLoad(g, g.typ)
1975 }
1976 }
1977 return fb.builtinValue(e.Value)
1978 }
1979 switch obj := obj.(type) {
1980 case *TCVar:
1981 if alloc, ok := fb.vars[obj]; ok {
1982 return fb.emitLoad(alloc, obj.Type())
1983 }
1984 if fv, ok := fb.freeVarPtrs[e.Value]; ok {
1985 return fb.emitLoad(fv, obj.Type())
1986 }
1987 if fb.parent != nil {
1988 if _, ok := fb.parent.vars[obj]; ok {
1989 fv := fb.getOrCreateFreeVar(e.Value, obj.Type())
1990 return fb.emitLoad(fv, obj.Type())
1991 }
1992 }
1993 if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
1994 return fb.emitLoad(g, obj.Type())
1995 }
1996 return &SSAConst{typ: obj.Type(), val: nil}
1997 case *TCConst:
1998 return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
1999 case *TCFunc:
2000 var fn *SSAFunction
2001 if okv, okok := fb.fn.Pkg.Members[e.Value].(*SSAFunction); okok {
2002 fn = okv
2003 }
2004 if fn != nil {
2005 return fn
2006 }
2007 return &SSAConst{typ: obj.Type(), val: nil}
2008 case *TypeName:
2009 return nil
2010 case *Builtin:
2011 return &SSABuiltin{id: obj.ID(), name: obj.Name()}
2012 }
2013 return nil
2014 }
2015
2016 func (fb *ssaFuncBuilder) builtinValue(name string) SSAValue {
2017 id, ok := ssaBuiltinID(name)
2018 if !ok {
2019 return nil
2020 }
2021 return &SSABuiltin{id: id, name: name}
2022 }
2023
2024 func (fb *ssaFuncBuilder) buildLit(e *BasicLit) SSAValue {
2025 cv := evalBasicLitLocal(e)
2026 if cv == nil {
2027 return nil
2028 }
2029 switch e.Kind {
2030 case IntLit:
2031 return &SSAConst{typ: Typ[UntypedInt], val: cv}
2032 case FloatLit:
2033 return &SSAConst{typ: Typ[UntypedFloat], val: cv}
2034 case StringLit:
2035 return &SSAConst{typ: Typ[UntypedString], val: cv}
2036 case RuneLit:
2037 return &SSAConst{typ: Typ[UntypedRune], val: cv}
2038 }
2039 return nil
2040 }
2041
2042 func (fb *ssaFuncBuilder) buildOperation(e *Operation) SSAValue {
2043 if e.Y == nil {
2044 if e.Op == Add {
2045 return fb.buildExpr(e.X)
2046 }
2047 op := syntaxOpToSSAOp(e.Op, true)
2048 if op == OpAnd {
2049 if name, ok := e.X.(*Name); ok {
2050 obj := fb.lookupObject(name.Value)
2051 if obj != nil {
2052 if alloc, ok2 := fb.vars[obj]; ok2 {
2053 return alloc
2054 }
2055 if g, ok2 := fb.fn.Pkg.Members[name.Value].(*SSAGlobal); ok2 {
2056 return g
2057 }
2058 }
2059 }
2060 if ie, ok := e.X.(*IndexExpr); ok {
2061 base := fb.buildExpr(ie.X)
2062 idx := fb.buildExpr(ie.Index)
2063 if base == nil || idx == nil {
2064 return nil
2065 }
2066 ia := &SSAIndexAddr{X: base, Index: idx}
2067 ia.typ = NewPointer(ssaElemType(base.SSAType()))
2068 ia.name = fb.nextName()
2069 fb.emit(ia)
2070 return ia
2071 }
2072 if sel, ok := e.X.(*SelectorExpr); ok {
2073 addr := fb.buildSelectorAddr(sel)
2074 if addr != nil {
2075 return addr
2076 }
2077 }
2078 x := fb.buildExpr(e.X)
2079 if x == nil {
2080 return nil
2081 }
2082 a := &SSAAlloc{Heap: true}
2083 a.typ = NewPointer(x.SSAType())
2084 a.name = fb.nextName()
2085 fb.emit(a)
2086 fb.emitStore(a, x)
2087 return a
2088 }
2089 x := fb.buildExpr(e.X)
2090 if x == nil {
2091 return nil
2092 }
2093 if op == OpArrow {
2094 u := &SSAUnOp{Op: OpArrow, X: x}
2095 u.typ = ssaChanElemType(x.SSAType())
2096 u.name = fb.nextName()
2097 fb.emit(u)
2098 return u
2099 }
2100 u := &SSAUnOp{Op: op, X: x}
2101 if op == OpMul {
2102 if p, ok := x.SSAType().(*Pointer); ok {
2103 u.typ = p.Elem()
2104 } else {
2105 u.typ = x.SSAType()
2106 }
2107 } else {
2108 u.typ = x.SSAType()
2109 }
2110 u.name = fb.nextName()
2111 fb.emit(u)
2112 return u
2113 }
2114 op := syntaxOpToSSAOp(e.Op, false)
2115 if op == OpLand || op == OpLor {
2116 x := fb.buildExpr(e.X)
2117 if x == nil {
2118 return nil
2119 }
2120 rhsBlock := fb.newBlock("sc.rhs")
2121 mergeBlock := fb.newBlock("sc.merge")
2122 entryBlock := fb.currentBlock
2123 fb.emit(&SSAIf{Cond: x})
2124 if op == OpLand {
2125 fb.currentBlock.Succs = append(fb.currentBlock.Succs, rhsBlock, mergeBlock)
2126 } else {
2127 fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock, rhsBlock)
2128 }
2129 rhsBlock.Preds = append(rhsBlock.Preds, entryBlock)
2130 mergeBlock.Preds = append(mergeBlock.Preds, entryBlock)
2131 fb.currentBlock = rhsBlock
2132 y := fb.buildExpr(e.Y)
2133 if y == nil {
2134 y = &SSAConst{typ: Typ[Bool], val: constBool{false}}
2135 }
2136 fb.emit(&SSAJump{Comment: "sc.merge"})
2137 fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock)
2138 mergeBlock.Preds = append(mergeBlock.Preds, fb.currentBlock)
2139 fb.currentBlock = mergeBlock
2140 var shortVal SSAValue
2141 if op == OpLand {
2142 shortVal = &SSAConst{typ: Typ[Bool], val: constBool{false}}
2143 } else {
2144 shortVal = &SSAConst{typ: Typ[Bool], val: constBool{true}}
2145 }
2146 phi := &SSAPhi{Edges: []SSAValue{shortVal, y}, Comment: "sc"}
2147 phi.typ = Typ[Bool]
2148 phi.name = fb.nextName()
2149 fb.emit(phi)
2150 return phi
2151 }
2152 x := fb.buildExpr(e.X)
2153 y := fb.buildExpr(e.Y)
2154 if x == nil || y == nil {
2155 return nil
2156 }
2157 if xc, ok := x.(*SSAConst); ok {
2158 if yc, ok2 := y.(*SSAConst); ok2 {
2159 if xc.val != nil && yc.val != nil {
2160 folded := evalBinaryLocal(e.Op, xc.val, yc.val)
2161 if folded != nil {
2162 ct := xc.typ
2163 if ct == nil {
2164 ct = yc.typ
2165 }
2166 if _, isBool := folded.(constBool); isBool {
2167 ct = Typ[Bool]
2168 }
2169 return &SSAConst{typ: ct, val: folded}
2170 }
2171 }
2172 }
2173 }
2174 b := &SSABinOp{Op: op, X: x, Y: y}
2175 b.name = fb.nextName()
2176 switch op {
2177 case OpEql, OpNeq, OpLss, OpLeq, OpGtr, OpGeq:
2178 b.typ = Typ[Bool]
2179 default:
2180 xT := x.SSAType()
2181 yT := y.SSAType()
2182 xUntyped := false
2183 if xB, ok := safeUnderlying(xT).(*Basic); ok && xB.Info()&IsUntyped != 0 {
2184 xUntyped = true
2185 }
2186 if xT != nil && !xUntyped {
2187 b.typ = xT
2188 } else if yT != nil {
2189 b.typ = yT
2190 } else {
2191 b.typ = xT
2192 }
2193 }
2194 fb.emit(b)
2195 return b
2196 }
2197
2198 func (fb *ssaFuncBuilder) buildCall(e *CallExpr) SSAValue {
2199 if ie, ok := e.Fun.(*IndexExpr); ok {
2200 if result := fb.tryGenericCallFromIndex(ie, e.ArgList, e.HasDots); result != nil {
2201 return result
2202 }
2203 }
2204 if name, ok := e.Fun.(*Name); ok {
2205 obj := fb.lookupObject(name.Value)
2206 if tn, ok2 := obj.(*TypeName); ok2 {
2207 if _, isTP := tn.Type().(*TypeParam); !isTP {
2208 args := fb.buildArgs(e.ArgList)
2209 if len(args) == 1 && args[0] != nil {
2210 conv := &SSAConvert{X: args[0]}
2211 conv.typ = tn.Type()
2212 conv.name = fb.nextName()
2213 fb.emit(conv)
2214 return conv
2215 }
2216 return nil
2217 }
2218 }
2219 if result := fb.tryGenericLocalCall(name.Value, e.ArgList, e.HasDots); result != nil {
2220 return result
2221 }
2222 }
2223 if convType := fb.resolveTypeAST(e.Fun); convType != nil {
2224 args := fb.buildArgs(e.ArgList)
2225 if len(args) == 1 && args[0] != nil {
2226 conv := &SSAConvert{X: args[0]}
2227 conv.typ = convType
2228 conv.name = fb.nextName()
2229 fb.emit(conv)
2230 return conv
2231 }
2232 return nil
2233 }
2234 if sel, ok := e.Fun.(*SelectorExpr); ok {
2235 if name, ok2 := sel.X.(*Name); ok2 {
2236 obj := fb.lookupObject(name.Value)
2237 if pn, ok3 := obj.(*PkgName); ok3 {
2238 return fb.buildPkgCall(pn, sel.Sel.Value, e.ArgList, e.HasDots)
2239 }
2240 }
2241 recv := fb.buildExpr(sel.X)
2242 if recv != nil && recv.SSAType() != nil {
2243 if fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv); fn != nil {
2244 args := fb.buildArgs(e.ArgList)
2245 if fn.Signature != nil {
2246 if fn.Signature.Variadic() && !e.HasDots {
2247 args = fb.wrapVariadicArgs(args, fn.Signature)
2248 }
2249 args = fb.coerceArgsToInterface(args, fn.Signature)
2250 }
2251 allArgs := []SSAValue{:0:len(args) + 1}
2252 allArgs = append(allArgs, fixedRecv)
2253 for _, ma := range args {
2254 allArgs = append(allArgs, ma)
2255 }
2256 var retType Type
2257 if fn.Signature != nil {
2258 if fn.Signature.Results() != nil && fn.Signature.Results().Len() == 1 {
2259 retType = fn.Signature.Results().At(0).Type()
2260 } else if fn.Signature.Results() != nil && fn.Signature.Results().Len() > 1 {
2261 retType = fn.Signature.Results()
2262 }
2263 }
2264 call := &SSACall{Call: SSACallCommon{Value: fn, Args: allArgs}}
2265 call.typ = retType
2266 call.name = fb.nextName()
2267 fb.emit(call)
2268 if retType == nil {
2269 return nil
2270 }
2271 return call
2272 }
2273 if inv := fb.buildIfaceMethodCall(sel, recv, e.ArgList); inv != nil {
2274 return inv
2275 }
2276 }
2277 }
2278 fn := fb.buildExpr(e.Fun)
2279 args := fb.buildArgs(e.ArgList)
2280
2281 if fn == nil {
2282 return nil
2283 }
2284 if bi, ok := fn.(*SSABuiltin); ok {
2285 return fb.buildBuiltinCall(e, bi, args)
2286 }
2287
2288 var retType Type
2289 if fn.SSAType() != nil {
2290 if sig, ok := safeUnderlying(fn.SSAType()).(*Signature); ok {
2291 if sig.Results() != nil && sig.Results().Len() == 1 {
2292 retType = sig.Results().At(0).Type()
2293 } else if sig.Results() != nil && sig.Results().Len() > 1 {
2294 retType = sig.Results()
2295 }
2296 }
2297 } else if ssaFn, ok := fn.(*SSAFunction); ok && ssaFn.Signature != nil {
2298 sig := ssaFn.Signature
2299 if sig.Results() != nil && sig.Results().Len() == 1 {
2300 retType = sig.Results().At(0).Type()
2301 } else if sig.Results() != nil && sig.Results().Len() > 1 {
2302 retType = sig.Results()
2303 }
2304 }
2305
2306 if fn.SSAType() != nil {
2307 if sig, ok := safeUnderlying(fn.SSAType()).(*Signature); ok {
2308 if sig.Variadic() && !e.HasDots {
2309 args = fb.wrapVariadicArgs(args, sig)
2310 }
2311 args = fb.coerceArgsToInterface(args, sig)
2312 }
2313 }
2314
2315 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
2316 call.typ = retType
2317 call.name = fb.nextName()
2318 fb.emit(call)
2319
2320 if retType == nil {
2321 return nil
2322 }
2323 return call
2324 }
2325
2326 func (fb *ssaFuncBuilder) coerceArgsToInterface(args []SSAValue, sig *Signature) []SSAValue {
2327 if sig.Params() == nil {
2328 return args
2329 }
2330 for i := 0; i < len(args) && i < sig.Params().Len(); i++ {
2331 paramType := sig.Params().At(i).Type()
2332 if paramType == nil || args[i] == nil || args[i].SSAType() == nil {
2333 continue
2334 }
2335 _, isIface := safeUnderlying(paramType).(*TCInterface)
2336 if !isIface {
2337 continue
2338 }
2339 _, argIsIface := safeUnderlying(args[i].SSAType()).(*TCInterface)
2340 if argIsIface {
2341 continue
2342 }
2343 mi := &SSAMakeInterface{X: args[i], IType: paramType}
2344 mi.typ = paramType
2345 mi.name = fb.nextName()
2346 fb.emit(mi)
2347 args[i] = mi
2348 }
2349 return args
2350 }
2351
2352 func (fb *ssaFuncBuilder) wrapVariadicArgs(args []SSAValue, sig *Signature) []SSAValue {
2353 if sig.Params() == nil {
2354 return args
2355 }
2356 nFixed := sig.Params().Len() - 1
2357 if nFixed < 0 {
2358 nFixed = 0
2359 }
2360 if nFixed > len(args) {
2361 nFixed = len(args)
2362 }
2363 nVariadic := len(args) - nFixed
2364 if nVariadic <= 0 {
2365 nilSlice := NewSSAConst(constNil{}, sig.Params().At(sig.Params().Len()-1).Type())
2366 result := []SSAValue{:nFixed:nFixed}
2367 copy(result, args[:nFixed])
2368 return append(result, nilSlice)
2369 }
2370 sliceType := sig.Params().At(sig.Params().Len() - 1).Type()
2371 var elemType Type
2372 if sl, ok := safeUnderlying(sliceType).(*Slice); ok {
2373 elemType = sl.Elem()
2374 }
2375 // HasDots lost in stage-2 compiled parser. Detect spread: if exactly 1
2376 // variadic arg whose type matches the variadic param's slice type, and
2377 // the element type is concrete, it must be a spread call (f(slice...)).
2378 // Passing []T to ...T without dots is a type error for concrete T.
2379 if nVariadic == 1 && elemType != nil {
2380 if _, isIface := safeUnderlying(elemType).(*TCInterface); !isIface {
2381 argT := args[nFixed].SSAType()
2382 if argT != nil && Identical(argT, sliceType) {
2383 return args
2384 }
2385 }
2386 }
2387 lenVal := NewSSAConst(constInt{int32(nVariadic)}, Typ[Int32])
2388 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal}
2389 ms.typ = sliceType
2390 ms.name = fb.nextName()
2391 fb.emit(ms)
2392 for i := 0; i < nVariadic; i++ {
2393 idx := NewSSAConst(constInt{int32(i)}, Typ[Int32])
2394 ia := &SSAIndexAddr{X: ms, Index: idx}
2395 ia.typ = NewPointer(elemType)
2396 ia.name = fb.nextName()
2397 fb.emit(ia)
2398 v := args[nFixed+i]
2399 if elemType != nil {
2400 v = fb.coerceToInterface(v, elemType)
2401 }
2402 fb.emitStore(ia, v)
2403 }
2404 result := []SSAValue{:nFixed:nFixed}
2405 copy(result, args[:nFixed])
2406 return append(result, ms)
2407 }
2408
2409 func (fb *ssaFuncBuilder) buildArgs(argList []Expr) []SSAValue {
2410 args := []SSAValue{:0:len(argList)}
2411 for _, a := range argList {
2412 v := fb.buildExpr(a)
2413 if v != nil {
2414 args = append(args, v)
2415 }
2416 }
2417 return args
2418 }
2419
2420 func (fb *ssaFuncBuilder) buildBuiltinCall(e *CallExpr, b *SSABuiltin, args []SSAValue) SSAValue {
2421 switch b.id {
2422 case BuiltinLen, BuiltinCap:
2423 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2424 call.typ = Typ[Int32]
2425 call.name = fb.nextName()
2426 fb.emit(call)
2427 return call
2428 case BuiltinAppend:
2429 if len(args) > 1 {
2430 if sl, ok := safeUnderlying(args[0].SSAType()).(*Slice); ok {
2431 if _, isIface := safeUnderlying(sl.Elem()).(*TCInterface); isIface {
2432 for i := 1; i < len(args); i++ {
2433 if e.HasDots && i == 1 {
2434 continue
2435 }
2436 if args[i] == nil || args[i].SSAType() == nil {
2437 continue
2438 }
2439 if _, argIface := safeUnderlying(args[i].SSAType()).(*TCInterface); argIface {
2440 continue
2441 }
2442 mi := &SSAMakeInterface{X: args[i], IType: sl.Elem()}
2443 mi.typ = sl.Elem()
2444 mi.name = fb.nextName()
2445 fb.emit(mi)
2446 args[i] = mi
2447 }
2448 }
2449 }
2450 }
2451 call := &SSACall{Call: SSACallCommon{Value: b, Args: args, HasDots: e.HasDots}}
2452 if len(args) > 0 {
2453 call.typ = args[0].SSAType()
2454 }
2455 call.name = fb.nextName()
2456 fb.emit(call)
2457 return call
2458 case BuiltinMake:
2459 if len(e.ArgList) == 0 {
2460 return nil
2461 }
2462 typ := fb.resolveType(e.ArgList[0])
2463 return fb.emitMake(typ, args)
2464 case BuiltinNew:
2465 if len(e.ArgList) == 0 {
2466 return nil
2467 }
2468 typ := fb.resolveType(e.ArgList[0])
2469 a := &SSAAlloc{Heap: true}
2470 a.typ = NewPointer(typ)
2471 a.name = fb.nextName()
2472 fb.emit(a)
2473 return a
2474 case BuiltinPanic:
2475 if len(args) > 0 {
2476 fb.emit(&SSAPanic{X: args[0]})
2477 fb.currentBlock = nil
2478 }
2479 return nil
2480 case BuiltinClose, BuiltinDelete, BuiltinClear, BuiltinPrint, BuiltinPrintln:
2481 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2482 call.name = fb.nextName()
2483 fb.emit(call)
2484 return nil
2485 case BuiltinCopy:
2486 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2487 call.typ = Typ[Int32]
2488 call.name = fb.nextName()
2489 fb.emit(call)
2490 return call
2491 case BuiltinRecover:
2492 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2493 call.typ = NewTCInterface(nil, nil)
2494 call.name = fb.nextName()
2495 fb.emit(call)
2496 return call
2497 case BuiltinMin, BuiltinMax:
2498 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2499 if len(args) > 0 && args[0] != nil {
2500 call.typ = args[0].SSAType()
2501 } else {
2502 call.typ = Typ[Int32]
2503 }
2504 call.name = fb.nextName()
2505 fb.emit(call)
2506 return call
2507 }
2508 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
2509 call.name = fb.nextName()
2510 fb.emit(call)
2511 return call
2512 }
2513
2514 func (fb *ssaFuncBuilder) emitMake(typ Type, sizeArgs []SSAValue) SSAValue {
2515 if typ == nil {
2516 return nil
2517 }
2518 switch u := safeUnderlying(typ).(type) {
2519 case *Basic:
2520 if u.kind == TCString {
2521 ms := &SSAMakeSlice{}
2522 ms.typ = typ
2523 ms.name = fb.nextName()
2524 if len(sizeArgs) > 0 {
2525 ms.Len = sizeArgs[0]
2526 }
2527 if len(sizeArgs) > 1 {
2528 ms.Cap = sizeArgs[1]
2529 }
2530 fb.emit(ms)
2531 return ms
2532 }
2533 case *Slice:
2534 ms := &SSAMakeSlice{}
2535 ms.typ = typ
2536 ms.name = fb.nextName()
2537 if len(sizeArgs) > 0 {
2538 ms.Len = sizeArgs[0]
2539 }
2540 if len(sizeArgs) > 1 {
2541 ms.Cap = sizeArgs[1]
2542 }
2543 fb.emit(ms)
2544 return ms
2545 case *TCMap:
2546 mm := &SSAMakeMap{}
2547 mm.typ = typ
2548 mm.name = fb.nextName()
2549 if len(sizeArgs) > 0 {
2550 mm.Reserve = sizeArgs[0]
2551 }
2552 fb.emit(mm)
2553 return mm
2554 case *TCChan:
2555 mc := &SSAMakeChan{}
2556 mc.typ = typ
2557 mc.name = fb.nextName()
2558 if len(sizeArgs) > 0 {
2559 mc.Size = sizeArgs[0]
2560 }
2561 fb.emit(mc)
2562 return mc
2563 }
2564 return nil
2565 }
2566
2567 func (fb *ssaFuncBuilder) buildSelector(e *SelectorExpr) SSAValue {
2568 if name, ok := e.X.(*Name); ok {
2569 obj := fb.lookupObject(name.Value)
2570 if pn, ok2 := obj.(*PkgName); ok2 {
2571 return fb.buildPkgMember(pn, e.Sel.Value)
2572 }
2573 }
2574 fa := fb.buildSelectorAddr(e)
2575 if fa != nil {
2576 elemType := fa.SSAType()
2577 if p, ok := safeUnderlying(elemType).(*Pointer); ok {
2578 elemType = p.Elem()
2579 }
2580 return fb.emitLoad(fa, elemType)
2581 }
2582 recv := fb.buildExpr(e.X)
2583 if recv == nil {
2584 return nil
2585 }
2586 return fb.buildMethodValue(e, recv)
2587 }
2588
2589 func (fb *ssaFuncBuilder) buildMethodValue(sel *SelectorExpr, recv SSAValue) SSAValue {
2590 fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv)
2591 if fn == nil || fn.Signature == nil {
2592 return nil
2593 }
2594 methodSig := fn.Signature
2595 var wrapperParams *Tuple
2596 if methodSig.Params() != nil && methodSig.Params().Len() > 0 {
2597 vars := []*TCVar{:0:methodSig.Params().Len()}
2598 for i := 0; i < methodSig.Params().Len(); i++ {
2599 vars = append(vars, methodSig.Params().At(i))
2600 }
2601 wrapperParams = NewTuple(vars...)
2602 }
2603 wrapperSig := NewSignature(nil, wrapperParams, methodSig.Results(), methodSig.Variadic())
2604 name := fb.fn.name | "__mval" | ssaItoa(len(fb.fn.AnonFuncs)+1)
2605 wrapper := &SSAFunction{
2606 name: name,
2607 Signature: wrapperSig,
2608 Pkg: fb.fn.Pkg,
2609 Prog: fb.fn.Prog,
2610 parent: fb.fn,
2611 }
2612 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, wrapper)
2613 recvType := fixedRecv.SSAType()
2614 fv := &SSAFreeVar{name: "recv", typ: recvType, parent: wrapper}
2615 wrapper.FreeVars = append(wrapper.FreeVars, fv)
2616 if wrapperParams != nil {
2617 for i := 0; i < wrapperParams.Len(); i++ {
2618 v := wrapperParams.At(i)
2619 p := &SSAParameter{name: v.Name(), typ: v.Type(), parent: wrapper}
2620 wrapper.Params = append(wrapper.Params, p)
2621 }
2622 }
2623 entry := NewSSABasicBlock(wrapper, "entry")
2624 args := []SSAValue{:0:1 + len(wrapper.Params)}
2625 args = append(args, fv)
2626 for _, p := range wrapper.Params {
2627 args = append(args, p)
2628 }
2629 var retType Type
2630 if methodSig.Results() != nil && methodSig.Results().Len() == 1 {
2631 retType = methodSig.Results().At(0).Type()
2632 } else if methodSig.Results() != nil && methodSig.Results().Len() > 1 {
2633 retType = methodSig.Results()
2634 }
2635 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
2636 call.typ = retType
2637 call.name = "t1"
2638 call.setBlock(entry)
2639 entry.Instrs = append(entry.Instrs, call)
2640 ret := &SSAReturn{}
2641 if retType != nil {
2642 ret.Results = []SSAValue{call}
2643 }
2644 ret.setBlock(entry)
2645 entry.Instrs = append(entry.Instrs, ret)
2646 mc := &SSAMakeClosure{Fn: wrapper, Bindings: []SSAValue{fixedRecv}}
2647 mc.typ = wrapperSig
2648 mc.name = fb.nextName()
2649 fb.emit(mc)
2650 return mc
2651 }
2652
2653 func (fb *ssaFuncBuilder) ensureImportedSSAPackage(imported *TCPackage) *SSAPackage {
2654 impPkg := fb.fn.Prog.ImportedPackage(imported.Path())
2655 if impPkg == nil {
2656 impPkg = &SSAPackage{
2657 Prog: fb.fn.Prog,
2658 Pkg: imported,
2659 Members: map[string]SSAMember{},
2660 }
2661 fb.fn.Prog.imported[imported.Path()] = impPkg
2662 fb.fn.Prog.packages[imported] = impPkg
2663 }
2664 return impPkg
2665 }
2666
2667 func (fb *ssaFuncBuilder) buildPkgMember(pn *PkgName, memberName string) SSAValue {
2668 imported := pn.Imported()
2669 if imported == nil {
2670 return nil
2671 }
2672 obj := imported.Scope().Lookup(memberName)
2673 if obj == nil {
2674 return nil
2675 }
2676 switch obj := obj.(type) {
2677 case *TCConst:
2678 return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
2679 case *TCVar:
2680 impPkg := fb.ensureImportedSSAPackage(imported)
2681 g, ok := impPkg.Members[memberName].(*SSAGlobal)
2682 if !ok {
2683 g = &SSAGlobal{
2684 name: memberName,
2685 typ: NewPointer(obj.Type()),
2686 pkg: impPkg,
2687 }
2688 impPkg.Members[memberName] = g
2689 }
2690 return fb.emitLoad(g, obj.Type())
2691 case *TCFunc:
2692 impPkg := fb.ensureImportedSSAPackage(imported)
2693 fn := impPkg.Func(memberName)
2694 if fn != nil {
2695 return fn
2696 }
2697 return nil
2698 }
2699 return nil
2700 }
2701
2702 func (fb *ssaFuncBuilder) buildSelectorAddr(e *SelectorExpr) SSAValue {
2703 var addr SSAValue
2704 var structType Type
2705 if inner, ok := e.X.(*SelectorExpr); ok {
2706 addr = fb.buildSelectorAddr(inner)
2707 if addr == nil {
2708 return nil
2709 }
2710 structType = addr.SSAType()
2711 if p, ok := safeUnderlying(structType).(*Pointer); ok {
2712 structType = p.Elem()
2713 }
2714 if p, ok := safeUnderlying(structType).(*Pointer); ok {
2715 ld := &SSAUnOp{Op: OpMul, X: addr}
2716 ld.typ = structType
2717 ld.name = fb.nextName()
2718 fb.emit(ld)
2719 addr = ld
2720 structType = p.Elem()
2721 }
2722 } else if ie, ok := e.X.(*IndexExpr); ok {
2723 x := fb.buildExpr(ie.X)
2724 idx := fb.buildExpr(ie.Index)
2725 if x == nil || idx == nil {
2726 return nil
2727 }
2728 ia := &SSAIndexAddr{X: x, Index: idx}
2729 elemT := ssaElemType(x.SSAType())
2730 ia.typ = NewPointer(elemT)
2731 ia.name = fb.nextName()
2732 fb.emit(ia)
2733 addr = ia
2734 structType = elemT
2735 if _, isPtr := safeUnderlying(elemT).(*Pointer); isPtr {
2736 ld := fb.emitLoad(ia, elemT)
2737 addr = ld
2738 structType = elemT
2739 }
2740 } else {
2741 x := fb.buildExpr(e.X)
2742 if x == nil || x.SSAType() == nil {
2743 if name, ok := e.X.(*Name); ok {
2744 obj := fb.lookupObject(name.Value)
2745 if pn, ok := obj.(*PkgName); ok {
2746 return fb.buildPkgMemberAddr(pn, e.Sel.Value)
2747 }
2748 }
2749 return nil
2750 }
2751 baseType := x.SSAType()
2752 addr = x
2753 if _, ok := safeUnderlying(baseType).(*Pointer); !ok {
2754 if name, ok := e.X.(*Name); ok {
2755 obj := fb.lookupObject(name.Value)
2756 if obj != nil {
2757 if alloc, ok2 := fb.vars[obj]; ok2 {
2758 addr = alloc
2759 baseType = NewPointer(baseType)
2760 } else if fb.freeVarPtrs != nil {
2761 if fv, ok2 := fb.freeVarPtrs[name.Value]; ok2 {
2762 addr = fv
2763 baseType = NewPointer(baseType)
2764 }
2765 }
2766 }
2767 }
2768 }
2769 structType = baseType
2770 if p, ok := safeUnderlying(structType).(*Pointer); ok {
2771 structType = p.Elem()
2772 }
2773 }
2774 fieldIdx := fb.fieldIndex(structType, e.Sel.Value)
2775 if fieldIdx >= 0 {
2776 fa := &SSAFieldAddr{X: addr, Field: fieldIdx}
2777 fa.typ = NewPointer(fb.fieldType(structType, fieldIdx))
2778 fa.name = fb.nextName()
2779 fb.emit(fa)
2780 return fa
2781 }
2782 path := fb.findEmbeddedFieldPath(structType, e.Sel.Value)
2783 if len(path) >= 2 {
2784 cur := addr
2785 curType := structType
2786 for pi, idx := range path {
2787 fa := &SSAFieldAddr{X: cur, Field: idx}
2788 fa.typ = NewPointer(fb.fieldType(curType, idx))
2789 fa.name = fb.nextName()
2790 fb.emit(fa)
2791 curType = fb.fieldType(curType, idx)
2792 if pi < len(path)-1 {
2793 if p, ok := safeUnderlying(curType).(*Pointer); ok {
2794 ld := &SSAUnOp{Op: OpMul, X: fa}
2795 ld.typ = curType
2796 ld.name = fb.nextName()
2797 fb.emit(ld)
2798 cur = ld
2799 curType = p.Elem()
2800 continue
2801 }
2802 }
2803 cur = fa
2804 }
2805 return cur
2806 }
2807 return nil
2808 }
2809
2810 func (fb *ssaFuncBuilder) buildIndex(e *IndexExpr) SSAValue {
2811 x := fb.buildExpr(e.X)
2812 idx := fb.buildExpr(e.Index)
2813 if x == nil || idx == nil {
2814 return nil
2815 }
2816 if x.SSAType() == nil {
2817 return nil
2818 }
2819 switch t := safeUnderlying(x.SSAType()).(type) {
2820 case *TCMap:
2821 idx = fb.coerceToInterface(idx, t.Key())
2822 l := &SSALookup{X: x, Index: idx}
2823 l.typ = t.Elem()
2824 l.name = fb.nextName()
2825 fb.emit(l)
2826 return l
2827 default:
2828 ia := &SSAIndexAddr{X: x, Index: idx}
2829 ia.typ = NewPointer(ssaElemType(x.SSAType()))
2830 ia.name = fb.nextName()
2831 fb.emit(ia)
2832 return fb.emitLoad(ia, ssaElemType(x.SSAType()))
2833 }
2834 }
2835
2836 func (fb *ssaFuncBuilder) buildSlice(e *SliceExpr) SSAValue {
2837 x := fb.buildExpr(e.X)
2838 if x == nil {
2839 return nil
2840 }
2841 sl := &SSASlice{X: x}
2842 if len(e.Index) > 0 && e.Index[0] != nil {
2843 sl.Low = fb.buildExpr(e.Index[0])
2844 }
2845 if len(e.Index) > 1 && e.Index[1] != nil {
2846 sl.High = fb.buildExpr(e.Index[1])
2847 }
2848 if len(e.Index) > 2 && e.Index[2] != nil {
2849 sl.Max = fb.buildExpr(e.Index[2])
2850 }
2851 sl.typ = ssaSliceOf(x.SSAType())
2852 sl.name = fb.nextName()
2853 fb.emit(sl)
2854 return sl
2855 }
2856
2857 func (fb *ssaFuncBuilder) buildAssert(e *AssertExpr) SSAValue {
2858 x := fb.buildExpr(e.X)
2859 assertedType := fb.resolveType(e.Type)
2860 if x == nil {
2861 return nil
2862 }
2863 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: false}
2864 ta.typ = assertedType
2865 ta.name = fb.nextName()
2866 fb.emit(ta)
2867 return ta
2868 }
2869
2870 func (fb *ssaFuncBuilder) buildCompositeLit(e *CompositeLit) SSAValue {
2871 var typ Type
2872 if e.Type != nil {
2873 typ = fb.resolveType(e.Type)
2874 }
2875 if typ == nil {
2876 return nil
2877 }
2878
2879 if sl, ok := safeUnderlying(typ).(*Slice); ok {
2880 return fb.buildSliceLit(e, typ, sl)
2881 }
2882
2883 if mt, isMap := safeUnderlying(typ).(*TCMap); isMap {
2884 mm := &SSAMakeMap{}
2885 mm.typ = typ
2886 mm.name = fb.nextName()
2887 fb.emit(mm)
2888 for _, el := range e.ElemList {
2889 if kv, ok := el.(*KeyValueExpr); ok {
2890 k := fb.buildExpr(kv.Key)
2891 v := fb.buildExpr(kv.Value)
2892 if k != nil && v != nil {
2893 k = fb.coerceToInterface(k, mt.Key())
2894 v = fb.coerceToInterface(v, mt.Elem())
2895 fb.emit(&SSAMapUpdate{Map: mm, Key: k, Value: v})
2896 }
2897 }
2898 }
2899 return mm
2900 }
2901
2902 if ar, isArr := safeUnderlying(typ).(*Array); isArr {
2903 return fb.buildArrayLit(e, typ, ar)
2904 }
2905
2906 alloc := fb.emitAlloc(typ, 0)
2907 posIdx := 0
2908 for _, el := range e.ElemList {
2909 if kv, ok := el.(*KeyValueExpr); ok {
2910 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2911 idx := fb.fieldIndex(typ, kv.Key.(*Name).Value)
2912 if idx >= 0 {
2913 fa := &SSAFieldAddr{X: alloc, Field: idx}
2914 ft := fb.fieldType(typ, idx)
2915 fa.typ = NewPointer(ft)
2916 fa.name = fb.nextName()
2917 fb.emit(fa)
2918 v := fb.buildExpr(kv.Value)
2919 if v != nil {
2920 v = fb.coerceToInterface(v, ft)
2921 fb.emitStore(fa, v)
2922 }
2923 }
2924 }
2925 } else {
2926 v := fb.buildExpr(el)
2927 if v != nil {
2928 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2929 ft := fb.fieldType(typ, posIdx)
2930 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
2931 fa.typ = NewPointer(ft)
2932 fa.name = fb.nextName()
2933 fb.emit(fa)
2934 v = fb.coerceToInterface(v, ft)
2935 fb.emitStore(fa, v)
2936 }
2937 }
2938 posIdx++
2939 }
2940 }
2941 return fb.emitLoad(alloc, typ)
2942 }
2943
2944 func (fb *ssaFuncBuilder) buildArrayLit(e *CompositeLit, typ Type, ar *Array) SSAValue {
2945 if ar.Len() < 0 {
2946 ar = NewArray(ar.Elem(), int32(len(e.ElemList)))
2947 typ = ar
2948 }
2949 alloc := fb.emitAlloc(typ, 0)
2950 elemTyp := ar.Elem()
2951 for i, el := range e.ElemList {
2952 var expr Expr
2953 if kv, ok := el.(*KeyValueExpr); ok {
2954 expr = kv.Value
2955 } else {
2956 expr = el
2957 }
2958 var v SSAValue
2959 if cl, ok := expr.(*CompositeLit); ok && cl.Type == nil {
2960 v = fb.buildCompositeLitWithType(cl, elemTyp)
2961 } else {
2962 v = fb.buildExpr(expr)
2963 }
2964 if v == nil {
2965 continue
2966 }
2967 idx := &SSAConst{typ: Typ[Int32], val: constInt{int32(i)}}
2968 ia := &SSAIndexAddr{X: alloc, Index: idx}
2969 ia.typ = NewPointer(elemTyp)
2970 ia.name = fb.nextName()
2971 fb.emit(ia)
2972 v = fb.coerceToInterface(v, elemTyp)
2973 fb.emitStore(ia, v)
2974 }
2975 return fb.emitLoad(alloc, typ)
2976 }
2977
2978 func (fb *ssaFuncBuilder) buildCompositeLitWithType(e *CompositeLit, typ Type) SSAValue {
2979 if sl, ok := safeUnderlying(typ).(*Slice); ok {
2980 return fb.buildSliceLit(e, typ, sl)
2981 }
2982 if ar, isArr := safeUnderlying(typ).(*Array); isArr {
2983 return fb.buildArrayLit(e, typ, ar)
2984 }
2985 alloc := fb.emitAlloc(typ, 0)
2986 posIdx := 0
2987 for _, el := range e.ElemList {
2988 if kv, ok := el.(*KeyValueExpr); ok {
2989 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
2990 idx := fb.fieldIndex(typ, kv.Key.(*Name).Value)
2991 if idx >= 0 {
2992 ft := fb.fieldType(typ, idx)
2993 fa := &SSAFieldAddr{X: alloc, Field: idx}
2994 fa.typ = NewPointer(ft)
2995 fa.name = fb.nextName()
2996 fb.emit(fa)
2997 v := fb.buildExpr(kv.Value)
2998 if v != nil {
2999 v = fb.coerceToInterface(v, ft)
3000 fb.emitStore(fa, v)
3001 }
3002 }
3003 }
3004 } else {
3005 v := fb.buildExpr(el)
3006 if v != nil {
3007 if _, ok2 := safeUnderlying(typ).(*TCStruct); ok2 {
3008 ft := fb.fieldType(typ, posIdx)
3009 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
3010 fa.typ = NewPointer(ft)
3011 fa.name = fb.nextName()
3012 fb.emit(fa)
3013 v = fb.coerceToInterface(v, ft)
3014 fb.emitStore(fa, v)
3015 }
3016 }
3017 posIdx++
3018 }
3019 }
3020 return fb.emitLoad(alloc, typ)
3021 }
3022
3023 func (fb *ssaFuncBuilder) buildSliceLit(e *CompositeLit, typ Type, sl *Slice) SSAValue {
3024 n := len(e.ElemList)
3025 nVal := &SSAConst{typ: Typ[Int32], val: constInt{int32(n)}}
3026 ms := &SSAMakeSlice{}
3027 ms.typ = typ
3028 ms.name = fb.nextName()
3029 ms.Len = nVal
3030 ms.Cap = nVal
3031 fb.emit(ms)
3032
3033 for i, el := range e.ElemList {
3034 var v SSAValue
3035 if kv, ok := el.(*KeyValueExpr); ok {
3036 v = fb.buildExpr(kv.Value)
3037 } else {
3038 v = fb.buildExpr(el)
3039 }
3040 if v == nil {
3041 continue
3042 }
3043 idx := &SSAConst{typ: Typ[Int32], val: constInt{int32(i)}}
3044 ia := &SSAIndexAddr{X: ms, Index: idx}
3045 ia.typ = NewPointer(sl.Elem())
3046 ia.name = fb.nextName()
3047 fb.emit(ia)
3048 v = fb.coerceToInterface(v, sl.Elem())
3049 fb.emitStore(ia, v)
3050 }
3051 return ms
3052 }
3053
3054 func (fb *ssaFuncBuilder) buildFuncLit(e *FuncLit) SSAValue {
3055 var sig *Signature
3056 if fb.info != nil {
3057 if tv, ok := fb.info.Types[e]; ok {
3058 if okv, okok := tv.Type.(*Signature); okok {
3059 sig = okv
3060 }
3061 }
3062 }
3063 if sig == nil && e.Type != nil {
3064 sig = tcResolveFuncInline(e.Type, fb.fn.Pkg.Pkg.Scope())
3065 }
3066 name := fb.fn.name | "__anon" | ssaItoa(len(fb.fn.AnonFuncs)+1)
3067 anon := &SSAFunction{
3068 name: name,
3069 Signature: sig,
3070 pos: 0,
3071 Pkg: fb.fn.Pkg,
3072 Prog: fb.fn.Prog,
3073 parent: fb.fn,
3074 }
3075 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, anon)
3076
3077 ab := newSSAFuncBuilder(anon, fb.info)
3078 ab.parent = fb
3079 d := &FuncDecl{
3080 Name: &Name{Value: name},
3081 Type: e.Type,
3082 Body: e.Body,
3083 }
3084 ab.buildBody(d)
3085
3086 if len(anon.FreeVars) == 0 {
3087 return anon
3088 }
3089 bindings := []SSAValue{:0:len(anon.FreeVars)}
3090 for _, fv := range anon.FreeVars {
3091 obj := fb.lookupObject(fv.name)
3092 if obj != nil {
3093 if alloc, ok := fb.vars[obj]; ok {
3094 alloc.Heap = true
3095 bindings = append(bindings, alloc)
3096 } else {
3097 bindings = append(bindings, &SSAConst{typ: NewPointer(fv.typ), val: nil})
3098 }
3099 } else {
3100 bindings = append(bindings, &SSAConst{typ: NewPointer(fv.typ), val: nil})
3101 }
3102 }
3103 mc := &SSAMakeClosure{Fn: anon, Bindings: bindings}
3104 mc.typ = sig
3105 mc.name = fb.nextName()
3106 fb.emit(mc)
3107 return mc
3108 }
3109
3110 func (fb *ssaFuncBuilder) saveVars() map[Object]*SSAAlloc {
3111 saved := map[Object]*SSAAlloc{}
3112 for k, v := range fb.vars {
3113 saved[k] = v
3114 }
3115 return saved
3116 }
3117
3118 func (fb *ssaFuncBuilder) removeVar(name string) {
3119 for o := range fb.vars {
3120 if o.Name() == name {
3121 delete(fb.vars, o)
3122 return
3123 }
3124 }
3125 }
3126
3127
3128 func (fb *ssaFuncBuilder) buildPkgMemberAddr(pn *PkgName, memberName string) SSAValue {
3129 imported := pn.Imported()
3130 if imported == nil {
3131 return nil
3132 }
3133 obj := imported.Scope().Lookup(memberName)
3134 if obj == nil {
3135 return nil
3136 }
3137 switch obj := obj.(type) {
3138 case *TCConst:
3139 return nil
3140 case *TCVar:
3141 impPkg := fb.ensureImportedSSAPackage(imported)
3142 g, ok := impPkg.Members[memberName].(*SSAGlobal)
3143 if !ok {
3144 g = &SSAGlobal{
3145 name: memberName,
3146 typ: NewPointer(obj.Type()),
3147 pkg: impPkg,
3148 }
3149 impPkg.Members[memberName] = g
3150 }
3151 return g
3152 }
3153 return nil
3154 }
3155
3156 func (fb *ssaFuncBuilder) buildPkgCall(pn *PkgName, funcName string, argList []Expr, hasDots bool) SSAValue {
3157 imported := pn.Imported()
3158 if imported == nil {
3159 return nil
3160 }
3161 if imported.Path() == "unsafe" && funcName == "Slice" {
3162 return fb.buildUnsafeSlice(argList)
3163 }
3164 if imported.Path() == "unsafe" && funcName == "SliceData" {
3165 arg := fb.buildExpr(argList[0])
3166 extract := &SSAExtract{Tuple: arg, Index: 0}
3167 extract.typ = Typ[UnsafePointer]
3168 extract.name = fb.nextName()
3169 extract.setBlock(fb.currentBlock)
3170 fb.currentBlock.Instrs = append(fb.currentBlock.Instrs, extract)
3171 return extract
3172 }
3173 if result := fb.tryGenericPkgCall(pn, funcName, argList, hasDots); result != nil {
3174 return result
3175 }
3176 obj := imported.Scope().Lookup(funcName)
3177 if obj == nil {
3178 return nil
3179 }
3180 fn, ok := obj.(*TCFunc)
3181 if !ok {
3182 return nil
3183 }
3184 impPkg := fb.ensureImportedSSAPackage(imported)
3185 ssaFn := impPkg.Func(funcName)
3186 if ssaFn == nil {
3187 ssaFn = &SSAFunction{
3188 name: funcName,
3189 object: fn,
3190 Signature: fn.Type().(*Signature),
3191 Pkg: impPkg,
3192 Prog: fb.fn.Prog,
3193 }
3194 if isNoContextExtern(imported.Path(), funcName) {
3195 ssaFn.isExternC = true
3196 }
3197 impPkg.Members[funcName] = ssaFn
3198 }
3199 args := fb.buildArgs(argList)
3200 var retType Type
3201 if ssaFn.Signature != nil {
3202 if ssaFn.Signature.Variadic() && !hasDots {
3203 args = fb.wrapVariadicArgs(args, ssaFn.Signature)
3204 }
3205 args = fb.coerceArgsToInterface(args, ssaFn.Signature)
3206 if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() == 1 {
3207 retType = ssaFn.Signature.Results().At(0).Type()
3208 } else if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() > 1 {
3209 retType = ssaFn.Signature.Results()
3210 }
3211 }
3212 call := &SSACall{Call: SSACallCommon{Value: ssaFn, Args: args}}
3213 call.typ = retType
3214 call.name = fb.nextName()
3215 fb.emit(call)
3216 if retType == nil {
3217 return nil
3218 }
3219 return call
3220 }
3221
3222 func (fb *ssaFuncBuilder) buildUnsafeSlice(argList []Expr) SSAValue {
3223 if len(argList) < 2 {
3224 return nil
3225 }
3226 ptrVal := fb.buildExpr(argList[0])
3227 lenVal := fb.buildExpr(argList[1])
3228 if ptrVal == nil || lenVal == nil {
3229 return nil
3230 }
3231 var elemType Type
3232 if pt, ok := safeUnderlying(ptrVal.SSAType()).(*Pointer); ok {
3233 elemType = pt.Elem()
3234 }
3235 if elemType == nil {
3236 elemType = Typ[Uint8]
3237 }
3238 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal, Data: ptrVal}
3239 if b, ok := elemType.(*Basic); ok && b.kind == Uint8 {
3240 ms.typ = Typ[TCString]
3241 } else {
3242 ms.typ = NewSlice(elemType)
3243 }
3244 ms.name = fb.nextName()
3245 fb.emit(ms)
3246 return ms
3247 }
3248
3249 // Helpers.
3250
3251 func (fb *ssaFuncBuilder) lookupObject(name string) Object {
3252 for obj := range fb.vars {
3253 if obj.Name() == name {
3254 return obj
3255 }
3256 }
3257 if fb.parent != nil {
3258 for obj := range fb.parent.vars {
3259 if obj.Name() == name {
3260 return obj
3261 }
3262 }
3263 }
3264 if fb.fn.Pkg != nil {
3265 if _, obj := fb.fn.Pkg.Pkg.Scope().LookupParent(name); obj != nil {
3266 return obj
3267 }
3268 }
3269 if fb.srcScope != nil {
3270 if _, obj := fb.srcScope.LookupParent(name); obj != nil {
3271 return obj
3272 }
3273 }
3274 if fb.info != nil {
3275 return nil
3276 }
3277 return nil
3278 }
3279
3280 func (fb *ssaFuncBuilder) getOrCreateFreeVar(name string, typ Type) SSAValue {
3281 for _, fv := range fb.fn.FreeVars {
3282 if fv.name == name {
3283 return fv
3284 }
3285 }
3286 fv := &SSAFreeVar{
3287 name: name,
3288 typ: typ,
3289 parent: fb.fn,
3290 }
3291 fb.fn.FreeVars = append(fb.fn.FreeVars, fv)
3292 if fb.freeVarPtrs == nil {
3293 fb.freeVarPtrs = map[string]*SSAFreeVar{}
3294 }
3295 fb.freeVarPtrs[name] = fv
3296 return fv
3297 }
3298
3299 func (fb *ssaFuncBuilder) lookupVar(name string) *TCVar {
3300 obj := fb.lookupObject(name)
3301 var v *TCVar
3302 if okv, okok := obj.(*TCVar); okok {
3303 v = okv
3304 }
3305 return v
3306 }
3307
3308 func (fb *ssaFuncBuilder) resolveMethodCallWithRecv(sel *SelectorExpr, recv SSAValue) (*SSAFunction, SSAValue) {
3309 typ := recv.SSAType()
3310 isPtr := false
3311 if p, ok := safeUnderlying(typ).(*Pointer); ok {
3312 typ = p.Elem()
3313 isPtr = true
3314 }
3315 if _, ok := safeUnderlying(typ).(*TCInterface); ok {
3316 return nil, nil
3317 }
3318 named, ok := typ.(*Named)
3319 if !ok {
3320 return nil, nil
3321 }
3322 typeName := ""
3323 if named.Obj() != nil {
3324 typeName = named.Obj().Name()
3325 }
3326 if typeName == "" {
3327 return nil, nil
3328 }
3329 mangledName := typeName | "." | sel.Sel.Value
3330 var fn *SSAFunction
3331 if okv, okok := fb.fn.Pkg.Members[mangledName].(*SSAFunction); okok {
3332 fn = okv
3333 }
3334 if fn == nil {
3335 for i := 0; i < named.NumMethods(); i++ {
3336 m := named.Method(i)
3337 if m.Name() == sel.Sel.Value {
3338 fn = fb.fn.Pkg.ExternalFunc(mangledName, m.Signature())
3339 if named.Obj() != nil && named.Obj().Pkg() != nil && named.Obj().Pkg().Path() != fb.fn.Pkg.Pkg.Path() {
3340 pkgPath := named.Obj().Pkg().Path()
3341 fn.externalSymbol = pkgPath | "." | typeName | "." | sel.Sel.Value
3342 }
3343 break
3344 }
3345 }
3346 }
3347 if fn != nil {
3348 if fn.Signature != nil && fn.Signature.Recv() != nil {
3349 recvParam := fn.Signature.Recv()
3350 _, recvIsPtr := safeUnderlying(recvParam.Type()).(*Pointer)
3351 if recvIsPtr && !isPtr {
3352 if nameExpr, ok2 := sel.X.(*Name); ok2 {
3353 obj := fb.lookupObject(nameExpr.Value)
3354 if obj != nil {
3355 if alloc, ok3 := fb.vars[obj]; ok3 {
3356 recv = alloc
3357 }
3358 }
3359 } else if innerSel, ok2 := sel.X.(*SelectorExpr); ok2 {
3360 addr := fb.buildSelectorAddr(innerSel)
3361 if addr != nil {
3362 recv = addr
3363 }
3364 }
3365 }
3366 }
3367 return fn, recv
3368 }
3369 st, ok2 := safeUnderlying(named).(*TCStruct)
3370 if !ok2 {
3371 return nil, nil
3372 }
3373 if !isPtr {
3374 fixed := false
3375 if innerSel, ok3 := sel.X.(*SelectorExpr); ok3 {
3376 addr := fb.buildSelectorAddr(innerSel)
3377 if addr != nil {
3378 recv = addr
3379 fixed = true
3380 }
3381 }
3382 if !fixed {
3383 if nameExpr, ok3 := sel.X.(*Name); ok3 {
3384 obj := fb.lookupObject(nameExpr.Value)
3385 if obj != nil {
3386 if a, ok4 := fb.vars[obj]; ok4 {
3387 recv = a
3388 fixed = true
3389 }
3390 }
3391 }
3392 }
3393 if !fixed {
3394 alloc := &SSAAlloc{}
3395 alloc.typ = NewPointer(recv.SSAType())
3396 alloc.name = fb.nextName()
3397 fb.emit(alloc)
3398 storeOp := &SSAStore{Addr: alloc, Val: recv}
3399 fb.emit(storeOp)
3400 recv = alloc
3401 }
3402 }
3403 for i := 0; i < st.NumFields(); i++ {
3404 f := st.Field(i)
3405 if !f.Anonymous() {
3406 continue
3407 }
3408 embedType := f.Type()
3409 embedNamed, ok3 := embedType.(*Named)
3410 if !ok3 {
3411 if p, ok4 := embedType.(*Pointer); ok4 {
3412 embedNamed, ok3 = p.Elem().(*Named)
3413 }
3414 }
3415 if !ok3 || embedNamed.Obj() == nil {
3416 continue
3417 }
3418 embedName := embedNamed.Obj().Name()
3419 embedMangledName := embedName | "." | sel.Sel.Value
3420 var embedFn *SSAFunction
3421 if okv, okok := fb.fn.Pkg.Members[embedMangledName].(*SSAFunction); okok {
3422 embedFn = okv
3423 }
3424 if embedFn != nil {
3425 fieldAddr := &SSAFieldAddr{
3426 X: recv,
3427 Field: i,
3428 }
3429 fieldAddr.typ = NewPointer(embedType)
3430 fieldAddr.name = fb.nextName()
3431 fb.emit(fieldAddr)
3432 var embedRecv SSAValue = fieldAddr
3433 if _, isEmbedPtr := safeUnderlying(embedType).(*Pointer); isEmbedPtr {
3434 ld := &SSAUnOp{Op: OpMul, X: fieldAddr}
3435 ld.typ = embedType
3436 ld.name = fb.nextName()
3437 fb.emit(ld)
3438 embedRecv = ld
3439 }
3440 return embedFn, embedRecv
3441 }
3442 embedSt, ok5 := safeUnderlying(embedNamed).(*TCStruct)
3443 if !ok5 {
3444 continue
3445 }
3446 for j := 0; j < embedSt.NumFields(); j++ {
3447 f2 := embedSt.Field(j)
3448 if !f2.Anonymous() {
3449 continue
3450 }
3451 embed2Type := f2.Type()
3452 embed2Named, ok6 := embed2Type.(*Named)
3453 if !ok6 {
3454 if p2, ok7 := embed2Type.(*Pointer); ok7 {
3455 embed2Named, ok6 = p2.Elem().(*Named)
3456 }
3457 }
3458 if !ok6 || embed2Named.Obj() == nil {
3459 continue
3460 }
3461 embed2Name := embed2Named.Obj().Name()
3462 embed2Mangled := embed2Name | "." | sel.Sel.Value
3463 var embed2Fn *SSAFunction
3464 if okv, okok := fb.fn.Pkg.Members[embed2Mangled].(*SSAFunction); okok {
3465 embed2Fn = okv
3466 }
3467 if embed2Fn == nil {
3468 continue
3469 }
3470 fieldAddr1 := &SSAFieldAddr{X: recv, Field: i}
3471 fieldAddr1.typ = NewPointer(embedType)
3472 fieldAddr1.name = fb.nextName()
3473 fb.emit(fieldAddr1)
3474 var cur1 SSAValue = fieldAddr1
3475 curEmbedType := embedType
3476 if p5, ok8 := safeUnderlying(embedType).(*Pointer); ok8 {
3477 ld := &SSAUnOp{Op: OpMul, X: fieldAddr1}
3478 ld.typ = embedType
3479 ld.name = fb.nextName()
3480 fb.emit(ld)
3481 cur1 = ld
3482 curEmbedType = p5.Elem()
3483 }
3484 _ = curEmbedType
3485 fieldAddr2 := &SSAFieldAddr{X: cur1, Field: j}
3486 fieldAddr2.typ = NewPointer(embed2Type)
3487 fieldAddr2.name = fb.nextName()
3488 fb.emit(fieldAddr2)
3489 var embedRecv2 SSAValue = fieldAddr2
3490 if _, isEmbedPtr2 := safeUnderlying(embed2Type).(*Pointer); isEmbedPtr2 {
3491 ld2 := &SSAUnOp{Op: OpMul, X: fieldAddr2}
3492 ld2.typ = embed2Type
3493 ld2.name = fb.nextName()
3494 fb.emit(ld2)
3495 embedRecv2 = ld2
3496 }
3497 return embed2Fn, embedRecv2
3498 }
3499 }
3500 return nil, nil
3501 }
3502
3503 func (fb *ssaFuncBuilder) buildIfaceMethodCall(sel *SelectorExpr, recv SSAValue, argExprs []Expr) SSAValue {
3504 typ := recv.SSAType()
3505 if p, ok := safeUnderlying(typ).(*Pointer); ok {
3506 typ = p.Elem()
3507 }
3508 iface, ok := safeUnderlying(typ).(*TCInterface)
3509 if !ok {
3510 return nil
3511 }
3512 var methodSig *Signature
3513 for i := 0; i < iface.NumMethods(); i++ {
3514 if iface.Method(i).Name() == sel.Sel.Value {
3515 methodSig = iface.Method(i).Sig()
3516 break
3517 }
3518 }
3519 var retType Type
3520 if methodSig != nil && methodSig.Results() != nil {
3521 if methodSig.Results().Len() == 1 {
3522 retType = methodSig.Results().At(0).Type()
3523 } else if methodSig.Results().Len() > 1 {
3524 retType = methodSig.Results()
3525 }
3526 }
3527 args := fb.buildArgs(argExprs)
3528 inv := &SSAInvoke{
3529 X: recv,
3530 MethodName: sel.Sel.Value,
3531 IfaceType: iface,
3532 Args: args,
3533 }
3534 inv.typ = retType
3535 inv.name = fb.nextName()
3536 fb.emit(inv)
3537 if retType == nil {
3538 return nil
3539 }
3540 return inv
3541 }
3542
3543 func (fb *ssaFuncBuilder) resolveType(e Expr) Type {
3544 if fb.info != nil {
3545 if tv, ok := fb.info.Types[e]; ok && tv.Type != nil {
3546 return tv.Type
3547 }
3548 }
3549 return fb.resolveTypeAST(e)
3550 }
3551
3552 func (fb *ssaFuncBuilder) resolveTypeAST(e Expr) Type {
3553 if e == nil {
3554 return nil
3555 }
3556 switch e := e.(type) {
3557 case *Name:
3558 if fb.typeSubst != nil {
3559 if t, ok := fb.typeSubst[e.Value]; ok {
3560 return t
3561 }
3562 }
3563 if t, ok := fb.localTypes[e.Value]; ok {
3564 return t
3565 }
3566 obj := fb.lookupObject(e.Value)
3567 if tn, ok := obj.(*TypeName); ok {
3568 if tp, ok2 := tn.Type().(*TypeParam); ok2 && fb.typeSubst != nil {
3569 if t, ok3 := fb.typeSubst[tp.String()]; ok3 {
3570 return t
3571 }
3572 }
3573 return tn.Type()
3574 }
3575 case *Operation:
3576 if e.Y == nil && e.Op == Mul {
3577 base := fb.resolveTypeAST(e.X)
3578 if base != nil {
3579 return NewPointer(base)
3580 }
3581 }
3582 case *SliceType:
3583 elem := fb.resolveTypeAST(e.Elem)
3584 if elem != nil {
3585 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
3586 return Typ[TCString]
3587 }
3588 return NewSlice(elem)
3589 }
3590 case *ArrayType:
3591 elem := fb.resolveTypeAST(e.Elem)
3592 if elem != nil {
3593 n := int32(-1)
3594 if lit, ok := e.Len.(*BasicLit); ok {
3595 n = ssaParseInt64(lit.Value)
3596 }
3597 return NewArray(elem, n)
3598 }
3599 case *MapType:
3600 key := fb.resolveTypeAST(e.Key)
3601 val := fb.resolveTypeAST(e.Value)
3602 if key != nil && val != nil {
3603 return NewTCMap(key, val)
3604 }
3605 case *StructType:
3606 return fb.resolveStructTypeAST(e)
3607 case *InterfaceType:
3608 return fb.resolveInterfaceTypeAST(e)
3609 case *FuncType:
3610 return fb.resolveFuncTypeAST(e)
3611 case *SelectorExpr:
3612 if x, ok := e.X.(*Name); ok {
3613 obj := fb.lookupObject(x.Value)
3614 if pn, ok2 := obj.(*PkgName); ok2 && pn.Imported() != nil {
3615 sel := pn.Imported().Scope().Lookup(e.Sel.Value)
3616 if tn, ok3 := sel.(*TypeName); ok3 {
3617 return tn.Type()
3618 }
3619 }
3620 }
3621 case *ParenExpr:
3622 return fb.resolveTypeAST(e.X)
3623 }
3624 return nil
3625 }
3626
3627 func (fb *ssaFuncBuilder) resolveInterfaceTypeAST(e *InterfaceType) *TCInterface {
3628 var methods []*IfaceMethod
3629 for _, f := range e.MethodList {
3630 if f.Name == nil {
3631 continue
3632 }
3633 ft, ok := f.Type.(*FuncType)
3634 if !ok {
3635 continue
3636 }
3637 sig := fb.resolveFuncTypeAST(ft)
3638 if sig != nil {
3639 methods = append(methods, NewTCIfaceMethod(f.Name.Value, sig))
3640 }
3641 }
3642 iface := NewTCInterface(methods, nil)
3643 iface.Complete()
3644 return iface
3645 }
3646
3647 func (fb *ssaFuncBuilder) resolveStructTypeAST(e *StructType) *TCStruct {
3648 var fields []*TCVar
3649 var tags []string
3650 for i, f := range e.FieldList {
3651 typ := fb.resolveTypeAST(f.Type)
3652 if typ == nil {
3653 return nil
3654 }
3655 name := ""
3656 if f.Name != nil {
3657 name = f.Name.Value
3658 }
3659 fields = append(fields, NewTCField(fb.fn.Pkg.Pkg, name, typ, f.Name == nil))
3660 tag := ""
3661 if i < len(e.TagList) && e.TagList[i] != nil {
3662 tag = e.TagList[i].Value
3663 }
3664 tags = append(tags, tag)
3665 }
3666 return NewTCStruct(fields, tags)
3667 }
3668
3669 func (fb *ssaFuncBuilder) resolveFuncTypeAST(ft *FuncType) *Signature {
3670 if ft == nil {
3671 return nil
3672 }
3673 var params []*TCVar
3674 for _, p := range ft.ParamList {
3675 typ := fb.resolveTypeAST(p.Type)
3676 pname := ""
3677 if p.Name != nil {
3678 pname = p.Name.Value
3679 }
3680 params = append(params, NewTCVar(nil, pname, typ))
3681 }
3682 var results []*TCVar
3683 for _, r := range ft.ResultList {
3684 typ := fb.resolveTypeAST(r.Type)
3685 rname := ""
3686 if r.Name != nil {
3687 rname = r.Name.Value
3688 }
3689 results = append(results, NewTCVar(nil, rname, typ))
3690 }
3691 var pTuple, rTuple *Tuple
3692 if len(params) > 0 {
3693 pTuple = NewTuple(params...)
3694 }
3695 if len(results) > 0 {
3696 rTuple = NewTuple(results...)
3697 }
3698 return NewSignature(nil, pTuple, rTuple, false)
3699 }
3700
3701 func (fb *ssaFuncBuilder) fieldIndex(t Type, name string) int32 {
3702 if t == nil {
3703 return -1
3704 }
3705 if pt, ok := safeUnderlying(t).(*Pointer); ok {
3706 t = pt.Elem()
3707 }
3708 if st, ok := safeUnderlying(t).(*TCStruct); ok {
3709 for i := 0; i < st.NumFields(); i++ {
3710 if st.Field(i).Name() == name {
3711 return i
3712 }
3713 }
3714 }
3715 return -1
3716 }
3717
3718 func (fb *ssaFuncBuilder) findEmbeddedField(t Type, name string) (embedIdx int32, innerIdx int32) {
3719 path := fb.findEmbeddedFieldPath(t, name)
3720 if len(path) < 2 {
3721 return -1, -1
3722 }
3723 return path[0], path[1]
3724 }
3725
3726 func (fb *ssaFuncBuilder) findEmbeddedFieldPath(t Type, name string) []int32 {
3727 if t == nil {
3728 return nil
3729 }
3730 if pt, ok := safeUnderlying(t).(*Pointer); ok {
3731 t = pt.Elem()
3732 }
3733 st, ok := safeUnderlying(t).(*TCStruct)
3734 if !ok {
3735 return nil
3736 }
3737 for i := 0; i < st.NumFields(); i++ {
3738 f := st.Field(i)
3739 if !f.Anonymous() {
3740 continue
3741 }
3742 embedType := f.Type()
3743 if pt, ok := safeUnderlying(embedType).(*Pointer); ok {
3744 embedType = pt.Elem()
3745 }
3746 inner := fb.fieldIndex(embedType, name)
3747 if inner >= 0 {
3748 return []int32{i, inner}
3749 }
3750 sub := fb.findEmbeddedFieldPath(embedType, name)
3751 if len(sub) > 0 {
3752 return append([]int32{i}, sub...)
3753 }
3754 }
3755 return nil
3756 }
3757
3758 func (fb *ssaFuncBuilder) fieldType(t Type, idx int32) Type {
3759 if t == nil {
3760 return nil
3761 }
3762 if pt, ok := safeUnderlying(t).(*Pointer); ok {
3763 t = pt.Elem()
3764 }
3765 if st, ok := safeUnderlying(t).(*TCStruct); ok {
3766 if idx >= 0 && idx < st.NumFields() {
3767 return st.Field(idx).Type()
3768 }
3769 }
3770 return nil
3771 }
3772
3773 func ssaExprNames(e Expr) []*Name {
3774 if e == nil {
3775 return nil
3776 }
3777 if n, ok := e.(*Name); ok {
3778 return []*Name{n}
3779 }
3780 if l, ok := e.(*ListExpr); ok {
3781 var names []*Name
3782 for _, el := range l.ElemList {
3783 if n, ok := el.(*Name); ok {
3784 names = append(names, n)
3785 }
3786 }
3787 return names
3788 }
3789 return nil
3790 }
3791
3792 func localizeConstVal(val ConstVal, typ Type) ConstVal {
3793 if val == nil {
3794 return nil
3795 }
3796 return val
3797 }
3798
3799 func mangleGenericName(baseName string, typeArgs []Type) string {
3800 s := baseName | "__"
3801 for i, t := range typeArgs {
3802 if i > 0 {
3803 s = s | "_"
3804 }
3805 if t == nil {
3806 s = s | "nil"
3807 } else {
3808 ts := t.String()
3809 for j := 0; j < len(ts); j++ {
3810 c := ts[j]
3811 if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') {
3812 s = s | string([]byte{c})
3813 } else if c == '.' {
3814 s = s | "."
3815 } else {
3816 s = s | "_"
3817 }
3818 }
3819 }
3820 }
3821 return s
3822 }
3823
3824 func resolveTypeExprWithSubst(e Expr, typeSubst map[string]Type, pkgScope *Scope) Type {
3825 if e == nil {
3826 return nil
3827 }
3828 switch e := e.(type) {
3829 case *Name:
3830 if t, ok := typeSubst[e.Value]; ok {
3831 return t
3832 }
3833 _, obj := Universe.LookupParent(e.Value)
3834 if obj != nil {
3835 if tn, ok := obj.(*TypeName); ok {
3836 return tn.typ
3837 }
3838 }
3839 if pkgScope != nil {
3840 tobj := pkgScope.Lookup(e.Value)
3841 if tobj != nil {
3842 if tn, ok := tobj.(*TypeName); ok {
3843 return tn.typ
3844 }
3845 }
3846 }
3847 if importRegistry != nil {
3848 var regKeys []string
3849 for k := range importRegistry {
3850 regKeys = append(regKeys, k)
3851 }
3852 for i := 1; i < len(regKeys); i++ {
3853 for j := i; j > 0 && regKeys[j] < regKeys[j-1]; j-- {
3854 regKeys[j], regKeys[j-1] = regKeys[j-1], regKeys[j]
3855 }
3856 }
3857 for _, k := range regKeys {
3858 pkg := importRegistry[k]
3859 tobj := pkg.Scope().Lookup(e.Value)
3860 if tobj != nil {
3861 if tn, ok := tobj.(*TypeName); ok {
3862 return tn.typ
3863 }
3864 }
3865 }
3866 }
3867 return nil
3868 case *DotsType:
3869 elem := resolveTypeExprWithSubst(e.Elem, typeSubst, pkgScope)
3870 if elem != nil {
3871 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
3872 return Typ[TCString]
3873 }
3874 return NewSlice(elem)
3875 }
3876 case *SliceType:
3877 elem := resolveTypeExprWithSubst(e.Elem, typeSubst, pkgScope)
3878 if elem != nil {
3879 if b, ok := elem.(*Basic); ok && b.kind == Uint8 {
3880 return Typ[TCString]
3881 }
3882 return NewSlice(elem)
3883 }
3884 case *Operation:
3885 if e.Y == nil && e.Op == Mul {
3886 base := resolveTypeExprWithSubst(e.X, typeSubst, pkgScope)
3887 if base != nil {
3888 return NewPointer(base)
3889 }
3890 }
3891 case *MapType:
3892 key := resolveTypeExprWithSubst(e.Key, typeSubst, pkgScope)
3893 val := resolveTypeExprWithSubst(e.Value, typeSubst, pkgScope)
3894 if key != nil && val != nil {
3895 return NewTCMap(key, val)
3896 }
3897 case *FuncType:
3898 return resolveSignatureWithSubst(e, typeSubst, pkgScope)
3899 case *SelectorExpr:
3900 if pkgName, ok := e.X.(*Name); ok {
3901 if importRegistry != nil {
3902 var regKeys []string
3903 for k := range importRegistry {
3904 regKeys = append(regKeys, k)
3905 }
3906 for i := 1; i < len(regKeys); i++ {
3907 for j := i; j > 0 && regKeys[j] < regKeys[j-1]; j-- {
3908 regKeys[j], regKeys[j-1] = regKeys[j-1], regKeys[j]
3909 }
3910 }
3911 for _, k := range regKeys {
3912 pkg := importRegistry[k]
3913 if pkg.Name() == pkgName.Value {
3914 typeObj := pkg.Scope().Lookup(e.Sel.Value)
3915 if typeObj != nil {
3916 if tn, ok2 := typeObj.(*TypeName); ok2 {
3917 return tn.typ
3918 }
3919 }
3920 break
3921 }
3922 }
3923 }
3924 }
3925 }
3926 return nil
3927 }
3928
3929 func resolveSignatureWithSubst(ft *FuncType, typeSubst map[string]Type, pkgScope *Scope) *Signature {
3930 if ft == nil {
3931 return nil
3932 }
3933 var params []*TCVar
3934 variadic := false
3935 for _, p := range ft.ParamList {
3936 typ := resolveTypeExprWithSubst(p.Type, typeSubst, pkgScope)
3937 name := ""
3938 if p.Name != nil {
3939 name = p.Name.Value
3940 }
3941 params = append(params, NewTCVar(nil, name, typ))
3942 }
3943 if len(ft.ParamList) > 0 {
3944 last := ft.ParamList[len(ft.ParamList)-1]
3945 if _, ok := last.Type.(*DotsType); ok {
3946 variadic = true
3947 }
3948 }
3949 var results []*TCVar
3950 for _, r := range ft.ResultList {
3951 typ := resolveTypeExprWithSubst(r.Type, typeSubst, pkgScope)
3952 name := ""
3953 if r.Name != nil {
3954 name = r.Name.Value
3955 }
3956 results = append(results, NewTCVar(nil, name, typ))
3957 }
3958 var paramTuple *Tuple
3959 if len(params) > 0 {
3960 paramTuple = NewTuple(params...)
3961 }
3962 var resultTuple *Tuple
3963 if len(results) > 0 {
3964 resultTuple = NewTuple(results...)
3965 }
3966 return NewSignature(nil, paramTuple, resultTuple, variadic)
3967 }
3968
3969 func matchTypeParam(paramType Expr, argType Type, tparams []*Field, typeMap map[string]Type) {
3970 if paramType == nil || argType == nil {
3971 return
3972 }
3973 switch pt := paramType.(type) {
3974 case *Name:
3975 for _, tp := range tparams {
3976 if tp.Name != nil && tp.Name.Value == pt.Value {
3977 typeMap[pt.Value] = argType
3978 return
3979 }
3980 }
3981 case *DotsType:
3982 if sl, ok := safeUnderlying(argType).(*Slice); ok {
3983 matchTypeParam(pt.Elem, sl.Elem(), tparams, typeMap)
3984 } else {
3985 matchTypeParam(pt.Elem, argType, tparams, typeMap)
3986 }
3987 case *SliceType:
3988 if sl, ok := safeUnderlying(argType).(*Slice); ok {
3989 matchTypeParam(pt.Elem, sl.Elem(), tparams, typeMap)
3990 }
3991 }
3992 }
3993
3994 func inferFromConstraints(tparams []*Field, typeMap map[string]Type) {
3995 for _, tp := range tparams {
3996 if tp.Name == nil || tp.Type == nil {
3997 continue
3998 }
3999 knownType, ok := typeMap[tp.Name.Value]
4000 if !ok {
4001 continue
4002 }
4003 extractConstraintTypeParams(tp.Type, knownType, tparams, typeMap)
4004 }
4005 }
4006
4007 func extractConstraintTypeParams(constraint Expr, concreteType Type, tparams []*Field, typeMap map[string]Type) {
4008 if constraint == nil || concreteType == nil {
4009 return
4010 }
4011 switch c := constraint.(type) {
4012 case *Operation:
4013 if c.Op == Tilde && c.Y == nil {
4014 extractConstraintTypeParams(c.X, concreteType, tparams, typeMap)
4015 }
4016 case *SliceType:
4017 if sl, ok := safeUnderlying(concreteType).(*Slice); ok {
4018 if name, ok2 := c.Elem.(*Name); ok2 {
4019 for _, tp := range tparams {
4020 if tp.Name != nil && tp.Name.Value == name.Value {
4021 if _, already := typeMap[name.Value]; !already {
4022 typeMap[name.Value] = sl.Elem()
4023 }
4024 }
4025 }
4026 }
4027 }
4028 }
4029 }
4030
4031 func inferTypeArgsFromFunc(fd *FuncDecl, args []SSAValue) []Type {
4032 typeMap := map[string]Type{}
4033 if fd.Type != nil {
4034 for i, param := range fd.Type.ParamList {
4035 if i >= len(args) || args[i] == nil || args[i].SSAType() == nil {
4036 continue
4037 }
4038 matchTypeParam(param.Type, args[i].SSAType(), fd.TParamList, typeMap)
4039 }
4040 }
4041 inferFromConstraints(fd.TParamList, typeMap)
4042 var result []Type
4043 for _, tp := range fd.TParamList {
4044 if tp.Name != nil {
4045 result = append(result, typeMap[tp.Name.Value])
4046 }
4047 }
4048 return result
4049 }
4050
4051 func (fb *ssaFuncBuilder) monomorphizeAndCall(fd *FuncDecl, baseName string, typeArgs []Type, args []SSAValue, targetPkg *SSAPackage, srcPkgPath string, hasDots bool) SSAValue {
4052 mangledName := mangleGenericName(baseName, typeArgs)
4053 if fn, ok := targetPkg.Members[mangledName].(*SSAFunction); ok {
4054 return fb.emitCallToSSAFunc(fn, args, hasDots)
4055 }
4056 typeSubst := map[string]Type{}
4057 for i, tp := range fd.TParamList {
4058 if tp.Name != nil && i < len(typeArgs) && typeArgs[i] != nil {
4059 typeSubst[tp.Name.Value] = typeArgs[i]
4060 }
4061 }
4062 var srcScope *Scope
4063 if genericPkgScopes != nil {
4064 if sc, ok := genericPkgScopes[srcPkgPath]; ok {
4065 srcScope = sc
4066 }
4067 }
4068 sig := resolveSignatureWithSubst(fd.Type, typeSubst, srcScope)
4069 if sig == nil {
4070 return nil
4071 }
4072 fn := &SSAFunction{
4073 name: mangledName,
4074 Signature: sig,
4075 Pkg: targetPkg,
4076 Prog: fb.fn.Prog,
4077 }
4078 targetPkg.Members[mangledName] = fn
4079 subFb := newSSAFuncBuilder(fn, fb.info)
4080 subFb.typeSubst = typeSubst
4081 subFb.srcScope = srcScope
4082 subFb.buildBody(fd)
4083 return fb.emitCallToSSAFunc(fn, args, hasDots)
4084 }
4085
4086 func (fb *ssaFuncBuilder) emitCallToSSAFunc(fn *SSAFunction, args []SSAValue, hasDots bool) SSAValue {
4087 if fn.Signature != nil {
4088 if fn.Signature.Variadic() && !hasDots {
4089 args = fb.wrapVariadicArgs(args, fn.Signature)
4090 }
4091 args = fb.coerceArgsToInterface(args, fn.Signature)
4092 }
4093 var retType Type
4094 if fn.Signature != nil && fn.Signature.Results() != nil {
4095 if fn.Signature.Results().Len() == 1 {
4096 retType = fn.Signature.Results().At(0).Type()
4097 } else if fn.Signature.Results().Len() > 1 {
4098 retType = fn.Signature.Results()
4099 }
4100 }
4101 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
4102 call.typ = retType
4103 call.name = fb.nextName()
4104 fb.emit(call)
4105 if retType == nil {
4106 return nil
4107 }
4108 return call
4109 }
4110
4111 func (fb *ssaFuncBuilder) tryGenericLocalCall(funcName string, argList []Expr, hasDots bool) SSAValue {
4112 pkgPath := fb.fn.Pkg.Pkg.Path()
4113 key := pkgPath + "." + funcName
4114 fd, ok := genericFuncDecls[key]
4115 if !ok {
4116 if fb.srcScope != nil && genericPkgScopes != nil {
4117 for gPkg, gScope := range genericPkgScopes {
4118 if gScope == fb.srcScope {
4119 key = gPkg + "." + funcName
4120 fd, ok = genericFuncDecls[key]
4121 if ok {
4122 pkgPath = gPkg
4123 break
4124 }
4125 }
4126 }
4127 }
4128 if !ok {
4129 return nil
4130 }
4131 }
4132 args := fb.buildArgs(argList)
4133 typeArgs := inferTypeArgsFromFunc(fd, args)
4134 return fb.monomorphizeAndCall(fd, funcName, typeArgs, args, fb.fn.Pkg, pkgPath, hasDots)
4135 }
4136
4137 func (fb *ssaFuncBuilder) tryGenericPkgCall(pn *PkgName, funcName string, argList []Expr, hasDots bool) SSAValue {
4138 imported := pn.Imported()
4139 if imported == nil {
4140 return nil
4141 }
4142 key := imported.Path() + "." + funcName
4143 fd, ok := genericFuncDecls[key]
4144 if !ok {
4145 return nil
4146 }
4147 args := fb.buildArgs(argList)
4148 typeArgs := inferTypeArgsFromFunc(fd, args)
4149 return fb.monomorphizeAndCall(fd, funcName, typeArgs, args, fb.fn.Pkg, imported.Path(), hasDots)
4150 }
4151
4152 func (fb *ssaFuncBuilder) tryGenericCallFromIndex(ie *IndexExpr, argList []Expr, hasDots bool) SSAValue {
4153 switch x := ie.X.(type) {
4154 case *Name:
4155 pkgPath := fb.fn.Pkg.Pkg.Path()
4156 key := pkgPath + "." + x.Value
4157 fd, ok := genericFuncDecls[key]
4158 if !ok {
4159 if fb.srcScope != nil && genericPkgScopes != nil {
4160 for gPkg, gScope := range genericPkgScopes {
4161 if gScope == fb.srcScope {
4162 key = gPkg + "." + x.Value
4163 fd, ok = genericFuncDecls[key]
4164 if ok {
4165 pkgPath = gPkg
4166 break
4167 }
4168 }
4169 }
4170 }
4171 if !ok {
4172 return nil
4173 }
4174 }
4175 typeArgs := fb.resolveExplicitTypeArgs(ie.Index, fd)
4176 args := fb.buildArgs(argList)
4177 return fb.monomorphizeAndCall(fd, x.Value, typeArgs, args, fb.fn.Pkg, pkgPath, hasDots)
4178 case *SelectorExpr:
4179 if pkgName, ok2 := x.X.(*Name); ok2 {
4180 obj := fb.lookupObject(pkgName.Value)
4181 if pn, ok3 := obj.(*PkgName); ok3 && pn.Imported() != nil {
4182 key := pn.Imported().Path() + "." + x.Sel.Value
4183 fd, ok4 := genericFuncDecls[key]
4184 if !ok4 {
4185 return nil
4186 }
4187 typeArgs := fb.resolveExplicitTypeArgs(ie.Index, fd)
4188 args := fb.buildArgs(argList)
4189 return fb.monomorphizeAndCall(fd, x.Sel.Value, typeArgs, args, fb.fn.Pkg, pn.Imported().Path(), hasDots)
4190 }
4191 }
4192 }
4193 return nil
4194 }
4195
4196 func (fb *ssaFuncBuilder) resolveExplicitTypeArgs(indexExpr Expr, fd *FuncDecl) []Type {
4197 var typeExprs []Expr
4198 if le, ok := indexExpr.(*ListExpr); ok {
4199 typeExprs = le.ElemList
4200 } else {
4201 typeExprs = []Expr{indexExpr}
4202 }
4203 var result []Type
4204 for _, te := range typeExprs {
4205 t := fb.resolveTypeAST(te)
4206 result = append(result, t)
4207 }
4208 if len(result) < len(fd.TParamList) {
4209 typeMap := map[string]Type{}
4210 for i, tp := range fd.TParamList {
4211 if tp.Name != nil && i < len(result) && result[i] != nil {
4212 typeMap[tp.Name.Value] = result[i]
4213 }
4214 }
4215 inferFromConstraints(fd.TParamList, typeMap)
4216 result = nil
4217 for _, tp := range fd.TParamList {
4218 if tp.Name != nil {
4219 result = append(result, typeMap[tp.Name.Value])
4220 }
4221 }
4222 }
4223 return result
4224 }
4225