// Copyright 2011 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. #undef EXTERN #define EXTERN #include "gg.h" #include "opt.h" void compile(Node *fn) { Plist *pl; Node nod1, *n; Prog *ptxt; int32 lno; Type *t; Iter save; if(newproc == N) { newproc = sysfunc("newproc"); deferproc = sysfunc("deferproc"); deferreturn = sysfunc("deferreturn"); panicindex = sysfunc("panicindex"); panicslice = sysfunc("panicslice"); throwreturn = sysfunc("throwreturn"); } if(fn->nbody == nil) return; // set up domain for labels clearlabels(); lno = setlineno(fn); curfn = fn; dowidth(curfn->type); if(curfn->type->outnamed) { // add clearing of the output parameters t = structfirst(&save, getoutarg(curfn->type)); while(t != T) { if(t->nname != N) { n = nod(OAS, t->nname, N); typecheck(&n, Etop); curfn->nbody = concat(list1(n), curfn->nbody); } t = structnext(&save); } } hasdefer = 0; walk(curfn); if(nerrors != 0 || isblank(curfn->nname)) goto ret; allocparams(); continpc = P; breakpc = P; pl = newplist(); pl->name = curfn->nname; setlineno(curfn); nodconst(&nod1, types[TINT32], 0); ptxt = gins(ATEXT, curfn->nname, &nod1); afunclit(&ptxt->from); ginit(); genlist(curfn->enter); retpc = nil; if(hasdefer || curfn->exit) { Prog *p1; p1 = gjmp(nil); retpc = gjmp(nil); patch(p1, pc); } genlist(curfn->nbody); gclean(); checklabels(); if(nerrors != 0) goto ret; if(curfn->endlineno) lineno = curfn->endlineno; if(curfn->type->outtuple != 0) ginscall(throwreturn, 0); if(retpc) patch(retpc, pc); ginit(); if(hasdefer) ginscall(deferreturn, 0); if(curfn->exit) genlist(curfn->exit); gclean(); if(nerrors != 0) goto ret; pc->as = ARET; // overwrite AEND pc->lineno = lineno; if(!debug['N'] || debug['R'] || debug['P']) { regopt(ptxt); } defframe(ptxt); if(debug['f']) frame(0); ret: lineno = lno; }