diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:16:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:16:40 +0000 |
commit | 47ab3d4a42e9ab51c465c4322d2ec233f6324e6b (patch) | |
tree | a61a0ffd83f4a3def4b36e5c8e99630c559aa723 /src/cmd/compile/internal/noder/object.go | |
parent | Initial commit. (diff) | |
download | golang-1.18-47ab3d4a42e9ab51c465c4322d2ec233f6324e6b.tar.xz golang-1.18-47ab3d4a42e9ab51c465c4322d2ec233f6324e6b.zip |
Adding upstream version 1.18.10.upstream/1.18.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/compile/internal/noder/object.go')
-rw-r--r-- | src/cmd/compile/internal/noder/object.go | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go new file mode 100644 index 0000000..37a995b --- /dev/null +++ b/src/cmd/compile/internal/noder/object.go @@ -0,0 +1,206 @@ +// Copyright 2021 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 noder + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/syntax" + "cmd/compile/internal/typecheck" + "cmd/compile/internal/types" + "cmd/compile/internal/types2" + "cmd/internal/src" +) + +func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) { + obj, ok := g.info.Defs[name] + if !ok { + base.FatalfAt(g.pos(name), "unknown name %v", name) + } + return g.obj(obj), obj +} + +// use returns the Name or InstExpr node associated with the use of name, +// possibly instantiated by type arguments. The returned node will have +// the correct type and be marked as typechecked. +func (g *irgen) use(name *syntax.Name) ir.Node { + obj2, ok := g.info.Uses[name] + if !ok { + base.FatalfAt(g.pos(name), "unknown name %v", name) + } + obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2)) + if obj.Defn != nil && obj.Defn.Op() == ir.ONAME { + // If CaptureName created a closure variable, then transfer the + // type of the captured name to the new closure variable. + obj.SetTypecheck(1) + obj.SetType(obj.Defn.Type()) + } + + if obj.Class == ir.PFUNC { + if inst, ok := g.info.Instances[name]; ok { + // This is the case where inferring types required the + // types of the function arguments. + targs := make([]ir.Node, inst.TypeArgs.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(inst.TypeArgs.At(i))) + } + typ := g.substType(obj.Type(), obj.Type().TParams(), targs) + return typed(typ, ir.NewInstExpr(g.pos(name), ir.OFUNCINST, obj, targs)) + } + } + + return obj +} + +// obj returns the Name that represents the given object. If no such Name exists +// yet, it will be implicitly created. The returned node will have the correct +// type and be marked as typechecked. +// +// For objects declared at function scope, ir.CurFunc must already be +// set to the respective function when the Name is created. +func (g *irgen) obj(obj types2.Object) *ir.Name { + // For imported objects, we use iimport directly instead of mapping + // the types2 representation. + if obj.Pkg() != g.self { + if sig, ok := obj.Type().(*types2.Signature); ok && sig.Recv() != nil { + // We can't import a method by name - must import the type + // and access the method from it. + base.FatalfAt(g.pos(obj), "tried to import a method directly") + } + sym := g.sym(obj) + if sym.Def != nil { + return sym.Def.(*ir.Name) + } + n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) + if n, ok := n.(*ir.Name); ok { + n.SetTypecheck(1) + return n + } + base.FatalfAt(g.pos(obj), "failed to resolve %v", obj) + } + + if name, ok := g.objs[obj]; ok { + return name // previously mapped + } + + var name *ir.Name + pos := g.pos(obj) + + class := typecheck.DeclContext + if obj.Parent() == g.self.Scope() { + class = ir.PEXTERN // forward reference to package-block declaration + } + + // "You are in a maze of twisting little passages, all different." + switch obj := obj.(type) { + case *types2.Const: + name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type())) + + case *types2.Func: + sig := obj.Type().(*types2.Signature) + var sym *types.Sym + var typ *types.Type + if recv := sig.Recv(); recv == nil { + if obj.Name() == "init" { + sym = renameinit() + } else { + sym = g.sym(obj) + } + typ = g.typ(sig) + } else { + sym = g.selector(obj) + if !sym.IsBlank() { + sym = ir.MethodSym(g.typ(recv.Type()), sym) + } + typ = g.signature(g.param(recv), sig) + } + name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ) + + case *types2.TypeName: + if obj.IsAlias() { + name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type())) + name.SetAlias(true) + } else { + name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj)) + g.objFinish(name, class, types.NewNamed(name)) + } + + case *types2.Var: + sym := g.sym(obj) + if class == ir.PPARAMOUT && (sym == nil || sym.IsBlank()) { + // Backend needs names for result parameters, + // even if they're anonymous or blank. + nresults := 0 + for _, n := range ir.CurFunc.Dcl { + if n.Class == ir.PPARAMOUT { + nresults++ + } + } + if sym == nil { + sym = typecheck.LookupNum("~r", nresults) // 'r' for "result" + } else { + sym = typecheck.LookupNum("~b", nresults) // 'b' for "blank" + } + } + name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type())) + + default: + g.unhandled("object", obj) + } + + g.objs[obj] = name + name.SetTypecheck(1) + return name +} + +func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name { + name := ir.NewDeclNameAt(pos, op, sym) + g.objFinish(name, class, typ) + return name +} + +func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) { + sym := name.Sym() + + name.SetType(typ) + name.Class = class + if name.Class == ir.PFUNC { + sym.SetFunc(true) + } + + name.SetTypecheck(1) + name.SetWalkdef(1) + + if ir.IsBlank(name) { + return + } + + switch class { + case ir.PEXTERN: + g.target.Externs = append(g.target.Externs, name) + fallthrough + case ir.PFUNC: + sym.Def = name + if name.Class == ir.PFUNC && name.Type().Recv() != nil { + break // methods are exported with their receiver type + } + if types.IsExported(sym.Name) { + // Generic functions can be marked for export here, even + // though they will not be compiled until instantiated. + typecheck.Export(name) + } + if base.Flag.AsmHdr != "" && !name.Sym().Asm() { + name.Sym().SetAsm(true) + g.target.Asms = append(g.target.Asms, name) + } + + default: + // Function-scoped declaration. + name.Curfn = ir.CurFunc + if name.Op() == ir.ONAME { + ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name) + } + } +} |