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