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