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