ssa_types.mx raw

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