| // 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; |
| } |