ssa_expr.mx raw

   1  package ssa
   2  
   3  import (
   4  	"git.smesh.lol/moxie/pkg/token"
   5  	"git.smesh.lol/moxie/pkg/syntax"
   6  	"git.smesh.lol/moxie/pkg/types"
   7  )
   8  
   9  func (fb *ssaFuncBuilder) buildExpr(e syntax.Expr) (s SSAValue) {
  10  	if e == nil || fb.currentBlock == nil {
  11  		return nil
  12  	}
  13  	switch e := e.(type) {
  14  	case *syntax.Name:
  15  		return fb.buildIdent(e)
  16  	case *syntax.BasicLit:
  17  		return fb.buildLit(e)
  18  	case *syntax.Operation:
  19  		return fb.buildOperation(e)
  20  	case *syntax.CallExpr:
  21  		return fb.buildCall(e)
  22  	case *syntax.SelectorExpr:
  23  		return fb.buildSelector(e)
  24  	case *syntax.IndexExpr:
  25  		return fb.buildIndex(e)
  26  	case *syntax.SliceExpr:
  27  		return fb.buildSlice(e)
  28  	case *syntax.AssertExpr:
  29  		return fb.buildAssert(e)
  30  	case *syntax.CompositeLit:
  31  		return fb.buildCompositeLit(e)
  32  	case *syntax.FuncLit:
  33  		return fb.buildFuncLit(e)
  34  	case *syntax.ParenExpr:
  35  		return fb.buildExpr(e.X)
  36  	case *syntax.ListExpr:
  37  		var last SSAValue
  38  		for _, el := range e.ElemList {
  39  			last = fb.buildExpr(el)
  40  		}
  41  		return last
  42  	case *syntax.KeyValueExpr:
  43  		return fb.buildExpr(e.Value)
  44  	}
  45  	return nil
  46  }
  47  
  48  func (fb *ssaFuncBuilder) buildIdent(e *syntax.Name) (s SSAValue) {
  49  	if e.Value == "_" || e.Value == "nil" {
  50  		return &SSAConst{typ: nil, val: nil}
  51  	}
  52  	if fb.localConsts != nil {
  53  		if c, ok := fb.localConsts[e.Value]; ok {
  54  			return c
  55  		}
  56  	}
  57  	obj := fb.lookupObject(e.Value)
  58  	if obj == nil && fb.info != nil {
  59  		obj = fb.info.Uses[e]
  60  	}
  61  	if obj == nil && fb.parent != nil {
  62  		for p := fb.parent; p != nil; p = p.parent {
  63  			for pobj := range p.vars {
  64  				if pobj.Name() == e.Value {
  65  					fv := fb.getOrCreateFreeVar(e.Value, pobj.Type())
  66  					return fb.emitLoad(fv, pobj.Type())
  67  				}
  68  			}
  69  			if p.freeVarPtrs != nil {
  70  				if pfv, ok := p.freeVarPtrs[e.Value]; ok {
  71  					fv := fb.getOrCreateFreeVar(e.Value, pfv.typ)
  72  					return fb.emitLoad(fv, pfv.typ)
  73  				}
  74  			}
  75  		}
  76  	}
  77  	if obj == nil {
  78  		if fb.fn.Pkg != nil {
  79  			if fn, ok := fb.fn.Pkg.Members[e.Value].(*SSAFunction); ok {
  80  				return fn
  81  			}
  82  			if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
  83  				return fb.emitLoad(g, g.typ)
  84  			}
  85  			if nc, ok := fb.fn.Pkg.Members[e.Value].(*SSANamedConst); ok {
  86  				return nc.Value
  87  			}
  88  		}
  89  		return fb.builtinValue(e.Value)
  90  	}
  91  	switch obj := obj.(type) {
  92  	case *types.TCVar:
  93  		if alloc, ok := fb.vars[obj]; ok {
  94  			return fb.emitLoad(alloc, obj.Type())
  95  		}
  96  		if fv, ok := fb.freeVarPtrs[e.Value]; ok {
  97  			return fb.emitLoad(fv, obj.Type())
  98  		}
  99  		for p := fb.parent; p != nil; p = p.parent {
 100  			found := false
 101  			if _, ok := p.vars[obj]; ok {
 102  				found = true
 103  			}
 104  			if !found {
 105  				for pobj := range p.vars {
 106  					if pobj.Name() == e.Value {
 107  						found = true
 108  						break
 109  					}
 110  				}
 111  			}
 112  			if !found && p.freeVarPtrs != nil {
 113  				if _, ok := p.freeVarPtrs[e.Value]; ok {
 114  					found = true
 115  				}
 116  			}
 117  			if found {
 118  				fv := fb.getOrCreateFreeVar(e.Value, obj.Type())
 119  				return fb.emitLoad(fv, obj.Type())
 120  			}
 121  		}
 122  		if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
 123  			return fb.emitLoad(g, obj.Type())
 124  		}
 125  		return &SSAConst{typ: obj.Type(), val: nil}
 126  	case *types.TCConst:
 127  		return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
 128  	case *types.TCFunc:
 129  		fn, _ := fb.fn.Pkg.Members[e.Value].(*SSAFunction)
 130  		if fn != nil {
 131  			return fn
 132  		}
 133  		return &SSAConst{typ: obj.Type(), val: nil}
 134  	case *types.TypeName:
 135  		return nil
 136  	case *types.Builtin:
 137  		return &SSABuiltin{id: obj.ID(), name: obj.Name()}
 138  	}
 139  	return nil
 140  }
 141  
 142  func (fb *ssaFuncBuilder) builtinValue(name string) (s SSAValue) {
 143  	id, ok := ssaBuiltinID(name)
 144  	if !ok {
 145  		return nil
 146  	}
 147  	return &SSABuiltin{id: id, name: name}
 148  }
 149  
 150  func (fb *ssaFuncBuilder) buildLit(e *syntax.BasicLit) (s SSAValue) {
 151  	cv := evalBasicLitLocal(e)
 152  	if cv == nil {
 153  		return nil
 154  	}
 155  	switch e.Kind {
 156  	case token.IntLit:
 157  		return &SSAConst{typ: types.Typ[types.UntypedInt], val: cv}
 158  	case token.FloatLit:
 159  		return &SSAConst{typ: types.Typ[types.UntypedFloat], val: cv}
 160  	case token.StringLit:
 161  		return &SSAConst{typ: types.Typ[types.UntypedString], val: cv}
 162  	case token.RuneLit:
 163  		return &SSAConst{typ: types.Typ[types.UntypedRune], val: cv}
 164  	}
 165  	return nil
 166  }
 167  
 168  func (fb *ssaFuncBuilder) buildOperation(e *syntax.Operation) (s SSAValue) {
 169  	if e.Y == nil {
 170  		if e.Op == token.Add {
 171  			return fb.buildExpr(e.X)
 172  		}
 173  		op := syntaxOpToSSAOp(e.Op, true)
 174  		if op == OpAnd {
 175  			if name, ok := e.X.(*syntax.Name); ok {
 176  				obj := fb.lookupObject(name.Value)
 177  				if obj != nil {
 178  					if alloc, ok2 := fb.vars[obj]; ok2 {
 179  						return alloc
 180  					}
 181  					if g, ok2 := fb.fn.Pkg.Members[name.Value].(*SSAGlobal); ok2 {
 182  						return g
 183  					}
 184  				}
 185  			}
 186  			if ie, ok := e.X.(*syntax.IndexExpr); ok {
 187  				base := fb.buildExpr(ie.X)
 188  				idx := fb.buildExpr(ie.Index)
 189  				if base == nil || idx == nil {
 190  					return nil
 191  				}
 192  				ia := &SSAIndexAddr{X: base, Index: idx}
 193  				ia.typ = types.NewPointer(ssaElemType(base.SSAType()))
 194  				ia.name = fb.nextName()
 195  				fb.emit(ia)
 196  				return ia
 197  			}
 198  			if sel, ok := e.X.(*syntax.SelectorExpr); ok {
 199  				addr := fb.buildSelectorAddr(sel)
 200  				if addr != nil {
 201  					return addr
 202  				}
 203  			}
 204  			x := fb.buildExpr(e.X)
 205  			if x == nil {
 206  				return nil
 207  			}
 208  			a := &SSAAlloc{Heap: true}
 209  			a.typ = types.NewPointer(x.SSAType())
 210  			a.name = fb.nextName()
 211  			fb.emit(a)
 212  			fb.emitStore(a, x)
 213  			return a
 214  		}
 215  		x := fb.buildExpr(e.X)
 216  		if x == nil {
 217  			return nil
 218  		}
 219  		if op == OpArrow {
 220  			u := &SSAUnOp{Op: OpArrow, X: x}
 221  			u.typ = ssaChanElemType(x.SSAType())
 222  			u.name = fb.nextName()
 223  			fb.emit(u)
 224  			return u
 225  		}
 226  		u := &SSAUnOp{Op: op, X: x}
 227  		if op == OpMul {
 228  			if p, ok := x.SSAType().(*types.Pointer); ok {
 229  				u.typ = p.Elem()
 230  			} else {
 231  				u.typ = x.SSAType()
 232  			}
 233  		} else {
 234  			u.typ = x.SSAType()
 235  		}
 236  		u.name = fb.nextName()
 237  		fb.emit(u)
 238  		return u
 239  	}
 240  	op := syntaxOpToSSAOp(e.Op, false)
 241  	if op == OpLand || op == OpLor {
 242  		x := fb.buildExpr(e.X)
 243  		if x == nil {
 244  			return nil
 245  		}
 246  		rhsBlock := fb.newBlock("sc.rhs")
 247  		mergeBlock := fb.newBlock("sc.merge")
 248  		entryBlock := fb.currentBlock
 249  		fb.emit(&SSAIf{Cond: x})
 250  		if op == OpLand {
 251  			fb.currentBlock.Succs = append(fb.currentBlock.Succs, rhsBlock, mergeBlock)
 252  		} else {
 253  			fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock, rhsBlock)
 254  		}
 255  		rhsBlock.Preds = append(rhsBlock.Preds, entryBlock)
 256  		mergeBlock.Preds = append(mergeBlock.Preds, entryBlock)
 257  		fb.currentBlock = rhsBlock
 258  		y := fb.buildExpr(e.Y)
 259  		if y == nil {
 260  			y = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:false}}
 261  		}
 262  		fb.emit(&SSAJump{Comment: "sc.merge"})
 263  		fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock)
 264  		mergeBlock.Preds = append(mergeBlock.Preds, fb.currentBlock)
 265  		fb.currentBlock = mergeBlock
 266  		var shortVal SSAValue
 267  		if op == OpLand {
 268  			shortVal = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:false}}
 269  		} else {
 270  			shortVal = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:true}}
 271  		}
 272  		phi := &SSAPhi{Edges: []SSAValue{shortVal, y}, Comment: "sc"}
 273  		phi.typ = types.Typ[types.Bool]
 274  		phi.name = fb.nextName()
 275  		fb.emit(phi)
 276  		return phi
 277  	}
 278  	x := fb.buildExpr(e.X)
 279  	y := fb.buildExpr(e.Y)
 280  	if x == nil || y == nil {
 281  		return nil
 282  	}
 283  	if (op == OpOr || op == OpAdd) && x.SSAType() != nil && y.SSAType() != nil {
 284  		if isRuneKind(x.SSAType()) && isStringKind(y.SSAType()) || isStringKind(x.SSAType()) && isRuneKind(y.SSAType()) {
 285  			writeStr(2, "compile error: cannot concatenate rune with string - convert to UTF-8 first\n")
 286  			compileErrors = append(compileErrors, "cannot concatenate rune with string")
 287  		}
 288  	}
 289  	if xc, ok := x.(*SSAConst); ok {
 290  		if yc, ok2 := y.(*SSAConst); ok2 {
 291  			if xc.val != nil && yc.val != nil {
 292  				folded := evalBinaryLocal(e.Op, xc.val, yc.val)
 293  				if folded != nil {
 294  					ct := xc.typ
 295  					if ct == nil {
 296  						ct = yc.typ
 297  					}
 298  					if _, isBool := folded.(*types.ConstBool); isBool {
 299  						ct = types.Typ[types.Bool]
 300  					}
 301  					return &SSAConst{typ: ct, val: folded}
 302  				}
 303  			}
 304  		}
 305  	}
 306  	b := &SSABinOp{Op: op, X: x, Y: y}
 307  	b.name = fb.nextName()
 308  	switch op {
 309  	case OpEql, OpNeq, OpLss, OpLeq, OpGtr, OpGeq:
 310  		b.typ = types.Typ[types.Bool]
 311  	default:
 312  		xT := x.SSAType()
 313  		yT := y.SSAType()
 314  		xUntyped := false
 315  		if xB, ok := types.SafeUnderlying(xT).(*types.Basic); ok && xB.Info()&IsUntyped != 0 {
 316  			xUntyped = true
 317  		}
 318  		if xT != nil && !xUntyped {
 319  			b.typ = xT
 320  		} else if yT != nil {
 321  			b.typ = yT
 322  		} else {
 323  			b.typ = xT
 324  		}
 325  	}
 326  	fb.emit(b)
 327  	return b
 328  }
 329  
 330  func (fb *ssaFuncBuilder) buildCall(e *syntax.CallExpr) (s SSAValue) {
 331  	if ie, ok := e.Fun.(*syntax.IndexExpr); ok {
 332  		if result := fb.tryGenericCallFromIndex(ie, e.ArgList, e.HasDots); result != nil {
 333  			return result
 334  		}
 335  	}
 336  	if name, ok := e.Fun.(*syntax.Name); ok {
 337  		obj := fb.lookupObject(name.Value)
 338  		if tn, ok2 := obj.(*types.TypeName); ok2 {
 339  			if _, isTP := tn.Type().(*types.TypeParam); !isTP {
 340  				args := fb.buildArgs(e.ArgList)
 341  				if len(args) == 1 && args[0] != nil {
 342  					conv := &SSAConvert{X: args[0]}
 343  					conv.typ = tn.Type()
 344  					conv.name = fb.nextName()
 345  					fb.emit(conv)
 346  					return conv
 347  				}
 348  				return nil
 349  			}
 350  		}
 351  		if result := fb.tryGenericLocalCall(name.Value, e.ArgList, e.HasDots); result != nil {
 352  			return result
 353  		}
 354  	}
 355  	if convType := fb.resolveTypeAST(e.Fun); convType != nil {
 356  		args := fb.buildArgs(e.ArgList)
 357  		if len(args) == 1 && args[0] != nil {
 358  			conv := &SSAConvert{X: args[0]}
 359  			conv.typ = convType
 360  			conv.name = fb.nextName()
 361  			fb.emit(conv)
 362  			return conv
 363  		}
 364  		return nil
 365  	}
 366  	if sel, ok := e.Fun.(*syntax.SelectorExpr); ok {
 367  		if name, ok2 := sel.X.(*syntax.Name); ok2 {
 368  			obj := fb.lookupObject(name.Value)
 369  			if pn, ok3 := obj.(*types.PkgName); ok3 {
 370  				return fb.buildPkgCall(pn, sel.Sel.Value, e.ArgList, e.HasDots)
 371  			}
 372  		}
 373  		recv := fb.buildExpr(sel.X)
 374  		if recv != nil && recv.SSAType() != nil {
 375  			if fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv); fn != nil {
 376  				args := fb.buildArgs(e.ArgList)
 377  				if fn.Signature != nil {
 378  					if fn.Signature.Variadic() && !e.HasDots {
 379  						args = fb.wrapVariadicArgs(args, fn.Signature)
 380  					}
 381  					args = fb.coerceArgsToInterface(args, fn.Signature)
 382  				}
 383  				allArgs := []SSAValue{:0:len(args) + 1}
 384  				allArgs = append(allArgs, fixedRecv)
 385  				for _, ma := range args {
 386  					allArgs = append(allArgs, ma)
 387  				}
 388  				var retType types.Type
 389  				if fn.Signature != nil {
 390  					if fn.Signature.Results() != nil && fn.Signature.Results().Len() == 1 {
 391  						retType = fn.Signature.Results().At(0).Type()
 392  					} else if fn.Signature.Results() != nil && fn.Signature.Results().Len() > 1 {
 393  						retType = fn.Signature.Results()
 394  					}
 395  				}
 396  				call := &SSACall{Call: SSACallCommon{Value: fn, Args: allArgs}}
 397  				call.typ = retType
 398  				call.name = fb.nextName()
 399  				fb.emit(call)
 400  				if retType == nil {
 401  					return nil
 402  				}
 403  				return call
 404  			}
 405  			if inv := fb.buildIfaceMethodCall(sel, recv, e.ArgList); inv != nil {
 406  				return inv
 407  			}
 408  		}
 409  	}
 410  	fn := fb.buildExpr(e.Fun)
 411  	args := fb.buildArgs(e.ArgList)
 412  
 413  	if fn == nil {
 414  		return nil
 415  	}
 416  	if bi, ok := fn.(*SSABuiltin); ok {
 417  		return fb.buildBuiltinCall(e, bi, args)
 418  	}
 419  
 420  	var retType types.Type
 421  	if fn.SSAType() != nil {
 422  		if sig, ok := types.SafeUnderlying(fn.SSAType()).(*types.Signature); ok {
 423  			if sig.Results() != nil && sig.Results().Len() == 1 {
 424  				retType = sig.Results().At(0).Type()
 425  			} else if sig.Results() != nil && sig.Results().Len() > 1 {
 426  				retType = sig.Results()
 427  			}
 428  		}
 429  	} else if ssaFn, ok := fn.(*SSAFunction); ok && ssaFn.Signature != nil {
 430  		sig := ssaFn.Signature
 431  		if sig.Results() != nil && sig.Results().Len() == 1 {
 432  			retType = sig.Results().At(0).Type()
 433  		} else if sig.Results() != nil && sig.Results().Len() > 1 {
 434  			retType = sig.Results()
 435  		}
 436  	}
 437  
 438  	if fn.SSAType() != nil {
 439  		if sig, ok := types.SafeUnderlying(fn.SSAType()).(*types.Signature); ok {
 440  			if sig.Variadic() && !e.HasDots {
 441  				args = fb.wrapVariadicArgs(args, sig)
 442  			}
 443  			args = fb.coerceArgsToInterface(args, sig)
 444  		}
 445  	}
 446  
 447  	call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
 448  	call.typ = retType
 449  	call.name = fb.nextName()
 450  	fb.emit(call)
 451  
 452  	if retType == nil {
 453  		return nil
 454  	}
 455  	return call
 456  }
 457  
 458  func (fb *ssaFuncBuilder) coerceArgsToInterface(args []SSAValue, sig *types.Signature) (ss []SSAValue) {
 459  	if sig.Params() == nil {
 460  		return args
 461  	}
 462  	for i := 0; i < len(args) && i < sig.Params().Len(); i++ {
 463  		paramType := sig.Params().At(i).Type()
 464  		if paramType == nil || args[i] == nil || args[i].SSAType() == nil {
 465  			continue
 466  		}
 467  		_, isIface := types.SafeUnderlying(paramType).(*types.TCInterface)
 468  		if !isIface {
 469  			continue
 470  		}
 471  		_, argIsIface := types.SafeUnderlying(args[i].SSAType()).(*types.TCInterface)
 472  		if argIsIface {
 473  			continue
 474  		}
 475  		mi := &SSAMakeInterface{X: args[i], IType: paramType}
 476  		mi.typ = paramType
 477  		mi.name = fb.nextName()
 478  		fb.emit(mi)
 479  		args[i] = mi
 480  	}
 481  	return args
 482  }
 483  
 484  func (fb *ssaFuncBuilder) wrapVariadicArgs(args []SSAValue, sig *types.Signature) (ss []SSAValue) {
 485  	if sig.Params() == nil {
 486  		return args
 487  	}
 488  	nFixed := sig.Params().Len() - 1
 489  	if nFixed < 0 {
 490  		nFixed = 0
 491  	}
 492  	if nFixed > len(args) {
 493  		nFixed = len(args)
 494  	}
 495  	nVariadic := len(args) - nFixed
 496  	if nVariadic <= 0 {
 497  		nilSlice := NewSSAConst(&types.ConstNil{}, sig.Params().At(sig.Params().Len()-1).Type())
 498  		result := []SSAValue{:nFixed:nFixed}
 499  		copy(result, args[:nFixed])
 500  		return append(result, nilSlice)
 501  	}
 502  	sliceType := sig.Params().At(sig.Params().Len() - 1).Type()
 503  	var elemType types.Type
 504  	if sl, ok := types.SafeUnderlying(sliceType).(*types.Slice); ok {
 505  		elemType = sl.Elem()
 506  	}
 507  	// HasDots lost because closures can't write to captured named returns.
 508  	// Detect spread: if exactly 1 variadic arg whose type matches the
 509  	// variadic param's slice type, pass it through. This covers both
 510  	// concrete T and interface{} variadics (e.g. fmt.Print -> fmt.Fprint).
 511  	if nVariadic == 1 && elemType != nil {
 512  		argT := args[nFixed].SSAType()
 513  		if argT != nil && types.Identical(argT, sliceType) {
 514  			return args
 515  		}
 516  	}
 517  	lenVal := NewSSAConst(&types.ConstInt{V:int64(nVariadic)}, types.Typ[types.Int32])
 518  	ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal}
 519  	ms.typ = sliceType
 520  	ms.name = fb.nextName()
 521  	fb.emit(ms)
 522  	for i := 0; i < nVariadic; i++ {
 523  		idx := NewSSAConst(&types.ConstInt{V:int64(i)}, types.Typ[types.Int32])
 524  		ia := &SSAIndexAddr{X: ms, Index: idx}
 525  		ia.typ = types.NewPointer(elemType)
 526  		ia.name = fb.nextName()
 527  		fb.emit(ia)
 528  		v := args[nFixed+i]
 529  		if elemType != nil {
 530  			v = fb.coerceToInterface(v, elemType)
 531  		}
 532  		fb.emitStore(ia, v)
 533  	}
 534  	result := []SSAValue{:nFixed:nFixed}
 535  	copy(result, args[:nFixed])
 536  	return append(result, ms)
 537  }
 538  
 539  func (fb *ssaFuncBuilder) buildArgs(argList []syntax.Expr) (ss []SSAValue) {
 540  	args := []SSAValue{:0:len(argList)}
 541  	for _, a := range argList {
 542  		v := fb.buildExpr(a)
 543  		if v != nil {
 544  			args = append(args, v)
 545  		}
 546  	}
 547  	if len(args) == 1 && args[0] != nil {
 548  		if t, ok := args[0].SSAType().(*types.Tuple); ok && t.Len() > 1 {
 549  			expanded := []SSAValue{:0:t.Len()}
 550  			for i := int32(0); i < int32(t.Len()); i++ {
 551  				ext := &SSAExtract{Tuple: args[0], Index: int32(i)}
 552  				ext.typ = t.At(int32(i)).Type()
 553  				ext.name = fb.nextName()
 554  				fb.emit(ext)
 555  				expanded = append(expanded, ext)
 556  			}
 557  			return expanded
 558  		}
 559  	}
 560  	return args
 561  }
 562  
 563  func (fb *ssaFuncBuilder) buildBuiltinCall(e *syntax.CallExpr, b *SSABuiltin, args []SSAValue) (s SSAValue) {
 564  	switch b.id {
 565  	case types.BuiltinLen, types.BuiltinCap:
 566  		if b.id == types.BuiltinLen && len(args) == 1 {
 567  			if c, ok := args[0].(*SSAConst); ok {
 568  				if cs, ok2 := c.val.(*types.ConstStr); ok2 {
 569  					return &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(len(cs.S))}}
 570  				}
 571  			}
 572  		}
 573  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 574  		call.typ = types.Typ[types.Int32]
 575  		call.name = fb.nextName()
 576  		fb.emit(call)
 577  		return call
 578  	case types.BuiltinAppend:
 579  		if len(args) > 1 {
 580  			if sl, ok := types.SafeUnderlying(args[0].SSAType()).(*types.Slice); ok {
 581  				if _, isIface := types.SafeUnderlying(sl.Elem()).(*types.TCInterface); isIface {
 582  					for i := 1; i < len(args); i++ {
 583  						if e.HasDots && i == 1 {
 584  							continue
 585  						}
 586  						if args[i] == nil || args[i].SSAType() == nil {
 587  							continue
 588  						}
 589  						if _, argIface := types.SafeUnderlying(args[i].SSAType()).(*types.TCInterface); argIface {
 590  							continue
 591  						}
 592  						mi := &SSAMakeInterface{X: args[i], IType: sl.Elem()}
 593  						mi.typ = sl.Elem()
 594  						mi.name = fb.nextName()
 595  						fb.emit(mi)
 596  						args[i] = mi
 597  					}
 598  				}
 599  			}
 600  		}
 601  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args, HasDots: e.HasDots}}
 602  		if len(args) > 0 {
 603  			call.typ = args[0].SSAType()
 604  		}
 605  		call.name = fb.nextName()
 606  		fb.emit(call)
 607  		return call
 608  	case types.BuiltinMake:
 609  		if len(e.ArgList) == 0 {
 610  			return nil
 611  		}
 612  		typ := fb.resolveType(e.ArgList[0])
 613  		return fb.emitMake(typ, args)
 614  	case types.BuiltinNew:
 615  		if len(e.ArgList) == 0 {
 616  			return nil
 617  		}
 618  		typ := fb.resolveType(e.ArgList[0])
 619  		a := &SSAAlloc{Heap: true}
 620  		a.typ = types.NewPointer(typ)
 621  		a.name = fb.nextName()
 622  		fb.emit(a)
 623  		return a
 624  	case types.BuiltinPanic:
 625  		if len(args) > 0 {
 626  			fb.emit(&SSAPanic{X: args[0]})
 627  			fb.currentBlock = nil
 628  		}
 629  		return nil
 630  	case types.BuiltinClose, types.BuiltinDelete, types.BuiltinClear, types.BuiltinPrint, types.BuiltinPrintln:
 631  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 632  		call.name = fb.nextName()
 633  		fb.emit(call)
 634  		return nil
 635  	case types.BuiltinCopy:
 636  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 637  		call.typ = types.Typ[types.Int32]
 638  		call.name = fb.nextName()
 639  		fb.emit(call)
 640  		return call
 641  	case types.BuiltinRecover:
 642  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 643  		call.typ = types.NewTCInterface(nil, nil)
 644  		call.name = fb.nextName()
 645  		fb.emit(call)
 646  		return call
 647  	case types.BuiltinMin, types.BuiltinMax:
 648  		call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 649  		if len(args) > 0 && args[0] != nil {
 650  			call.typ = args[0].SSAType()
 651  		} else {
 652  			call.typ = types.Typ[types.Int32]
 653  		}
 654  		call.name = fb.nextName()
 655  		fb.emit(call)
 656  		return call
 657  	}
 658  	call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
 659  	call.name = fb.nextName()
 660  	fb.emit(call)
 661  	return call
 662  }
 663  
 664  func (fb *ssaFuncBuilder) emitMake(typ types.Type, sizeArgs []SSAValue) (s SSAValue) {
 665  	if typ == nil {
 666  		return nil
 667  	}
 668  	switch u := types.SafeUnderlying(typ).(type) {
 669  	case *types.Basic:
 670  		if u.Kind() == types.TCString {
 671  			ms := &SSAMakeSlice{}
 672  			ms.typ = typ
 673  			ms.name = fb.nextName()
 674  			if len(sizeArgs) > 0 {
 675  				ms.Len = sizeArgs[0]
 676  			}
 677  			if len(sizeArgs) > 1 {
 678  				ms.Cap = sizeArgs[1]
 679  			}
 680  			fb.emit(ms)
 681  			return ms
 682  		}
 683  	case *types.Slice:
 684  		ms := &SSAMakeSlice{}
 685  		ms.typ = typ
 686  		ms.name = fb.nextName()
 687  		if len(sizeArgs) > 0 {
 688  			ms.Len = sizeArgs[0]
 689  		}
 690  		if len(sizeArgs) > 1 {
 691  			ms.Cap = sizeArgs[1]
 692  		}
 693  		fb.emit(ms)
 694  		return ms
 695  	case *types.TCMap:
 696  		mm := &SSAMakeMap{}
 697  		mm.typ = typ
 698  		mm.name = fb.nextName()
 699  		if len(sizeArgs) > 0 {
 700  			mm.Reserve = sizeArgs[0]
 701  		}
 702  		fb.emit(mm)
 703  		return mm
 704  	case *types.TCChan:
 705  		mc := &SSAMakeChan{}
 706  		mc.typ = typ
 707  		mc.name = fb.nextName()
 708  		if len(sizeArgs) > 0 {
 709  			mc.Size = sizeArgs[0]
 710  		}
 711  		fb.emit(mc)
 712  		return mc
 713  	}
 714  	return nil
 715  }
 716  
 717  func (fb *ssaFuncBuilder) buildSelector(e *syntax.SelectorExpr) (s SSAValue) {
 718  	if name, ok := e.X.(*syntax.Name); ok {
 719  		obj := fb.lookupObject(name.Value)
 720  		if pn, ok2 := obj.(*types.PkgName); ok2 {
 721  			return fb.buildPkgMember(pn, e.Sel.Value)
 722  		}
 723  	}
 724  	fa := fb.buildSelectorAddr(e)
 725  	if fa != nil {
 726  		elemType := fa.SSAType()
 727  		if p, ok := types.SafeUnderlying(elemType).(*types.Pointer); ok {
 728  			elemType = p.Elem()
 729  		}
 730  		return fb.emitLoad(fa, elemType)
 731  	}
 732  	recv := fb.buildExpr(e.X)
 733  	if recv == nil {
 734  		return nil
 735  	}
 736  	return fb.buildMethodValue(e, recv)
 737  }
 738  
 739  func (fb *ssaFuncBuilder) buildMethodValue(sel *syntax.SelectorExpr, recv SSAValue) (s SSAValue) {
 740  	fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv)
 741  	if fn == nil || fn.Signature == nil {
 742  		return nil
 743  	}
 744  	methodSig := fn.Signature
 745  	var wrapperParams *types.Tuple
 746  	if methodSig.Params() != nil && methodSig.Params().Len() > 0 {
 747  		vars := []*types.TCVar{:0:methodSig.Params().Len()}
 748  		for i := 0; i < methodSig.Params().Len(); i++ {
 749  			vars = append(vars, methodSig.Params().At(i))
 750  		}
 751  		wrapperParams = types.NewTuple(vars...)
 752  	}
 753  	wrapperSig := types.NewSignature(nil, wrapperParams, methodSig.Results(), methodSig.Variadic())
 754  	name := fb.fn.name | "__mval" | ssaItoa(len(fb.fn.AnonFuncs)+1)
 755  	wrapper := &SSAFunction{
 756  		name:      name,
 757  		Signature: wrapperSig,
 758  		Pkg:       fb.fn.Pkg,
 759  		Prog:      fb.fn.Prog,
 760  		parent:    fb.fn,
 761  	}
 762  	fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, wrapper)
 763  	recvType := fixedRecv.SSAType()
 764  	fv := &SSAFreeVar{name: "recv", typ: recvType, parent: wrapper}
 765  	wrapper.FreeVars = append(wrapper.FreeVars, fv)
 766  	if wrapperParams != nil {
 767  		for i := 0; i < wrapperParams.Len(); i++ {
 768  			v := wrapperParams.At(i)
 769  			p := &SSAParameter{name: v.Name(), typ: v.Type(), parent: wrapper}
 770  			wrapper.Params = append(wrapper.Params, p)
 771  		}
 772  	}
 773  	entry := NewSSABasicBlock(wrapper, "entry")
 774  	args := []SSAValue{:0:1 + len(wrapper.Params)}
 775  	args = append(args, fv)
 776  	for _, p := range wrapper.Params {
 777  		args = append(args, p)
 778  	}
 779  	var retType types.Type
 780  	if methodSig.Results() != nil && methodSig.Results().Len() == 1 {
 781  		retType = methodSig.Results().At(0).Type()
 782  	} else if methodSig.Results() != nil && methodSig.Results().Len() > 1 {
 783  		retType = methodSig.Results()
 784  	}
 785  	call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
 786  	call.typ = retType
 787  	call.name = "t1"
 788  	call.setBlock(entry)
 789  	entry.Instrs = append(entry.Instrs, call)
 790  	ret := &SSAReturn{}
 791  	if retType != nil {
 792  		ret.Results = []SSAValue{call}
 793  	}
 794  	ret.setBlock(entry)
 795  	entry.Instrs = append(entry.Instrs, ret)
 796  	mc := &SSAMakeClosure{Fn: wrapper, Bindings: []SSAValue{fixedRecv}}
 797  	mc.typ = wrapperSig
 798  	mc.name = fb.nextName()
 799  	fb.emit(mc)
 800  	return mc
 801  }
 802  
 803  func (fb *ssaFuncBuilder) ensureImportedSSAPackage(imported *types.TCPackage) (s *SSAPackage) {
 804  	impPkg := fb.fn.Prog.ImportedPackage(imported.Path())
 805  	if impPkg == nil {
 806  		impPkg = &SSAPackage{
 807  			Prog:    fb.fn.Prog,
 808  			Pkg:     imported,
 809  			Members: map[string]SSAMember{},
 810  		}
 811  		fb.fn.Prog.imported[imported.Path()] = impPkg
 812  		fb.fn.Prog.packages[imported] = impPkg
 813  	}
 814  	return impPkg
 815  }
 816  
 817  func (fb *ssaFuncBuilder) buildPkgMember(pn *types.PkgName, memberName string) (s SSAValue) {
 818  	imported := pn.Imported()
 819  	if imported == nil {
 820  		return nil
 821  	}
 822  	obj := imported.Scope().Lookup(memberName)
 823  	if obj == nil {
 824  		return nil
 825  	}
 826  	switch obj := obj.(type) {
 827  	case *types.TCConst:
 828  		return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
 829  	case *types.TCVar:
 830  		impPkg := fb.ensureImportedSSAPackage(imported)
 831  		g, ok := impPkg.Members[memberName].(*SSAGlobal)
 832  		if !ok {
 833  			g = &SSAGlobal{
 834  				name: memberName,
 835  				typ:  types.NewPointer(obj.Type()),
 836  				pkg:  impPkg,
 837  			}
 838  			impPkg.Members[memberName] = g
 839  		}
 840  		return fb.emitLoad(g, obj.Type())
 841  	case *types.TCFunc:
 842  		impPkg := fb.ensureImportedSSAPackage(imported)
 843  		fn := impPkg.Func(memberName)
 844  		if fn != nil {
 845  			return fn
 846  		}
 847  		return nil
 848  	}
 849  	return nil
 850  }
 851  
 852  func (fb *ssaFuncBuilder) buildSelectorAddr(e *syntax.SelectorExpr) (s SSAValue) {
 853  	var addr SSAValue
 854  	var structType types.Type
 855  	if inner, ok := e.X.(*syntax.SelectorExpr); ok {
 856  		addr = fb.buildSelectorAddr(inner)
 857  		if addr == nil {
 858  			return nil
 859  		}
 860  		structType = addr.SSAType()
 861  		if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
 862  			structType = p.Elem()
 863  		}
 864  		if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
 865  			ld := &SSAUnOp{Op: OpMul, X: addr}
 866  			ld.typ = structType
 867  			ld.name = fb.nextName()
 868  			fb.emit(ld)
 869  			addr = ld
 870  			structType = p.Elem()
 871  		}
 872  	} else if ie, ok := e.X.(*syntax.IndexExpr); ok {
 873  		x := fb.buildExpr(ie.X)
 874  		idx := fb.buildExpr(ie.Index)
 875  		if x == nil || idx == nil {
 876  			return nil
 877  		}
 878  		ia := &SSAIndexAddr{X: x, Index: idx}
 879  		elemT := ssaElemType(x.SSAType())
 880  		ia.typ = types.NewPointer(elemT)
 881  		ia.name = fb.nextName()
 882  		fb.emit(ia)
 883  		addr = ia
 884  		structType = elemT
 885  		if _, isPtr := types.SafeUnderlying(elemT).(*types.Pointer); isPtr {
 886  			ld := fb.emitLoad(ia, elemT)
 887  			addr = ld
 888  			structType = elemT
 889  		}
 890  	} else {
 891  		x := fb.buildExpr(e.X)
 892  		if x == nil || x.SSAType() == nil {
 893  			if name, ok := e.X.(*syntax.Name); ok {
 894  				obj := fb.lookupObject(name.Value)
 895  				if pn, ok := obj.(*types.PkgName); ok {
 896  					return fb.buildPkgMemberAddr(pn, e.Sel.Value)
 897  				}
 898  			}
 899  			return nil
 900  		}
 901  		baseType := x.SSAType()
 902  		addr = x
 903  		if _, ok := types.SafeUnderlying(baseType).(*types.Pointer); !ok {
 904  			found := false
 905  			if name, ok := e.X.(*syntax.Name); ok {
 906  				obj := fb.lookupObject(name.Value)
 907  				if obj != nil {
 908  					if alloc, ok2 := fb.vars[obj]; ok2 {
 909  						addr = alloc
 910  						baseType = types.NewPointer(baseType)
 911  						found = true
 912  					} else if fb.freeVarPtrs != nil {
 913  						if fv, ok2 := fb.freeVarPtrs[name.Value]; ok2 {
 914  							addr = fv
 915  							baseType = types.NewPointer(baseType)
 916  							found = true
 917  						}
 918  					}
 919  				}
 920  			}
 921  			if !found {
 922  				alloc := &SSAAlloc{Comment: "fieldaddr.tmp"}
 923  				alloc.typ = types.NewPointer(baseType)
 924  				alloc.name = fb.nextName()
 925  				fb.emit(alloc)
 926  				fb.emitStore(alloc, x)
 927  				addr = alloc
 928  				baseType = types.NewPointer(baseType)
 929  			}
 930  		}
 931  		structType = baseType
 932  		if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
 933  			structType = p.Elem()
 934  		}
 935  	}
 936  	fieldIdx := fb.fieldIndex(structType, e.Sel.Value)
 937  	if fieldIdx >= 0 {
 938  		fa := &SSAFieldAddr{X: addr, Field: fieldIdx}
 939  		fa.typ = types.NewPointer(fb.fieldType(structType, fieldIdx))
 940  		fa.name = fb.nextName()
 941  		fb.emit(fa)
 942  		return fa
 943  	}
 944  	path := fb.findEmbeddedFieldPath(structType, e.Sel.Value)
 945  	if len(path) >= 2 {
 946  		cur := addr
 947  		curType := structType
 948  		for pi, idx := range path {
 949  			fa := &SSAFieldAddr{X: cur, Field: idx}
 950  			fa.typ = types.NewPointer(fb.fieldType(curType, idx))
 951  			fa.name = fb.nextName()
 952  			fb.emit(fa)
 953  			curType = fb.fieldType(curType, idx)
 954  			if pi < len(path)-1 {
 955  				if p, ok := types.SafeUnderlying(curType).(*types.Pointer); ok {
 956  					ld := &SSAUnOp{Op: OpMul, X: fa}
 957  					ld.typ = curType
 958  					ld.name = fb.nextName()
 959  					fb.emit(ld)
 960  					cur = ld
 961  					curType = p.Elem()
 962  					continue
 963  				}
 964  			}
 965  			cur = fa
 966  		}
 967  		return cur
 968  	}
 969  	return nil
 970  }
 971  
 972  func (fb *ssaFuncBuilder) buildIndex(e *syntax.IndexExpr) (s SSAValue) {
 973  	x := fb.buildExpr(e.X)
 974  	idx := fb.buildExpr(e.Index)
 975  	if x == nil || idx == nil {
 976  		return nil
 977  	}
 978  	if x.SSAType() == nil {
 979  		return nil
 980  	}
 981  	switch t := types.SafeUnderlying(x.SSAType()).(type) {
 982  	case *types.TCMap:
 983  		idx = fb.coerceToInterface(idx, t.Key())
 984  		l := &SSALookup{X: x, Index: idx}
 985  		l.typ = t.Elem()
 986  		l.name = fb.nextName()
 987  		fb.emit(l)
 988  		return l
 989  	case *types.Pointer:
 990  		if arr, ok2 := types.SafeUnderlying(t.Elem()).(*types.Array); ok2 {
 991  			ia := &SSAIndexAddr{X: x, Index: idx}
 992  			ia.typ = types.NewPointer(t.Elem())
 993  			ia.name = fb.nextName()
 994  			fb.emit(ia)
 995  			return fb.emitLoad(ia, arr.Elem())
 996  		}
 997  		et := ssaElemType(x.SSAType())
 998  		ia := &SSAIndexAddr{X: x, Index: idx}
 999  		ia.typ = types.NewPointer(et)
1000  		ia.name = fb.nextName()
1001  		fb.emit(ia)
1002  		return fb.emitLoad(ia, et)
1003  	default:
1004  		et := ssaElemType(x.SSAType())
1005  		ia := &SSAIndexAddr{X: x, Index: idx}
1006  		ia.typ = types.NewPointer(et)
1007  		ia.name = fb.nextName()
1008  		fb.emit(ia)
1009  		return fb.emitLoad(ia, et)
1010  	}
1011  }
1012  
1013  func (fb *ssaFuncBuilder) buildSlice(e *syntax.SliceExpr) (s SSAValue) {
1014  	x := fb.buildExpr(e.X)
1015  	if x == nil {
1016  		return nil
1017  	}
1018  	sl := &SSASlice{X: x}
1019  	if len(e.Index) > 0 && e.Index[0] != nil {
1020  		sl.Low = fb.buildExpr(e.Index[0])
1021  	}
1022  	if len(e.Index) > 1 && e.Index[1] != nil {
1023  		sl.High = fb.buildExpr(e.Index[1])
1024  	}
1025  	if len(e.Index) > 2 && e.Index[2] != nil {
1026  		sl.Max = fb.buildExpr(e.Index[2])
1027  	}
1028  	sl.typ = ssaSliceOf(x.SSAType())
1029  	sl.name = fb.nextName()
1030  	fb.emit(sl)
1031  	return sl
1032  }
1033  
1034  func (fb *ssaFuncBuilder) buildAssert(e *syntax.AssertExpr) (s SSAValue) {
1035  	x := fb.buildExpr(e.X)
1036  	assertedType := fb.resolveType(e.Type)
1037  	if x == nil {
1038  		return nil
1039  	}
1040  	ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: false}
1041  	ta.typ = assertedType
1042  	ta.name = fb.nextName()
1043  	fb.emit(ta)
1044  	return ta
1045  }
1046  
1047  func (fb *ssaFuncBuilder) buildCompositeLit(e *syntax.CompositeLit) (s SSAValue) {
1048  	var typ types.Type
1049  	if e.Type != nil {
1050  		typ = fb.resolveType(e.Type)
1051  	}
1052  	if typ == nil {
1053  		return nil
1054  	}
1055  
1056  	if sl, ok := types.SafeUnderlying(typ).(*types.Slice); ok {
1057  		return fb.buildSliceLit(e, typ, sl)
1058  	}
1059  
1060  	if mt, isMap := types.SafeUnderlying(typ).(*types.TCMap); isMap {
1061  		mm := &SSAMakeMap{}
1062  		mm.typ = typ
1063  		mm.name = fb.nextName()
1064  		fb.emit(mm)
1065  		for _, el := range e.ElemList {
1066  			if kv, ok := el.(*syntax.KeyValueExpr); ok {
1067  				k := fb.buildExpr(kv.Key)
1068  				v := fb.buildExpr(kv.Value)
1069  				if k != nil && v != nil {
1070  					k = fb.coerceToInterface(k, mt.Key())
1071  					v = fb.coerceToInterface(v, mt.Elem())
1072  					fb.emit(&SSAMapUpdate{Map: mm, Key: k, Value: v})
1073  				}
1074  			}
1075  		}
1076  		return mm
1077  	}
1078  
1079  	if ar, isArr := types.SafeUnderlying(typ).(*types.Array); isArr {
1080  		return fb.buildArrayLit(e, typ, ar)
1081  	}
1082  
1083  	alloc := fb.emitAlloc(typ, 0)
1084  	posIdx := 0
1085  	for _, el := range e.ElemList {
1086  		if kv, ok := el.(*syntax.KeyValueExpr); ok {
1087  			if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1088  				idx := fb.fieldIndex(typ, kv.Key.(*syntax.Name).Value)
1089  				if idx >= 0 {
1090  					fa := &SSAFieldAddr{X: alloc, Field: idx}
1091  					ft := fb.fieldType(typ, idx)
1092  					fa.typ = types.NewPointer(ft)
1093  					fa.name = fb.nextName()
1094  					fb.emit(fa)
1095  					v := fb.buildExpr(kv.Value)
1096  					if v != nil {
1097  						v = fb.coerceToInterface(v, ft)
1098  						fb.emitStore(fa, v)
1099  					}
1100  				}
1101  			}
1102  		} else {
1103  			v := fb.buildExpr(el)
1104  			if v != nil {
1105  				if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1106  					ft := fb.fieldType(typ, posIdx)
1107  					fa := &SSAFieldAddr{X: alloc, Field: posIdx}
1108  					fa.typ = types.NewPointer(ft)
1109  					fa.name = fb.nextName()
1110  					fb.emit(fa)
1111  					v = fb.coerceToInterface(v, ft)
1112  					fb.emitStore(fa, v)
1113  				}
1114  			}
1115  			posIdx++
1116  		}
1117  	}
1118  	return fb.emitLoad(alloc, typ)
1119  }
1120  
1121  func (fb *ssaFuncBuilder) buildArrayLit(e *syntax.CompositeLit, typ types.Type, ar *types.Array) (s SSAValue) {
1122  	if ar.Len() < 0 {
1123  		ar = types.NewArray(ar.Elem(), int64(len(e.ElemList)))
1124  		typ = ar
1125  	}
1126  	alloc := fb.emitAlloc(typ, 0)
1127  	elemTyp := ar.Elem()
1128  	for i, el := range e.ElemList {
1129  		var expr syntax.Expr
1130  		if kv, ok := el.(*syntax.KeyValueExpr); ok {
1131  			expr = kv.Value
1132  		} else {
1133  			expr = el
1134  		}
1135  		var v SSAValue
1136  		if cl, ok := expr.(*syntax.CompositeLit); ok && cl.Type == nil {
1137  			v = fb.buildCompositeLitWithType(cl, elemTyp)
1138  		} else {
1139  			v = fb.buildExpr(expr)
1140  		}
1141  		if v == nil {
1142  			continue
1143  		}
1144  		idx := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(i)}}
1145  		ia := &SSAIndexAddr{X: alloc, Index: idx}
1146  		ia.typ = types.NewPointer(elemTyp)
1147  		ia.name = fb.nextName()
1148  		fb.emit(ia)
1149  		v = fb.coerceToInterface(v, elemTyp)
1150  		fb.emitStore(ia, v)
1151  	}
1152  	return fb.emitLoad(alloc, typ)
1153  }
1154  
1155  func (fb *ssaFuncBuilder) buildCompositeLitWithType(e *syntax.CompositeLit, typ types.Type) (s SSAValue) {
1156  	if sl, ok := types.SafeUnderlying(typ).(*types.Slice); ok {
1157  		return fb.buildSliceLit(e, typ, sl)
1158  	}
1159  	if ar, isArr := types.SafeUnderlying(typ).(*types.Array); isArr {
1160  		return fb.buildArrayLit(e, typ, ar)
1161  	}
1162  	alloc := fb.emitAlloc(typ, 0)
1163  	posIdx := 0
1164  	for _, el := range e.ElemList {
1165  		if kv, ok := el.(*syntax.KeyValueExpr); ok {
1166  			if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1167  				idx := fb.fieldIndex(typ, kv.Key.(*syntax.Name).Value)
1168  				if idx >= 0 {
1169  					ft := fb.fieldType(typ, idx)
1170  					fa := &SSAFieldAddr{X: alloc, Field: idx}
1171  					fa.typ = types.NewPointer(ft)
1172  					fa.name = fb.nextName()
1173  					fb.emit(fa)
1174  					v := fb.buildExpr(kv.Value)
1175  					if v != nil {
1176  						v = fb.coerceToInterface(v, ft)
1177  						fb.emitStore(fa, v)
1178  					}
1179  				}
1180  			}
1181  		} else {
1182  			v := fb.buildExpr(el)
1183  			if v != nil {
1184  				if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1185  					ft := fb.fieldType(typ, posIdx)
1186  					fa := &SSAFieldAddr{X: alloc, Field: posIdx}
1187  					fa.typ = types.NewPointer(ft)
1188  					fa.name = fb.nextName()
1189  					fb.emit(fa)
1190  					v = fb.coerceToInterface(v, ft)
1191  					fb.emitStore(fa, v)
1192  				}
1193  			}
1194  			posIdx++
1195  		}
1196  	}
1197  	return fb.emitLoad(alloc, typ)
1198  }
1199  
1200  func (fb *ssaFuncBuilder) buildSliceLit(e *syntax.CompositeLit, typ types.Type, sl *types.Slice) (s SSAValue) {
1201  	n := len(e.ElemList)
1202  	nVal := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(n)}}
1203  	ms := &SSAMakeSlice{}
1204  	ms.typ = typ
1205  	ms.name = fb.nextName()
1206  	ms.Len = nVal
1207  	ms.Cap = nVal
1208  	fb.emit(ms)
1209  
1210  	elemTyp := sl.Elem()
1211  	for i, el := range e.ElemList {
1212  		var expr syntax.Expr
1213  		if kv, ok := el.(*syntax.KeyValueExpr); ok {
1214  			expr = kv.Value
1215  		} else {
1216  			expr = el
1217  		}
1218  		var v SSAValue
1219  		if cl, ok := expr.(*syntax.CompositeLit); ok && cl.Type == nil {
1220  			v = fb.buildCompositeLitWithType(cl, elemTyp)
1221  		} else {
1222  			v = fb.buildExpr(expr)
1223  		}
1224  		if v == nil {
1225  			continue
1226  		}
1227  		idx := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(i)}}
1228  		ia := &SSAIndexAddr{X: ms, Index: idx}
1229  		ia.typ = types.NewPointer(elemTyp)
1230  		ia.name = fb.nextName()
1231  		fb.emit(ia)
1232  		v = fb.coerceToInterface(v, elemTyp)
1233  		fb.emitStore(ia, v)
1234  	}
1235  	return ms
1236  }
1237  
1238  func (fb *ssaFuncBuilder) buildFuncLit(e *syntax.FuncLit) (s SSAValue) {
1239  	var sig *types.Signature
1240  	if fb.info != nil {
1241  		if tv, ok := fb.info.Types[e]; ok {
1242  			sig, _ = tv.Type.(*types.Signature)
1243  		}
1244  	}
1245  	if sig == nil && e.Type != nil {
1246  		sig = tcResolveFuncInline(e.Type, fb.fn.Pkg.Pkg.Scope())
1247  	}
1248  	name := fb.fn.name | "__anon" | ssaItoa(len(fb.fn.AnonFuncs)+1)
1249  	anon := &SSAFunction{
1250  		name:      name,
1251  		Signature: sig,
1252  		pos:       0,
1253  		Pkg:       fb.fn.Pkg,
1254  		Prog:      fb.fn.Prog,
1255  		parent:    fb.fn,
1256  	}
1257  	fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, anon)
1258  
1259  	ab := newSSAFuncBuilder(anon, fb.info)
1260  	ab.parent = fb
1261  	d := &syntax.FuncDecl{
1262  		Name: &Name{Value: name},
1263  		Type: e.Type,
1264  		Body: e.Body,
1265  	}
1266  	ab.buildBody(d)
1267  
1268  	if len(anon.FreeVars) == 0 {
1269  		return anon
1270  	}
1271  	bindings := []SSAValue{:0:len(anon.FreeVars)}
1272  	for _, fv := range anon.FreeVars {
1273  		obj := fb.lookupObject(fv.name)
1274  		if obj != nil {
1275  			if alloc, ok := fb.vars[obj]; ok {
1276  				alloc.Heap = true
1277  				bindings = append(bindings, alloc)
1278  			} else if pfv, ok := fb.freeVarPtrs[fv.name]; ok {
1279  				bindings = append(bindings, pfv)
1280  			} else {
1281  				bindings = append(bindings, &SSAConst{typ: types.NewPointer(fv.typ), val: nil})
1282  			}
1283  		} else if pfv, ok := fb.freeVarPtrs[fv.name]; ok {
1284  			bindings = append(bindings, pfv)
1285  		} else {
1286  			bindings = append(bindings, &SSAConst{typ: types.NewPointer(fv.typ), val: nil})
1287  		}
1288  	}
1289  	mc := &SSAMakeClosure{Fn: anon, Bindings: bindings}
1290  	mc.typ = sig
1291  	mc.name = fb.nextName()
1292  	fb.emit(mc)
1293  	return mc
1294  }
1295  
1296  func (fb *ssaFuncBuilder) saveVars() (m map[types.Object]*SSAAlloc) {
1297  	saved := map[types.Object]*SSAAlloc{}
1298  	for k, v := range fb.vars {
1299  		saved[k] = v
1300  	}
1301  	return saved
1302  }
1303  
1304  func (fb *ssaFuncBuilder) removeVar(name string) {
1305  	for o := range fb.vars {
1306  		if o.Name() == name {
1307  			delete(fb.vars, o)
1308  			return
1309  		}
1310  	}
1311  }
1312  
1313  
1314  func (fb *ssaFuncBuilder) buildPkgMemberAddr(pn *types.PkgName, memberName string) (s SSAValue) {
1315  	imported := pn.Imported()
1316  	if imported == nil {
1317  		return nil
1318  	}
1319  	obj := imported.Scope().Lookup(memberName)
1320  	if obj == nil {
1321  		return nil
1322  	}
1323  	switch obj := obj.(type) {
1324  	case *types.TCConst:
1325  		return nil
1326  	case *types.TCVar:
1327  		impPkg := fb.ensureImportedSSAPackage(imported)
1328  		g, ok := impPkg.Members[memberName].(*SSAGlobal)
1329  		if !ok {
1330  			g = &SSAGlobal{
1331  				name: memberName,
1332  				typ:  types.NewPointer(obj.Type()),
1333  				pkg:  impPkg,
1334  			}
1335  			impPkg.Members[memberName] = g
1336  		}
1337  		return g
1338  	}
1339  	return nil
1340  }
1341  
1342  func (fb *ssaFuncBuilder) buildPkgCall(pn *types.PkgName, funcName string, argList []syntax.Expr, hasDots bool) (s SSAValue) {
1343  	imported := pn.Imported()
1344  	if imported == nil {
1345  		return nil
1346  	}
1347  	if imported.Path() == "unsafe" && funcName == "Slice" {
1348  		return fb.buildUnsafeSlice(argList)
1349  	}
1350  	if imported.Path() == "unsafe" && funcName == "SliceData" {
1351  		arg := fb.buildExpr(argList[0])
1352  		extract := &SSAExtract{Tuple: arg, Index: 0}
1353  		extract.typ = types.Typ[types.UnsafePointer]
1354  		extract.name = fb.nextName()
1355  		extract.setBlock(fb.currentBlock)
1356  		fb.currentBlock.Instrs = append(fb.currentBlock.Instrs, extract)
1357  		return extract
1358  	}
1359  	if result := fb.tryGenericPkgCall(pn, funcName, argList, hasDots); result != nil {
1360  		return result
1361  	}
1362  	obj := imported.Scope().Lookup(funcName)
1363  	if obj == nil {
1364  		return nil
1365  	}
1366  	fn, ok := obj.(*types.TCFunc)
1367  	if !ok {
1368  		return nil
1369  	}
1370  	impPkg := fb.ensureImportedSSAPackage(imported)
1371  	ssaFn := impPkg.Func(funcName)
1372  	if ssaFn == nil {
1373  		ssaFn = &SSAFunction{
1374  			name:      funcName,
1375  			object:    fn,
1376  			Signature: fn.Type().(*types.Signature),
1377  			Pkg:       impPkg,
1378  			Prog:      fb.fn.Prog,
1379  		}
1380  		if isNoContextExtern(imported.Path(), funcName) {
1381  			ssaFn.isExternC = true
1382  		}
1383  		impPkg.Members[funcName] = ssaFn
1384  	}
1385  	args := fb.buildArgs(argList)
1386  	var retType types.Type
1387  	if ssaFn.Signature != nil {
1388  		if ssaFn.Signature.Variadic() && !hasDots {
1389  			args = fb.wrapVariadicArgs(args, ssaFn.Signature)
1390  		}
1391  		args = fb.coerceArgsToInterface(args, ssaFn.Signature)
1392  		if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() == 1 {
1393  			retType = ssaFn.Signature.Results().At(0).Type()
1394  		} else if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() > 1 {
1395  			retType = ssaFn.Signature.Results()
1396  		}
1397  	}
1398  	call := &SSACall{Call: SSACallCommon{Value: ssaFn, Args: args}}
1399  	call.typ = retType
1400  	call.name = fb.nextName()
1401  	fb.emit(call)
1402  	if retType == nil {
1403  		return nil
1404  	}
1405  	return call
1406  }
1407  
1408  func (fb *ssaFuncBuilder) buildUnsafeSlice(argList []syntax.Expr) (s SSAValue) {
1409  	if len(argList) < 2 {
1410  		return nil
1411  	}
1412  	ptrVal := fb.buildExpr(argList[0])
1413  	lenVal := fb.buildExpr(argList[1])
1414  	if ptrVal == nil || lenVal == nil {
1415  		return nil
1416  	}
1417  	var elemType types.Type
1418  	if pt, ok := types.SafeUnderlying(ptrVal.SSAType()).(*types.Pointer); ok {
1419  		elemType = pt.Elem()
1420  	}
1421  	if elemType == nil {
1422  		elemType = types.Typ[types.Uint8]
1423  	}
1424  	ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal, Data: ptrVal}
1425  	if b, ok := elemType.(*types.Basic); ok && b.Kind() == types.Uint8 {
1426  		ms.typ = types.Typ[types.TCString]
1427  	} else {
1428  		ms.typ = types.NewSlice(elemType)
1429  	}
1430  	ms.name = fb.nextName()
1431  	fb.emit(ms)
1432  	return ms
1433  }
1434  
1435  // Helpers.
1436  
1437  func (fb *ssaFuncBuilder) lookupObject(name string) (o Object) {
1438  	for obj := range fb.vars {
1439  		if obj.Name() == name {
1440  			return obj
1441  		}
1442  	}
1443  	if fb.parent != nil {
1444  		for obj := range fb.parent.vars {
1445  			if obj.Name() == name {
1446  				return obj
1447  			}
1448  		}
1449  	}
1450  	if fb.srcScope != nil {
1451  		if _, obj := fb.srcScope.LookupParent(name); obj != nil {
1452  			return obj
1453  		}
1454  	}
1455  	if fb.fn.Pkg != nil {
1456  		if _, obj := fb.fn.Pkg.Pkg.Scope().LookupParent(name); obj != nil {
1457  			return obj
1458  		}
1459  	}
1460  	if fb.info != nil {
1461  		return nil
1462  	}
1463  	return nil
1464  }
1465  
1466  func (fb *ssaFuncBuilder) getOrCreateFreeVar(name string, typ types.Type) (s SSAValue) {
1467  	for _, fv := range fb.fn.FreeVars {
1468  		if fv.name == name {
1469  			return fv
1470  		}
1471  	}
1472  	fv := &SSAFreeVar{
1473  		name:   name,
1474  		typ:    typ,
1475  		parent: fb.fn,
1476  	}
1477  	fb.fn.FreeVars = append(fb.fn.FreeVars, fv)
1478  	if fb.freeVarPtrs == nil {
1479  		fb.freeVarPtrs = map[string]*SSAFreeVar{}
1480  	}
1481  	fb.freeVarPtrs[name] = fv
1482  	return fv
1483  }
1484  
1485  func (fb *ssaFuncBuilder) lookupVar(name string) (t *types.TCVar) {
1486  	obj := fb.lookupObject(name)
1487  	v, _ := obj.(*types.TCVar)
1488  	return v
1489  }
1490