ssa_builder.mx raw

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