summaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/tools/go/ssa/wrappers.go
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2025-06-06 02:49:26 +0200
committerThomas Voss <mail@thomasvoss.com> 2025-06-06 02:49:26 +0200
commit746a09a5854b9ce17e40caead51e1a42c2721bb1 (patch)
tree474d9a11c3b82196577b61333dffe3c94c5258fb /vendor/golang.org/x/tools/go/ssa/wrappers.go
parentefa0bd7df5f51d47c50efc446fd2f32996ab79be (diff)
Unvendor dependencies
Diffstat (limited to 'vendor/golang.org/x/tools/go/ssa/wrappers.go')
-rw-r--r--vendor/golang.org/x/tools/go/ssa/wrappers.go348
1 files changed, 0 insertions, 348 deletions
diff --git a/vendor/golang.org/x/tools/go/ssa/wrappers.go b/vendor/golang.org/x/tools/go/ssa/wrappers.go
deleted file mode 100644
index d09b4f2..0000000
--- a/vendor/golang.org/x/tools/go/ssa/wrappers.go
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssa
-
-// This file defines synthesis of Functions that delegate to declared
-// methods; they come in three kinds:
-//
-// (1) wrappers: methods that wrap declared methods, performing
-// implicit pointer indirections and embedded field selections.
-//
-// (2) thunks: funcs that wrap declared methods. Like wrappers,
-// thunks perform indirections and field selections. The thunk's
-// first parameter is used as the receiver for the method call.
-//
-// (3) bounds: funcs that wrap declared methods. The bound's sole
-// free variable, supplied by a closure, is used as the receiver
-// for the method call. No indirections or field selections are
-// performed since they can be done before the call.
-
-import (
- "fmt"
-
- "go/token"
- "go/types"
-
- "golang.org/x/tools/internal/typeparams"
-)
-
-// -- wrappers -----------------------------------------------------------
-
-// createWrapper returns a synthetic method that delegates to the
-// declared method denoted by meth.Obj(), first performing any
-// necessary pointer indirections or field selections implied by meth.
-//
-// The resulting method's receiver type is meth.Recv().
-//
-// This function is versatile but quite subtle! Consider the
-// following axes of variation when making changes:
-// - optional receiver indirection
-// - optional implicit field selections
-// - meth.Obj() may denote a concrete or an interface method
-// - the result may be a thunk or a wrapper.
-func createWrapper(prog *Program, sel *selection) *Function {
- obj := sel.obj.(*types.Func) // the declared function
- sig := sel.typ.(*types.Signature) // type of this wrapper
-
- var recv *types.Var // wrapper's receiver or thunk's params[0]
- name := obj.Name()
- var description string
- if sel.kind == types.MethodExpr {
- name += "$thunk"
- description = "thunk"
- recv = sig.Params().At(0)
- } else {
- description = "wrapper"
- recv = sig.Recv()
- }
-
- description = fmt.Sprintf("%s for %s", description, sel.obj)
- if prog.mode&LogSource != 0 {
- defer logStack("create %s to (%s)", description, recv.Type())()
- }
- /* method wrapper */
- return &Function{
- name: name,
- method: sel,
- object: obj,
- Signature: sig,
- Synthetic: description,
- Prog: prog,
- pos: obj.Pos(),
- // wrappers have no syntax
- build: (*builder).buildWrapper,
- syntax: nil,
- info: nil,
- goversion: "",
- }
-}
-
-// buildWrapper builds fn.Body for a method wrapper.
-func (b *builder) buildWrapper(fn *Function) {
- var recv *types.Var // wrapper's receiver or thunk's params[0]
- var start int // first regular param
- if fn.method.kind == types.MethodExpr {
- recv = fn.Signature.Params().At(0)
- start = 1
- } else {
- recv = fn.Signature.Recv()
- }
-
- fn.startBody()
- fn.addSpilledParam(recv)
- createParams(fn, start)
-
- indices := fn.method.index
-
- var v Value = fn.Locals[0] // spilled receiver
- if isPointer(fn.method.recv) {
- v = emitLoad(fn, v)
-
- // For simple indirection wrappers, perform an informative nil-check:
- // "value method (T).f called using nil *T pointer"
- if len(indices) == 1 && !isPointer(recvType(fn.object)) {
- var c Call
- c.Call.Value = &Builtin{
- name: "ssa:wrapnilchk",
- sig: types.NewSignature(nil,
- types.NewTuple(anonVar(fn.method.recv), anonVar(tString), anonVar(tString)),
- types.NewTuple(anonVar(fn.method.recv)), false),
- }
- c.Call.Args = []Value{
- v,
- stringConst(typeparams.MustDeref(fn.method.recv).String()),
- stringConst(fn.method.obj.Name()),
- }
- c.setType(v.Type())
- v = fn.emit(&c)
- }
- }
-
- // Invariant: v is a pointer, either
- // value of *A receiver param, or
- // address of A spilled receiver.
-
- // We use pointer arithmetic (FieldAddr possibly followed by
- // Load) in preference to value extraction (Field possibly
- // preceded by Load).
-
- v = emitImplicitSelections(fn, v, indices[:len(indices)-1], token.NoPos)
-
- // Invariant: v is a pointer, either
- // value of implicit *C field, or
- // address of implicit C field.
-
- var c Call
- if r := recvType(fn.object); !types.IsInterface(r) { // concrete method
- if !isPointer(r) {
- v = emitLoad(fn, v)
- }
- c.Call.Value = fn.Prog.objectMethod(fn.object, b)
- c.Call.Args = append(c.Call.Args, v)
- } else {
- c.Call.Method = fn.object
- c.Call.Value = emitLoad(fn, v) // interface (possibly a typeparam)
- }
- for _, arg := range fn.Params[1:] {
- c.Call.Args = append(c.Call.Args, arg)
- }
- emitTailCall(fn, &c)
- fn.finishBody()
-}
-
-// createParams creates parameters for wrapper method fn based on its
-// Signature.Params, which do not include the receiver.
-// start is the index of the first regular parameter to use.
-func createParams(fn *Function, start int) {
- tparams := fn.Signature.Params()
- for i, n := start, tparams.Len(); i < n; i++ {
- fn.addParamVar(tparams.At(i))
- }
-}
-
-// -- bounds -----------------------------------------------------------
-
-// createBound returns a bound method wrapper (or "bound"), a synthetic
-// function that delegates to a concrete or interface method denoted
-// by obj. The resulting function has no receiver, but has one free
-// variable which will be used as the method's receiver in the
-// tail-call.
-//
-// Use MakeClosure with such a wrapper to construct a bound method
-// closure. e.g.:
-//
-// type T int or: type T interface { meth() }
-// func (t T) meth()
-// var t T
-// f := t.meth
-// f() // calls t.meth()
-//
-// f is a closure of a synthetic wrapper defined as if by:
-//
-// f := func() { return t.meth() }
-//
-// Unlike createWrapper, createBound need perform no indirection or field
-// selections because that can be done before the closure is
-// constructed.
-func createBound(prog *Program, obj *types.Func) *Function {
- description := fmt.Sprintf("bound method wrapper for %s", obj)
- if prog.mode&LogSource != 0 {
- defer logStack("%s", description)()
- }
- /* bound method wrapper */
- fn := &Function{
- name: obj.Name() + "$bound",
- object: obj,
- Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver
- Synthetic: description,
- Prog: prog,
- pos: obj.Pos(),
- // wrappers have no syntax
- build: (*builder).buildBound,
- syntax: nil,
- info: nil,
- goversion: "",
- }
- fn.FreeVars = []*FreeVar{{name: "recv", typ: recvType(obj), parent: fn}} // (cyclic)
- return fn
-}
-
-// buildBound builds fn.Body for a bound method closure.
-func (b *builder) buildBound(fn *Function) {
- fn.startBody()
- createParams(fn, 0)
- var c Call
-
- recv := fn.FreeVars[0]
- if !types.IsInterface(recvType(fn.object)) { // concrete
- c.Call.Value = fn.Prog.objectMethod(fn.object, b)
- c.Call.Args = []Value{recv}
- } else {
- c.Call.Method = fn.object
- c.Call.Value = recv // interface (possibly a typeparam)
- }
- for _, arg := range fn.Params {
- c.Call.Args = append(c.Call.Args, arg)
- }
- emitTailCall(fn, &c)
- fn.finishBody()
-}
-
-// -- thunks -----------------------------------------------------------
-
-// createThunk returns a thunk, a synthetic function that delegates to a
-// concrete or interface method denoted by sel.obj. The resulting
-// function has no receiver, but has an additional (first) regular
-// parameter.
-//
-// Precondition: sel.kind == types.MethodExpr.
-//
-// type T int or: type T interface { meth() }
-// func (t T) meth()
-// f := T.meth
-// var t T
-// f(t) // calls t.meth()
-//
-// f is a synthetic wrapper defined as if by:
-//
-// f := func(t T) { return t.meth() }
-func createThunk(prog *Program, sel *selection) *Function {
- if sel.kind != types.MethodExpr {
- panic(sel)
- }
-
- fn := createWrapper(prog, sel)
- if fn.Signature.Recv() != nil {
- panic(fn) // unexpected receiver
- }
-
- return fn
-}
-
-func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
- return types.NewSignature(recv, s.Params(), s.Results(), s.Variadic())
-}
-
-// A local version of *types.Selection.
-// Needed for some additional control, such as creating a MethodExpr for an instantiation.
-type selection struct {
- kind types.SelectionKind
- recv types.Type
- typ types.Type
- obj types.Object
- index []int
- indirect bool
-}
-
-func toSelection(sel *types.Selection) *selection {
- return &selection{
- kind: sel.Kind(),
- recv: sel.Recv(),
- typ: sel.Type(),
- obj: sel.Obj(),
- index: sel.Index(),
- indirect: sel.Indirect(),
- }
-}
-
-// -- instantiations --------------------------------------------------
-
-// buildInstantiationWrapper builds the body of an instantiation
-// wrapper fn. The body calls the original generic function,
-// bracketed by ChangeType conversions on its arguments and results.
-func (b *builder) buildInstantiationWrapper(fn *Function) {
- orig := fn.topLevelOrigin
- sig := fn.Signature
-
- fn.startBody()
- if sig.Recv() != nil {
- fn.addParamVar(sig.Recv())
- }
- createParams(fn, 0)
-
- // Create body. Add a call to origin generic function
- // and make type changes between argument and parameters,
- // as well as return values.
- var c Call
- c.Call.Value = orig
- if res := orig.Signature.Results(); res.Len() == 1 {
- c.typ = res.At(0).Type()
- } else {
- c.typ = res
- }
-
- // parameter of instance becomes an argument to the call
- // to the original generic function.
- argOffset := 0
- for i, arg := range fn.Params {
- var typ types.Type
- if i == 0 && sig.Recv() != nil {
- typ = orig.Signature.Recv().Type()
- argOffset = 1
- } else {
- typ = orig.Signature.Params().At(i - argOffset).Type()
- }
- c.Call.Args = append(c.Call.Args, emitTypeCoercion(fn, arg, typ))
- }
-
- results := fn.emit(&c)
- var ret Return
- switch res := sig.Results(); res.Len() {
- case 0:
- // no results, do nothing.
- case 1:
- ret.Results = []Value{emitTypeCoercion(fn, results, res.At(0).Type())}
- default:
- for i := 0; i < sig.Results().Len(); i++ {
- v := emitExtract(fn, results, i)
- ret.Results = append(ret.Results, emitTypeCoercion(fn, v, res.At(i).Type()))
- }
- }
-
- fn.emit(&ret)
- fn.currentBlock = nil
-
- fn.finishBody()
-}