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  }
 467  
 468  func (m *SSAMakeSlice) InstrPos() int32    { return m.pos }
 469  func (m *SSAMakeSlice) InstrString() string { return "makeslice" }
 470  
 471  // Slice.
 472  type SSASlice struct {
 473  	ssaRegister
 474  	X    SSAValue
 475  	Low  SSAValue
 476  	High SSAValue
 477  	Max  SSAValue
 478  }
 479  
 480  func (s *SSASlice) InstrPos() int32    { return s.pos }
 481  func (s *SSASlice) InstrString() string { return "slice" }
 482  
 483  // FieldAddr.
 484  type SSAFieldAddr struct {
 485  	ssaRegister
 486  	X     SSAValue
 487  	Field int
 488  }
 489  
 490  func (f *SSAFieldAddr) InstrPos() int32    { return f.pos }
 491  func (f *SSAFieldAddr) InstrString() string { return "fieldaddr" }
 492  
 493  // IndexAddr.
 494  type SSAIndexAddr struct {
 495  	ssaRegister
 496  	X     SSAValue
 497  	Index SSAValue
 498  }
 499  
 500  func (i *SSAIndexAddr) InstrPos() int32    { return i.pos }
 501  func (i *SSAIndexAddr) InstrString() string { return "indexaddr" }
 502  
 503  // Lookup (map[k]).
 504  type SSALookup struct {
 505  	ssaRegister
 506  	X       SSAValue
 507  	Index   SSAValue
 508  	CommaOk bool
 509  }
 510  
 511  func (l *SSALookup) InstrPos() int32    { return l.pos }
 512  func (l *SSALookup) InstrString() string { return "lookup" }
 513  
 514  // Range.
 515  type SSARange struct {
 516  	ssaRegister
 517  	X SSAValue
 518  }
 519  
 520  func (r *SSARange) InstrPos() int32    { return r.pos }
 521  func (r *SSARange) InstrString() string { return "range" }
 522  
 523  // Next (iterator advance).
 524  type SSANext struct {
 525  	ssaRegister
 526  	Iter     SSAValue
 527  	IsString bool
 528  }
 529  
 530  func (n *SSANext) InstrPos() int32    { return n.pos }
 531  func (n *SSANext) InstrString() string { return "next" }
 532  
 533  // TypeAssert.
 534  type SSATypeAssert struct {
 535  	ssaRegister
 536  	X            SSAValue
 537  	AssertedType Type
 538  	CommaOk      bool
 539  }
 540  
 541  func (t *SSATypeAssert) InstrPos() int32    { return t.pos }
 542  func (t *SSATypeAssert) InstrString() string { return "typeassert" }
 543  
 544  // Extract (tuple component).
 545  type SSAExtract struct {
 546  	ssaRegister
 547  	Tuple SSAValue
 548  	Index int
 549  }
 550  
 551  func (e *SSAExtract) InstrPos() int32    { return e.pos }
 552  func (e *SSAExtract) InstrString() string { return "extract" }
 553  
 554  // -- Terminator instructions --
 555  
 556  // Jump.
 557  type SSAJump struct {
 558  	ssaInstr
 559  	Comment string
 560  }
 561  
 562  func (j *SSAJump) InstrPos() int32    { return 0 }
 563  func (j *SSAJump) InstrString() string { return "jump " | j.Comment }
 564  
 565  // If.
 566  type SSAIf struct {
 567  	ssaInstr
 568  	Cond SSAValue
 569  }
 570  
 571  func (i *SSAIf) InstrPos() int32    { return 0 }
 572  func (i *SSAIf) InstrString() string { return "if" }
 573  
 574  // Return.
 575  type SSAReturn struct {
 576  	ssaInstr
 577  	Results []SSAValue
 578  	pos     int32
 579  }
 580  
 581  func (r *SSAReturn) InstrPos() int32    { return r.pos }
 582  func (r *SSAReturn) InstrString() string { return "return" }
 583  
 584  // RunDefers.
 585  type SSARunDefers struct {
 586  	ssaInstr
 587  }
 588  
 589  func (rd *SSARunDefers) InstrPos() int32    { return 0 }
 590  func (rd *SSARunDefers) InstrString() string { return "rundefers" }
 591  
 592  // Panic.
 593  type SSAPanic struct {
 594  	ssaInstr
 595  	X   SSAValue
 596  	pos int32
 597  }
 598  
 599  func (p *SSAPanic) InstrPos() int32    { return p.pos }
 600  func (p *SSAPanic) InstrString() string { return "panic" }
 601  
 602  // Go (spawn).
 603  type SSAGo struct {
 604  	ssaInstr
 605  	Call SSACallCommon
 606  	pos  int32
 607  }
 608  
 609  func (g *SSAGo) InstrPos() int32    { return g.pos }
 610  func (g *SSAGo) InstrString() string { return "go" }
 611  
 612  // Defer.
 613  type SSADefer struct {
 614  	ssaInstr
 615  	Call SSACallCommon
 616  	pos  int32
 617  }
 618  
 619  func (d *SSADefer) InstrPos() int32    { return d.pos }
 620  func (d *SSADefer) InstrString() string { return "defer" }
 621  
 622  // -- Side-effecting instructions --
 623  
 624  // Send.
 625  type SSASend struct {
 626  	ssaInstr
 627  	Chan SSAValue
 628  	X    SSAValue
 629  	pos  int32
 630  }
 631  
 632  func (s *SSASend) InstrPos() int32    { return s.pos }
 633  func (s *SSASend) InstrString() string { return "send" }
 634  
 635  // Store.
 636  type SSAStore struct {
 637  	ssaInstr
 638  	Addr SSAValue
 639  	Val  SSAValue
 640  	pos  int32
 641  }
 642  
 643  func (s *SSAStore) InstrPos() int32    { return s.pos }
 644  func (s *SSAStore) InstrString() string { return "store" }
 645  
 646  // MapUpdate.
 647  type SSAMapUpdate struct {
 648  	ssaInstr
 649  	Map   SSAValue
 650  	Key   SSAValue
 651  	Value SSAValue
 652  	pos   int32
 653  }
 654  
 655  func (m *SSAMapUpdate) InstrPos() int32    { return m.pos }
 656  func (m *SSAMapUpdate) InstrString() string { return "mapupdate" }
 657  
 658  // SelectState describes one case of a select statement.
 659  type SSASelectState struct {
 660  	Dir  token.Token // token.ARROW for send, token.DEFAULT for recv
 661  	Chan SSAValue
 662  	Send SSAValue
 663  }
 664  
 665  // Select instruction.
 666  type SSASelect struct {
 667  	ssaRegister
 668  	States   []*SSASelectState
 669  	Blocking bool
 670  }
 671  
 672  func (s *SSASelect) InstrPos() int32    { return s.pos }
 673  func (s *SSASelect) InstrString() string { return "select" }
 674  
 675  // Operator mapping from syntax.Operator to SSAOp.
 676  func syntaxOpToSSAOp(op Operator, unary bool) SSAOp {
 677  	if unary {
 678  		switch op {
 679  		case Not:
 680  			return OpNot
 681  		case Recv:
 682  			return OpArrow
 683  		case And:
 684  			return OpAnd
 685  		case Mul:
 686  			return OpMul
 687  		case Sub:
 688  			return OpSub
 689  		case Xor:
 690  			return OpXor
 691  		}
 692  	}
 693  	switch op {
 694  	case Add:
 695  		return OpAdd
 696  	case Or:
 697  		return OpOr
 698  	case Sub:
 699  		return OpSub
 700  	case Mul:
 701  		return OpMul
 702  	case Div:
 703  		return OpQuo
 704  	case Rem:
 705  		return OpRem
 706  	case And:
 707  		return OpAnd
 708  	case Xor:
 709  		return OpXor
 710  	case Shl:
 711  		return OpShl
 712  	case Shr:
 713  		return OpShr
 714  	case AndNot:
 715  		return OpAndNot
 716  	case OrOr:
 717  		return OpLor
 718  	case AndAnd:
 719  		return OpLand
 720  	case Eql:
 721  		return OpEql
 722  	case Neq:
 723  		return OpNeq
 724  	case Lss:
 725  		return OpLss
 726  	case Leq:
 727  		return OpLeq
 728  	case Gtr:
 729  		return OpGtr
 730  	case Geq:
 731  		return OpGeq
 732  	}
 733  	return OpIllegal
 734  }
 735  
 736  func compoundOp(op Operator) SSAOp {
 737  	switch op {
 738  	case Add:
 739  		return OpAdd
 740  	case Or:
 741  		return OpOr
 742  	case Sub:
 743  		return OpSub
 744  	case Mul:
 745  		return OpMul
 746  	case Div:
 747  		return OpQuo
 748  	case Rem:
 749  		return OpRem
 750  	case And:
 751  		return OpAnd
 752  	case Xor:
 753  		return OpXor
 754  	case Shl:
 755  		return OpShl
 756  	case Shr:
 757  		return OpShr
 758  	case AndNot:
 759  		return OpAndNot
 760  	}
 761  	return OpIllegal
 762  }
 763  
 764  func ssaBuiltinID(name string) (BuiltinID, bool) {
 765  	switch name {
 766  	case "append":
 767  		return BuiltinAppend, true
 768  	case "cap":
 769  		return BuiltinCap, true
 770  	case "clear":
 771  		return BuiltinClear, true
 772  	case "close":
 773  		return BuiltinClose, true
 774  	case "copy":
 775  		return BuiltinCopy, true
 776  	case "delete":
 777  		return BuiltinDelete, true
 778  	case "len":
 779  		return BuiltinLen, true
 780  	case "make":
 781  		return BuiltinMake, true
 782  	case "max":
 783  		return BuiltinMax, true
 784  	case "min":
 785  		return BuiltinMin, true
 786  	case "new":
 787  		return BuiltinNew, true
 788  	case "panic":
 789  		return BuiltinPanic, true
 790  	case "print":
 791  		return BuiltinPrint, true
 792  	case "println":
 793  		return BuiltinPrintln, true
 794  	case "recover":
 795  		return BuiltinRecover, true
 796  	}
 797  	return 0, false
 798  }
 799  
 800  func ssaItoa(n int) string {
 801  	if n == 0 {
 802  		return "0"
 803  	}
 804  	neg := n < 0
 805  	if neg {
 806  		n = -n
 807  	}
 808  	buf := []byte{:0:20}
 809  	for n > 0 {
 810  		buf = append(buf, byte('0'+n%10))
 811  		n /= 10
 812  	}
 813  	if neg {
 814  		buf = append(buf, '-')
 815  	}
 816  	for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
 817  		buf[i], buf[j] = buf[j], buf[i]
 818  	}
 819  	return string(buf)
 820  }
 821  
 822  // Type helpers for SSA builder.
 823  func ssaElemType(t Type) Type {
 824  	if t == nil {
 825  		return nil
 826  	}
 827  	switch t := t.Underlying().(type) {
 828  	case *Slice:
 829  		return t.Elem()
 830  	case *Array:
 831  		return t.Elem()
 832  	case *TCMap:
 833  		return t.Elem()
 834  	case *Pointer:
 835  		return t.Elem()
 836  	case *Basic:
 837  		if t.Info()&IsString != 0 {
 838  			return Typ[Uint8]
 839  		}
 840  	}
 841  	return nil
 842  }
 843  
 844  func ssaChanElemType(t Type) Type {
 845  	if t == nil {
 846  		return nil
 847  	}
 848  	if ch, ok := t.Underlying().(*TCChan); ok {
 849  		return ch.Elem()
 850  	}
 851  	return nil
 852  }
 853  
 854  func ssaIsStringType(t Type) bool {
 855  	if t == nil {
 856  		return false
 857  	}
 858  	if b, ok := t.Underlying().(*Basic); ok {
 859  		return b.Info()&IsString != 0
 860  	}
 861  	return false
 862  }
 863  
 864  func ssaSliceOf(t Type) Type {
 865  	if t == nil {
 866  		return nil
 867  	}
 868  	if b, ok := t.Underlying().(*Basic); ok && b.Info()&IsString != 0 {
 869  		return t
 870  	}
 871  	switch t := t.Underlying().(type) {
 872  	case *Slice:
 873  		return t
 874  	case *Array:
 875  		if b, ok := t.Elem().(*Basic); ok && b.kind == Uint8 {
 876  			return Typ[TCString]
 877  		}
 878  		return NewSlice(t.Elem())
 879  	}
 880  	return Typ[TCString]
 881  }
 882  
 883  func ssaTupleElemType(t Type, i int) Type {
 884  	if t == nil {
 885  		return nil
 886  	}
 887  	if tup, ok := t.(*Tuple); ok && i < tup.Len() {
 888  		return tup.At(i).Type()
 889  	}
 890  	return nil
 891  }
 892  
 893  func ssaParseInt64(s string) int64 {
 894  	var n int64
 895  	for i := 0; i < len(s); i++ {
 896  		c := s[i]
 897  		if c < '0' || c > '9' {
 898  			break
 899  		}
 900  		n = n*10 + int64(c-'0')
 901  	}
 902  	return n
 903  }
 904