// esc.c needs to find f given a PPARAM to add the tag.
if l.N.Left != nil && l.N.Left.Class == PPARAM {
- l.N.Left.Paramfld = f
+ l.N.Left.Param.Field = f
}
*tp = f
case EscNone, // not touched by escflood
EscReturn:
if haspointers(ll.N.Type) { // don't bother tagging for scalars
- ll.N.Paramfld.Note = mktag(int(ll.N.Esc))
+ ll.N.Param.Field.Note = mktag(int(ll.N.Esc))
}
case EscHeap, // touched by escflood, moved to heap
gcargs = makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps)
gclocals = makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps)
- for t := Curfn.Paramfld; t != nil; t = t.Down {
- gtrack(tracksym(t.Type))
+ for _, t := range Curfn.Func.Fieldtrack {
+ gtrack(tracksym(t))
}
for l := fn.Func.Dcl; l != nil; l = l.Next {
Func *Func
// ONAME
- Name *Name
- Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
- Pack *Node // real package for import . names
- Curfn *Node // function for local variables
- Paramfld *Type // TFIELD for this PPARAM; also for ODOT, curfn
- Alloc *Node // allocation call
- Param *Param
+ Name *Name
+ Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
+ Pack *Node // real package for import . names
+ Curfn *Node // function for local variables
+ Alloc *Node // allocation call
+ Param *Param
// OPACK
Pkg *Pkg
- // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
-
// Escape analysis.
Escflowsrc *NodeList // flow(this, src)
Escretval *NodeList // on OCALLxxx, list of dummy return values
Outerexpr *Node // expression copied into closure for variable
Stackparam *Node // OPARAM node referring to stack copy of param
+ // ONAME PPARAM
+ Field *Type // TFIELD in arg struct
+
// ONAME closure param with PPARAMREF
Outer *Node // outer PPARAMREF in nested closure
Closure *Node // ONAME/PHEAP <-> ONAME/PPARAMREF
// Func holds Node fields used only with function-like nodes.
type Func struct {
- Shortname *Node
- Enter *NodeList
- Exit *NodeList
- Cvars *NodeList // closure params
- Dcl *NodeList // autodcl for this func/closure
- Inldcl *NodeList // copy of dcl for use in inlining
- Closgen int
- Outerfunc *Node
+ Shortname *Node
+ Enter *NodeList
+ Exit *NodeList
+ Cvars *NodeList // closure params
+ Dcl *NodeList // autodcl for this func/closure
+ Inldcl *NodeList // copy of dcl for use in inlining
+ Closgen int
+ Outerfunc *Node
+ Fieldtrack []*Type
Inl *NodeList // copy of the body for use in inlining
InlCost int32
return t
}
+type typeSym struct {
+ t *Type
+ s *Sym
+}
+
+// dotField maps (*Type, *Sym) pairs to the corresponding struct field (*Type with Etype==TFIELD).
+// It is a cache for use during usefield in walk.go, only enabled when field tracking.
+var dotField = map[typeSym]*Type{}
+
func lookdot(n *Node, t *Type, dostrcmp int) *Type {
s := n.Right.Sym
}
n.Xoffset = f1.Width
n.Type = f1.Type
- n.Paramfld = f1
+ if obj.Fieldtrack_enabled > 0 {
+ dotField[typeSym{t, s}] = f1
+ }
if t.Etype == TINTER {
if Isptr[n.Left.Type.Etype] {
n.Left = Nod(OIND, n.Left, nil) // implicitstar
break
}
- field := n.Paramfld
+ t := n.Left.Type
+ if Isptr[t.Etype] {
+ t = t.Type
+ }
+ field := dotField[typeSym{t, n.Right.Sym}]
if field == nil {
Fatal("usefield %v %v without paramfld", n.Left.Type, n.Right.Sym)
}
Yyerror("tracked field must be exported (upper case)")
}
- l := typ(0)
- l.Type = field
- l.Down = Curfn.Paramfld
- Curfn.Paramfld = l
+ Curfn.Func.Fieldtrack = append(Curfn.Func.Fieldtrack, field)
}
func candiscardlist(l *NodeList) bool {