|  | // Inferno utils/5l/obj.c | 
|  | // http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c | 
|  | // | 
|  | //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved. | 
|  | //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | 
|  | //	Portions Copyright © 1997-1999 Vita Nuova Limited | 
|  | //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) | 
|  | //	Portions Copyright © 2004,2006 Bruce Ellis | 
|  | //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | 
|  | //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | 
|  | //	Portions Copyright © 2009 The Go Authors.  All rights reserved. | 
|  | // | 
|  | // Permission is hereby granted, free of charge, to any person obtaining a copy | 
|  | // of this software and associated documentation files (the "Software"), to deal | 
|  | // in the Software without restriction, including without limitation the rights | 
|  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
|  | // copies of the Software, and to permit persons to whom the Software is | 
|  | // furnished to do so, subject to the following conditions: | 
|  | // | 
|  | // The above copyright notice and this permission notice shall be included in | 
|  | // all copies or substantial portions of the Software. | 
|  | // | 
|  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE | 
|  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
|  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
|  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
|  | // THE SOFTWARE. | 
|  |  | 
|  | // Profiling. | 
|  |  | 
|  | #include "l.h" | 
|  | #include "../ld/lib.h" | 
|  |  | 
|  | void | 
|  | doprof1(void) | 
|  | { | 
|  | #ifdef	NOTDEF	// TODO(rsc) | 
|  | Sym *s; | 
|  | int32 n; | 
|  | Prog *p, *q; | 
|  |  | 
|  | if(debug['v']) | 
|  | Bprint(&bso, "%5.2f profile 1\n", cputime()); | 
|  | Bflush(&bso); | 
|  | s = lookup("__mcount", 0); | 
|  | n = 1; | 
|  | for(p = firstp->link; p != P; p = p->link) { | 
|  | if(p->as == ATEXT) { | 
|  | q = prg(); | 
|  | q->line = p->line; | 
|  | q->link = datap; | 
|  | datap = q; | 
|  | q->as = ADATA; | 
|  | q->from.type = D_OREG; | 
|  | q->from.name = D_EXTERN; | 
|  | q->from.offset = n*4; | 
|  | q->from.sym = s; | 
|  | q->reg = 4; | 
|  | q->to = p->from; | 
|  | q->to.type = D_CONST; | 
|  |  | 
|  | q = prg(); | 
|  | q->line = p->line; | 
|  | q->pc = p->pc; | 
|  | q->link = p->link; | 
|  | p->link = q; | 
|  | p = q; | 
|  | p->as = AMOVW; | 
|  | p->from.type = D_OREG; | 
|  | p->from.name = D_EXTERN; | 
|  | p->from.sym = s; | 
|  | p->from.offset = n*4 + 4; | 
|  | p->to.type = D_REG; | 
|  | p->to.reg = REGTMP; | 
|  |  | 
|  | q = prg(); | 
|  | q->line = p->line; | 
|  | q->pc = p->pc; | 
|  | q->link = p->link; | 
|  | p->link = q; | 
|  | p = q; | 
|  | p->as = AADD; | 
|  | p->from.type = D_CONST; | 
|  | p->from.offset = 1; | 
|  | p->to.type = D_REG; | 
|  | p->to.reg = REGTMP; | 
|  |  | 
|  | q = prg(); | 
|  | q->line = p->line; | 
|  | q->pc = p->pc; | 
|  | q->link = p->link; | 
|  | p->link = q; | 
|  | p = q; | 
|  | p->as = AMOVW; | 
|  | p->from.type = D_REG; | 
|  | p->from.reg = REGTMP; | 
|  | p->to.type = D_OREG; | 
|  | p->to.name = D_EXTERN; | 
|  | p->to.sym = s; | 
|  | p->to.offset = n*4 + 4; | 
|  |  | 
|  | n += 2; | 
|  | continue; | 
|  | } | 
|  | } | 
|  | q = prg(); | 
|  | q->line = 0; | 
|  | q->link = datap; | 
|  | datap = q; | 
|  |  | 
|  | q->as = ADATA; | 
|  | q->from.type = D_OREG; | 
|  | q->from.name = D_EXTERN; | 
|  | q->from.sym = s; | 
|  | q->reg = 4; | 
|  | q->to.type = D_CONST; | 
|  | q->to.offset = n; | 
|  |  | 
|  | s->type = SBSS; | 
|  | s->value = n*4; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void | 
|  | doprof2(void) | 
|  | { | 
|  | Sym *s2, *s4; | 
|  | Prog *p, *q, *ps2, *ps4; | 
|  |  | 
|  | if(debug['v']) | 
|  | Bprint(&bso, "%5.2f profile 2\n", cputime()); | 
|  | Bflush(&bso); | 
|  | s2 = lookup("_profin", 0); | 
|  | s4 = lookup("_profout", 0); | 
|  | if(s2->type != STEXT || s4->type != STEXT) { | 
|  | diag("_profin/_profout not defined"); | 
|  | return; | 
|  | } | 
|  | ps2 = P; | 
|  | ps4 = P; | 
|  | for(cursym = textp; cursym != nil; cursym = cursym->next) { | 
|  | p = cursym->text; | 
|  | if(cursym == s2) { | 
|  | ps2 = p; | 
|  | p->reg = 1; | 
|  | } | 
|  | if(cursym == s4) { | 
|  | ps4 = p; | 
|  | p->reg = 1; | 
|  | } | 
|  | } | 
|  | for(cursym = textp; cursym != nil; cursym = cursym->next) | 
|  | for(p = cursym->text; p != P; p = p->link) { | 
|  | if(p->as == ATEXT) { | 
|  | if(p->reg & NOPROF) { | 
|  | for(;;) { | 
|  | q = p->link; | 
|  | if(q == P) | 
|  | break; | 
|  | if(q->as == ATEXT) | 
|  | break; | 
|  | p = q; | 
|  | } | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * BL	profin, R2 | 
|  | */ | 
|  | q = prg(); | 
|  | q->line = p->line; | 
|  | q->pc = p->pc; | 
|  | q->link = p->link; | 
|  | p->link = q; | 
|  | p = q; | 
|  | p->as = ABL; | 
|  | p->to.type = D_BRANCH; | 
|  | p->cond = ps2; | 
|  | p->to.sym = s2; | 
|  |  | 
|  | continue; | 
|  | } | 
|  | if(p->as == ARET) { | 
|  | /* | 
|  | * RET | 
|  | */ | 
|  | q = prg(); | 
|  | q->as = ARET; | 
|  | q->from = p->from; | 
|  | q->to = p->to; | 
|  | q->link = p->link; | 
|  | p->link = q; | 
|  |  | 
|  | /* | 
|  | * BL	profout | 
|  | */ | 
|  | p->as = ABL; | 
|  | p->from = zprg.from; | 
|  | p->to = zprg.to; | 
|  | p->to.type = D_BRANCH; | 
|  | p->cond = ps4; | 
|  | p->to.sym = s4; | 
|  |  | 
|  | p = q; | 
|  |  | 
|  | continue; | 
|  | } | 
|  | } | 
|  | } |