ssa_types.mx raw

   1  package main
   2  
   3  type SelectDir int32
   4  
   5  const (
   6  	SelectDirRecv SelectDir = 0
   7  	SelectDirSend SelectDir = 1
   8  )
   9  
  10  // SSA operator codes (replacing go/token.Token for BinOp/UnOp).
  11  type SSAOp int32
  12  
  13  const (
  14  	OpIllegal SSAOp = iota
  15  	OpAdd
  16  	OpSub
  17  	OpMul
  18  	OpQuo
  19  	OpRem
  20  	OpAnd
  21  	OpXor
  22  	OpShl
  23  	OpShr
  24  	OpOr
  25  	OpAndNot
  26  	OpLand
  27  	OpLor
  28  	OpArrow
  29  	OpNot
  30  	OpEql
  31  	OpNeq
  32  	OpLss
  33  	OpLeq
  34  	OpGtr
  35  	OpGeq
  36  )
  37  
  38  func (op SSAOp) String() string {
  39  	switch op {
  40  	case OpAdd:
  41  		return "+"
  42  	case OpSub:
  43  		return "-"
  44  	case OpMul:
  45  		return "*"
  46  	case OpQuo:
  47  		return "/"
  48  	case OpRem:
  49  		return "%"
  50  	case OpAnd:
  51  		return "&"
  52  	case OpXor:
  53  		return "^"
  54  	case OpOr:
  55  		return "|"
  56  	case OpShl:
  57  		return "<<"
  58  	case OpShr:
  59  		return ">>"
  60  	case OpAndNot:
  61  		return "&^"
  62  	case OpLand:
  63  		return "&&"
  64  	case OpLor:
  65  		return "||"
  66  	case OpArrow:
  67  		return "<-"
  68  	case OpNot:
  69  		return "!"
  70  	case OpEql:
  71  		return "=="
  72  	case OpNeq:
  73  		return "!="
  74  	case OpLss:
  75  		return "<"
  76  	case OpLeq:
  77  		return "<="
  78  	case OpGtr:
  79  		return ">"
  80  	case OpGeq:
  81  		return ">="
  82  	}
  83  	return "?"
  84  }
  85  
  86  // ssaConstString returns a string representation of a constant value.
  87  func ssaConstString(val ConstVal) string {
  88  	if val == nil {
  89  		return "nil"
  90  	}
  91  	return val.String()
  92  }
  93  
  94  // SSA Value interface.
  95  type SSAValue interface {
  96  	SSAName() string
  97  	String() string
  98  	SSAType() Type
  99  	SSAParent() *SSAFunction
 100  	SSAPos() int32
 101  }
 102  
 103  // SSA Instruction interface.
 104  type SSAInstruction interface {
 105  	InstrBlock() *SSABasicBlock
 106  	InstrParent() *SSAFunction
 107  	InstrPos() int32
 108  	InstrString() string
 109  	setBlock(*SSABasicBlock)
 110  }
 111  
 112  // SSA Member interface (package-level declaration).
 113  type SSAMember interface {
 114  	MemberName() string
 115  	MemberString() string
 116  	MemberType() Type
 117  	MemberPkg() *SSAPackage
 118  }
 119  
 120  // SSA Program - top-level container.
 121  type SSAProgram struct {
 122  	imported map[string]*SSAPackage
 123  	packages map[*TCPackage]*SSAPackage
 124  }
 125  
 126  func NewSSAProgram() *SSAProgram {
 127  	return &SSAProgram{
 128  		imported: map[string]*SSAPackage{},
 129  		packages: map[*TCPackage]*SSAPackage{},
 130  	}
 131  }
 132  
 133  func (prog *SSAProgram) ImportedPackage(path string) *SSAPackage {
 134  	return prog.imported[path]
 135  }
 136  
 137  func (prog *SSAProgram) release() {
 138  	prog.imported = nil
 139  	prog.packages = nil
 140  }
 141  
 142  // SSA Package.
 143  type SSAPackage struct {
 144  	Prog    *SSAProgram
 145  	Pkg     *TCPackage
 146  	Members map[string]SSAMember
 147  }
 148  
 149  func (p *SSAPackage) Func(name string) *SSAFunction {
 150  	m := p.Members[name]
 151  	if m == nil {
 152  		return nil
 153  	}
 154  	var fn *SSAFunction
 155  	if okv, okok := m.(*SSAFunction); okok {
 156  		fn = okv
 157  	}
 158  	return fn
 159  }
 160  
 161  func (p *SSAPackage) ExternalFunc(name string, sig *Signature) *SSAFunction {
 162  	if fn := p.Func(name); fn != nil {
 163  		return fn
 164  	}
 165  	fn := &SSAFunction{
 166  		name:      name,
 167  		Signature: sig,
 168  		Pkg:       p,
 169  		Prog:      p.Prog,
 170  	}
 171  	p.Members[name] = fn
 172  	return fn
 173  }
 174  
 175  func (p *SSAPackage) release() {
 176  	for k, m := range p.Members {
 177  		if fn, ok := m.(*SSAFunction); ok {
 178  			fn.Blocks = nil
 179  			fn.Locals = nil
 180  			fn.AnonFuncs = nil
 181  			fn.Params = nil
 182  			fn.FreeVars = nil
 183  			fn.NamedResults = nil
 184  			fn.vars = nil
 185  			fn.Pkg = nil
 186  			fn.Prog = nil
 187  		}
 188  		delete(p.Members, k)
 189  	}
 190  	p.Prog = nil
 191  	p.Pkg = nil
 192  }
 193  
 194  // SSA Function.
 195  type SSAFunction struct {
 196  	name           string
 197  	object         *TCFunc
 198  	Signature      *Signature
 199  	pos            int32
 200  	Synthetic      string
 201  	externalSymbol string
 202  	isExternC      bool
 203  
 204  	Pkg  *SSAPackage
 205  	Prog *SSAProgram
 206  
 207  	Params       []*SSAParameter
 208  	FreeVars     []*SSAFreeVar
 209  	Locals       []*SSAAlloc
 210  	Blocks       []*SSABasicBlock
 211  	AnonFuncs    []*SSAFunction
 212  	NamedResults []*SSAAlloc
 213  
 214  	parent *SSAFunction
 215  	vars   map[Object]SSAValue
 216  }
 217  
 218  func (f *SSAFunction) MemberName() string   { return f.name }
 219  func (f *SSAFunction) MemberString() string { return f.name }
 220  func (f *SSAFunction) MemberType() Type {
 221  	if f.Signature == nil {
 222  		return nil
 223  	}
 224  	return f.Signature
 225  }
 226  func (f *SSAFunction) MemberPkg() *SSAPackage { return f.Pkg }
 227  func (f *SSAFunction) SSAName() string         { return f.name }
 228  func (f *SSAFunction) String() string          { return f.name }
 229  func (f *SSAFunction) SSAType() Type           { return f.MemberType() }
 230  func (f *SSAFunction) SSAParent() *SSAFunction { return f.parent }
 231  func (f *SSAFunction) SSAPos() int32           { return f.pos }
 232  
 233  // SSA BasicBlock.
 234  type SSABasicBlock struct {
 235  	Index   int32
 236  	Comment string
 237  	parent  *SSAFunction
 238  	Instrs  []SSAInstruction
 239  	Preds   []*SSABasicBlock
 240  	Succs   []*SSABasicBlock
 241  }
 242  
 243  func (b *SSABasicBlock) Parent() *SSAFunction { return b.parent }
 244  
 245  func NewSSABasicBlock(parent *SSAFunction, comment string) *SSABasicBlock {
 246  	b := &SSABasicBlock{
 247  		Index:   len(parent.Blocks),
 248  		Comment: comment,
 249  		parent:  parent,
 250  	}
 251  	parent.Blocks = append(parent.Blocks, b)
 252  	return b
 253  }
 254  
 255  // ssaRegister - shared base for instructions that produce a value.
 256  type ssaRegister struct {
 257  	ssaInstr
 258  	name string
 259  	typ  Type
 260  	pos  int32
 261  }
 262  
 263  func (r *ssaRegister) SSAName() string         { return r.name }
 264  func (r *ssaRegister) SSAType() Type           { return r.typ }
 265  func (r *ssaRegister) SSAPos() int32           { return r.pos }
 266  func (r *ssaRegister) SSAParent() *SSAFunction { if r.block != nil { return r.block.parent }; return nil }
 267  func (r *ssaRegister) String() string          { return r.name }
 268  func (r *ssaRegister) InstrBlock() *SSABasicBlock { return r.block }
 269  func (r *ssaRegister) InstrParent() *SSAFunction  { if r.block != nil { return r.block.parent }; return nil }
 270  func (r *ssaRegister) setBlock(b *SSABasicBlock)  { r.block = b }
 271  
 272  // ssaInstr - base for all instructions.
 273  type ssaInstr struct {
 274  	block *SSABasicBlock
 275  }
 276  
 277  func (a *ssaInstr) InstrBlock() *SSABasicBlock  { return a.block }
 278  func (a *ssaInstr) InstrParent() *SSAFunction   { return a.block.parent }
 279  func (a *ssaInstr) setBlock(b *SSABasicBlock)   { a.block = b }
 280  
 281  // Package-level global variable.
 282  type SSAGlobal struct {
 283  	name      string
 284  	object    *TCVar
 285  	typ       Type
 286  	pos       int32
 287  	pkg       *SSAPackage
 288  	initConst ConstVal
 289  	initType  Type
 290  }
 291  
 292  func (g *SSAGlobal) MemberName() string   { return g.name }
 293  func (g *SSAGlobal) MemberString() string { return g.pkg.Pkg.Path() | "." | g.name }
 294  func (g *SSAGlobal) MemberType() Type     { return g.typ }
 295  func (g *SSAGlobal) MemberPkg() *SSAPackage { return g.pkg }
 296  func (g *SSAGlobal) SSAName() string       { return g.name }
 297  func (g *SSAGlobal) String() string        { return g.MemberString() }
 298  func (g *SSAGlobal) SSAType() Type         { return g.typ }
 299  func (g *SSAGlobal) SSAParent() *SSAFunction { return nil }
 300  func (g *SSAGlobal) SSAPos() int32         { return g.pos }
 301  
 302  // Package-level named type.
 303  type SSAType_ struct {
 304  	object *TypeName
 305  	pkg    *SSAPackage
 306  }
 307  
 308  func (t *SSAType_) MemberName() string   { return t.object.Name() }
 309  func (t *SSAType_) MemberString() string { return t.pkg.Pkg.Path() | "." | t.object.Name() }
 310  func (t *SSAType_) MemberType() Type     { return t.object.Type() }
 311  func (t *SSAType_) MemberPkg() *SSAPackage { return t.pkg }
 312  
 313  // Package-level named constant.
 314  type SSANamedConst struct {
 315  	object *TCConst
 316  	Value  *SSAConst
 317  	pkg    *SSAPackage
 318  }
 319  
 320  func (c *SSANamedConst) MemberName() string   { return c.object.Name() }
 321  func (c *SSANamedConst) MemberString() string { return c.pkg.Pkg.Path() | "." | c.object.Name() }
 322  func (c *SSANamedConst) MemberType() Type     { return c.object.Type() }
 323  func (c *SSANamedConst) MemberPkg() *SSAPackage { return c.pkg }
 324  
 325  // Parameter.
 326  type SSAParameter struct {
 327  	name   string
 328  	object *TCVar
 329  	typ    Type
 330  	pos    int32
 331  	parent *SSAFunction
 332  }
 333  
 334  func (p *SSAParameter) SSAName() string         { return p.name }
 335  func (p *SSAParameter) String() string          { return p.name }
 336  func (p *SSAParameter) SSAType() Type           { return p.typ }
 337  func (p *SSAParameter) SSAParent() *SSAFunction { return p.parent }
 338  func (p *SSAParameter) SSAPos() int32           { return p.pos }
 339  
 340  // FreeVar (closure capture).
 341  type SSAFreeVar struct {
 342  	name   string
 343  	typ    Type
 344  	pos    int32
 345  	parent *SSAFunction
 346  }
 347  
 348  func (v *SSAFreeVar) SSAName() string         { return v.name }
 349  func (v *SSAFreeVar) String() string          { return v.name }
 350  func (v *SSAFreeVar) SSAType() Type           { return v.typ }
 351  func (v *SSAFreeVar) SSAParent() *SSAFunction { return v.parent }
 352  func (v *SSAFreeVar) SSAPos() int32           { return v.pos }
 353  
 354  // Const value.
 355  type SSAConst struct {
 356  	typ Type
 357  	val ConstVal
 358  }
 359  
 360  func NewSSAConst(val ConstVal, typ Type) *SSAConst {
 361  	return &SSAConst{typ: typ, val: val}
 362  }
 363  
 364  func (c *SSAConst) SSAName() string         { return ssaConstString(c.val) }
 365  func (c *SSAConst) String() string          { return ssaConstString(c.val) }
 366  func (c *SSAConst) SSAType() Type           { return c.typ }
 367  func (c *SSAConst) SSAParent() *SSAFunction { return nil }
 368  func (c *SSAConst) SSAPos() int32           { return 0 }
 369  func (c *SSAConst) Value() ConstVal         { return c.val }
 370  
 371  type SSABuiltin struct {
 372  	id   BuiltinID
 373  	name string
 374  }
 375  
 376  func (b *SSABuiltin) SSAName() string         { return b.name }
 377  func (b *SSABuiltin) String() string          { return b.name }
 378  func (b *SSABuiltin) SSAType() Type           { return nil }
 379  func (b *SSABuiltin) SSAParent() *SSAFunction { return nil }
 380  func (b *SSABuiltin) SSAPos() int32           { return 0 }
 381  
 382  // CallCommon describes a function/method call.
 383  type SSACallCommon struct {
 384  	Value   SSAValue
 385  	Args    []SSAValue
 386  	pos     int32
 387  	HasDots bool
 388  }
 389  
 390  // -- Instruction types --
 391  
 392  // Alloc allocates space for a variable.
 393  type SSAAlloc struct {
 394  	ssaRegister
 395  	Heap    bool
 396  	Comment string
 397  }
 398  
 399  func (a *SSAAlloc) InstrPos() int32    { return a.pos }
 400  func (a *SSAAlloc) InstrString() string {
 401  	if a.Heap {
 402  		return "new " | a.typ.String()
 403  	}
 404  	return "local " | a.typ.String()
 405  }
 406  
 407  // Phi node.
 408  type SSAPhi struct {
 409  	ssaRegister
 410  	Comment string
 411  	Edges   []SSAValue
 412  }
 413  
 414  func (p *SSAPhi) InstrPos() int32    { return p.pos }
 415  func (p *SSAPhi) InstrString() string { return "phi " | p.Comment }
 416  
 417  // Call instruction.
 418  type SSACall struct {
 419  	ssaRegister
 420  	Call SSACallCommon
 421  }
 422  
 423  func (c *SSACall) InstrPos() int32    { return c.Call.pos }
 424  func (c *SSACall) InstrString() string { return "call " | c.Call.Value.SSAName() }
 425  
 426  // BinOp.
 427  type SSABinOp struct {
 428  	ssaRegister
 429  	Op SSAOp
 430  	X  SSAValue
 431  	Y  SSAValue
 432  }
 433  
 434  func (b *SSABinOp) InstrPos() int32    { return b.pos }
 435  func (b *SSABinOp) InstrString() string { return "binop " | b.Op.String() }
 436  
 437  // UnOp.
 438  type SSAUnOp struct {
 439  	ssaRegister
 440  	Op      SSAOp
 441  	X       SSAValue
 442  	CommaOk bool
 443  }
 444  
 445  func (u *SSAUnOp) InstrPos() int32    { return u.pos }
 446  func (u *SSAUnOp) InstrString() string { return "unop " | u.Op.String() }
 447  
 448  // ChangeType.
 449  type SSAChangeType struct {
 450  	ssaRegister
 451  	X SSAValue
 452  }
 453  
 454  func (c *SSAChangeType) InstrPos() int32    { return c.pos }
 455  func (c *SSAChangeType) InstrString() string { return "changetype" }
 456  
 457  // Convert.
 458  type SSAConvert struct {
 459  	ssaRegister
 460  	X SSAValue
 461  }
 462  
 463  func (c *SSAConvert) InstrPos() int32    { return c.pos }
 464  func (c *SSAConvert) InstrString() string { return "convert" }
 465  
 466  // MakeInterface.
 467  type SSAMakeInterface struct {
 468  	ssaRegister
 469  	X     SSAValue
 470  	IType Type
 471  }
 472  
 473  func (m *SSAMakeInterface) InstrPos() int32    { return m.pos }
 474  func (m *SSAMakeInterface) InstrString() string { return "makeinterface" }
 475  
 476  // Invoke - interface method call.
 477  type SSAInvoke struct {
 478  	ssaRegister
 479  	X          SSAValue
 480  	MethodName string
 481  	IfaceType  *TCInterface
 482  	Args       []SSAValue
 483  }
 484  
 485  func (inv *SSAInvoke) InstrPos() int32    { return inv.pos }
 486  func (inv *SSAInvoke) InstrString() string { return "invoke " | inv.MethodName }
 487  
 488  // MakeClosure.
 489  type SSAMakeClosure struct {
 490  	ssaRegister
 491  	Fn       SSAValue
 492  	Bindings []SSAValue
 493  }
 494  
 495  func (m *SSAMakeClosure) InstrPos() int32    { return m.pos }
 496  func (m *SSAMakeClosure) InstrString() string { return "makeclosure" }
 497  
 498  // MakeMap.
 499  type SSAMakeMap struct {
 500  	ssaRegister
 501  	Reserve SSAValue
 502  }
 503  
 504  func (m *SSAMakeMap) InstrPos() int32    { return m.pos }
 505  func (m *SSAMakeMap) InstrString() string { return "makemap" }
 506  
 507  // MakeChan.
 508  type SSAMakeChan struct {
 509  	ssaRegister
 510  	Size SSAValue
 511  }
 512  
 513  func (m *SSAMakeChan) InstrPos() int32    { return m.pos }
 514  func (m *SSAMakeChan) InstrString() string { return "makechan" }
 515  
 516  // MakeSlice.
 517  type SSAMakeSlice struct {
 518  	ssaRegister
 519  	Len  SSAValue
 520  	Cap  SSAValue
 521  	Data SSAValue
 522  }
 523  
 524  func (m *SSAMakeSlice) InstrPos() int32    { return m.pos }
 525  func (m *SSAMakeSlice) InstrString() string { return "makeslice" }
 526  
 527  // Slice.
 528  type SSASlice struct {
 529  	ssaRegister
 530  	X    SSAValue
 531  	Low  SSAValue
 532  	High SSAValue
 533  	Max  SSAValue
 534  }
 535  
 536  func (s *SSASlice) InstrPos() int32    { return s.pos }
 537  func (s *SSASlice) InstrString() string { return "slice" }
 538  
 539  // FieldAddr.
 540  type SSAFieldAddr struct {
 541  	ssaRegister
 542  	X     SSAValue
 543  	Field int32
 544  }
 545  
 546  func (f *SSAFieldAddr) InstrPos() int32    { return f.pos }
 547  func (f *SSAFieldAddr) InstrString() string { return "fieldaddr" }
 548  
 549  // IndexAddr.
 550  type SSAIndexAddr struct {
 551  	ssaRegister
 552  	X     SSAValue
 553  	Index SSAValue
 554  }
 555  
 556  func (i *SSAIndexAddr) InstrPos() int32    { return i.pos }
 557  func (i *SSAIndexAddr) InstrString() string { return "indexaddr" }
 558  
 559  // Lookup (map[k]).
 560  type SSALookup struct {
 561  	ssaRegister
 562  	X       SSAValue
 563  	Index   SSAValue
 564  	CommaOk bool
 565  }
 566  
 567  func (l *SSALookup) InstrPos() int32    { return l.pos }
 568  func (l *SSALookup) InstrString() string { return "lookup" }
 569  
 570  // Range.
 571  type SSARange struct {
 572  	ssaRegister
 573  	X SSAValue
 574  }
 575  
 576  func (r *SSARange) InstrPos() int32    { return r.pos }
 577  func (r *SSARange) InstrString() string { return "range" }
 578  
 579  // Next (iterator advance).
 580  type SSANext struct {
 581  	ssaRegister
 582  	Iter     SSAValue
 583  	IsString bool
 584  }
 585  
 586  func (n *SSANext) InstrPos() int32    { return n.pos }
 587  func (n *SSANext) InstrString() string { return "next" }
 588  
 589  // TypeAssert.
 590  type SSATypeAssert struct {
 591  	ssaRegister
 592  	X            SSAValue
 593  	AssertedType Type
 594  	CommaOk      bool
 595  }
 596  
 597  func (t *SSATypeAssert) InstrPos() int32    { return t.pos }
 598  func (t *SSATypeAssert) InstrString() string { return "typeassert" }
 599  
 600  // Extract (tuple component).
 601  type SSAExtract struct {
 602  	ssaRegister
 603  	Tuple SSAValue
 604  	Index int32
 605  }
 606  
 607  func (e *SSAExtract) InstrPos() int32    { return e.pos }
 608  func (e *SSAExtract) InstrString() string { return "extract" }
 609  
 610  // -- Terminator instructions --
 611  
 612  // Jump.
 613  type SSAJump struct {
 614  	ssaInstr
 615  	Comment string
 616  }
 617  
 618  func (j *SSAJump) InstrPos() int32    { return 0 }
 619  func (j *SSAJump) InstrString() string { return "jump " | j.Comment }
 620  
 621  // If.
 622  type SSAIf struct {
 623  	ssaInstr
 624  	Cond SSAValue
 625  }
 626  
 627  func (i *SSAIf) InstrPos() int32    { return 0 }
 628  func (i *SSAIf) InstrString() string { return "if" }
 629  
 630  // Return.
 631  type SSAReturn struct {
 632  	ssaInstr
 633  	Results []SSAValue
 634  	pos     int32
 635  }
 636  
 637  func (r *SSAReturn) InstrPos() int32    { return r.pos }
 638  func (r *SSAReturn) InstrString() string { return "return" }
 639  
 640  // RunDefers.
 641  type SSARunDefers struct {
 642  	ssaInstr
 643  }
 644  
 645  func (rd *SSARunDefers) InstrPos() int32    { return 0 }
 646  func (rd *SSARunDefers) InstrString() string { return "rundefers" }
 647  
 648  // Panic.
 649  type SSAPanic struct {
 650  	ssaInstr
 651  	X   SSAValue
 652  	pos int32
 653  }
 654  
 655  func (p *SSAPanic) InstrPos() int32    { return p.pos }
 656  func (p *SSAPanic) InstrString() string { return "panic" }
 657  
 658  // Go (spawn).
 659  type SSAGo struct {
 660  	ssaInstr
 661  	Call SSACallCommon
 662  	pos  int32
 663  }
 664  
 665  func (g *SSAGo) InstrPos() int32    { return g.pos }
 666  func (g *SSAGo) InstrString() string { return "go" }
 667  
 668  // Defer.
 669  type SSADefer struct {
 670  	ssaInstr
 671  	Call SSACallCommon
 672  	pos  int32
 673  }
 674  
 675  func (d *SSADefer) InstrPos() int32    { return d.pos }
 676  func (d *SSADefer) InstrString() string { return "defer" }
 677  
 678  // -- Side-effecting instructions --
 679  
 680  // Send.
 681  type SSASend struct {
 682  	ssaInstr
 683  	Chan SSAValue
 684  	X    SSAValue
 685  	pos  int32
 686  }
 687  
 688  func (s *SSASend) InstrPos() int32    { return s.pos }
 689  func (s *SSASend) InstrString() string { return "send" }
 690  
 691  // Store.
 692  type SSAStore struct {
 693  	ssaInstr
 694  	Addr SSAValue
 695  	Val  SSAValue
 696  	pos  int32
 697  }
 698  
 699  func (s *SSAStore) InstrPos() int32    { return s.pos }
 700  func (s *SSAStore) InstrString() string { return "store" }
 701  
 702  // MapUpdate.
 703  type SSAMapUpdate struct {
 704  	ssaInstr
 705  	Map   SSAValue
 706  	Key   SSAValue
 707  	Value SSAValue
 708  	pos   int32
 709  }
 710  
 711  func (m *SSAMapUpdate) InstrPos() int32    { return m.pos }
 712  func (m *SSAMapUpdate) InstrString() string { return "mapupdate" }
 713  
 714  // SelectState describes one case of a select statement.
 715  type SSASelectState struct {
 716  	Dir  SelectDir
 717  	Chan SSAValue
 718  	Send SSAValue
 719  }
 720  
 721  // Select instruction.
 722  type SSASelect struct {
 723  	ssaRegister
 724  	States   []*SSASelectState
 725  	Blocking bool
 726  }
 727  
 728  func (s *SSASelect) InstrPos() int32    { return s.pos }
 729  func (s *SSASelect) InstrString() string { return "select" }
 730  
 731  // Operator mapping from syntax.Operator to SSAOp.
 732  func syntaxOpToSSAOp(op Operator, unary bool) SSAOp {
 733  	if unary {
 734  		switch op {
 735  		case Not:
 736  			return OpNot
 737  		case Recv:
 738  			return OpArrow
 739  		case And:
 740  			return OpAnd
 741  		case Mul:
 742  			return OpMul
 743  		case Sub:
 744  			return OpSub
 745  		case Xor:
 746  			return OpXor
 747  		}
 748  	}
 749  	switch op {
 750  	case Add:
 751  		return OpAdd
 752  	case Or:
 753  		return OpOr
 754  	case Sub:
 755  		return OpSub
 756  	case Mul:
 757  		return OpMul
 758  	case Div:
 759  		return OpQuo
 760  	case Rem:
 761  		return OpRem
 762  	case And:
 763  		return OpAnd
 764  	case Xor:
 765  		return OpXor
 766  	case Shl:
 767  		return OpShl
 768  	case Shr:
 769  		return OpShr
 770  	case AndNot:
 771  		return OpAndNot
 772  	case OrOr:
 773  		return OpLor
 774  	case AndAnd:
 775  		return OpLand
 776  	case Eql:
 777  		return OpEql
 778  	case Neq:
 779  		return OpNeq
 780  	case Lss:
 781  		return OpLss
 782  	case Leq:
 783  		return OpLeq
 784  	case Gtr:
 785  		return OpGtr
 786  	case Geq:
 787  		return OpGeq
 788  	}
 789  	return OpIllegal
 790  }
 791  
 792  func compoundOp(op Operator) SSAOp {
 793  	switch op {
 794  	case Add:
 795  		return OpAdd
 796  	case Or:
 797  		return OpOr
 798  	case Sub:
 799  		return OpSub
 800  	case Mul:
 801  		return OpMul
 802  	case Div:
 803  		return OpQuo
 804  	case Rem:
 805  		return OpRem
 806  	case And:
 807  		return OpAnd
 808  	case Xor:
 809  		return OpXor
 810  	case Shl:
 811  		return OpShl
 812  	case Shr:
 813  		return OpShr
 814  	case AndNot:
 815  		return OpAndNot
 816  	}
 817  	return OpIllegal
 818  }
 819  
 820  func ssaBuiltinID(name string) (BuiltinID, bool) {
 821  	switch name {
 822  	case "append":
 823  		return BuiltinAppend, true
 824  	case "cap":
 825  		return BuiltinCap, true
 826  	case "clear":
 827  		return BuiltinClear, true
 828  	case "close":
 829  		return BuiltinClose, true
 830  	case "copy":
 831  		return BuiltinCopy, true
 832  	case "delete":
 833  		return BuiltinDelete, true
 834  	case "len":
 835  		return BuiltinLen, true
 836  	case "make":
 837  		return BuiltinMake, true
 838  	case "max":
 839  		return BuiltinMax, true
 840  	case "min":
 841  		return BuiltinMin, true
 842  	case "new":
 843  		return BuiltinNew, true
 844  	case "panic":
 845  		return BuiltinPanic, true
 846  	case "print":
 847  		return BuiltinPrint, true
 848  	case "println":
 849  		return BuiltinPrintln, true
 850  	case "recover":
 851  		return BuiltinRecover, true
 852  	}
 853  	return 0, false
 854  }
 855  
 856  func ssaItoa(n int32) string {
 857  	if n == 0 {
 858  		return "0"
 859  	}
 860  	neg := n < 0
 861  	if neg {
 862  		n = -n
 863  	}
 864  	buf := []byte{:0:20}
 865  	for n > 0 {
 866  		buf = append(buf, byte('0'+n%10))
 867  		n /= 10
 868  	}
 869  	if neg {
 870  		buf = append(buf, '-')
 871  	}
 872  	for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
 873  		buf[i], buf[j] = buf[j], buf[i]
 874  	}
 875  	return string(buf)
 876  }
 877  
 878  // Type helpers for SSA builder.
 879  func ssaElemType(t Type) Type {
 880  	if t == nil {
 881  		return nil
 882  	}
 883  	switch t := safeUnderlying(t).(type) {
 884  	case *Slice:
 885  		return t.Elem()
 886  	case *Array:
 887  		return t.Elem()
 888  	case *TCMap:
 889  		return t.Elem()
 890  	case *Pointer:
 891  		return t.Elem()
 892  	case *Basic:
 893  		if t.Info()&IsString != 0 {
 894  			return Typ[Uint8]
 895  		}
 896  	}
 897  	return nil
 898  }
 899  
 900  func ssaChanElemType(t Type) Type {
 901  	if t == nil {
 902  		return nil
 903  	}
 904  	if ch, ok := safeUnderlying(t).(*TCChan); ok {
 905  		return ch.Elem()
 906  	}
 907  	return nil
 908  }
 909  
 910  func ssaIsStringType(t Type) bool {
 911  	if t == nil {
 912  		return false
 913  	}
 914  	if b, ok := safeUnderlying(t).(*Basic); ok {
 915  		return b.Info()&IsString != 0
 916  	}
 917  	return false
 918  }
 919  
 920  func ssaSliceOf(t Type) Type {
 921  	if t == nil {
 922  		return nil
 923  	}
 924  	if b, ok := safeUnderlying(t).(*Basic); ok && b.Info()&IsString != 0 {
 925  		return t
 926  	}
 927  	switch t := safeUnderlying(t).(type) {
 928  	case *Slice:
 929  		return t
 930  	case *Array:
 931  		if b, ok := t.Elem().(*Basic); ok && b.kind == Uint8 {
 932  			return Typ[TCString]
 933  		}
 934  		return NewSlice(t.Elem())
 935  	}
 936  	return Typ[TCString]
 937  }
 938  
 939  func ssaTupleElemType(t Type, i int32) Type {
 940  	if t == nil {
 941  		return nil
 942  	}
 943  	if tup, ok := t.(*Tuple); ok && i < tup.Len() {
 944  		return tup.At(i).Type()
 945  	}
 946  	return nil
 947  }
 948  
 949  func ssaParseInt64(s string) int32 {
 950  	var n int32
 951  	for i := 0; i < len(s); i++ {
 952  		c := s[i]
 953  		if c < '0' || c > '9' {
 954  			break
 955  		}
 956  		n = n*10 + int32(c-'0')
 957  	}
 958  	return n
 959  }
 960