github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/6c/swt.c (about)

     1  // Inferno utils/6c/swt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.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  #include "gc.h"
    32  
    33  void
    34  swit1(C1 *q, int nc, int32 def, Node *n)
    35  {
    36  	Node nreg;
    37  
    38  	regalloc(&nreg, n, Z);
    39  	if(typev[n->type->etype])
    40  		nreg.type = types[TVLONG];
    41  	else
    42  		nreg.type = types[TLONG];
    43  	cgen(n, &nreg);
    44  	swit2(q, nc, def, &nreg);
    45  	regfree(&nreg);
    46  }
    47  
    48  void
    49  swit2(C1 *q, int nc, int32 def, Node *n)
    50  {
    51  	C1 *r;
    52  	int i;
    53  	Prog *sp;
    54  
    55  	if(nc < 5) {
    56  		for(i=0; i<nc; i++) {
    57  			if(debug['W'])
    58  				print("case = %.8llux\n", q->val);
    59  			gcmp(OEQ, n, q->val);
    60  			patch(p, q->label);
    61  			q++;
    62  		}
    63  		gbranch(OGOTO);
    64  		patch(p, def);
    65  		return;
    66  	}
    67  	i = nc / 2;
    68  	r = q+i;
    69  	if(debug['W'])
    70  		print("case > %.8llux\n", r->val);
    71  	gcmp(OGT, n, r->val);
    72  	sp = p;
    73  	gbranch(OGOTO);
    74  	p->as = AJEQ;
    75  	patch(p, r->label);
    76  	swit2(q, i, def, n);
    77  
    78  	if(debug['W'])
    79  		print("case < %.8llux\n", r->val);
    80  	patch(sp, pc);
    81  	swit2(r+1, nc-i-1, def, n);
    82  }
    83  
    84  void
    85  bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
    86  {
    87  	int sh;
    88  	int32 v;
    89  	Node *l;
    90  
    91  	/*
    92  	 * n1 gets adjusted/masked value
    93  	 * n2 gets address of cell
    94  	 * n3 gets contents of cell
    95  	 */
    96  	l = b->left;
    97  	if(n2 != Z) {
    98  		regalloc(n1, l, nn);
    99  		reglcgen(n2, l, Z);
   100  		regalloc(n3, l, Z);
   101  		gmove(n2, n3);
   102  		gmove(n3, n1);
   103  	} else {
   104  		regalloc(n1, l, nn);
   105  		cgen(l, n1);
   106  	}
   107  	if(b->type->shift == 0 && typeu[b->type->etype]) {
   108  		v = ~0 + (1L << b->type->nbits);
   109  		gopcode(OAND, tfield, nodconst(v), n1);
   110  	} else {
   111  		sh = 32 - b->type->shift - b->type->nbits;
   112  		if(sh > 0)
   113  			gopcode(OASHL, tfield, nodconst(sh), n1);
   114  		sh += b->type->shift;
   115  		if(sh > 0)
   116  			if(typeu[b->type->etype])
   117  				gopcode(OLSHR, tfield, nodconst(sh), n1);
   118  			else
   119  				gopcode(OASHR, tfield, nodconst(sh), n1);
   120  	}
   121  }
   122  
   123  void
   124  bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
   125  {
   126  	int32 v;
   127  	Node nod;
   128  	int sh;
   129  
   130  	regalloc(&nod, b->left, Z);
   131  	v = ~0 + (1L << b->type->nbits);
   132  	gopcode(OAND, types[TLONG], nodconst(v), n1);
   133  	gmove(n1, &nod);
   134  	if(nn != Z)
   135  		gmove(n1, nn);
   136  	sh = b->type->shift;
   137  	if(sh > 0)
   138  		gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
   139  	v <<= sh;
   140  	gopcode(OAND, types[TLONG], nodconst(~v), n3);
   141  	gopcode(OOR, types[TLONG], n3, &nod);
   142  	gmove(&nod, n2);
   143  
   144  	regfree(&nod);
   145  	regfree(n1);
   146  	regfree(n2);
   147  	regfree(n3);
   148  }
   149  
   150  int32
   151  outstring(char *s, int32 n)
   152  {
   153  	int32 r;
   154  
   155  	if(suppress)
   156  		return nstring;
   157  	r = nstring;
   158  	while(n) {
   159  		string[mnstring] = *s++;
   160  		mnstring++;
   161  		nstring++;
   162  		if(mnstring >= NSNAME) {
   163  			gpseudo(ADATA, symstring, nodconst(0L));
   164  			p->from.offset += nstring - NSNAME;
   165  			p->from.scale = NSNAME;
   166  			p->to.type = D_SCONST;
   167  			memmove(p->to.sval, string, NSNAME);
   168  			mnstring = 0;
   169  		}
   170  		n--;
   171  	}
   172  	return r;
   173  }
   174  
   175  void
   176  sextern(Sym *s, Node *a, int32 o, int32 w)
   177  {
   178  	int32 e, lw;
   179  
   180  	for(e=0; e<w; e+=NSNAME) {
   181  		lw = NSNAME;
   182  		if(w-e < lw)
   183  			lw = w-e;
   184  		gpseudo(ADATA, s, nodconst(0L));
   185  		p->from.offset += o+e;
   186  		p->from.scale = lw;
   187  		p->to.type = D_SCONST;
   188  		memmove(p->to.sval, a->cstring+e, lw);
   189  	}
   190  }
   191  
   192  void
   193  gextern(Sym *s, Node *a, int32 o, int32 w)
   194  {
   195  	if(0 && a->op == OCONST && typev[a->type->etype]) {
   196  		gpseudo(ADATA, s, lo64(a));
   197  		p->from.offset += o;
   198  		p->from.scale = 4;
   199  		gpseudo(ADATA, s, hi64(a));
   200  		p->from.offset += o + 4;
   201  		p->from.scale = 4;
   202  		return;
   203  	}
   204  	gpseudo(ADATA, s, a);
   205  	p->from.offset += o;
   206  	p->from.scale = w;
   207  	switch(p->to.type) {
   208  	default:
   209  		p->to.index = p->to.type;
   210  		p->to.type = D_ADDR;
   211  	case D_CONST:
   212  	case D_FCONST:
   213  	case D_ADDR:
   214  		break;
   215  	}
   216  }
   217  
   218  void	zname(Biobuf*, Sym*, int);
   219  void	zaddr(Biobuf*, Adr*, int);
   220  void	outhist(Biobuf*);
   221  
   222  void
   223  outcode(void)
   224  {
   225  	struct { Sym *sym; short type; } h[NSYM];
   226  	Prog *p;
   227  	Sym *s;
   228  	int f, sf, st, t, sym;
   229  	Biobuf b;
   230  
   231  	if(debug['S']) {
   232  		for(p = firstp; p != P; p = p->link)
   233  			if(p->as != ADATA && p->as != AGLOBL)
   234  				pc--;
   235  		for(p = firstp; p != P; p = p->link) {
   236  			print("%P\n", p);
   237  			if(p->as != ADATA && p->as != AGLOBL)
   238  				pc++;
   239  		}
   240  	}
   241  
   242  	f = open(outfile, OWRITE);
   243  	if(f < 0) {
   244  		diag(Z, "cannot open %s", outfile);
   245  		return;
   246  	}
   247  	Binit(&b, f, OWRITE);
   248  
   249  	Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
   250  	if(pragcgobuf.to > pragcgobuf.start) {
   251  		Bprint(&b, "\n");
   252  		Bprint(&b, "$$  // exports\n\n");
   253  		Bprint(&b, "$$  // local types\n\n");
   254  		Bprint(&b, "$$  // cgo\n");
   255  		Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
   256  		Bprint(&b, "\n$$\n\n");
   257  	}
   258  	Bprint(&b, "!\n");
   259  
   260  	outhist(&b);
   261  	for(sym=0; sym<NSYM; sym++) {
   262  		h[sym].sym = S;
   263  		h[sym].type = 0;
   264  	}
   265  	sym = 1;
   266  	for(p = firstp; p != P; p = p->link) {
   267  	jackpot:
   268  		sf = 0;
   269  		s = p->from.sym;
   270  		while(s != S) {
   271  			sf = s->sym;
   272  			if(sf < 0 || sf >= NSYM)
   273  				sf = 0;
   274  			t = p->from.type;
   275  			if(t == D_ADDR)
   276  				t = p->from.index;
   277  			if(h[sf].type == t)
   278  			if(h[sf].sym == s)
   279  				break;
   280  			s->sym = sym;
   281  			zname(&b, s, t);
   282  			h[sym].sym = s;
   283  			h[sym].type = t;
   284  			sf = sym;
   285  			sym++;
   286  			if(sym >= NSYM)
   287  				sym = 1;
   288  			break;
   289  		}
   290  		st = 0;
   291  		s = p->to.sym;
   292  		while(s != S) {
   293  			st = s->sym;
   294  			if(st < 0 || st >= NSYM)
   295  				st = 0;
   296  			t = p->to.type;
   297  			if(t == D_ADDR)
   298  				t = p->to.index;
   299  			if(h[st].type == t)
   300  			if(h[st].sym == s)
   301  				break;
   302  			s->sym = sym;
   303  			zname(&b, s, t);
   304  			h[sym].sym = s;
   305  			h[sym].type = t;
   306  			st = sym;
   307  			sym++;
   308  			if(sym >= NSYM)
   309  				sym = 1;
   310  			if(st == sf)
   311  				goto jackpot;
   312  			break;
   313  		}
   314  		Bputc(&b, p->as);
   315  		Bputc(&b, p->as>>8);
   316  		Bputc(&b, p->lineno);
   317  		Bputc(&b, p->lineno>>8);
   318  		Bputc(&b, p->lineno>>16);
   319  		Bputc(&b, p->lineno>>24);
   320  		zaddr(&b, &p->from, sf);
   321  		zaddr(&b, &p->to, st);
   322  	}
   323  	Bterm(&b);
   324  	close(f);
   325  	firstp = P;
   326  	lastp = P;
   327  }
   328  
   329  void
   330  outhist(Biobuf *b)
   331  {
   332  	Hist *h;
   333  	char *p, *q, *op, c;
   334  	Prog pg;
   335  	int n;
   336  	char *tofree;
   337  	static int first = 1;
   338  	static char *goroot, *goroot_final;
   339  
   340  	if(first) {
   341  		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
   342  		first = 0;
   343  		goroot = getenv("GOROOT");
   344  		goroot_final = getenv("GOROOT_FINAL");
   345  		if(goroot == nil)
   346  			goroot = "";
   347  		if(goroot_final == nil)
   348  			goroot_final = goroot;
   349  		if(strcmp(goroot, goroot_final) == 0) {
   350  			goroot = nil;
   351  			goroot_final = nil;
   352  		}
   353  	}
   354  
   355  	tofree = nil;
   356  	pg = zprog;
   357  	pg.as = AHISTORY;
   358  	c = pathchar();
   359  	for(h = hist; h != H; h = h->link) {
   360  		p = h->name;
   361  		if(p != nil && goroot != nil) {
   362  			n = strlen(goroot);
   363  			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
   364  				tofree = smprint("%s%s", goroot_final, p+n);
   365  				p = tofree;
   366  			}
   367  		}
   368  		op = 0;
   369  		if(systemtype(Windows) && p && p[1] == ':'){
   370  			c = p[2];
   371  		} else if(p && p[0] != c && h->offset == 0 && pathname){
   372  			if(systemtype(Windows) && pathname[1] == ':') {
   373  				op = p;
   374  				p = pathname;
   375  				c = p[2];
   376  			} else if(pathname[0] == c){
   377  				op = p;
   378  				p = pathname;
   379  			}
   380  		}
   381  		while(p) {
   382  			q = utfrune(p, c);
   383  			if(q) {
   384  				n = q-p;
   385  				if(n == 0){
   386  					n = 1;	/* leading "/" */
   387  					*p = '/';	/* don't emit "\" on windows */
   388  				}
   389  				q++;
   390  			} else {
   391  				n = strlen(p);
   392  				q = 0;
   393  			}
   394  			if(n) {
   395  				Bputc(b, ANAME);
   396  				Bputc(b, ANAME>>8);
   397  				Bputc(b, D_FILE);
   398  				Bputc(b, 1);
   399  				Bputc(b, '<');
   400  				Bwrite(b, p, n);
   401  				Bputc(b, 0);
   402  			}
   403  			p = q;
   404  			if(p == 0 && op) {
   405  				p = op;
   406  				op = 0;
   407  			}
   408  		}
   409  		pg.lineno = h->line;
   410  		pg.to.type = zprog.to.type;
   411  		pg.to.offset = h->offset;
   412  		if(h->offset)
   413  			pg.to.type = D_CONST;
   414  
   415  		Bputc(b, pg.as);
   416  		Bputc(b, pg.as>>8);
   417  		Bputc(b, pg.lineno);
   418  		Bputc(b, pg.lineno>>8);
   419  		Bputc(b, pg.lineno>>16);
   420  		Bputc(b, pg.lineno>>24);
   421  		zaddr(b, &pg.from, 0);
   422  		zaddr(b, &pg.to, 0);
   423  
   424  		if(tofree) {
   425  			free(tofree);
   426  			tofree = nil;
   427  		}
   428  	}
   429  }
   430  
   431  void
   432  zname(Biobuf *b, Sym *s, int t)
   433  {
   434  	char *n;
   435  	uint32 sig;
   436  
   437  	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
   438  		sig = sign(s);
   439  		Bputc(b, ASIGNAME);
   440  		Bputc(b, ASIGNAME>>8);
   441  		Bputc(b, sig);
   442  		Bputc(b, sig>>8);
   443  		Bputc(b, sig>>16);
   444  		Bputc(b, sig>>24);
   445  		s->sig = SIGDONE;
   446  	}
   447  	else{
   448  		Bputc(b, ANAME);	/* as */
   449  		Bputc(b, ANAME>>8);	/* as */
   450  	}
   451  	Bputc(b, t);			/* type */
   452  	Bputc(b, s->sym);		/* sym */
   453  	n = s->name;
   454  	while(*n) {
   455  		Bputc(b, *n);
   456  		n++;
   457  	}
   458  	Bputc(b, 0);
   459  }
   460  
   461  void
   462  zaddr(Biobuf *b, Adr *a, int s)
   463  {
   464  	int32 l;
   465  	int i, t;
   466  	char *n;
   467  	Ieee e;
   468  
   469  	t = 0;
   470  	if(a->index != D_NONE || a->scale != 0)
   471  		t |= T_INDEX;
   472  	if(s != 0)
   473  		t |= T_SYM;
   474  
   475  	switch(a->type) {
   476  	default:
   477  		t |= T_TYPE;
   478  	case D_NONE:
   479  		if(a->offset != 0) {
   480  			t |= T_OFFSET;
   481  			l = a->offset;
   482  			if((vlong)l != a->offset)
   483  				t |= T_64;
   484  		}
   485  		break;
   486  	case D_FCONST:
   487  		t |= T_FCONST;
   488  		break;
   489  	case D_SCONST:
   490  		t |= T_SCONST;
   491  		break;
   492  	}
   493  	Bputc(b, t);
   494  
   495  	if(t & T_INDEX) {	/* implies index, scale */
   496  		Bputc(b, a->index);
   497  		Bputc(b, a->scale);
   498  	}
   499  	if(t & T_OFFSET) {	/* implies offset */
   500  		l = a->offset;
   501  		Bputc(b, l);
   502  		Bputc(b, l>>8);
   503  		Bputc(b, l>>16);
   504  		Bputc(b, l>>24);
   505  		if(t & T_64) {
   506  			l = a->offset>>32;
   507  			Bputc(b, l);
   508  			Bputc(b, l>>8);
   509  			Bputc(b, l>>16);
   510  			Bputc(b, l>>24);
   511  		}
   512  	}
   513  	if(t & T_SYM)		/* implies sym */
   514  		Bputc(b, s);
   515  	if(t & T_FCONST) {
   516  		ieeedtod(&e, a->dval);
   517  		l = e.l;
   518  		Bputc(b, l);
   519  		Bputc(b, l>>8);
   520  		Bputc(b, l>>16);
   521  		Bputc(b, l>>24);
   522  		l = e.h;
   523  		Bputc(b, l);
   524  		Bputc(b, l>>8);
   525  		Bputc(b, l>>16);
   526  		Bputc(b, l>>24);
   527  		return;
   528  	}
   529  	if(t & T_SCONST) {
   530  		n = a->sval;
   531  		for(i=0; i<NSNAME; i++) {
   532  			Bputc(b, *n);
   533  			n++;
   534  		}
   535  		return;
   536  	}
   537  	if(t & T_TYPE)
   538  		Bputc(b, a->type);
   539  }
   540  
   541  int32
   542  align(int32 i, Type *t, int op, int32 *maxalign)
   543  {
   544  	int32 o;
   545  	Type *v;
   546  	int w;
   547  
   548  	o = i;
   549  	w = 1;
   550  	switch(op) {
   551  	default:
   552  		diag(Z, "unknown align opcode %d", op);
   553  		break;
   554  
   555  	case Asu2:	/* padding at end of a struct */
   556  		w = *maxalign;
   557  		if(w < 1)
   558  			w = 1;
   559  		if(packflg)
   560  			w = packflg;
   561  		break;
   562  
   563  	case Ael1:	/* initial align of struct element */
   564  		for(v=t; v->etype==TARRAY; v=v->link)
   565  			;
   566  		if(v->etype == TSTRUCT || v->etype == TUNION)
   567  			w = v->align;
   568  		else
   569  			w = ewidth[v->etype];
   570  		if(w < 1 || w > SZ_VLONG)
   571  			fatal(Z, "align");
   572  		if(packflg) 
   573  			w = packflg;
   574  		break;
   575  
   576  	case Ael2:	/* width of a struct element */
   577  		o += t->width;
   578  		break;
   579  
   580  	case Aarg0:	/* initial passbyptr argument in arg list */
   581  		if(typesu[t->etype]) {
   582  			o = align(o, types[TIND], Aarg1, nil);
   583  			o = align(o, types[TIND], Aarg2, nil);
   584  		}
   585  		break;
   586  
   587  	case Aarg1:	/* initial align of parameter */
   588  		w = ewidth[t->etype];
   589  		if(w <= 0 || w >= SZ_VLONG) {
   590  			w = SZ_VLONG;
   591  			break;
   592  		}
   593  		w = 1;		/* little endian no adjustment */
   594  		break;
   595  
   596  	case Aarg2:	/* width of a parameter */
   597  		o += t->width;
   598  		w = t->width;
   599  		if(w > SZ_VLONG)
   600  			w = SZ_VLONG;
   601  		break;
   602  
   603  	case Aaut3:	/* total align of automatic */
   604  		o = align(o, t, Ael1, nil);
   605  		o = align(o, t, Ael2, nil);
   606  		break;
   607  	}
   608  	o = xround(o, w);
   609  	if(maxalign && *maxalign < w)
   610  		*maxalign = w;
   611  	if(debug['A'])
   612  		print("align %s %d %T = %d\n", bnames[op], i, t, o);
   613  	return o;
   614  }
   615  
   616  int32
   617  maxround(int32 max, int32 v)
   618  {
   619  	v = xround(v, SZ_VLONG);
   620  	if(v > max)
   621  		return v;
   622  	return max;
   623  }