github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/6a/a.y (about)

     1  // Inferno utils/6a/a.y
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
     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  %{
    32  #include <u.h>
    33  #include <stdio.h>	/* if we don't, bison will, and a.h re-#defines getc */
    34  #include <libc.h>
    35  #include "a.h"
    36  #include "../../runtime/funcdata.h"
    37  %}
    38  %union	{
    39  	Sym	*sym;
    40  	vlong	lval;
    41  	double	dval;
    42  	char	sval[8];
    43  	Addr	addr;
    44  	Addr2	addr2;
    45  }
    46  %left	'|'
    47  %left	'^'
    48  %left	'&'
    49  %left	'<' '>'
    50  %left	'+' '-'
    51  %left	'*' '/' '%'
    52  %token	<lval>	LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
    53  %token	<lval>	LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC
    54  %token	<lval>	LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF
    55  %token	<lval>	LCONST LFP LPC LSB
    56  %token	<lval>	LBREG LLREG LSREG LFREG LMREG LXREG
    57  %token	<dval>	LFCONST
    58  %token	<sval>	LSCONST LSP
    59  %token	<sym>	LNAME LLAB LVAR
    60  %type	<lval>	con con2 expr pointer offset
    61  %type	<addr>	mem imm imm2 reg nam rel rem rim rom omem nmem
    62  %type	<addr2>	nonnon nonrel nonrem rimnon rimrem remrim
    63  %type	<addr2>	spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
    64  %type	<addr2>	spec10 spec11 spec12 spec13
    65  %%
    66  prog:
    67  |	prog 
    68  	{
    69  		stmtline = lineno;
    70  	}
    71  	line
    72  
    73  line:
    74  	LNAME ':'
    75  	{
    76  		$1 = labellookup($1);
    77  		if($1->type == LLAB && $1->value != pc)
    78  			yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
    79  		$1->type = LLAB;
    80  		$1->value = pc;
    81  	}
    82  	line
    83  |	';'
    84  |	inst ';'
    85  |	error ';'
    86  
    87  inst:
    88  	LNAME '=' expr
    89  	{
    90  		$1->type = LVAR;
    91  		$1->value = $3;
    92  	}
    93  |	LVAR '=' expr
    94  	{
    95  		if($1->value != $3)
    96  			yyerror("redeclaration of %s", $1->name);
    97  		$1->value = $3;
    98  	}
    99  |	LTYPE0 nonnon	{ outcode($1, &$2); }
   100  |	LTYPE1 nonrem	{ outcode($1, &$2); }
   101  |	LTYPE2 rimnon	{ outcode($1, &$2); }
   102  |	LTYPE3 rimrem	{ outcode($1, &$2); }
   103  |	LTYPE4 remrim	{ outcode($1, &$2); }
   104  |	LTYPER nonrel	{ outcode($1, &$2); }
   105  |	LTYPED spec1	{ outcode($1, &$2); }
   106  |	LTYPET spec2	{ outcode($1, &$2); }
   107  |	LTYPEC spec3	{ outcode($1, &$2); }
   108  |	LTYPEN spec4	{ outcode($1, &$2); }
   109  |	LTYPES spec5	{ outcode($1, &$2); }
   110  |	LTYPEM spec6	{ outcode($1, &$2); }
   111  |	LTYPEI spec7	{ outcode($1, &$2); }
   112  |	LTYPEXC spec8	{ outcode($1, &$2); }
   113  |	LTYPEX spec9	{ outcode($1, &$2); }
   114  |	LTYPERT spec10	{ outcode($1, &$2); }
   115  |	LTYPEG spec11	{ outcode($1, &$2); }
   116  |	LTYPEPC spec12	{ outcode($1, &$2); }
   117  |	LTYPEF spec13	{ outcode($1, &$2); }
   118  
   119  nonnon:
   120  	{
   121  		$$.from = nullgen;
   122  		$$.to = nullgen;
   123  	}
   124  |	','
   125  	{
   126  		$$.from = nullgen;
   127  		$$.to = nullgen;
   128  	}
   129  
   130  rimrem:
   131  	rim ',' rem
   132  	{
   133  		$$.from = $1;
   134  		$$.to = $3;
   135  	}
   136  
   137  remrim:
   138  	rem ',' rim
   139  	{
   140  		$$.from = $1;
   141  		$$.to = $3;
   142  	}
   143  
   144  rimnon:
   145  	rim ','
   146  	{
   147  		$$.from = $1;
   148  		$$.to = nullgen;
   149  	}
   150  |	rim
   151  	{
   152  		$$.from = $1;
   153  		$$.to = nullgen;
   154  	}
   155  
   156  nonrem:
   157  	',' rem
   158  	{
   159  		$$.from = nullgen;
   160  		$$.to = $2;
   161  	}
   162  |	rem
   163  	{
   164  		$$.from = nullgen;
   165  		$$.to = $1;
   166  	}
   167  
   168  nonrel:
   169  	',' rel
   170  	{
   171  		$$.from = nullgen;
   172  		$$.to = $2;
   173  	}
   174  |	rel
   175  	{
   176  		$$.from = nullgen;
   177  		$$.to = $1;
   178  	}
   179  |	imm ',' rel
   180  	{
   181  		$$.from = $1;
   182  		$$.to = $3;
   183  	}
   184  
   185  spec1:	/* DATA */
   186  	nam '/' con ',' imm
   187  	{
   188  		$$.from = $1;
   189  		$$.from.scale = $3;
   190  		$$.to = $5;
   191  	}
   192  
   193  spec2:	/* TEXT */
   194  	mem ',' imm2
   195  	{
   196  		settext($1.sym);
   197  		$$.from = $1;
   198  		$$.to = $3;
   199  	}
   200  |	mem ',' con ',' imm2
   201  	{
   202  		settext($1.sym);
   203  		$$.from = $1;
   204  		$$.from.scale = $3;
   205  		$$.to = $5;
   206  	}
   207  
   208  spec3:	/* JMP/CALL */
   209  	',' rom
   210  	{
   211  		$$.from = nullgen;
   212  		$$.to = $2;
   213  	}
   214  |	rom
   215  	{
   216  		$$.from = nullgen;
   217  		$$.to = $1;
   218  	}
   219  
   220  spec4:	/* NOP */
   221  	nonnon
   222  |	nonrem
   223  
   224  spec5:	/* SHL/SHR */
   225  	rim ',' rem
   226  	{
   227  		$$.from = $1;
   228  		$$.to = $3;
   229  	}
   230  |	rim ',' rem ':' LLREG
   231  	{
   232  		$$.from = $1;
   233  		$$.to = $3;
   234  		if($$.from.index != D_NONE)
   235  			yyerror("dp shift with lhs index");
   236  		$$.from.index = $5;
   237  	}
   238  
   239  spec6:	/* MOVW/MOVL */
   240  	rim ',' rem
   241  	{
   242  		$$.from = $1;
   243  		$$.to = $3;
   244  	}
   245  |	rim ',' rem ':' LSREG
   246  	{
   247  		$$.from = $1;
   248  		$$.to = $3;
   249  		if($$.to.index != D_NONE)
   250  			yyerror("dp move with lhs index");
   251  		$$.to.index = $5;
   252  	}
   253  
   254  spec7:
   255  	rim ','
   256  	{
   257  		$$.from = $1;
   258  		$$.to = nullgen;
   259  	}
   260  |	rim
   261  	{
   262  		$$.from = $1;
   263  		$$.to = nullgen;
   264  	}
   265  |	rim ',' rem
   266  	{
   267  		$$.from = $1;
   268  		$$.to = $3;
   269  	}
   270  
   271  spec8:	/* CMPPS/CMPPD */
   272  	reg ',' rem ',' con
   273  	{
   274  		$$.from = $1;
   275  		$$.to = $3;
   276  		$$.to.offset = $5;
   277  	}
   278  
   279  spec9:	/* shufl */
   280  	imm ',' rem ',' reg
   281  	{
   282  		$$.from = $3;
   283  		$$.to = $5;
   284  		if($1.type != D_CONST)
   285  			yyerror("illegal constant");
   286  		$$.to.offset = $1.offset;
   287  	}
   288  
   289  spec10:	/* RET/RETF */
   290  	{
   291  		$$.from = nullgen;
   292  		$$.to = nullgen;
   293  	}
   294  |	imm
   295  	{
   296  		$$.from = $1;
   297  		$$.to = nullgen;
   298  	}
   299  
   300  spec11:	/* GLOBL */
   301  	mem ',' imm
   302  	{
   303  		$$.from = $1;
   304  		$$.to = $3;
   305  	}
   306  |	mem ',' con ',' imm
   307  	{
   308  		$$.from = $1;
   309  		$$.from.scale = $3;
   310  		$$.to = $5;
   311  	}
   312  
   313  spec12:	/* PCDATA */
   314  	rim ',' rim
   315  	{
   316  		if($1.type != D_CONST || $3.type != D_CONST)
   317  			yyerror("arguments to PCDATA must be integer constants");
   318  		$$.from = $1;
   319  		$$.to = $3;
   320  	}
   321  
   322  spec13:	/* FUNCDATA */
   323  	rim ',' rim
   324  	{
   325  		if($1.type != D_CONST)
   326  			yyerror("index for FUNCDATA must be integer constant");
   327  		if($3.type != D_EXTERN && $3.type != D_STATIC)
   328  			yyerror("value for FUNCDATA must be symbol reference");
   329  		$$.from = $1;
   330  		$$.to = $3;
   331  	}
   332  
   333  rem:
   334  	reg
   335  |	mem
   336  
   337  rom:
   338  	rel
   339  |	nmem
   340  |	'*' reg
   341  	{
   342  		$$ = $2;
   343  	}
   344  |	'*' omem
   345  	{
   346  		$$ = $2;
   347  	}
   348  |	reg
   349  |	omem
   350  
   351  rim:
   352  	rem
   353  |	imm
   354  
   355  rel:
   356  	con '(' LPC ')'
   357  	{
   358  		$$ = nullgen;
   359  		$$.type = D_BRANCH;
   360  		$$.offset = $1 + pc;
   361  	}
   362  |	LNAME offset
   363  	{
   364  		$1 = labellookup($1);
   365  		$$ = nullgen;
   366  		if(pass == 2 && $1->type != LLAB)
   367  			yyerror("undefined label: %s", $1->labelname);
   368  		$$.type = D_BRANCH;
   369  		$$.offset = $1->value + $2;
   370  	}
   371  
   372  reg:
   373  	LBREG
   374  	{
   375  		$$ = nullgen;
   376  		$$.type = $1;
   377  	}
   378  |	LFREG
   379  	{
   380  		$$ = nullgen;
   381  		$$.type = $1;
   382  	}
   383  |	LLREG
   384  	{
   385  		$$ = nullgen;
   386  		$$.type = $1;
   387  	}
   388  |	LMREG
   389  	{
   390  		$$ = nullgen;
   391  		$$.type = $1;
   392  	}
   393  |	LSP
   394  	{
   395  		$$ = nullgen;
   396  		$$.type = D_SP;
   397  	}
   398  |	LSREG
   399  	{
   400  		$$ = nullgen;
   401  		$$.type = $1;
   402  	}
   403  |	LXREG
   404  	{
   405  		$$ = nullgen;
   406  		$$.type = $1;
   407  	}
   408  imm2:
   409  	'$' con2
   410  	{
   411  		$$ = nullgen;
   412  		$$.type = D_CONST;
   413  		$$.offset = $2;
   414  	}
   415  
   416  imm:
   417  	'$' con
   418  	{
   419  		$$ = nullgen;
   420  		$$.type = D_CONST;
   421  		$$.offset = $2;
   422  	}
   423  |	'$' nam
   424  	{
   425  		$$ = $2;
   426  		$$.index = $2.type;
   427  		$$.type = D_ADDR;
   428  		/*
   429  		if($2.type == D_AUTO || $2.type == D_PARAM)
   430  			yyerror("constant cannot be automatic: %s",
   431  				$2.sym->name);
   432  		 */
   433  	}
   434  |	'$' LSCONST
   435  	{
   436  		$$ = nullgen;
   437  		$$.type = D_SCONST;
   438  		memcpy($$.u.sval, $2, sizeof($$.u.sval));
   439  	}
   440  |	'$' LFCONST
   441  	{
   442  		$$ = nullgen;
   443  		$$.type = D_FCONST;
   444  		$$.u.dval = $2;
   445  	}
   446  |	'$' '(' LFCONST ')'
   447  	{
   448  		$$ = nullgen;
   449  		$$.type = D_FCONST;
   450  		$$.u.dval = $3;
   451  	}
   452  |	'$' '(' '-' LFCONST ')'
   453  	{
   454  		$$ = nullgen;
   455  		$$.type = D_FCONST;
   456  		$$.u.dval = -$4;
   457  	}
   458  |	'$' '-' LFCONST
   459  	{
   460  		$$ = nullgen;
   461  		$$.type = D_FCONST;
   462  		$$.u.dval = -$3;
   463  	}
   464  
   465  mem:
   466  	omem
   467  |	nmem
   468  
   469  omem:
   470  	con
   471  	{
   472  		$$ = nullgen;
   473  		$$.type = D_INDIR+D_NONE;
   474  		$$.offset = $1;
   475  	}
   476  |	con '(' LLREG ')'
   477  	{
   478  		$$ = nullgen;
   479  		$$.type = D_INDIR+$3;
   480  		$$.offset = $1;
   481  	}
   482  |	con '(' LSP ')'
   483  	{
   484  		$$ = nullgen;
   485  		$$.type = D_INDIR+D_SP;
   486  		$$.offset = $1;
   487  	}
   488  |	con '(' LSREG ')'
   489  	{
   490  		$$ = nullgen;
   491  		$$.type = D_INDIR+$3;
   492  		$$.offset = $1;
   493  	}
   494  |	con '(' LLREG '*' con ')'
   495  	{
   496  		$$ = nullgen;
   497  		$$.type = D_INDIR+D_NONE;
   498  		$$.offset = $1;
   499  		$$.index = $3;
   500  		$$.scale = $5;
   501  		checkscale($$.scale);
   502  	}
   503  |	con '(' LLREG ')' '(' LLREG '*' con ')'
   504  	{
   505  		$$ = nullgen;
   506  		$$.type = D_INDIR+$3;
   507  		$$.offset = $1;
   508  		$$.index = $6;
   509  		$$.scale = $8;
   510  		checkscale($$.scale);
   511  	}
   512  |	con '(' LLREG ')' '(' LSREG '*' con ')'
   513  	{
   514  		$$ = nullgen;
   515  		$$.type = D_INDIR+$3;
   516  		$$.offset = $1;
   517  		$$.index = $6;
   518  		$$.scale = $8;
   519  		checkscale($$.scale);
   520  	}
   521  |	'(' LLREG ')'
   522  	{
   523  		$$ = nullgen;
   524  		$$.type = D_INDIR+$2;
   525  	}
   526  |	'(' LSP ')'
   527  	{
   528  		$$ = nullgen;
   529  		$$.type = D_INDIR+D_SP;
   530  	}
   531  |	'(' LLREG '*' con ')'
   532  	{
   533  		$$ = nullgen;
   534  		$$.type = D_INDIR+D_NONE;
   535  		$$.index = $2;
   536  		$$.scale = $4;
   537  		checkscale($$.scale);
   538  	}
   539  |	'(' LLREG ')' '(' LLREG '*' con ')'
   540  	{
   541  		$$ = nullgen;
   542  		$$.type = D_INDIR+$2;
   543  		$$.index = $5;
   544  		$$.scale = $7;
   545  		checkscale($$.scale);
   546  	}
   547  
   548  nmem:
   549  	nam
   550  	{
   551  		$$ = $1;
   552  	}
   553  |	nam '(' LLREG '*' con ')'
   554  	{
   555  		$$ = $1;
   556  		$$.index = $3;
   557  		$$.scale = $5;
   558  		checkscale($$.scale);
   559  	}
   560  
   561  nam:
   562  	LNAME offset '(' pointer ')'
   563  	{
   564  		$$ = nullgen;
   565  		$$.type = $4;
   566  		$$.sym = linklookup(ctxt, $1->name, 0);
   567  		$$.offset = $2;
   568  	}
   569  |	LNAME '<' '>' offset '(' LSB ')'
   570  	{
   571  		$$ = nullgen;
   572  		$$.type = D_STATIC;
   573  		$$.sym = linklookup(ctxt, $1->name, 1);
   574  		$$.offset = $4;
   575  	}
   576  
   577  offset:
   578  	{
   579  		$$ = 0;
   580  	}
   581  |	'+' con
   582  	{
   583  		$$ = $2;
   584  	}
   585  |	'-' con
   586  	{
   587  		$$ = -$2;
   588  	}
   589  
   590  pointer:
   591  	LSB
   592  |	LSP
   593  	{
   594  		$$ = D_AUTO;
   595  	}
   596  |	LFP
   597  
   598  con:
   599  	LCONST
   600  |	LVAR
   601  	{
   602  		$$ = $1->value;
   603  	}
   604  |	'-' con
   605  	{
   606  		$$ = -$2;
   607  	}
   608  |	'+' con
   609  	{
   610  		$$ = $2;
   611  	}
   612  |	'~' con
   613  	{
   614  		$$ = ~$2;
   615  	}
   616  |	'(' expr ')'
   617  	{
   618  		$$ = $2;
   619  	}
   620  
   621  con2:
   622  	LCONST
   623  	{
   624  		$$ = ($1 & 0xffffffffLL) +
   625  			((vlong)ArgsSizeUnknown << 32);
   626  	}
   627  |	'-' LCONST
   628  	{
   629  		$$ = (-$2 & 0xffffffffLL) +
   630  			((vlong)ArgsSizeUnknown << 32);
   631  	}
   632  |	LCONST '-' LCONST
   633  	{
   634  		$$ = ($1 & 0xffffffffLL) +
   635  			(($3 & 0xffffLL) << 32);
   636  	}
   637  |	'-' LCONST '-' LCONST
   638  	{
   639  		$$ = (-$2 & 0xffffffffLL) +
   640  			(($4 & 0xffffLL) << 32);
   641  	}
   642  
   643  expr:
   644  	con
   645  |	expr '+' expr
   646  	{
   647  		$$ = $1 + $3;
   648  	}
   649  |	expr '-' expr
   650  	{
   651  		$$ = $1 - $3;
   652  	}
   653  |	expr '*' expr
   654  	{
   655  		$$ = $1 * $3;
   656  	}
   657  |	expr '/' expr
   658  	{
   659  		$$ = $1 / $3;
   660  	}
   661  |	expr '%' expr
   662  	{
   663  		$$ = $1 % $3;
   664  	}
   665  |	expr '<' '<' expr
   666  	{
   667  		$$ = $1 << $4;
   668  	}
   669  |	expr '>' '>' expr
   670  	{
   671  		$$ = $1 >> $4;
   672  	}
   673  |	expr '&' expr
   674  	{
   675  		$$ = $1 & $3;
   676  	}
   677  |	expr '^' expr
   678  	{
   679  		$$ = $1 ^ $3;
   680  	}
   681  |	expr '|' expr
   682  	{
   683  		$$ = $1 | $3;
   684  	}