ssa_builder.mx raw

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