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

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