mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.regabi] cmd/compile: split out package reflectdata [generated]
[git-generate]
cd src/cmd/compile/internal/gc
rf '
ex {
import "cmd/compile/internal/base"
thearch.LinkArch.Name -> base.Ctxt.Arch.Name
}
# Move out of reflect.go a few functions that should stay.
mv addsignats obj.go
mv deferstruct ssa.go
# Export reflectdata API.
mv zerosize ZeroSize
mv hmap MapType
mv bmap MapBucketType
mv hiter MapIterType
mv addsignat NeedRuntimeType
mv typename TypePtr
mv typenamesym TypeSym
mv typesymprefix TypeSymPrefix
mv itabsym ITabSym
mv tracksym TrackSym
mv zeroaddr ZeroAddr
mv itabname ITabAddr
mv ifaceMethodOffset InterfaceMethodOffset
mv peekitabs CompileITabs
mv addptabs CollectPTabs
mv algtype AlgType
mv dtypesym WriteType
mv dumpbasictypes WriteBasicTypes
mv dumpimportstrings WriteImportStrings
mv dumpsignats WriteRuntimeTypes
mv dumptabs WriteTabs
mv eqinterface EqInterface
mv eqstring EqString
mv GCProg gcProg
mv EqCanPanic eqCanPanic
mv IsRegularMemory isRegularMemory
mv Sig typeSig
mv hashmem alg.go
mv CollectPTabs genwrapper ZeroSize reflect.go
mv alg.go reflect.go cmd/compile/internal/reflectdata
'
Change-Id: Iaae9da9e9fad5f772f5216004823ccff2ea8f139
Reviewed-on: https://go-review.googlesource.com/c/go/+/279475
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4dfb5d91a8
commit
de65151e50
13 changed files with 418 additions and 406 deletions
|
|
@ -6,9 +6,8 @@ package gc
|
|||
|
||||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/escape"
|
||||
"cmd/compile/internal/inline"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/reflectdata"
|
||||
"cmd/compile/internal/typecheck"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
|
|
@ -319,144 +318,9 @@ func cheapexpr(n ir.Node, init *ir.Nodes) ir.Node {
|
|||
return copyexpr(n, n.Type(), init)
|
||||
}
|
||||
|
||||
// Generate a wrapper function to convert from
|
||||
// a receiver of type T to a receiver of type U.
|
||||
// That is,
|
||||
//
|
||||
// func (t T) M() {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// already exists; this function generates
|
||||
//
|
||||
// func (u U) M() {
|
||||
// u.M()
|
||||
// }
|
||||
//
|
||||
// where the types T and U are such that u.M() is valid
|
||||
// and calls the T.M method.
|
||||
// The resulting function is for use in method tables.
|
||||
//
|
||||
// rcvr - U
|
||||
// method - M func (t T)(), a TFIELD type struct
|
||||
// newnam - the eventual mangled name of this function
|
||||
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||
if false && base.Flag.LowerR != 0 {
|
||||
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
||||
}
|
||||
|
||||
// Only generate (*T).M wrappers for T.M in T's own package.
|
||||
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
|
||||
rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg {
|
||||
return
|
||||
}
|
||||
|
||||
// Only generate I.M wrappers for I in I's own package
|
||||
// but keep doing it for error.Error (was issue #29304).
|
||||
if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && rcvr != types.ErrorType {
|
||||
return
|
||||
}
|
||||
|
||||
base.Pos = base.AutogeneratedPos
|
||||
typecheck.DeclContext = ir.PEXTERN
|
||||
|
||||
tfn := ir.NewFuncType(base.Pos,
|
||||
ir.NewField(base.Pos, typecheck.Lookup(".this"), nil, rcvr),
|
||||
typecheck.NewFuncParams(method.Type.Params(), true),
|
||||
typecheck.NewFuncParams(method.Type.Results(), false))
|
||||
|
||||
fn := typecheck.DeclFunc(newnam, tfn)
|
||||
fn.SetDupok(true)
|
||||
|
||||
nthis := ir.AsNode(tfn.Type().Recv().Nname)
|
||||
|
||||
methodrcvr := method.Type.Recv().Type
|
||||
|
||||
// generate nil pointer check for better error
|
||||
if rcvr.IsPtr() && rcvr.Elem() == methodrcvr {
|
||||
// generating wrapper from *T to T.
|
||||
n := ir.NewIfStmt(base.Pos, nil, nil, nil)
|
||||
n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil())
|
||||
call := ir.NewCallExpr(base.Pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)
|
||||
n.Body = []ir.Node{call}
|
||||
fn.Body.Append(n)
|
||||
}
|
||||
|
||||
dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym))
|
||||
|
||||
// generate call
|
||||
// It's not possible to use a tail call when dynamic linking on ppc64le. The
|
||||
// bad scenario is when a local call is made to the wrapper: the wrapper will
|
||||
// call the implementation, which might be in a different module and so set
|
||||
// the TOC to the appropriate value for that module. But if it returns
|
||||
// directly to the wrapper's caller, nothing will reset it to the correct
|
||||
// value for that function.
|
||||
if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(thearch.LinkArch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) {
|
||||
// generate tail call: adjust pointer receiver and jump to embedded method.
|
||||
left := dot.X // skip final .M
|
||||
if !left.Type().IsPtr() {
|
||||
left = typecheck.NodAddr(left)
|
||||
}
|
||||
as := ir.NewAssignStmt(base.Pos, nthis, typecheck.ConvNop(left, rcvr))
|
||||
fn.Body.Append(as)
|
||||
fn.Body.Append(ir.NewBranchStmt(base.Pos, ir.ORETJMP, ir.MethodSym(methodrcvr, method.Sym)))
|
||||
} else {
|
||||
fn.SetWrapper(true) // ignore frame for panic+recover matching
|
||||
call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
|
||||
call.Args.Set(ir.ParamNames(tfn.Type()))
|
||||
call.IsDDD = tfn.Type().IsVariadic()
|
||||
if method.Type.NumResults() > 0 {
|
||||
ret := ir.NewReturnStmt(base.Pos, nil)
|
||||
ret.Results = []ir.Node{call}
|
||||
fn.Body.Append(ret)
|
||||
} else {
|
||||
fn.Body.Append(call)
|
||||
}
|
||||
}
|
||||
|
||||
if false && base.Flag.LowerR != 0 {
|
||||
ir.DumpList("genwrapper body", fn.Body)
|
||||
}
|
||||
|
||||
typecheck.FinishFuncBody()
|
||||
if base.Debug.DclStack != 0 {
|
||||
types.CheckDclstack()
|
||||
}
|
||||
|
||||
typecheck.Func(fn)
|
||||
ir.CurFunc = fn
|
||||
typecheck.Stmts(fn.Body)
|
||||
|
||||
// Inline calls within (*T).M wrappers. This is safe because we only
|
||||
// generate those wrappers within the same compilation unit as (T).M.
|
||||
// TODO(mdempsky): Investigate why we can't enable this more generally.
|
||||
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil {
|
||||
inline.InlineCalls(fn)
|
||||
}
|
||||
escape.Batch([]*ir.Func{fn}, false)
|
||||
|
||||
ir.CurFunc = nil
|
||||
typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
|
||||
}
|
||||
|
||||
func hashmem(t *types.Type) ir.Node {
|
||||
sym := ir.Pkgs.Runtime.Lookup("memhash")
|
||||
|
||||
n := typecheck.NewName(sym)
|
||||
ir.MarkFunc(n)
|
||||
n.SetType(typecheck.NewFuncType(nil, []*ir.Field{
|
||||
ir.NewField(base.Pos, nil, nil, types.NewPtr(t)),
|
||||
ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
|
||||
ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
|
||||
}, []*ir.Field{
|
||||
ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
|
||||
}))
|
||||
return n
|
||||
}
|
||||
|
||||
func ngotype(n ir.Node) *types.Sym {
|
||||
if n.Type() != nil {
|
||||
return typenamesym(n.Type())
|
||||
return reflectdata.TypeSym(n.Type())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue