1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 // Declaration stack & operations
18 var blockgen int32 // max block number
20 var block int32 // current block number
22 // dclstack maintains a stack of shadowed symbol declarations so that
23 // popdcl can restore their declarations when a block scope ends.
24 // The stack is maintained as a linked list, using Sym's Link field.
26 // In practice, the "stack" actually ends up forming a tree: goto and label
27 // statements record the current state of dclstack so that checkgoto can
28 // validate that a goto statement does not jump over any declarations or
29 // into a new block scope.
31 // Finally, the Syms in this list are not "real" Syms as they don't actually
32 // represent object names. Sym is just a convenient type for saving shadowed
33 // Sym definitions, and only a subset of its fields are actually used.
36 func dcopy(a, b *Sym) {
41 a.Lastlineno = b.Lastlineno
52 // pushdcl pushes the current declaration for symbol s (if any) so that
53 // it can be shadowed by a new declaration within a nested block scope.
54 func pushdcl(s *Sym) *Sym {
60 // popdcl pops the innermost block scope and restores all symbol declarations
61 // to their previous state.
64 for ; d != nil && d.Name != ""; d = d.Link {
65 s := Pkglookup(d.Name, d.Pkg)
72 Fatalf("popdcl: no mark")
75 dclstack = d.Link // pop mark
79 // markdcl records the start of a new block scope for declarations.
82 d.Name = "" // used as a mark in fifo
89 // keep around for debugging
92 for d := dclstack; d != nil; d = d.Link {
93 fmt.Printf("%6d %p", i, d)
95 fmt.Printf(" '%s' %v\n", d.Name, Pkglookup(d.Name, d.Pkg))
103 func testdclstack() {
104 for d := dclstack; d != nil; d = d.Link {
109 yyerror("mark left on the stack")
114 // redeclare emits a diagnostic about symbol s being redeclared somewhere.
115 func redeclare(s *Sym, where string) {
116 if s.Lastlineno == 0 {
118 if s.Origpkg != nil {
124 yyerror("%v redeclared %s\n"+
125 "\tprevious declaration during import %q", s, where, pkgstr)
128 line2 := s.Lastlineno
130 // When an import and a declaration collide in separate files,
131 // present the import as the "redeclared", because the declaration
132 // is visible where the import is, but not vice versa.
139 yyerrorl(line1, "%v redeclared %s\n"+
140 "\tprevious declaration at %v", s, where, linestr(line2))
146 // declare individual names - var, typ, const
148 var declare_typegen int
150 // declare records that Node n declares symbol n.Sym in the specified
151 // declaration context.
152 func declare(n *Node, ctxt Class) {
153 if ctxt == PDISCARD {
162 // named OLITERAL needs Name; most OLITERALs don't.
168 // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
169 if importpkg == nil && !typecheckok && s.Pkg != localpkg {
170 yyerror("cannot declare name %v", s)
173 if ctxt == PEXTERN && s.Name == "init" {
174 yyerror("cannot declare init - must be func")
179 externdcl = append(externdcl, n)
181 if Curfn == nil && ctxt == PAUTO {
182 Fatalf("automatic outside function")
185 Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
189 gen = declare_typegen
190 } else if n.Op == ONAME && ctxt == PAUTO && !strings.Contains(s.Name, "·") {
202 if s.Block == block {
203 // functype will print errors about duplicate function arguments.
204 // Don't repeat the error here.
205 if ctxt != PPARAM && ctxt != PPARAMOUT {
206 redeclare(s, "in this block")
211 s.Lastlineno = lineno
213 n.Name.Vargen = int32(gen)
214 n.Name.Funcdepth = funcdepth
220 func addvar(n *Node, t *Type, ctxt Class) {
221 if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil {
222 Fatalf("addvar: n=%v t=%v nil", n, t)
230 // declare variables from grammar
231 // new_name_list (type | [type] = expr_list)
232 func variter(vl []*Node, t *Node, el []*Node) []*Node {
234 doexpr := len(el) > 0
236 if len(el) == 1 && len(vl) > 1 {
238 as2 := nod(OAS2, nil, nil)
241 for _, v := range vl {
243 declare(v, dclcontext)
244 v.Name.Param.Ntype = t
247 init = append(init, nod(ODCL, v, nil))
251 return append(init, as2)
254 for _, v := range vl {
258 yyerror("missing expression in var declaration")
266 declare(v, dclcontext)
267 v.Name.Param.Ntype = t
269 if e != nil || funcdepth > 0 || isblank(v) {
271 init = append(init, nod(ODCL, v, nil))
274 init = append(init, e)
282 yyerror("extra expression in var declaration")
287 // declare constants from grammar
288 // new_name_list [[type] = expr_list]
289 func constiter(vl []*Node, t *Node, cl []*Node) []*Node {
290 lno := int32(0) // default is to leave line number alone in listtreecopy
293 yyerror("const declaration cannot have type without expression")
302 clcopy := listtreecopy(cl, lno)
305 for _, v := range vl {
306 if len(clcopy) == 0 {
307 yyerror("missing value in const declaration")
315 declare(v, dclcontext)
317 v.Name.Param.Ntype = t
320 vv = append(vv, nod(ODCLCONST, v, nil))
323 if len(clcopy) != 0 {
324 yyerror("extra expression in const declaration")
330 // newname returns a new ONAME Node associated with symbol s.
331 func newname(s *Sym) *Node {
333 Fatalf("newname nil")
335 n := nod(ONAME, nil, nil)
343 // newnoname returns a new ONONAME Node associated with symbol s.
344 func newnoname(s *Sym) *Node {
346 Fatalf("newnoname nil")
348 n := nod(ONONAME, nil, nil)
356 // newfuncname generates a new name node for a function or method.
357 // TODO(rsc): Use an ODCLFUNC node instead. See comment in CL 7360.
358 func newfuncname(s *Sym) *Node {
361 n.Func.IsHiddenClosure = Curfn != nil
365 // this generates a new name node for a name
367 func dclname(s *Sym) *Node {
369 n.Op = ONONAME // caller will correct it
373 func typenod(t *Type) *Node {
374 // if we copied another type with *t = *u
375 // then t->nod might be out of date, so
376 // check t->nod->type too
377 if t.nod == nil || t.nod.Type != t {
378 t.nod = nod(OTYPE, nil, nil)
386 func anonfield(typ *Type) *Node {
387 return nod(ODCLFIELD, nil, typenod(typ))
390 func namedfield(s string, typ *Type) *Node {
391 return nod(ODCLFIELD, newname(lookup(s)), typenod(typ))
394 // oldname returns the Node that declares symbol s in the current scope.
395 // If no such Node currently exists, an ONONAME Node is returned instead.
396 func oldname(s *Sym) *Node {
399 // Maybe a top-level declaration will come along later to
400 // define s. resolve will check s.Def again once all input
401 // source has been processed.
403 n.SetIota(iota_) // save current iota value in const declarations
407 if Curfn != nil && n.Op == ONAME && n.Name.Funcdepth > 0 && n.Name.Funcdepth != funcdepth {
408 // Inner func is referring to var in outer func.
410 // TODO(rsc): If there is an outer variable x and we
411 // are parsing x := 5 inside the closure, until we get to
412 // the := it looks like a reference to the outer x so we'll
413 // make x a closure variable unnecessarily.
414 c := n.Name.Param.Innermost
415 if c == nil || c.Name.Funcdepth != funcdepth {
416 // Do not have a closure var for the active closure yet; make one.
417 c = nod(ONAME, nil, nil)
420 c.setIsClosureVar(true)
425 c.Name.Funcdepth = funcdepth
427 // Link into list of active closure variables.
428 // Popped from list in func closurebody.
429 c.Name.Param.Outer = n.Name.Param.Innermost
430 n.Name.Param.Innermost = c
433 Curfn.Func.Cvars.Append(c)
436 // return ref to closure var, not original
444 func colasname(n *Node) bool {
457 func colasdefn(left []*Node, defn *Node) {
458 for _, n := range left {
460 n.Sym.Flags |= SymUniq
465 for i, n := range left {
470 yyerrorl(defn.Lineno, "non-name %v on left side of :=", n)
475 if n.Sym.Flags&SymUniq == 0 {
476 yyerrorl(defn.Lineno, "%v repeated on left side of :=", n.Sym)
482 n.Sym.Flags &^= SymUniq
483 if n.Sym.Block == block {
489 declare(n, dclcontext)
491 defn.Ninit.Append(nod(ODCL, n, nil))
495 if nnew == 0 && nerr == 0 {
496 yyerrorl(defn.Lineno, "no new variables on left side of :=")
500 // declare the arguments in an
501 // interface field declaration.
502 func ifacedcl(n *Node) {
503 if n.Op != ODCLFIELD || n.Right == nil {
508 yyerror("methods must have a unique non-blank name")
512 // declare the function proper
513 // and declare the arguments.
514 // called in extern-declaration context
515 // returns in auto-declaration context.
516 func funchdr(n *Node) {
517 // change the declaration context from extern to auto
518 if funcdepth == 0 && dclcontext != PEXTERN {
519 Fatalf("funchdr: dclcontext = %d", dclcontext)
525 if n.Func.Nname != nil {
526 funcargs(n.Func.Nname.Name.Param.Ntype)
527 } else if n.Func.Ntype != nil {
528 funcargs(n.Func.Ntype)
534 func funcargs(nt *Node) {
536 Fatalf("funcargs %v", nt.Op)
539 // re-start the variable generation number
540 // we want to use small numbers for the return variables,
541 // so let them have the chunk starting at 1.
542 vargen = nt.Rlist.Len()
544 // declare the receiver and in arguments.
545 // no n->defn because type checking of func header
546 // will not fill in the types until later
549 if n.Op != ODCLFIELD {
550 Fatalf("funcargs receiver %v", n.Op)
554 n.Left.Name.Param.Ntype = n.Right
555 declare(n.Left, PPARAM)
556 if dclcontext == PAUTO {
558 n.Left.Name.Vargen = int32(vargen)
563 for _, n := range nt.List.Slice() {
564 if n.Op != ODCLFIELD {
565 Fatalf("funcargs in %v", n.Op)
569 n.Left.Name.Param.Ntype = n.Right
570 declare(n.Left, PPARAM)
571 if dclcontext == PAUTO {
573 n.Left.Name.Vargen = int32(vargen)
578 // declare the out arguments.
581 for _, n := range nt.Rlist.Slice() {
582 if n.Op != ODCLFIELD {
583 Fatalf("funcargs out %v", n.Op)
587 // Name so that escape analysis can track it. ~r stands for 'result'.
588 n.Left = newname(lookupN("~r", gen))
592 // TODO: n->left->missing = 1;
596 // Give it a name so we can assign to it during return. ~b stands for 'blank'.
597 // The name must be different from ~r above because if you have
600 // f is allowed to use a plain 'return' with no arguments, while g is not.
601 // So the two cases must be distinguished.
602 // We do not record a pointer to the original node (n->orig).
603 // Having multiple names causes too much confusion in later passes.
606 nn.Sym = lookupN("~b", gen)
611 n.Left.Name.Param.Ntype = n.Right
612 declare(n.Left, PPARAMOUT)
613 if dclcontext == PAUTO {
615 n.Left.Name.Vargen = int32(i)
620 // Same as funcargs, except run over an already constructed TFUNC.
621 // This happens during import, where the hidden_fndcl rule has
622 // used functype directly to parse the function's type.
623 func funcargs2(t *Type) {
624 if t.Etype != TFUNC {
625 Fatalf("funcargs2 %v", t)
628 for _, ft := range t.Recvs().Fields().Slice() {
629 if ft.Nname == nil || ft.Nname.Sym == nil {
632 n := ft.Nname // no need for newname(ft->nname->sym)
637 for _, ft := range t.Params().Fields().Slice() {
638 if ft.Nname == nil || ft.Nname.Sym == nil {
646 for _, ft := range t.Results().Fields().Slice() {
647 if ft.Nname == nil || ft.Nname.Sym == nil {
652 declare(n, PPARAMOUT)
656 var funcstack []*Node // stack of previous values of Curfn
657 var funcdepth int32 // len(funcstack) during parsing, but then forced to be the same later during compilation
659 // start the function.
660 // called before funcargs; undone at end of funcbody.
661 func funcstart(n *Node) {
663 funcstack = append(funcstack, Curfn)
669 // called in auto-declaration context.
670 // returns in extern-declaration context.
671 func funcbody(n *Node) {
672 // change the declaration context from auto to extern
673 if dclcontext != PAUTO {
674 Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
677 funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
684 // new type being defined with name s.
685 func typedcl0(s *Sym) *Node {
688 declare(n, dclcontext)
692 // node n, which was returned by typedcl0
693 // is being declared to have uncompiled type t.
694 // returns the ODCLTYPE node to use.
695 func typedcl1(n *Node, t *Node, pragma Pragma, alias bool) *Node {
696 if pragma != 0 && alias {
697 yyerror("cannot specify directive with type alias")
708 return nod(ODCLTYPE, n, nil)
711 // structs, functions, and methods.
712 // they don't belong here, but where do they belong?
713 func checkembeddedtype(t *Type) {
718 if t.Sym == nil && t.IsPtr() {
721 yyerror("embedded type cannot be a pointer to interface")
725 if t.IsPtr() || t.IsUnsafePtr() {
726 yyerror("embedded type cannot be a pointer")
727 } else if t.Etype == TFORW && t.ForwardType().Embedlineno == 0 {
728 t.ForwardType().Embedlineno = lineno
732 func structfield(n *Node) *Field {
736 if n.Op != ODCLFIELD {
737 Fatalf("structfield: oops %v\n", n)
744 n.Right = typecheck(n.Right, Etype)
745 n.Type = n.Right.Type
750 checkembeddedtype(n.Type)
761 switch u := n.Val().U.(type) {
765 yyerror("field annotation must be string")
770 if n.Left != nil && n.Left.Op == ONAME {
772 f.Embedded = n.Embedded
780 // checkdupfields emits errors for duplicately named fields or methods in
781 // a list of struct or interface types.
782 func checkdupfields(what string, ts ...*Type) {
785 seen := make(map[*Sym]bool)
786 for _, t := range ts {
787 for _, f := range t.Fields().Slice() {
788 if f.Sym == nil || f.Nname == nil || isblank(f.Nname) {
792 lineno = f.Nname.Lineno
793 yyerror("duplicate %s %s", what, f.Sym.Name)
803 // convert a parsed id/type list into
804 // a type for struct/interface/arglist
805 func tostruct(l []*Node) *Type {
811 func tostruct0(t *Type, l []*Node) {
812 if t == nil || !t.IsStruct() {
813 Fatalf("struct expected")
816 fields := make([]*Field, len(l))
817 for i, n := range l {
826 checkdupfields("field", t)
833 func tofunargs(l []*Node, funarg Funarg) *Type {
835 t.StructType().Funarg = funarg
837 fields := make([]*Field, len(l))
838 for i, n := range l {
842 // esc.go needs to find f given a PPARAM to add the tag.
843 if n.Left != nil && n.Left.Class == PPARAM {
844 n.Left.Name.Param.Field = f
855 func tofunargsfield(fields []*Field, funarg Funarg) *Type {
857 t.StructType().Funarg = funarg
859 for _, f := range fields {
862 // esc.go needs to find f given a PPARAM to add the tag.
863 if f.Nname != nil && f.Nname.Class == PPARAM {
864 f.Nname.Name.Param.Field = f
871 func interfacefield(n *Node) *Field {
875 if n.Op != ODCLFIELD {
876 Fatalf("interfacefield: oops %v\n", n)
879 if n.Val().Ctype() != CTxxx {
880 yyerror("interface method cannot have annotation")
888 // queue resolution of method type for later.
889 // right now all we need is the name list.
890 // avoids cycles for recursive interface types.
891 n.Type = typ(TINTERMETH)
892 n.Type.SetNname(n.Right)
896 if n.Left.Op == ONAME {
898 f.Embedded = n.Embedded
902 n.Right = typecheck(n.Right, Etype)
903 n.Type = n.Right.Type
906 checkembeddedtype(n.Type)
910 switch n.Type.Etype {
915 yyerror("interface type loop involving %v", n.Type)
919 yyerror("interface contains embedded non-interface %v", n.Type)
937 func tointerface(l []*Node) *Type {
943 func tointerface0(t *Type, l []*Node) *Type {
944 if t == nil || !t.IsInterface() {
945 Fatalf("interface expected")
949 for _, n := range l {
950 f := interfacefield(n)
952 if n.Left == nil && f.Type.IsInterface() {
953 // embedded interface, inline methods
954 for _, t1 := range f.Type.Fields().Slice() {
960 f.Nname = newname(f.Sym)
962 fields = append(fields, f)
965 fields = append(fields, f)
971 sort.Sort(methcmp(fields))
974 checkdupfields("method", t)
980 func embedded(s *Sym, pkg *Pkg) *Node {
984 // Names sometimes have disambiguation junk
985 // appended after a center dot. Discard it when
986 // making the name for the embedded struct field.
989 if i := strings.Index(s.Name, string(CenterDot)); i >= 0 {
994 if exportname(name) {
995 n = newname(lookup(name))
996 } else if s.Pkg == builtinpkg {
997 // The name of embedded builtins belongs to pkg.
998 n = newname(Pkglookup(name, pkg))
1000 n = newname(Pkglookup(name, s.Pkg))
1002 n = nod(ODCLFIELD, n, oldname(s))
1007 // thisT is the singleton type used for interface method receivers.
1010 func fakethis() *Node {
1012 thisT = ptrto(typ(TSTRUCT))
1014 return nod(ODCLFIELD, nil, typenod(thisT))
1017 func fakethisfield() *Field {
1019 thisT = ptrto(typ(TSTRUCT))
1026 // Is this field a method on an interface?
1027 // Those methods have thisT as the receiver.
1028 // (See fakethis above.)
1029 func isifacemethod(f *Type) bool {
1030 return f.Recv().Type == thisT
1033 // turn a parsed function declaration into a type
1034 func functype(this *Node, in, out []*Node) *Type {
1036 functype0(t, this, in, out)
1040 func functype0(t *Type, this *Node, in, out []*Node) {
1041 if t == nil || t.Etype != TFUNC {
1042 Fatalf("function type expected")
1047 rcvr = []*Node{this}
1049 t.FuncType().Receiver = tofunargs(rcvr, FunargRcvr)
1050 t.FuncType().Results = tofunargs(out, FunargResults)
1051 t.FuncType().Params = tofunargs(in, FunargParams)
1053 checkdupfields("argument", t.Recvs(), t.Results(), t.Params())
1055 if t.Recvs().Broke || t.Results().Broke || t.Params().Broke {
1059 t.FuncType().Outnamed = false
1060 if len(out) > 0 && out[0].Left != nil && out[0].Left.Orig != nil {
1061 s := out[0].Left.Orig.Sym
1062 if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result
1063 t.FuncType().Outnamed = true
1068 func functypefield(this *Field, in, out []*Field) *Type {
1070 functypefield0(t, this, in, out)
1074 func functypefield0(t *Type, this *Field, in, out []*Field) {
1077 rcvr = []*Field{this}
1079 t.FuncType().Receiver = tofunargsfield(rcvr, FunargRcvr)
1080 t.FuncType().Results = tofunargsfield(out, FunargRcvr)
1081 t.FuncType().Params = tofunargsfield(in, FunargRcvr)
1083 t.FuncType().Outnamed = false
1084 if len(out) > 0 && out[0].Nname != nil && out[0].Nname.Orig != nil {
1085 s := out[0].Nname.Orig.Sym
1086 if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result
1087 t.FuncType().Outnamed = true
1092 var methodsym_toppkg *Pkg
1094 func methodsym(nsym *Sym, t0 *Type, iface int) *Sym {
1105 if s == nil && t.IsPtr() {
1118 // if t0 == *t and t0 has a sym,
1119 // we want to see *t, not t0, in the method name.
1120 if t != t0 && t0.Sym != nil {
1127 if t0.Width < Types[Tptr].Width {
1132 if (spkg == nil || nsym.Pkg != spkg) && !exportname(nsym.Name) {
1133 if t0.Sym == nil && t0.IsPtr() {
1134 p = fmt.Sprintf("(%-S).%s.%s%s", t0, nsym.Pkg.Prefix, nsym.Name, suffix)
1136 p = fmt.Sprintf("%-S.%s.%s%s", t0, nsym.Pkg.Prefix, nsym.Name, suffix)
1139 if t0.Sym == nil && t0.IsPtr() {
1140 p = fmt.Sprintf("(%-S).%s%s", t0, nsym.Name, suffix)
1142 p = fmt.Sprintf("%-S.%s%s", t0, nsym.Name, suffix)
1147 if methodsym_toppkg == nil {
1148 methodsym_toppkg = mkpkg("go")
1150 spkg = methodsym_toppkg
1153 s = Pkglookup(p, spkg)
1158 yyerror("illegal receiver type: %v", t0)
1162 // methodname is a misnomer because this now returns a Sym, rather
1164 // TODO(mdempsky): Reconcile with methodsym.
1165 func methodname(s *Sym, recv *Type) *Sym {
1173 if tsym == nil || isblanksym(s) {
1179 p = fmt.Sprintf("(*%v).%v", tsym, s)
1181 p = fmt.Sprintf("%v.%v", tsym, s)
1184 if exportname(tsym.Name) {
1187 s = Pkglookup(p, tsym.Pkg)
1193 // Add a method, declared as a function.
1194 // - msym is the method symbol
1195 // - t is function type (with receiver)
1196 func addmethod(msym *Sym, t *Type, local, nointerface bool) {
1198 Fatalf("no method symbol")
1201 // get parent type sym
1202 rf := t.Recv() // ptr to this structure
1204 yyerror("missing receiver")
1208 mt := methtype(rf.Type)
1209 if mt == nil || mt.Sym == nil {
1212 if t != nil && t.IsPtr() {
1214 yyerror("invalid receiver type %v (%v is a pointer type)", pa, t)
1221 case t == nil || t.Broke:
1222 // rely on typecheck having complained before
1224 yyerror("invalid receiver type %v (%v is an unnamed type)", pa, t)
1226 yyerror("invalid receiver type %v (%v is a pointer type)", pa, t)
1227 case t.IsInterface():
1228 yyerror("invalid receiver type %v (%v is an interface type)", pa, t)
1230 // Should have picked off all the reasons above,
1231 // but just in case, fall back to generic error.
1232 yyerror("invalid receiver type %v (%L / %L)", pa, pa, t)
1237 if local && !mt.Local {
1238 yyerror("cannot define new methods on non-local type %v", mt)
1242 if isblanksym(msym) {
1247 for _, f := range mt.Fields().Slice() {
1249 yyerror("type %v has both field and method named %v", mt, msym)
1255 for _, f := range mt.Methods().Slice() {
1256 if msym.Name != f.Sym.Name {
1259 // eqtype only checks that incoming and result parameters match,
1260 // so explicitly check that the receiver parameters match too.
1261 if !eqtype(t, f.Type) || !eqtype(t.Recv().Type, f.Type.Recv().Type) {
1262 yyerror("method redeclared: %v.%v\n\t%v\n\t%v", mt, msym, f.Type, t)
1269 f.Nname = newname(msym)
1271 f.Nointerface = nointerface
1273 mt.Methods().Append(f)
1276 func funccompile(n *Node) {
1282 Fatalf("funccompile missing type")
1287 // assign parameter offsets
1291 Fatalf("funccompile %v inside %v", n.Func.Nname.Sym, Curfn.Func.Nname.Sym)
1296 funcdepth = n.Func.Depth + 1
1301 dclcontext = PEXTERN
1303 // If we have compile errors, ignore any assembler/linker errors.
1304 Ctxt.DiagFunc = func(string, ...interface{}) {}
1306 obj.Flushplist(Ctxt) // convert from Prog list to machine code
1309 func funcsym(s *Sym) *Sym {
1314 s1 := Pkglookup(s.Name+"·f", s.Pkg)
1315 if !Ctxt.Flag_dynlink && s1.Def == nil {
1316 s1.Def = newfuncname(s1)
1317 s1.Def.Func.Shortname = s
1318 funcsyms = append(funcsyms, s1.Def)
1324 func makefuncsym(s *Sym) {
1328 if compiling_runtime && s.Name == "getg" {
1329 // runtime.getg() is not a real function and so does
1330 // not get a funcsym.
1337 s1.Def = newfuncname(s1)
1338 s1.Def.Func.Shortname = s
1339 funcsyms = append(funcsyms, s1.Def)
1342 type nowritebarrierrecChecker struct {
1346 // best maps from the ODCLFUNC of each visited function that
1347 // recursively invokes a write barrier to the called function
1348 // on the shortest path to a write barrier.
1349 best map[*Node]nowritebarrierrecCall
1352 type nowritebarrierrecCall struct {
1358 func checknowritebarrierrec() {
1359 c := nowritebarrierrecChecker{
1360 best: make(map[*Node]nowritebarrierrecCall),
1362 visitBottomUp(xtop, func(list []*Node, recursive bool) {
1363 // Functions with write barriers have depth 0.
1364 for _, n := range list {
1365 if n.Func.WBLineno != 0 && n.Func.Pragma&Yeswritebarrierrec == 0 {
1366 c.best[n] = nowritebarrierrecCall{target: nil, depth: 0, lineno: n.Func.WBLineno}
1370 // Propagate write barrier depth up from callees. In
1371 // the recursive case, we have to update this at most
1372 // len(list) times and can stop when we an iteration
1373 // that doesn't change anything.
1374 for _ = range list {
1376 for _, n := range list {
1377 if n.Func.Pragma&Yeswritebarrierrec != 0 {
1378 // Don't propagate write
1380 // yeswritebarrierrec function.
1383 if n.Func.WBLineno == 0 {
1385 c.visitcodelist(n.Nbody)
1393 // Check nowritebarrierrec functions.
1394 for _, n := range list {
1395 if n.Func.Pragma&Nowritebarrierrec == 0 {
1398 call, hasWB := c.best[n]
1403 // Build the error message in reverse.
1405 for call.target != nil {
1406 err = fmt.Sprintf("\n\t%v: called by %v%s", linestr(call.lineno), n.Func.Nname, err)
1410 err = fmt.Sprintf("write barrier prohibited by caller; %v%s", n.Func.Nname, err)
1411 yyerrorl(n.Func.WBLineno, err)
1416 func (c *nowritebarrierrecChecker) visitcodelist(l Nodes) {
1417 for _, n := range l.Slice() {
1422 func (c *nowritebarrierrecChecker) visitcode(n *Node) {
1427 if n.Op == OCALLFUNC || n.Op == OCALLMETH {
1431 c.visitcodelist(n.Ninit)
1433 c.visitcode(n.Right)
1434 c.visitcodelist(n.List)
1435 c.visitcodelist(n.Nbody)
1436 c.visitcodelist(n.Rlist)
1439 func (c *nowritebarrierrecChecker) visitcall(n *Node) {
1441 if n.Op == OCALLMETH {
1444 if fn == nil || fn.Op != ONAME || fn.Class != PFUNC || fn.Name.Defn == nil {
1447 defn := fn.Name.Defn
1449 fnbest, ok := c.best[defn]
1453 best, ok := c.best[c.curfn]
1454 if ok && fnbest.depth+1 >= best.depth {
1457 c.best[c.curfn] = nowritebarrierrecCall{target: defn, depth: fnbest.depth + 1, lineno: n.Lineno}