ssa_expr.mx raw
1 package ssa
2
3 import (
4 "git.smesh.lol/moxie/pkg/token"
5 "git.smesh.lol/moxie/pkg/syntax"
6 "git.smesh.lol/moxie/pkg/types"
7 )
8
9 func (fb *ssaFuncBuilder) buildExpr(e syntax.Expr) (s SSAValue) {
10 if e == nil || fb.currentBlock == nil {
11 return nil
12 }
13 switch e := e.(type) {
14 case *syntax.Name:
15 return fb.buildIdent(e)
16 case *syntax.BasicLit:
17 return fb.buildLit(e)
18 case *syntax.Operation:
19 return fb.buildOperation(e)
20 case *syntax.CallExpr:
21 return fb.buildCall(e)
22 case *syntax.SelectorExpr:
23 return fb.buildSelector(e)
24 case *syntax.IndexExpr:
25 return fb.buildIndex(e)
26 case *syntax.SliceExpr:
27 return fb.buildSlice(e)
28 case *syntax.AssertExpr:
29 return fb.buildAssert(e)
30 case *syntax.CompositeLit:
31 return fb.buildCompositeLit(e)
32 case *syntax.FuncLit:
33 return fb.buildFuncLit(e)
34 case *syntax.ParenExpr:
35 return fb.buildExpr(e.X)
36 case *syntax.ListExpr:
37 var last SSAValue
38 for _, el := range e.ElemList {
39 last = fb.buildExpr(el)
40 }
41 return last
42 case *syntax.KeyValueExpr:
43 return fb.buildExpr(e.Value)
44 }
45 return nil
46 }
47
48 func (fb *ssaFuncBuilder) buildIdent(e *syntax.Name) (s SSAValue) {
49 if e.Value == "_" || e.Value == "nil" {
50 return &SSAConst{typ: nil, val: nil}
51 }
52 if fb.localConsts != nil {
53 if c, ok := fb.localConsts[e.Value]; ok {
54 return c
55 }
56 }
57 obj := fb.lookupObject(e.Value)
58 if obj == nil && fb.info != nil {
59 obj = fb.info.Uses[e]
60 }
61 if obj == nil && fb.parent != nil {
62 for p := fb.parent; p != nil; p = p.parent {
63 for pobj := range p.vars {
64 if pobj.Name() == e.Value {
65 fv := fb.getOrCreateFreeVar(e.Value, pobj.Type())
66 return fb.emitLoad(fv, pobj.Type())
67 }
68 }
69 if p.freeVarPtrs != nil {
70 if pfv, ok := p.freeVarPtrs[e.Value]; ok {
71 fv := fb.getOrCreateFreeVar(e.Value, pfv.typ)
72 return fb.emitLoad(fv, pfv.typ)
73 }
74 }
75 }
76 }
77 if obj == nil {
78 if fb.fn.Pkg != nil {
79 if fn, ok := fb.fn.Pkg.Members[e.Value].(*SSAFunction); ok {
80 return fn
81 }
82 if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
83 return fb.emitLoad(g, g.typ)
84 }
85 if nc, ok := fb.fn.Pkg.Members[e.Value].(*SSANamedConst); ok {
86 return nc.Value
87 }
88 }
89 return fb.builtinValue(e.Value)
90 }
91 switch obj := obj.(type) {
92 case *types.TCVar:
93 if alloc, ok := fb.vars[obj]; ok {
94 return fb.emitLoad(alloc, obj.Type())
95 }
96 if fv, ok := fb.freeVarPtrs[e.Value]; ok {
97 return fb.emitLoad(fv, obj.Type())
98 }
99 for p := fb.parent; p != nil; p = p.parent {
100 found := false
101 if _, ok := p.vars[obj]; ok {
102 found = true
103 }
104 if !found {
105 for pobj := range p.vars {
106 if pobj.Name() == e.Value {
107 found = true
108 break
109 }
110 }
111 }
112 if !found && p.freeVarPtrs != nil {
113 if _, ok := p.freeVarPtrs[e.Value]; ok {
114 found = true
115 }
116 }
117 if found {
118 fv := fb.getOrCreateFreeVar(e.Value, obj.Type())
119 return fb.emitLoad(fv, obj.Type())
120 }
121 }
122 if g, ok := fb.fn.Pkg.Members[e.Value].(*SSAGlobal); ok {
123 return fb.emitLoad(g, obj.Type())
124 }
125 return &SSAConst{typ: obj.Type(), val: nil}
126 case *types.TCConst:
127 return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
128 case *types.TCFunc:
129 fn, _ := fb.fn.Pkg.Members[e.Value].(*SSAFunction)
130 if fn != nil {
131 return fn
132 }
133 return &SSAConst{typ: obj.Type(), val: nil}
134 case *types.TypeName:
135 return nil
136 case *types.Builtin:
137 return &SSABuiltin{id: obj.ID(), name: obj.Name()}
138 }
139 return nil
140 }
141
142 func (fb *ssaFuncBuilder) builtinValue(name string) (s SSAValue) {
143 id, ok := ssaBuiltinID(name)
144 if !ok {
145 return nil
146 }
147 return &SSABuiltin{id: id, name: name}
148 }
149
150 func (fb *ssaFuncBuilder) buildLit(e *syntax.BasicLit) (s SSAValue) {
151 cv := evalBasicLitLocal(e)
152 if cv == nil {
153 return nil
154 }
155 switch e.Kind {
156 case token.IntLit:
157 return &SSAConst{typ: types.Typ[types.UntypedInt], val: cv}
158 case token.FloatLit:
159 return &SSAConst{typ: types.Typ[types.UntypedFloat], val: cv}
160 case token.StringLit:
161 return &SSAConst{typ: types.Typ[types.UntypedString], val: cv}
162 case token.RuneLit:
163 return &SSAConst{typ: types.Typ[types.UntypedRune], val: cv}
164 }
165 return nil
166 }
167
168 func (fb *ssaFuncBuilder) buildOperation(e *syntax.Operation) (s SSAValue) {
169 if e.Y == nil {
170 if e.Op == token.Add {
171 return fb.buildExpr(e.X)
172 }
173 op := syntaxOpToSSAOp(e.Op, true)
174 if op == OpAnd {
175 if name, ok := e.X.(*syntax.Name); ok {
176 obj := fb.lookupObject(name.Value)
177 if obj != nil {
178 if alloc, ok2 := fb.vars[obj]; ok2 {
179 return alloc
180 }
181 if g, ok2 := fb.fn.Pkg.Members[name.Value].(*SSAGlobal); ok2 {
182 return g
183 }
184 }
185 }
186 if ie, ok := e.X.(*syntax.IndexExpr); ok {
187 base := fb.buildExpr(ie.X)
188 idx := fb.buildExpr(ie.Index)
189 if base == nil || idx == nil {
190 return nil
191 }
192 ia := &SSAIndexAddr{X: base, Index: idx}
193 ia.typ = types.NewPointer(ssaElemType(base.SSAType()))
194 ia.name = fb.nextName()
195 fb.emit(ia)
196 return ia
197 }
198 if sel, ok := e.X.(*syntax.SelectorExpr); ok {
199 addr := fb.buildSelectorAddr(sel)
200 if addr != nil {
201 return addr
202 }
203 }
204 x := fb.buildExpr(e.X)
205 if x == nil {
206 return nil
207 }
208 a := &SSAAlloc{Heap: true}
209 a.typ = types.NewPointer(x.SSAType())
210 a.name = fb.nextName()
211 fb.emit(a)
212 fb.emitStore(a, x)
213 return a
214 }
215 x := fb.buildExpr(e.X)
216 if x == nil {
217 return nil
218 }
219 if op == OpArrow {
220 u := &SSAUnOp{Op: OpArrow, X: x}
221 u.typ = ssaChanElemType(x.SSAType())
222 u.name = fb.nextName()
223 fb.emit(u)
224 return u
225 }
226 u := &SSAUnOp{Op: op, X: x}
227 if op == OpMul {
228 if p, ok := x.SSAType().(*types.Pointer); ok {
229 u.typ = p.Elem()
230 } else {
231 u.typ = x.SSAType()
232 }
233 } else {
234 u.typ = x.SSAType()
235 }
236 u.name = fb.nextName()
237 fb.emit(u)
238 return u
239 }
240 op := syntaxOpToSSAOp(e.Op, false)
241 if op == OpLand || op == OpLor {
242 x := fb.buildExpr(e.X)
243 if x == nil {
244 return nil
245 }
246 rhsBlock := fb.newBlock("sc.rhs")
247 mergeBlock := fb.newBlock("sc.merge")
248 entryBlock := fb.currentBlock
249 fb.emit(&SSAIf{Cond: x})
250 if op == OpLand {
251 fb.currentBlock.Succs = append(fb.currentBlock.Succs, rhsBlock, mergeBlock)
252 } else {
253 fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock, rhsBlock)
254 }
255 rhsBlock.Preds = append(rhsBlock.Preds, entryBlock)
256 mergeBlock.Preds = append(mergeBlock.Preds, entryBlock)
257 fb.currentBlock = rhsBlock
258 y := fb.buildExpr(e.Y)
259 if y == nil {
260 y = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:false}}
261 }
262 fb.emit(&SSAJump{Comment: "sc.merge"})
263 fb.currentBlock.Succs = append(fb.currentBlock.Succs, mergeBlock)
264 mergeBlock.Preds = append(mergeBlock.Preds, fb.currentBlock)
265 fb.currentBlock = mergeBlock
266 var shortVal SSAValue
267 if op == OpLand {
268 shortVal = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:false}}
269 } else {
270 shortVal = &SSAConst{typ: types.Typ[types.Bool], val: &types.ConstBool{V:true}}
271 }
272 phi := &SSAPhi{Edges: []SSAValue{shortVal, y}, Comment: "sc"}
273 phi.typ = types.Typ[types.Bool]
274 phi.name = fb.nextName()
275 fb.emit(phi)
276 return phi
277 }
278 x := fb.buildExpr(e.X)
279 y := fb.buildExpr(e.Y)
280 if x == nil || y == nil {
281 return nil
282 }
283 if (op == OpOr || op == OpAdd) && x.SSAType() != nil && y.SSAType() != nil {
284 if isRuneKind(x.SSAType()) && isStringKind(y.SSAType()) || isStringKind(x.SSAType()) && isRuneKind(y.SSAType()) {
285 writeStr(2, "compile error: cannot concatenate rune with string - convert to UTF-8 first\n")
286 compileErrors = append(compileErrors, "cannot concatenate rune with string")
287 }
288 }
289 if xc, ok := x.(*SSAConst); ok {
290 if yc, ok2 := y.(*SSAConst); ok2 {
291 if xc.val != nil && yc.val != nil {
292 folded := evalBinaryLocal(e.Op, xc.val, yc.val)
293 if folded != nil {
294 ct := xc.typ
295 if ct == nil {
296 ct = yc.typ
297 }
298 if _, isBool := folded.(*types.ConstBool); isBool {
299 ct = types.Typ[types.Bool]
300 }
301 return &SSAConst{typ: ct, val: folded}
302 }
303 }
304 }
305 }
306 b := &SSABinOp{Op: op, X: x, Y: y}
307 b.name = fb.nextName()
308 switch op {
309 case OpEql, OpNeq, OpLss, OpLeq, OpGtr, OpGeq:
310 b.typ = types.Typ[types.Bool]
311 default:
312 xT := x.SSAType()
313 yT := y.SSAType()
314 xUntyped := false
315 if xB, ok := types.SafeUnderlying(xT).(*types.Basic); ok && xB.Info()&IsUntyped != 0 {
316 xUntyped = true
317 }
318 if xT != nil && !xUntyped {
319 b.typ = xT
320 } else if yT != nil {
321 b.typ = yT
322 } else {
323 b.typ = xT
324 }
325 }
326 fb.emit(b)
327 return b
328 }
329
330 func (fb *ssaFuncBuilder) buildCall(e *syntax.CallExpr) (s SSAValue) {
331 if ie, ok := e.Fun.(*syntax.IndexExpr); ok {
332 if result := fb.tryGenericCallFromIndex(ie, e.ArgList, e.HasDots); result != nil {
333 return result
334 }
335 }
336 if name, ok := e.Fun.(*syntax.Name); ok {
337 obj := fb.lookupObject(name.Value)
338 if tn, ok2 := obj.(*types.TypeName); ok2 {
339 if _, isTP := tn.Type().(*types.TypeParam); !isTP {
340 args := fb.buildArgs(e.ArgList)
341 if len(args) == 1 && args[0] != nil {
342 conv := &SSAConvert{X: args[0]}
343 conv.typ = tn.Type()
344 conv.name = fb.nextName()
345 fb.emit(conv)
346 return conv
347 }
348 return nil
349 }
350 }
351 if result := fb.tryGenericLocalCall(name.Value, e.ArgList, e.HasDots); result != nil {
352 return result
353 }
354 }
355 if convType := fb.resolveTypeAST(e.Fun); convType != nil {
356 args := fb.buildArgs(e.ArgList)
357 if len(args) == 1 && args[0] != nil {
358 conv := &SSAConvert{X: args[0]}
359 conv.typ = convType
360 conv.name = fb.nextName()
361 fb.emit(conv)
362 return conv
363 }
364 return nil
365 }
366 if sel, ok := e.Fun.(*syntax.SelectorExpr); ok {
367 if name, ok2 := sel.X.(*syntax.Name); ok2 {
368 obj := fb.lookupObject(name.Value)
369 if pn, ok3 := obj.(*types.PkgName); ok3 {
370 return fb.buildPkgCall(pn, sel.Sel.Value, e.ArgList, e.HasDots)
371 }
372 }
373 recv := fb.buildExpr(sel.X)
374 if recv != nil && recv.SSAType() != nil {
375 if fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv); fn != nil {
376 args := fb.buildArgs(e.ArgList)
377 if fn.Signature != nil {
378 if fn.Signature.Variadic() && !e.HasDots {
379 args = fb.wrapVariadicArgs(args, fn.Signature)
380 }
381 args = fb.coerceArgsToInterface(args, fn.Signature)
382 }
383 allArgs := []SSAValue{:0:len(args) + 1}
384 allArgs = append(allArgs, fixedRecv)
385 for _, ma := range args {
386 allArgs = append(allArgs, ma)
387 }
388 var retType types.Type
389 if fn.Signature != nil {
390 if fn.Signature.Results() != nil && fn.Signature.Results().Len() == 1 {
391 retType = fn.Signature.Results().At(0).Type()
392 } else if fn.Signature.Results() != nil && fn.Signature.Results().Len() > 1 {
393 retType = fn.Signature.Results()
394 }
395 }
396 call := &SSACall{Call: SSACallCommon{Value: fn, Args: allArgs}}
397 call.typ = retType
398 call.name = fb.nextName()
399 fb.emit(call)
400 if retType == nil {
401 return nil
402 }
403 return call
404 }
405 if inv := fb.buildIfaceMethodCall(sel, recv, e.ArgList); inv != nil {
406 return inv
407 }
408 }
409 }
410 fn := fb.buildExpr(e.Fun)
411 args := fb.buildArgs(e.ArgList)
412
413 if fn == nil {
414 return nil
415 }
416 if bi, ok := fn.(*SSABuiltin); ok {
417 return fb.buildBuiltinCall(e, bi, args)
418 }
419
420 var retType types.Type
421 if fn.SSAType() != nil {
422 if sig, ok := types.SafeUnderlying(fn.SSAType()).(*types.Signature); ok {
423 if sig.Results() != nil && sig.Results().Len() == 1 {
424 retType = sig.Results().At(0).Type()
425 } else if sig.Results() != nil && sig.Results().Len() > 1 {
426 retType = sig.Results()
427 }
428 }
429 } else if ssaFn, ok := fn.(*SSAFunction); ok && ssaFn.Signature != nil {
430 sig := ssaFn.Signature
431 if sig.Results() != nil && sig.Results().Len() == 1 {
432 retType = sig.Results().At(0).Type()
433 } else if sig.Results() != nil && sig.Results().Len() > 1 {
434 retType = sig.Results()
435 }
436 }
437
438 if fn.SSAType() != nil {
439 if sig, ok := types.SafeUnderlying(fn.SSAType()).(*types.Signature); ok {
440 if sig.Variadic() && !e.HasDots {
441 args = fb.wrapVariadicArgs(args, sig)
442 }
443 args = fb.coerceArgsToInterface(args, sig)
444 }
445 }
446
447 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
448 call.typ = retType
449 call.name = fb.nextName()
450 fb.emit(call)
451
452 if retType == nil {
453 return nil
454 }
455 return call
456 }
457
458 func (fb *ssaFuncBuilder) coerceArgsToInterface(args []SSAValue, sig *types.Signature) (ss []SSAValue) {
459 if sig.Params() == nil {
460 return args
461 }
462 for i := 0; i < len(args) && i < sig.Params().Len(); i++ {
463 paramType := sig.Params().At(i).Type()
464 if paramType == nil || args[i] == nil || args[i].SSAType() == nil {
465 continue
466 }
467 _, isIface := types.SafeUnderlying(paramType).(*types.TCInterface)
468 if !isIface {
469 continue
470 }
471 _, argIsIface := types.SafeUnderlying(args[i].SSAType()).(*types.TCInterface)
472 if argIsIface {
473 continue
474 }
475 mi := &SSAMakeInterface{X: args[i], IType: paramType}
476 mi.typ = paramType
477 mi.name = fb.nextName()
478 fb.emit(mi)
479 args[i] = mi
480 }
481 return args
482 }
483
484 func (fb *ssaFuncBuilder) wrapVariadicArgs(args []SSAValue, sig *types.Signature) (ss []SSAValue) {
485 if sig.Params() == nil {
486 return args
487 }
488 nFixed := sig.Params().Len() - 1
489 if nFixed < 0 {
490 nFixed = 0
491 }
492 if nFixed > len(args) {
493 nFixed = len(args)
494 }
495 nVariadic := len(args) - nFixed
496 if nVariadic <= 0 {
497 nilSlice := NewSSAConst(&types.ConstNil{}, sig.Params().At(sig.Params().Len()-1).Type())
498 result := []SSAValue{:nFixed:nFixed}
499 copy(result, args[:nFixed])
500 return append(result, nilSlice)
501 }
502 sliceType := sig.Params().At(sig.Params().Len() - 1).Type()
503 var elemType types.Type
504 if sl, ok := types.SafeUnderlying(sliceType).(*types.Slice); ok {
505 elemType = sl.Elem()
506 }
507 // HasDots lost because closures can't write to captured named returns.
508 // Detect spread: if exactly 1 variadic arg whose type matches the
509 // variadic param's slice type, pass it through. This covers both
510 // concrete T and interface{} variadics (e.g. fmt.Print -> fmt.Fprint).
511 if nVariadic == 1 && elemType != nil {
512 argT := args[nFixed].SSAType()
513 if argT != nil && types.Identical(argT, sliceType) {
514 return args
515 }
516 }
517 lenVal := NewSSAConst(&types.ConstInt{V:int64(nVariadic)}, types.Typ[types.Int32])
518 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal}
519 ms.typ = sliceType
520 ms.name = fb.nextName()
521 fb.emit(ms)
522 for i := 0; i < nVariadic; i++ {
523 idx := NewSSAConst(&types.ConstInt{V:int64(i)}, types.Typ[types.Int32])
524 ia := &SSAIndexAddr{X: ms, Index: idx}
525 ia.typ = types.NewPointer(elemType)
526 ia.name = fb.nextName()
527 fb.emit(ia)
528 v := args[nFixed+i]
529 if elemType != nil {
530 v = fb.coerceToInterface(v, elemType)
531 }
532 fb.emitStore(ia, v)
533 }
534 result := []SSAValue{:nFixed:nFixed}
535 copy(result, args[:nFixed])
536 return append(result, ms)
537 }
538
539 func (fb *ssaFuncBuilder) buildArgs(argList []syntax.Expr) (ss []SSAValue) {
540 args := []SSAValue{:0:len(argList)}
541 for _, a := range argList {
542 v := fb.buildExpr(a)
543 if v != nil {
544 args = append(args, v)
545 }
546 }
547 if len(args) == 1 && args[0] != nil {
548 if t, ok := args[0].SSAType().(*types.Tuple); ok && t.Len() > 1 {
549 expanded := []SSAValue{:0:t.Len()}
550 for i := int32(0); i < int32(t.Len()); i++ {
551 ext := &SSAExtract{Tuple: args[0], Index: int32(i)}
552 ext.typ = t.At(int32(i)).Type()
553 ext.name = fb.nextName()
554 fb.emit(ext)
555 expanded = append(expanded, ext)
556 }
557 return expanded
558 }
559 }
560 return args
561 }
562
563 func (fb *ssaFuncBuilder) buildBuiltinCall(e *syntax.CallExpr, b *SSABuiltin, args []SSAValue) (s SSAValue) {
564 switch b.id {
565 case types.BuiltinLen, types.BuiltinCap:
566 if b.id == types.BuiltinLen && len(args) == 1 {
567 if c, ok := args[0].(*SSAConst); ok {
568 if cs, ok2 := c.val.(*types.ConstStr); ok2 {
569 return &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(len(cs.S))}}
570 }
571 }
572 }
573 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
574 call.typ = types.Typ[types.Int32]
575 call.name = fb.nextName()
576 fb.emit(call)
577 return call
578 case types.BuiltinAppend:
579 if len(args) > 1 {
580 if sl, ok := types.SafeUnderlying(args[0].SSAType()).(*types.Slice); ok {
581 if _, isIface := types.SafeUnderlying(sl.Elem()).(*types.TCInterface); isIface {
582 for i := 1; i < len(args); i++ {
583 if e.HasDots && i == 1 {
584 continue
585 }
586 if args[i] == nil || args[i].SSAType() == nil {
587 continue
588 }
589 if _, argIface := types.SafeUnderlying(args[i].SSAType()).(*types.TCInterface); argIface {
590 continue
591 }
592 mi := &SSAMakeInterface{X: args[i], IType: sl.Elem()}
593 mi.typ = sl.Elem()
594 mi.name = fb.nextName()
595 fb.emit(mi)
596 args[i] = mi
597 }
598 }
599 }
600 }
601 call := &SSACall{Call: SSACallCommon{Value: b, Args: args, HasDots: e.HasDots}}
602 if len(args) > 0 {
603 call.typ = args[0].SSAType()
604 }
605 call.name = fb.nextName()
606 fb.emit(call)
607 return call
608 case types.BuiltinMake:
609 if len(e.ArgList) == 0 {
610 return nil
611 }
612 typ := fb.resolveType(e.ArgList[0])
613 return fb.emitMake(typ, args)
614 case types.BuiltinNew:
615 if len(e.ArgList) == 0 {
616 return nil
617 }
618 typ := fb.resolveType(e.ArgList[0])
619 a := &SSAAlloc{Heap: true}
620 a.typ = types.NewPointer(typ)
621 a.name = fb.nextName()
622 fb.emit(a)
623 return a
624 case types.BuiltinPanic:
625 if len(args) > 0 {
626 fb.emit(&SSAPanic{X: args[0]})
627 fb.currentBlock = nil
628 }
629 return nil
630 case types.BuiltinClose, types.BuiltinDelete, types.BuiltinClear, types.BuiltinPrint, types.BuiltinPrintln:
631 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
632 call.name = fb.nextName()
633 fb.emit(call)
634 return nil
635 case types.BuiltinCopy:
636 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
637 call.typ = types.Typ[types.Int32]
638 call.name = fb.nextName()
639 fb.emit(call)
640 return call
641 case types.BuiltinRecover:
642 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
643 call.typ = types.NewTCInterface(nil, nil)
644 call.name = fb.nextName()
645 fb.emit(call)
646 return call
647 case types.BuiltinMin, types.BuiltinMax:
648 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
649 if len(args) > 0 && args[0] != nil {
650 call.typ = args[0].SSAType()
651 } else {
652 call.typ = types.Typ[types.Int32]
653 }
654 call.name = fb.nextName()
655 fb.emit(call)
656 return call
657 }
658 call := &SSACall{Call: SSACallCommon{Value: b, Args: args}}
659 call.name = fb.nextName()
660 fb.emit(call)
661 return call
662 }
663
664 func (fb *ssaFuncBuilder) emitMake(typ types.Type, sizeArgs []SSAValue) (s SSAValue) {
665 if typ == nil {
666 return nil
667 }
668 switch u := types.SafeUnderlying(typ).(type) {
669 case *types.Basic:
670 if u.Kind() == types.TCString {
671 ms := &SSAMakeSlice{}
672 ms.typ = typ
673 ms.name = fb.nextName()
674 if len(sizeArgs) > 0 {
675 ms.Len = sizeArgs[0]
676 }
677 if len(sizeArgs) > 1 {
678 ms.Cap = sizeArgs[1]
679 }
680 fb.emit(ms)
681 return ms
682 }
683 case *types.Slice:
684 ms := &SSAMakeSlice{}
685 ms.typ = typ
686 ms.name = fb.nextName()
687 if len(sizeArgs) > 0 {
688 ms.Len = sizeArgs[0]
689 }
690 if len(sizeArgs) > 1 {
691 ms.Cap = sizeArgs[1]
692 }
693 fb.emit(ms)
694 return ms
695 case *types.TCMap:
696 mm := &SSAMakeMap{}
697 mm.typ = typ
698 mm.name = fb.nextName()
699 if len(sizeArgs) > 0 {
700 mm.Reserve = sizeArgs[0]
701 }
702 fb.emit(mm)
703 return mm
704 case *types.TCChan:
705 mc := &SSAMakeChan{}
706 mc.typ = typ
707 mc.name = fb.nextName()
708 if len(sizeArgs) > 0 {
709 mc.Size = sizeArgs[0]
710 }
711 fb.emit(mc)
712 return mc
713 }
714 return nil
715 }
716
717 func (fb *ssaFuncBuilder) buildSelector(e *syntax.SelectorExpr) (s SSAValue) {
718 if name, ok := e.X.(*syntax.Name); ok {
719 obj := fb.lookupObject(name.Value)
720 if pn, ok2 := obj.(*types.PkgName); ok2 {
721 return fb.buildPkgMember(pn, e.Sel.Value)
722 }
723 }
724 fa := fb.buildSelectorAddr(e)
725 if fa != nil {
726 elemType := fa.SSAType()
727 if p, ok := types.SafeUnderlying(elemType).(*types.Pointer); ok {
728 elemType = p.Elem()
729 }
730 return fb.emitLoad(fa, elemType)
731 }
732 recv := fb.buildExpr(e.X)
733 if recv == nil {
734 return nil
735 }
736 return fb.buildMethodValue(e, recv)
737 }
738
739 func (fb *ssaFuncBuilder) buildMethodValue(sel *syntax.SelectorExpr, recv SSAValue) (s SSAValue) {
740 fn, fixedRecv := fb.resolveMethodCallWithRecv(sel, recv)
741 if fn == nil || fn.Signature == nil {
742 return nil
743 }
744 methodSig := fn.Signature
745 var wrapperParams *types.Tuple
746 if methodSig.Params() != nil && methodSig.Params().Len() > 0 {
747 vars := []*types.TCVar{:0:methodSig.Params().Len()}
748 for i := 0; i < methodSig.Params().Len(); i++ {
749 vars = append(vars, methodSig.Params().At(i))
750 }
751 wrapperParams = types.NewTuple(vars...)
752 }
753 wrapperSig := types.NewSignature(nil, wrapperParams, methodSig.Results(), methodSig.Variadic())
754 name := fb.fn.name | "__mval" | ssaItoa(len(fb.fn.AnonFuncs)+1)
755 wrapper := &SSAFunction{
756 name: name,
757 Signature: wrapperSig,
758 Pkg: fb.fn.Pkg,
759 Prog: fb.fn.Prog,
760 parent: fb.fn,
761 }
762 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, wrapper)
763 recvType := fixedRecv.SSAType()
764 fv := &SSAFreeVar{name: "recv", typ: recvType, parent: wrapper}
765 wrapper.FreeVars = append(wrapper.FreeVars, fv)
766 if wrapperParams != nil {
767 for i := 0; i < wrapperParams.Len(); i++ {
768 v := wrapperParams.At(i)
769 p := &SSAParameter{name: v.Name(), typ: v.Type(), parent: wrapper}
770 wrapper.Params = append(wrapper.Params, p)
771 }
772 }
773 entry := NewSSABasicBlock(wrapper, "entry")
774 args := []SSAValue{:0:1 + len(wrapper.Params)}
775 args = append(args, fv)
776 for _, p := range wrapper.Params {
777 args = append(args, p)
778 }
779 var retType types.Type
780 if methodSig.Results() != nil && methodSig.Results().Len() == 1 {
781 retType = methodSig.Results().At(0).Type()
782 } else if methodSig.Results() != nil && methodSig.Results().Len() > 1 {
783 retType = methodSig.Results()
784 }
785 call := &SSACall{Call: SSACallCommon{Value: fn, Args: args}}
786 call.typ = retType
787 call.name = "t1"
788 call.setBlock(entry)
789 entry.Instrs = append(entry.Instrs, call)
790 ret := &SSAReturn{}
791 if retType != nil {
792 ret.Results = []SSAValue{call}
793 }
794 ret.setBlock(entry)
795 entry.Instrs = append(entry.Instrs, ret)
796 mc := &SSAMakeClosure{Fn: wrapper, Bindings: []SSAValue{fixedRecv}}
797 mc.typ = wrapperSig
798 mc.name = fb.nextName()
799 fb.emit(mc)
800 return mc
801 }
802
803 func (fb *ssaFuncBuilder) ensureImportedSSAPackage(imported *types.TCPackage) (s *SSAPackage) {
804 impPkg := fb.fn.Prog.ImportedPackage(imported.Path())
805 if impPkg == nil {
806 impPkg = &SSAPackage{
807 Prog: fb.fn.Prog,
808 Pkg: imported,
809 Members: map[string]SSAMember{},
810 }
811 fb.fn.Prog.imported[imported.Path()] = impPkg
812 fb.fn.Prog.packages[imported] = impPkg
813 }
814 return impPkg
815 }
816
817 func (fb *ssaFuncBuilder) buildPkgMember(pn *types.PkgName, memberName string) (s SSAValue) {
818 imported := pn.Imported()
819 if imported == nil {
820 return nil
821 }
822 obj := imported.Scope().Lookup(memberName)
823 if obj == nil {
824 return nil
825 }
826 switch obj := obj.(type) {
827 case *types.TCConst:
828 return &SSAConst{typ: obj.Type(), val: localizeConstVal(obj.Val(), obj.Type())}
829 case *types.TCVar:
830 impPkg := fb.ensureImportedSSAPackage(imported)
831 g, ok := impPkg.Members[memberName].(*SSAGlobal)
832 if !ok {
833 g = &SSAGlobal{
834 name: memberName,
835 typ: types.NewPointer(obj.Type()),
836 pkg: impPkg,
837 }
838 impPkg.Members[memberName] = g
839 }
840 return fb.emitLoad(g, obj.Type())
841 case *types.TCFunc:
842 impPkg := fb.ensureImportedSSAPackage(imported)
843 fn := impPkg.Func(memberName)
844 if fn != nil {
845 return fn
846 }
847 return nil
848 }
849 return nil
850 }
851
852 func (fb *ssaFuncBuilder) buildSelectorAddr(e *syntax.SelectorExpr) (s SSAValue) {
853 var addr SSAValue
854 var structType types.Type
855 if inner, ok := e.X.(*syntax.SelectorExpr); ok {
856 addr = fb.buildSelectorAddr(inner)
857 if addr == nil {
858 return nil
859 }
860 structType = addr.SSAType()
861 if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
862 structType = p.Elem()
863 }
864 if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
865 ld := &SSAUnOp{Op: OpMul, X: addr}
866 ld.typ = structType
867 ld.name = fb.nextName()
868 fb.emit(ld)
869 addr = ld
870 structType = p.Elem()
871 }
872 } else if ie, ok := e.X.(*syntax.IndexExpr); ok {
873 x := fb.buildExpr(ie.X)
874 idx := fb.buildExpr(ie.Index)
875 if x == nil || idx == nil {
876 return nil
877 }
878 ia := &SSAIndexAddr{X: x, Index: idx}
879 elemT := ssaElemType(x.SSAType())
880 ia.typ = types.NewPointer(elemT)
881 ia.name = fb.nextName()
882 fb.emit(ia)
883 addr = ia
884 structType = elemT
885 if _, isPtr := types.SafeUnderlying(elemT).(*types.Pointer); isPtr {
886 ld := fb.emitLoad(ia, elemT)
887 addr = ld
888 structType = elemT
889 }
890 } else {
891 x := fb.buildExpr(e.X)
892 if x == nil || x.SSAType() == nil {
893 if name, ok := e.X.(*syntax.Name); ok {
894 obj := fb.lookupObject(name.Value)
895 if pn, ok := obj.(*types.PkgName); ok {
896 return fb.buildPkgMemberAddr(pn, e.Sel.Value)
897 }
898 }
899 return nil
900 }
901 baseType := x.SSAType()
902 addr = x
903 if _, ok := types.SafeUnderlying(baseType).(*types.Pointer); !ok {
904 found := false
905 if name, ok := e.X.(*syntax.Name); ok {
906 obj := fb.lookupObject(name.Value)
907 if obj != nil {
908 if alloc, ok2 := fb.vars[obj]; ok2 {
909 addr = alloc
910 baseType = types.NewPointer(baseType)
911 found = true
912 } else if fb.freeVarPtrs != nil {
913 if fv, ok2 := fb.freeVarPtrs[name.Value]; ok2 {
914 addr = fv
915 baseType = types.NewPointer(baseType)
916 found = true
917 }
918 }
919 }
920 }
921 if !found {
922 alloc := &SSAAlloc{Comment: "fieldaddr.tmp"}
923 alloc.typ = types.NewPointer(baseType)
924 alloc.name = fb.nextName()
925 fb.emit(alloc)
926 fb.emitStore(alloc, x)
927 addr = alloc
928 baseType = types.NewPointer(baseType)
929 }
930 }
931 structType = baseType
932 if p, ok := types.SafeUnderlying(structType).(*types.Pointer); ok {
933 structType = p.Elem()
934 }
935 }
936 fieldIdx := fb.fieldIndex(structType, e.Sel.Value)
937 if fieldIdx >= 0 {
938 fa := &SSAFieldAddr{X: addr, Field: fieldIdx}
939 fa.typ = types.NewPointer(fb.fieldType(structType, fieldIdx))
940 fa.name = fb.nextName()
941 fb.emit(fa)
942 return fa
943 }
944 path := fb.findEmbeddedFieldPath(structType, e.Sel.Value)
945 if len(path) >= 2 {
946 cur := addr
947 curType := structType
948 for pi, idx := range path {
949 fa := &SSAFieldAddr{X: cur, Field: idx}
950 fa.typ = types.NewPointer(fb.fieldType(curType, idx))
951 fa.name = fb.nextName()
952 fb.emit(fa)
953 curType = fb.fieldType(curType, idx)
954 if pi < len(path)-1 {
955 if p, ok := types.SafeUnderlying(curType).(*types.Pointer); ok {
956 ld := &SSAUnOp{Op: OpMul, X: fa}
957 ld.typ = curType
958 ld.name = fb.nextName()
959 fb.emit(ld)
960 cur = ld
961 curType = p.Elem()
962 continue
963 }
964 }
965 cur = fa
966 }
967 return cur
968 }
969 return nil
970 }
971
972 func (fb *ssaFuncBuilder) buildIndex(e *syntax.IndexExpr) (s SSAValue) {
973 x := fb.buildExpr(e.X)
974 idx := fb.buildExpr(e.Index)
975 if x == nil || idx == nil {
976 return nil
977 }
978 if x.SSAType() == nil {
979 return nil
980 }
981 switch t := types.SafeUnderlying(x.SSAType()).(type) {
982 case *types.TCMap:
983 idx = fb.coerceToInterface(idx, t.Key())
984 l := &SSALookup{X: x, Index: idx}
985 l.typ = t.Elem()
986 l.name = fb.nextName()
987 fb.emit(l)
988 return l
989 case *types.Pointer:
990 if arr, ok2 := types.SafeUnderlying(t.Elem()).(*types.Array); ok2 {
991 ia := &SSAIndexAddr{X: x, Index: idx}
992 ia.typ = types.NewPointer(t.Elem())
993 ia.name = fb.nextName()
994 fb.emit(ia)
995 return fb.emitLoad(ia, arr.Elem())
996 }
997 et := ssaElemType(x.SSAType())
998 ia := &SSAIndexAddr{X: x, Index: idx}
999 ia.typ = types.NewPointer(et)
1000 ia.name = fb.nextName()
1001 fb.emit(ia)
1002 return fb.emitLoad(ia, et)
1003 default:
1004 et := ssaElemType(x.SSAType())
1005 ia := &SSAIndexAddr{X: x, Index: idx}
1006 ia.typ = types.NewPointer(et)
1007 ia.name = fb.nextName()
1008 fb.emit(ia)
1009 return fb.emitLoad(ia, et)
1010 }
1011 }
1012
1013 func (fb *ssaFuncBuilder) buildSlice(e *syntax.SliceExpr) (s SSAValue) {
1014 x := fb.buildExpr(e.X)
1015 if x == nil {
1016 return nil
1017 }
1018 sl := &SSASlice{X: x}
1019 if len(e.Index) > 0 && e.Index[0] != nil {
1020 sl.Low = fb.buildExpr(e.Index[0])
1021 }
1022 if len(e.Index) > 1 && e.Index[1] != nil {
1023 sl.High = fb.buildExpr(e.Index[1])
1024 }
1025 if len(e.Index) > 2 && e.Index[2] != nil {
1026 sl.Max = fb.buildExpr(e.Index[2])
1027 }
1028 sl.typ = ssaSliceOf(x.SSAType())
1029 sl.name = fb.nextName()
1030 fb.emit(sl)
1031 return sl
1032 }
1033
1034 func (fb *ssaFuncBuilder) buildAssert(e *syntax.AssertExpr) (s SSAValue) {
1035 x := fb.buildExpr(e.X)
1036 assertedType := fb.resolveType(e.Type)
1037 if x == nil {
1038 return nil
1039 }
1040 ta := &SSATypeAssert{X: x, AssertedType: assertedType, CommaOk: false}
1041 ta.typ = assertedType
1042 ta.name = fb.nextName()
1043 fb.emit(ta)
1044 return ta
1045 }
1046
1047 func (fb *ssaFuncBuilder) buildCompositeLit(e *syntax.CompositeLit) (s SSAValue) {
1048 var typ types.Type
1049 if e.Type != nil {
1050 typ = fb.resolveType(e.Type)
1051 }
1052 if typ == nil {
1053 return nil
1054 }
1055
1056 if sl, ok := types.SafeUnderlying(typ).(*types.Slice); ok {
1057 return fb.buildSliceLit(e, typ, sl)
1058 }
1059
1060 if mt, isMap := types.SafeUnderlying(typ).(*types.TCMap); isMap {
1061 mm := &SSAMakeMap{}
1062 mm.typ = typ
1063 mm.name = fb.nextName()
1064 fb.emit(mm)
1065 for _, el := range e.ElemList {
1066 if kv, ok := el.(*syntax.KeyValueExpr); ok {
1067 k := fb.buildExpr(kv.Key)
1068 v := fb.buildExpr(kv.Value)
1069 if k != nil && v != nil {
1070 k = fb.coerceToInterface(k, mt.Key())
1071 v = fb.coerceToInterface(v, mt.Elem())
1072 fb.emit(&SSAMapUpdate{Map: mm, Key: k, Value: v})
1073 }
1074 }
1075 }
1076 return mm
1077 }
1078
1079 if ar, isArr := types.SafeUnderlying(typ).(*types.Array); isArr {
1080 return fb.buildArrayLit(e, typ, ar)
1081 }
1082
1083 alloc := fb.emitAlloc(typ, 0)
1084 posIdx := 0
1085 for _, el := range e.ElemList {
1086 if kv, ok := el.(*syntax.KeyValueExpr); ok {
1087 if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1088 idx := fb.fieldIndex(typ, kv.Key.(*syntax.Name).Value)
1089 if idx >= 0 {
1090 fa := &SSAFieldAddr{X: alloc, Field: idx}
1091 ft := fb.fieldType(typ, idx)
1092 fa.typ = types.NewPointer(ft)
1093 fa.name = fb.nextName()
1094 fb.emit(fa)
1095 v := fb.buildExpr(kv.Value)
1096 if v != nil {
1097 v = fb.coerceToInterface(v, ft)
1098 fb.emitStore(fa, v)
1099 }
1100 }
1101 }
1102 } else {
1103 v := fb.buildExpr(el)
1104 if v != nil {
1105 if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1106 ft := fb.fieldType(typ, posIdx)
1107 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
1108 fa.typ = types.NewPointer(ft)
1109 fa.name = fb.nextName()
1110 fb.emit(fa)
1111 v = fb.coerceToInterface(v, ft)
1112 fb.emitStore(fa, v)
1113 }
1114 }
1115 posIdx++
1116 }
1117 }
1118 return fb.emitLoad(alloc, typ)
1119 }
1120
1121 func (fb *ssaFuncBuilder) buildArrayLit(e *syntax.CompositeLit, typ types.Type, ar *types.Array) (s SSAValue) {
1122 if ar.Len() < 0 {
1123 ar = types.NewArray(ar.Elem(), int64(len(e.ElemList)))
1124 typ = ar
1125 }
1126 alloc := fb.emitAlloc(typ, 0)
1127 elemTyp := ar.Elem()
1128 for i, el := range e.ElemList {
1129 var expr syntax.Expr
1130 if kv, ok := el.(*syntax.KeyValueExpr); ok {
1131 expr = kv.Value
1132 } else {
1133 expr = el
1134 }
1135 var v SSAValue
1136 if cl, ok := expr.(*syntax.CompositeLit); ok && cl.Type == nil {
1137 v = fb.buildCompositeLitWithType(cl, elemTyp)
1138 } else {
1139 v = fb.buildExpr(expr)
1140 }
1141 if v == nil {
1142 continue
1143 }
1144 idx := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(i)}}
1145 ia := &SSAIndexAddr{X: alloc, Index: idx}
1146 ia.typ = types.NewPointer(elemTyp)
1147 ia.name = fb.nextName()
1148 fb.emit(ia)
1149 v = fb.coerceToInterface(v, elemTyp)
1150 fb.emitStore(ia, v)
1151 }
1152 return fb.emitLoad(alloc, typ)
1153 }
1154
1155 func (fb *ssaFuncBuilder) buildCompositeLitWithType(e *syntax.CompositeLit, typ types.Type) (s SSAValue) {
1156 if sl, ok := types.SafeUnderlying(typ).(*types.Slice); ok {
1157 return fb.buildSliceLit(e, typ, sl)
1158 }
1159 if ar, isArr := types.SafeUnderlying(typ).(*types.Array); isArr {
1160 return fb.buildArrayLit(e, typ, ar)
1161 }
1162 alloc := fb.emitAlloc(typ, 0)
1163 posIdx := 0
1164 for _, el := range e.ElemList {
1165 if kv, ok := el.(*syntax.KeyValueExpr); ok {
1166 if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1167 idx := fb.fieldIndex(typ, kv.Key.(*syntax.Name).Value)
1168 if idx >= 0 {
1169 ft := fb.fieldType(typ, idx)
1170 fa := &SSAFieldAddr{X: alloc, Field: idx}
1171 fa.typ = types.NewPointer(ft)
1172 fa.name = fb.nextName()
1173 fb.emit(fa)
1174 v := fb.buildExpr(kv.Value)
1175 if v != nil {
1176 v = fb.coerceToInterface(v, ft)
1177 fb.emitStore(fa, v)
1178 }
1179 }
1180 }
1181 } else {
1182 v := fb.buildExpr(el)
1183 if v != nil {
1184 if _, ok2 := types.SafeUnderlying(typ).(*types.TCStruct); ok2 {
1185 ft := fb.fieldType(typ, posIdx)
1186 fa := &SSAFieldAddr{X: alloc, Field: posIdx}
1187 fa.typ = types.NewPointer(ft)
1188 fa.name = fb.nextName()
1189 fb.emit(fa)
1190 v = fb.coerceToInterface(v, ft)
1191 fb.emitStore(fa, v)
1192 }
1193 }
1194 posIdx++
1195 }
1196 }
1197 return fb.emitLoad(alloc, typ)
1198 }
1199
1200 func (fb *ssaFuncBuilder) buildSliceLit(e *syntax.CompositeLit, typ types.Type, sl *types.Slice) (s SSAValue) {
1201 n := len(e.ElemList)
1202 nVal := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(n)}}
1203 ms := &SSAMakeSlice{}
1204 ms.typ = typ
1205 ms.name = fb.nextName()
1206 ms.Len = nVal
1207 ms.Cap = nVal
1208 fb.emit(ms)
1209
1210 elemTyp := sl.Elem()
1211 for i, el := range e.ElemList {
1212 var expr syntax.Expr
1213 if kv, ok := el.(*syntax.KeyValueExpr); ok {
1214 expr = kv.Value
1215 } else {
1216 expr = el
1217 }
1218 var v SSAValue
1219 if cl, ok := expr.(*syntax.CompositeLit); ok && cl.Type == nil {
1220 v = fb.buildCompositeLitWithType(cl, elemTyp)
1221 } else {
1222 v = fb.buildExpr(expr)
1223 }
1224 if v == nil {
1225 continue
1226 }
1227 idx := &SSAConst{typ: types.Typ[types.Int32], val: &types.ConstInt{V:int64(i)}}
1228 ia := &SSAIndexAddr{X: ms, Index: idx}
1229 ia.typ = types.NewPointer(elemTyp)
1230 ia.name = fb.nextName()
1231 fb.emit(ia)
1232 v = fb.coerceToInterface(v, elemTyp)
1233 fb.emitStore(ia, v)
1234 }
1235 return ms
1236 }
1237
1238 func (fb *ssaFuncBuilder) buildFuncLit(e *syntax.FuncLit) (s SSAValue) {
1239 var sig *types.Signature
1240 if fb.info != nil {
1241 if tv, ok := fb.info.Types[e]; ok {
1242 sig, _ = tv.Type.(*types.Signature)
1243 }
1244 }
1245 if sig == nil && e.Type != nil {
1246 sig = tcResolveFuncInline(e.Type, fb.fn.Pkg.Pkg.Scope())
1247 }
1248 name := fb.fn.name | "__anon" | ssaItoa(len(fb.fn.AnonFuncs)+1)
1249 anon := &SSAFunction{
1250 name: name,
1251 Signature: sig,
1252 pos: 0,
1253 Pkg: fb.fn.Pkg,
1254 Prog: fb.fn.Prog,
1255 parent: fb.fn,
1256 }
1257 fb.fn.AnonFuncs = append(fb.fn.AnonFuncs, anon)
1258
1259 ab := newSSAFuncBuilder(anon, fb.info)
1260 ab.parent = fb
1261 d := &syntax.FuncDecl{
1262 Name: &Name{Value: name},
1263 Type: e.Type,
1264 Body: e.Body,
1265 }
1266 ab.buildBody(d)
1267
1268 if len(anon.FreeVars) == 0 {
1269 return anon
1270 }
1271 bindings := []SSAValue{:0:len(anon.FreeVars)}
1272 for _, fv := range anon.FreeVars {
1273 obj := fb.lookupObject(fv.name)
1274 if obj != nil {
1275 if alloc, ok := fb.vars[obj]; ok {
1276 alloc.Heap = true
1277 bindings = append(bindings, alloc)
1278 } else if pfv, ok := fb.freeVarPtrs[fv.name]; ok {
1279 bindings = append(bindings, pfv)
1280 } else {
1281 bindings = append(bindings, &SSAConst{typ: types.NewPointer(fv.typ), val: nil})
1282 }
1283 } else if pfv, ok := fb.freeVarPtrs[fv.name]; ok {
1284 bindings = append(bindings, pfv)
1285 } else {
1286 bindings = append(bindings, &SSAConst{typ: types.NewPointer(fv.typ), val: nil})
1287 }
1288 }
1289 mc := &SSAMakeClosure{Fn: anon, Bindings: bindings}
1290 mc.typ = sig
1291 mc.name = fb.nextName()
1292 fb.emit(mc)
1293 return mc
1294 }
1295
1296 func (fb *ssaFuncBuilder) saveVars() (m map[types.Object]*SSAAlloc) {
1297 saved := map[types.Object]*SSAAlloc{}
1298 for k, v := range fb.vars {
1299 saved[k] = v
1300 }
1301 return saved
1302 }
1303
1304 func (fb *ssaFuncBuilder) removeVar(name string) {
1305 for o := range fb.vars {
1306 if o.Name() == name {
1307 delete(fb.vars, o)
1308 return
1309 }
1310 }
1311 }
1312
1313
1314 func (fb *ssaFuncBuilder) buildPkgMemberAddr(pn *types.PkgName, memberName string) (s SSAValue) {
1315 imported := pn.Imported()
1316 if imported == nil {
1317 return nil
1318 }
1319 obj := imported.Scope().Lookup(memberName)
1320 if obj == nil {
1321 return nil
1322 }
1323 switch obj := obj.(type) {
1324 case *types.TCConst:
1325 return nil
1326 case *types.TCVar:
1327 impPkg := fb.ensureImportedSSAPackage(imported)
1328 g, ok := impPkg.Members[memberName].(*SSAGlobal)
1329 if !ok {
1330 g = &SSAGlobal{
1331 name: memberName,
1332 typ: types.NewPointer(obj.Type()),
1333 pkg: impPkg,
1334 }
1335 impPkg.Members[memberName] = g
1336 }
1337 return g
1338 }
1339 return nil
1340 }
1341
1342 func (fb *ssaFuncBuilder) buildPkgCall(pn *types.PkgName, funcName string, argList []syntax.Expr, hasDots bool) (s SSAValue) {
1343 imported := pn.Imported()
1344 if imported == nil {
1345 return nil
1346 }
1347 if imported.Path() == "unsafe" && funcName == "Slice" {
1348 return fb.buildUnsafeSlice(argList)
1349 }
1350 if imported.Path() == "unsafe" && funcName == "SliceData" {
1351 arg := fb.buildExpr(argList[0])
1352 extract := &SSAExtract{Tuple: arg, Index: 0}
1353 extract.typ = types.Typ[types.UnsafePointer]
1354 extract.name = fb.nextName()
1355 extract.setBlock(fb.currentBlock)
1356 fb.currentBlock.Instrs = append(fb.currentBlock.Instrs, extract)
1357 return extract
1358 }
1359 if result := fb.tryGenericPkgCall(pn, funcName, argList, hasDots); result != nil {
1360 return result
1361 }
1362 obj := imported.Scope().Lookup(funcName)
1363 if obj == nil {
1364 return nil
1365 }
1366 fn, ok := obj.(*types.TCFunc)
1367 if !ok {
1368 return nil
1369 }
1370 impPkg := fb.ensureImportedSSAPackage(imported)
1371 ssaFn := impPkg.Func(funcName)
1372 if ssaFn == nil {
1373 ssaFn = &SSAFunction{
1374 name: funcName,
1375 object: fn,
1376 Signature: fn.Type().(*types.Signature),
1377 Pkg: impPkg,
1378 Prog: fb.fn.Prog,
1379 }
1380 if isNoContextExtern(imported.Path(), funcName) {
1381 ssaFn.isExternC = true
1382 }
1383 impPkg.Members[funcName] = ssaFn
1384 }
1385 args := fb.buildArgs(argList)
1386 var retType types.Type
1387 if ssaFn.Signature != nil {
1388 if ssaFn.Signature.Variadic() && !hasDots {
1389 args = fb.wrapVariadicArgs(args, ssaFn.Signature)
1390 }
1391 args = fb.coerceArgsToInterface(args, ssaFn.Signature)
1392 if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() == 1 {
1393 retType = ssaFn.Signature.Results().At(0).Type()
1394 } else if ssaFn.Signature.Results() != nil && ssaFn.Signature.Results().Len() > 1 {
1395 retType = ssaFn.Signature.Results()
1396 }
1397 }
1398 call := &SSACall{Call: SSACallCommon{Value: ssaFn, Args: args}}
1399 call.typ = retType
1400 call.name = fb.nextName()
1401 fb.emit(call)
1402 if retType == nil {
1403 return nil
1404 }
1405 return call
1406 }
1407
1408 func (fb *ssaFuncBuilder) buildUnsafeSlice(argList []syntax.Expr) (s SSAValue) {
1409 if len(argList) < 2 {
1410 return nil
1411 }
1412 ptrVal := fb.buildExpr(argList[0])
1413 lenVal := fb.buildExpr(argList[1])
1414 if ptrVal == nil || lenVal == nil {
1415 return nil
1416 }
1417 var elemType types.Type
1418 if pt, ok := types.SafeUnderlying(ptrVal.SSAType()).(*types.Pointer); ok {
1419 elemType = pt.Elem()
1420 }
1421 if elemType == nil {
1422 elemType = types.Typ[types.Uint8]
1423 }
1424 ms := &SSAMakeSlice{Len: lenVal, Cap: lenVal, Data: ptrVal}
1425 if b, ok := elemType.(*types.Basic); ok && b.Kind() == types.Uint8 {
1426 ms.typ = types.Typ[types.TCString]
1427 } else {
1428 ms.typ = types.NewSlice(elemType)
1429 }
1430 ms.name = fb.nextName()
1431 fb.emit(ms)
1432 return ms
1433 }
1434
1435 // Helpers.
1436
1437 func (fb *ssaFuncBuilder) lookupObject(name string) (o Object) {
1438 for obj := range fb.vars {
1439 if obj.Name() == name {
1440 return obj
1441 }
1442 }
1443 if fb.parent != nil {
1444 for obj := range fb.parent.vars {
1445 if obj.Name() == name {
1446 return obj
1447 }
1448 }
1449 }
1450 if fb.srcScope != nil {
1451 if _, obj := fb.srcScope.LookupParent(name); obj != nil {
1452 return obj
1453 }
1454 }
1455 if fb.fn.Pkg != nil {
1456 if _, obj := fb.fn.Pkg.Pkg.Scope().LookupParent(name); obj != nil {
1457 return obj
1458 }
1459 }
1460 if fb.info != nil {
1461 return nil
1462 }
1463 return nil
1464 }
1465
1466 func (fb *ssaFuncBuilder) getOrCreateFreeVar(name string, typ types.Type) (s SSAValue) {
1467 for _, fv := range fb.fn.FreeVars {
1468 if fv.name == name {
1469 return fv
1470 }
1471 }
1472 fv := &SSAFreeVar{
1473 name: name,
1474 typ: typ,
1475 parent: fb.fn,
1476 }
1477 fb.fn.FreeVars = append(fb.fn.FreeVars, fv)
1478 if fb.freeVarPtrs == nil {
1479 fb.freeVarPtrs = map[string]*SSAFreeVar{}
1480 }
1481 fb.freeVarPtrs[name] = fv
1482 return fv
1483 }
1484
1485 func (fb *ssaFuncBuilder) lookupVar(name string) (t *types.TCVar) {
1486 obj := fb.lookupObject(name)
1487 v, _ := obj.(*types.TCVar)
1488 return v
1489 }
1490