The Go Programming Language

Text file src/cmd/5l/pass.c

     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)
   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("cant 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)
   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("cant 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){
   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					switch(s->type) {
   217					default:
   218						diag("undefined: %s", s->name);
   219						s->type = STEXT;
   220						s->value = vexit;
   221						continue;	// avoid more error messages
   222					case STEXT:
   223						p->to.offset = s->value;
   224						p->to.type = D_BRANCH;
   225						break;
   226					}
   227				}
   228				if(p->to.type != D_BRANCH)
   229					continue;
   230				c = p->to.offset;
   231				for(q = textp->text; q != P;) {
   232					if(c == q->pc)
   233						break;
   234					if(q->forwd != P && c >= q->forwd->pc)
   235						q = q->forwd;
   236					else
   237						q = q->link;
   238				}
   239				if(q == P) {
   240					diag("branch out of range %d\n%P", c, p);
   241					p->to.type = D_NONE;
   242				}
   243				p->cond = q;
   244			}
   245		}
   246	
   247		for(cursym = textp; cursym != nil; cursym = cursym->next) {
   248			for(p = cursym->text; p != P; p = p->link) {
   249				if(p->cond != P) {
   250					p->cond = brloop(p->cond);
   251					if(p->cond != P)
   252					if(p->to.type == D_BRANCH)
   253						p->to.offset = p->cond->pc;
   254				}
   255			}
   256		}
   257	}
   258	
   259	Prog*
   260	brloop(Prog *p)
   261	{
   262		Prog *q;
   263		int c;
   264	
   265		for(c=0; p!=P;) {
   266			if(p->as != AB)
   267				return p;
   268			q = p->cond;
   269			if(q <= p) {
   270				c++;
   271				if(q == p || c > 5000)
   272					break;
   273			}
   274			p = q;
   275		}
   276		return P;
   277	}
   278	
   279	int32
   280	atolwhex(char *s)
   281	{
   282		int32 n;
   283		int f;
   284	
   285		n = 0;
   286		f = 0;
   287		while(*s == ' ' || *s == '\t')
   288			s++;
   289		if(*s == '-' || *s == '+') {
   290			if(*s++ == '-')
   291				f = 1;
   292			while(*s == ' ' || *s == '\t')
   293				s++;
   294		}
   295		if(s[0]=='0' && s[1]){
   296			if(s[1]=='x' || s[1]=='X'){
   297				s += 2;
   298				for(;;){
   299					if(*s >= '0' && *s <= '9')
   300						n = n*16 + *s++ - '0';
   301					else if(*s >= 'a' && *s <= 'f')
   302						n = n*16 + *s++ - 'a' + 10;
   303					else if(*s >= 'A' && *s <= 'F')
   304						n = n*16 + *s++ - 'A' + 10;
   305					else
   306						break;
   307				}
   308			} else
   309				while(*s >= '0' && *s <= '7')
   310					n = n*8 + *s++ - '0';
   311		} else
   312			while(*s >= '0' && *s <= '9')
   313				n = n*10 + *s++ - '0';
   314		if(f)
   315			n = -n;
   316		return n;
   317	}
   318	
   319	int32
   320	rnd(int32 v, int32 r)
   321	{
   322		int32 c;
   323	
   324		if(r <= 0)
   325			return v;
   326		v += r - 1;
   327		c = v % r;
   328		if(c < 0)
   329			c += r;
   330		v -= c;
   331		return v;
   332	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.