ssa_types.mx raw

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