ssa_builder.mx raw

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