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