func compile(fn *Node) { if Newproc == nil { Newproc = Sysfunc("newproc") Deferproc = Sysfunc("deferproc") Deferreturn = Sysfunc("deferreturn") Panicindex = Sysfunc("panicindex") panicslice = Sysfunc("panicslice") panicdivide = Sysfunc("panicdivide") throwreturn = Sysfunc("throwreturn") growslice = Sysfunc("growslice") writebarrierptr = Sysfunc("writebarrierptr") typedmemmove = Sysfunc("typedmemmove") panicdottype = Sysfunc("panicdottype") } lno := setlineno(fn) Curfn = fn dowidth(Curfn.Type) var nod1 Node var ptxt *obj.Prog var pl *obj.Plist var p *obj.Prog var n *Node var nam *Node var gcargs *Sym var gclocals *Sym var ssafn *ssa.Func if len(fn.Nbody.Slice()) == 0 { if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") { Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name) goto ret } if Debug['A'] != 0 { goto ret } emitptrargsmap() goto ret } saveerrors() // set up domain for labels clearlabels() if Curfn.Type.Outnamed { // add clearing of the output parameters var save Iter t := Structfirst(&save, Getoutarg(Curfn.Type)) for t != nil { if t.Nname != nil { n = Nod(OAS, t.Nname, nil) typecheck(&n, Etop) Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...)) } t = structnext(&save) } } order(Curfn) if nerrors != 0 { goto ret } hasdefer = false walk(Curfn) if nerrors != 0 { goto ret } if instrumenting { instrument(Curfn) } if nerrors != 0 { goto ret } // Build an SSA backend function. if shouldssa(Curfn) { ssafn = buildssa(Curfn) } continpc = nil breakpc = nil pl = newplist() pl.Name = Linksym(Curfn.Func.Nname.Sym) setlineno(Curfn) Nodconst(&nod1, Types[TINT32], 0) nam = Curfn.Func.Nname if isblank(nam) { nam = nil } ptxt = Thearch.Gins(obj.ATEXT, nam, &nod1) Afunclit(&ptxt.From, Curfn.Func.Nname) ptxt.From3 = new(obj.Addr) if fn.Func.Dupok { ptxt.From3.Offset |= obj.DUPOK } if fn.Func.Wrapper { ptxt.From3.Offset |= obj.WRAPPER } if fn.Func.Needctxt { ptxt.From3.Offset |= obj.NEEDCTXT } if fn.Func.Pragma&Nosplit != 0 { ptxt.From3.Offset |= obj.NOSPLIT } if fn.Func.Pragma&Systemstack != 0 { ptxt.From.Sym.Cfunc = 1 } // Clumsy but important. // See test/recover.go for test cases and src/reflect/value.go // for the actual functions being considered. if myimportpath != "" && myimportpath == "reflect" { if Curfn.Func.Nname.Sym.Name == "callReflect" || Curfn.Func.Nname.Sym.Name == "callMethod" { ptxt.From3.Offset |= obj.WRAPPER } } ginit() gcargs = makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps) gclocals = makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps) for _, t := range Curfn.Func.Fieldtrack { gtrack(tracksym(t)) } for _, n := range fn.Func.Dcl { if n.Op != ONAME { // might be OTYPE or OLITERAL continue } switch n.Class { case PAUTO, PPARAM, PPARAMOUT: Nodconst(&nod1, Types[TUINTPTR], n.Type.Width) p = Thearch.Gins(obj.ATYPE, n, &nod1) p.From.Gotype = Linksym(ngotype(n)) } } if ssafn != nil { genssa(ssafn, ptxt, gcargs, gclocals) if Curfn.Func.Endlineno != 0 { lineno = Curfn.Func.Endlineno } ssafn.Free() return } Genlist(Curfn.Func.Enter) Genlist(Curfn.Nbody) gclean() checklabels() if nerrors != 0 { goto ret } if Curfn.Func.Endlineno != 0 { lineno = Curfn.Func.Endlineno } if Curfn.Type.Outtuple != 0 { Ginscall(throwreturn, 0) } ginit() // TODO: Determine when the final cgen_ret can be omitted. Perhaps always? cgen_ret(nil) if hasdefer { // deferreturn pretends to have one uintptr argument. // Reserve space for it so stack scanner is happy. if Maxarg < int64(Widthptr) { Maxarg = int64(Widthptr) } } gclean() if nerrors != 0 { goto ret } Pc.As = obj.ARET // overwrite AEND Pc.Lineno = lineno fixjmp(ptxt) if Debug['N'] == 0 || Debug['R'] != 0 || Debug['P'] != 0 { regopt(ptxt) nilopt(ptxt) } Thearch.Expandchecks(ptxt) allocauto(ptxt) setlineno(Curfn) if Stksize+Maxarg > 1<<31 { Yyerror("stack frame too large (>2GB)") goto ret } // Emit garbage collection symbols. liveness(Curfn, ptxt, gcargs, gclocals) gcsymdup(gcargs) gcsymdup(gclocals) Thearch.Defframe(ptxt) if Debug['f'] != 0 { frame(0) } // Remove leftover instrumentation from the instruction stream. removevardef(ptxt) ret: lineno = lno }
func compile(fn *Node) { if Newproc == nil { Newproc = Sysfunc("newproc") Deferproc = Sysfunc("deferproc") Deferreturn = Sysfunc("deferreturn") Panicindex = Sysfunc("panicindex") panicslice = Sysfunc("panicslice") panicdivide = Sysfunc("panicdivide") throwreturn = Sysfunc("throwreturn") growslice = Sysfunc("growslice") writebarrierptr = Sysfunc("writebarrierptr") typedmemmove = Sysfunc("typedmemmove") panicdottype = Sysfunc("panicdottype") } defer func(lno int32) { lineno = lno }(setlineno(fn)) Curfn = fn dowidth(Curfn.Type) if fn.Nbody.Len() == 0 { if pure_go || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") { Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name) return } if Debug['A'] != 0 { return } emitptrargsmap() return } saveerrors() // set up domain for labels clearlabels() if Curfn.Type.FuncType().Outnamed { // add clearing of the output parameters for _, t := range Curfn.Type.Results().Fields().Slice() { if t.Nname != nil { n := Nod(OAS, t.Nname, nil) n = typecheck(n, Etop) Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...)) } } } order(Curfn) if nerrors != 0 { return } hasdefer = false walk(Curfn) if nerrors != 0 { return } if instrumenting { instrument(Curfn) } if nerrors != 0 { return } // Build an SSA backend function. var ssafn *ssa.Func if shouldssa(Curfn) { ssafn = buildssa(Curfn) } continpc = nil breakpc = nil pl := newplist() pl.Name = Linksym(Curfn.Func.Nname.Sym) setlineno(Curfn) var nod1 Node Nodconst(&nod1, Types[TINT32], 0) nam := Curfn.Func.Nname if isblank(nam) { nam = nil } ptxt := Thearch.Gins(obj.ATEXT, nam, &nod1) Afunclit(&ptxt.From, Curfn.Func.Nname) ptxt.From3 = new(obj.Addr) if fn.Func.Dupok { ptxt.From3.Offset |= obj.DUPOK } if fn.Func.Wrapper { ptxt.From3.Offset |= obj.WRAPPER } if fn.Func.Needctxt { ptxt.From3.Offset |= obj.NEEDCTXT } if fn.Func.Pragma&Nosplit != 0 { ptxt.From3.Offset |= obj.NOSPLIT } if fn.Func.ReflectMethod { ptxt.From3.Offset |= obj.REFLECTMETHOD } if fn.Func.Pragma&Systemstack != 0 { ptxt.From.Sym.Cfunc = true } // Clumsy but important. // See test/recover.go for test cases and src/reflect/value.go // for the actual functions being considered. if myimportpath == "reflect" { if Curfn.Func.Nname.Sym.Name == "callReflect" || Curfn.Func.Nname.Sym.Name == "callMethod" { ptxt.From3.Offset |= obj.WRAPPER } } ginit() gcargs := makefuncdatasym("gcargs·", obj.FUNCDATA_ArgsPointerMaps) gclocals := makefuncdatasym("gclocals·", obj.FUNCDATA_LocalsPointerMaps) if obj.Fieldtrack_enabled != 0 && len(Curfn.Func.FieldTrack) > 0 { trackSyms := make([]*Sym, 0, len(Curfn.Func.FieldTrack)) for sym := range Curfn.Func.FieldTrack { trackSyms = append(trackSyms, sym) } sort.Sort(symByName(trackSyms)) for _, sym := range trackSyms { gtrack(sym) } } for _, n := range fn.Func.Dcl { if n.Op != ONAME { // might be OTYPE or OLITERAL continue } switch n.Class { case PAUTO, PPARAM, PPARAMOUT: Nodconst(&nod1, Types[TUINTPTR], n.Type.Width) p := Thearch.Gins(obj.ATYPE, n, &nod1) p.From.Gotype = Linksym(ngotype(n)) } } if ssafn != nil { genssa(ssafn, ptxt, gcargs, gclocals) ssafn.Free() } else { genlegacy(ptxt, gcargs, gclocals) } }