github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/5l/pass.c (about)

     1  // Inferno utils/5l/pass.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5l/pass.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  // Code and data passes.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  
    36  static void xfol(Prog*, Prog**);
    37  
    38  Prog*
    39  brchain(Prog *p)
    40  {
    41  	int i;
    42  
    43  	for(i=0; i<20; i++) {
    44  		if(p == P || p->as != AB)
    45  			return p;
    46  		p = p->cond;
    47  	}
    48  	return P;
    49  }
    50  
    51  int
    52  relinv(int a)
    53  {
    54  	switch(a) {
    55  	case ABEQ:	return ABNE;
    56  	case ABNE:	return ABEQ;
    57  	case ABCS:	return ABCC;
    58  	case ABHS:	return ABLO;
    59  	case ABCC:	return ABCS;
    60  	case ABLO:	return ABHS;
    61  	case ABMI:	return ABPL;
    62  	case ABPL:	return ABMI;
    63  	case ABVS:	return ABVC;
    64  	case ABVC:	return ABVS;
    65  	case ABHI:	return ABLS;
    66  	case ABLS:	return ABHI;
    67  	case ABGE:	return ABLT;
    68  	case ABLT:	return ABGE;
    69  	case ABGT:	return ABLE;
    70  	case ABLE:	return ABGT;
    71  	}
    72  	diag("unknown relation: %s", anames[a]);
    73  	return a;
    74  }
    75  
    76  void
    77  follow(void)
    78  {
    79  	Prog *firstp, *lastp;
    80  
    81  	if(debug['v'])
    82  		Bprint(&bso, "%5.2f follow\n", cputime());
    83  	Bflush(&bso);
    84  
    85  	for(cursym = textp; cursym != nil; cursym = cursym->next) {
    86  		firstp = prg();
    87  		lastp = firstp;
    88  		xfol(cursym->text, &lastp);
    89  		lastp->link = nil;
    90  		cursym->text = firstp->link;
    91  	}
    92  }
    93  
    94  static void
    95  xfol(Prog *p, Prog **last)
    96  {
    97  	Prog *q, *r;
    98  	int a, i;
    99  
   100  loop:
   101  	if(p == P)
   102  		return;
   103  	a = p->as;
   104  	if(a == AB) {
   105  		q = p->cond;
   106  		if(q != P && q->as != ATEXT) {
   107  			p->mark |= FOLL;
   108  			p = q;
   109  			if(!(p->mark & FOLL))
   110  				goto loop;
   111  		}
   112  	}
   113  	if(p->mark & FOLL) {
   114  		for(i=0,q=p; i<4; i++,q=q->link) {
   115  			if(q == *last || q == nil)
   116  				break;
   117  			a = q->as;
   118  			if(a == ANOP) {
   119  				i--;
   120  				continue;
   121  			}
   122  			if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF)
   123  				goto copy;
   124  			if(q->cond == P || (q->cond->mark&FOLL))
   125  				continue;
   126  			if(a != ABEQ && a != ABNE)
   127  				continue;
   128  		copy:
   129  			for(;;) {
   130  				r = prg();
   131  				*r = *p;
   132  				if(!(r->mark&FOLL))
   133  					print("can't happen 1\n");
   134  				r->mark |= FOLL;
   135  				if(p != q) {
   136  					p = p->link;
   137  					(*last)->link = r;
   138  					*last = r;
   139  					continue;
   140  				}
   141  				(*last)->link = r;
   142  				*last = r;
   143  				if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF)
   144  					return;
   145  				r->as = ABNE;
   146  				if(a == ABNE)
   147  					r->as = ABEQ;
   148  				r->cond = p->link;
   149  				r->link = p->cond;
   150  				if(!(r->link->mark&FOLL))
   151  					xfol(r->link, last);
   152  				if(!(r->cond->mark&FOLL))
   153  					print("can't happen 2\n");
   154  				return;
   155  			}
   156  		}
   157  		a = AB;
   158  		q = prg();
   159  		q->as = a;
   160  		q->line = p->line;
   161  		q->to.type = D_BRANCH;
   162  		q->to.offset = p->pc;
   163  		q->cond = p;
   164  		p = q;
   165  	}
   166  	p->mark |= FOLL;
   167  	(*last)->link = p;
   168  	*last = p;
   169  	if(a == AB || (a == ARET && p->scond == 14) || a == ARFE || a == AUNDEF){
   170  		return;
   171  	}
   172  	if(p->cond != P)
   173  	if(a != ABL && a != ABX && p->link != P) {
   174  		q = brchain(p->link);
   175  		if(a != ATEXT && a != ABCASE)
   176  		if(q != P && (q->mark&FOLL)) {
   177  			p->as = relinv(a);
   178  			p->link = p->cond;
   179  			p->cond = q;
   180  		}
   181  		xfol(p->link, last);
   182  		q = brchain(p->cond);
   183  		if(q == P)
   184  			q = p->cond;
   185  		if(q->mark&FOLL) {
   186  			p->cond = q;
   187  			return;
   188  		}
   189  		p = q;
   190  		goto loop;
   191  	}
   192  	p = p->link;
   193  	goto loop;
   194  }
   195  
   196  void
   197  patch(void)
   198  {
   199  	int32 c, vexit;
   200  	Prog *p, *q;
   201  	Sym *s;
   202  	int a;
   203  
   204  	if(debug['v'])
   205  		Bprint(&bso, "%5.2f patch\n", cputime());
   206  	Bflush(&bso);
   207  	mkfwd();
   208  	s = lookup("exit", 0);
   209  	vexit = s->value;
   210  	for(cursym = textp; cursym != nil; cursym = cursym->next) {
   211  		for(p = cursym->text; p != P; p = p->link) {
   212  			a = p->as;
   213  			if((a == ABL || a == ABX || a == AB || a == ARET) &&
   214  			   p->to.type != D_BRANCH && p->to.sym != S) {
   215  				s = p->to.sym;
   216  				if(s->text == nil)
   217  					continue;
   218  				switch(s->type&SMASK) {
   219  				default:
   220  					diag("undefined: %s", s->name);
   221  					s->type = STEXT;
   222  					s->value = vexit;
   223  					continue;	// avoid more error messages
   224  				case STEXT:
   225  					p->to.offset = s->value;
   226  					p->to.type = D_BRANCH;
   227  					p->cond = s->text;
   228  					continue;
   229  				}
   230  			}
   231  			if(p->to.type != D_BRANCH)
   232  				continue;
   233  			c = p->to.offset;
   234  			for(q = cursym->text; q != P;) {
   235  				if(c == q->pc)
   236  					break;
   237  				if(q->forwd != P && c >= q->forwd->pc)
   238  					q = q->forwd;
   239  				else
   240  					q = q->link;
   241  			}
   242  			if(q == P) {
   243  				diag("branch out of range %d\n%P", c, p);
   244  				p->to.type = D_NONE;
   245  			}
   246  			p->cond = q;
   247  		}
   248  	}
   249  	if(flag_shared) {
   250  		s = lookup("init_array", 0);
   251  		s->type = SINITARR;
   252  		s->reachable = 1;
   253  		s->hide = 1;
   254  		addaddr(s, lookup(INITENTRY, 0));
   255  	}
   256  
   257  	for(cursym = textp; cursym != nil; cursym = cursym->next) {
   258  		for(p = cursym->text; p != P; p = p->link) {
   259  			if(p->cond != P) {
   260  				p->cond = brloop(p->cond);
   261  				if(p->cond != P)
   262  				if(p->to.type == D_BRANCH)
   263  					p->to.offset = p->cond->pc;
   264  			}
   265  		}
   266  	}
   267  }
   268  
   269  Prog*
   270  brloop(Prog *p)
   271  {
   272  	Prog *q;
   273  	int c;
   274  
   275  	for(c=0; p!=P;) {
   276  		if(p->as != AB)
   277  			return p;
   278  		q = p->cond;
   279  		if(q <= p) {
   280  			c++;
   281  			if(q == p || c > 5000)
   282  				break;
   283  		}
   284  		p = q;
   285  	}
   286  	return P;
   287  }
   288  
   289  int32
   290  atolwhex(char *s)
   291  {
   292  	int32 n;
   293  	int f;
   294  
   295  	n = 0;
   296  	f = 0;
   297  	while(*s == ' ' || *s == '\t')
   298  		s++;
   299  	if(*s == '-' || *s == '+') {
   300  		if(*s++ == '-')
   301  			f = 1;
   302  		while(*s == ' ' || *s == '\t')
   303  			s++;
   304  	}
   305  	if(s[0]=='0' && s[1]){
   306  		if(s[1]=='x' || s[1]=='X'){
   307  			s += 2;
   308  			for(;;){
   309  				if(*s >= '0' && *s <= '9')
   310  					n = n*16 + *s++ - '0';
   311  				else if(*s >= 'a' && *s <= 'f')
   312  					n = n*16 + *s++ - 'a' + 10;
   313  				else if(*s >= 'A' && *s <= 'F')
   314  					n = n*16 + *s++ - 'A' + 10;
   315  				else
   316  					break;
   317  			}
   318  		} else
   319  			while(*s >= '0' && *s <= '7')
   320  				n = n*8 + *s++ - '0';
   321  	} else
   322  		while(*s >= '0' && *s <= '9')
   323  			n = n*10 + *s++ - '0';
   324  	if(f)
   325  		n = -n;
   326  	return n;
   327  }
   328  
   329  int32
   330  rnd(int32 v, int32 r)
   331  {
   332  	int32 c;
   333  
   334  	if(r <= 0)
   335  		return v;
   336  	v += r - 1;
   337  	c = v % r;
   338  	if(c < 0)
   339  		c += r;
   340  	v -= c;
   341  	return v;
   342  }
   343  
   344  void
   345  dozerostk(void)
   346  {
   347  	Prog *p, *pl;
   348  	int32 autoffset;
   349  
   350  	for(cursym = textp; cursym != nil; cursym = cursym->next) {
   351  		if(cursym->text == nil || cursym->text->link == nil)
   352  			continue;				
   353  		p = cursym->text;
   354  		autoffset = p->to.offset;
   355  		if(autoffset < 0)
   356  			autoffset = 0;
   357  		if(autoffset && !(p->reg&NOSPLIT)) {
   358  			// MOVW $4(R13), R1
   359  			p = appendp(p);
   360  			p->as = AMOVW;
   361  			p->from.type = D_CONST;
   362  			p->from.reg = 13;
   363  			p->from.offset = 4;
   364  			p->to.type = D_REG;
   365  			p->to.reg = 1;
   366  
   367  			// MOVW $n(R13), R2
   368  			p = appendp(p);
   369  			p->as = AMOVW;
   370  			p->from.type = D_CONST;
   371  			p->from.reg = 13;
   372  			p->from.offset = 4 + autoffset;
   373  			p->to.type = D_REG;
   374  			p->to.reg = 2;
   375  
   376  			// MOVW $0, R3
   377  			p = appendp(p);
   378  			p->as = AMOVW;
   379  			p->from.type = D_CONST;
   380  			p->from.offset = 0;
   381  			p->to.type = D_REG;
   382  			p->to.reg = 3;
   383  
   384  			// L:
   385  			//	MOVW.P R3, 0(R1) +4
   386  			//	CMP R1, R2
   387  			//	BNE L
   388  			p = pl = appendp(p);
   389  			p->as = AMOVW;
   390  			p->from.type = D_REG;
   391  			p->from.reg = 3;
   392  			p->to.type = D_OREG;
   393  			p->to.reg = 1;
   394  			p->to.offset = 4;
   395  			p->scond |= C_PBIT;
   396  
   397  			p = appendp(p);
   398  			p->as = ACMP;
   399  			p->from.type = D_REG;
   400  			p->from.reg = 1;
   401  			p->reg = 2;
   402  
   403  			p = appendp(p);
   404  			p->as = ABNE;
   405  			p->to.type = D_BRANCH;
   406  			p->cond = pl;
   407  		}
   408  	}
   409  }