2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
7 static char rcsid[]= "$Id: cgg.y,v 0.19 1994/06/24 10:36:56 ceriel Exp $";
22 int instline,saveline;
26 int patindex[MAXPATTERNS];
27 extern set_t l_sets[];
29 int emhere=0; /* lexical analyzer flag */
30 int optexact=0; /* Inside "with exact" rule */
31 int optstack=0; /* Inside with <blah> STACK rule */
34 int in_em_repl=0; /* set when in EM replacement part */
35 struct varinfo *defcost;
36 int Xstackflag=0; /* set in coercions, moves, and tests. %1 means something
40 struct varinfo *gen_inst(),*gen_move(),*gen_test(),*gen_preturn(),*gen_tlab();
41 struct varinfo *gen_label(), *make_erase();
42 expr_t make_expr(),ident_expr(),subreg_expr(),tokm_expr(),all_expr();
43 expr_t perc_ident_expr(),sum_expr(),regvar_expr();
45 set_t ident_to_set(),setproduct(),setsum(),setdiff();
47 iocc_t subr_iocc(),tokm_iocc(),ident_iocc(),all_iocc(),percident_iocc(), descr_iocc();
50 extern expr_t arexp[];
72 %token STACKINGRULES COERCIONS
74 %token TOPELTSIZE FALLTHROUGH LABELDEF
75 %token PROC CALL EXAMPLE
77 %token TEST MOVE STACK RETURN
78 %token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING
79 %token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW ISROM
80 %token CMPEQ CMPNE CMPLT CMPGT CMPLE CMPGE OR2 AND2 LSHIFT RSHIFT NOT COMP
81 %token INREG REGVAR REG_ANY REG_FLOAT REG_LOOP REG_POINTER
82 %token <yy_int> ADORNACCESS
83 %token <yy_int> ADORNCC
86 %token <yy_int> EMMNEM
87 %token <yy_int> NUMBER
88 %token <yy_int> DOLLAR PERCENT ALLREG
89 %token <yy_str> IDENT PERC_IDENT
90 %token <yy_str> STRING
91 %token TIMEFACTOR SIZEFACTOR
93 %type <yy_varinfo> prop_list property ident_list ident_list_el
94 %type <yy_varinfo> att_list att_list_el att_list_el_list att_ident structdecl optcost optformat
95 %type <yy_varinfo> kills allocates yields leaving
96 %type <yy_varinfo> generates kill_list kill_list_el uselist uselist_el genlist yieldlist
97 %type <yy_varinfo> leavelist leavelist_el gen_instruction
98 %type <yy_varinfo> opt_erase_list erase_list erase_list_el
99 %type <yy_str> opt_par_string optstring
100 %type <yy_int> register propno att_list_el_type tokenset_no
101 %type <yy_int> adornlist optstar optuses optregvar regvartype optregvartype
102 %type <yy_int> emarg tokarg subreg allreg
103 %type <yy_expr> expr regvarexpr
104 %type <yy_iocc> tokeninstance
105 %type <yy_int> optexpr optexact optstack
106 %type <yy_set> tokenset
107 %type <yy_oplist> oplist oplist_el
115 %left CMPLT,CMPLE,CMPGT,CMPGE
119 %nonassoc NOT,COMP,UMINUS
125 * The machine table consists of a number of sections, with their
126 * own associated parsers.
144 * Constants are parsed as name=value pairs
151 | constdeflist constdef
155 { n_const($1,$3); free($1); }
157 { n_sconst($1,$3); free($1); free($3); }
158 | TIMEFACTOR '=' NUMBER '/' NUMBER
159 { fc1 = $3; fc2 = $5; }
160 | SIZEFACTOR '=' NUMBER '/' NUMBER
161 { fc3 = $3; fc4 = $5; }
166 * Properties are parsed as a list of names optionally followed by their size
169 : PROPERTIES { make_const(); } prdef_list
173 | prdef_list optcomma prdef_list_el
177 { n_prop($1,wordsize); free($1); }
178 | IDENT '(' NUMBER ')'
179 { n_prop($1,$3); free($1); }
183 * Registers are rows of reglist:proplist pairs
186 : REGISTERS regdef_list
190 | regdef_list regdef_list_el
193 : ident_list ':' prop_list optregvar '.'
194 { regline($1,$3,$4); free((char *) $1); free((char *) $3); }
202 | REGVAR '(' regvartype ')'
219 | ident_list optcomma ident_list_el
220 { $3->vi_next = $1; $$ = $3; }
223 : IDENT opt_par_string
224 { NEW($$,struct varinfo);
226 $$->vi_int[0] = n_reg($1,$2,0,0,0);
227 free($1); if($2!=0) free($2);
229 | IDENT opt_par_string '=' register
230 { NEW($$,struct varinfo);
232 $$->vi_int[0] = n_reg($1,$2,1,$4,0);
233 free($1); if($2!=0) free($2);
235 | IDENT opt_par_string '=' register '+' register
236 { NEW($$,struct varinfo);
238 $$->vi_int[0] = n_reg($1,$2,2,$4,$6);
239 free($1); if($2!=0) free($2);
250 { register symbol *sy_p;
252 sy_p = lookup($1,symreg,mustexist);
253 $$ = sy_p->sy_value.syv_regno;
259 | prop_list optcomma property
260 { $3->vi_next = $1; $$ = $3; }
264 { register symbol *sy_p;
265 sy_p = lookup($1,symprop,mustexist);
266 NEW($$,struct varinfo);
268 $$->vi_int[0]=sy_p->sy_value.syv_propno;
274 { register symbol *sy_p;
275 sy_p = lookup($1,symprop,mustexist);
276 $$ = sy_p->sy_value.syv_propno;
281 /* tokens are parsed as struct definitions
282 * types in the struct can be register properties, ADDR or INT
290 | tokdeflist tokdeflist_el
293 : IDENT '=' structdecl NUMBER optcost optformat '.'
294 { n_tok($1,$3,$4,$5,$6);
309 | att_list_el att_list
310 { $$ = $1; while ($$->vi_next) $$ = $$->vi_next;
311 $$->vi_next = $2; $$ = $1;
323 | att_ident ',' att_list_el_list
324 { $1->vi_next = $3; $$ = $1; }
328 { NEW($$, struct varinfo);
330 $$->vi_int[0] = att_type;
343 { if (defcost==VI_NULL)
346 NEW($$,struct varinfo);
350 | COST '(' NUMBER ',' NUMBER ')'
351 { NEW ($$,struct varinfo);
360 { NEW($$,struct varinfo);
366 { NEW($$,struct varinfo);
377 /* sets are parsed as ident = expression */
384 | setdeflist setdeflist_el
387 : IDENT '=' tokenset_no '.'
388 { n_set($1,$3); free($1); }
393 { $$ = setlookup($1); }
397 { $$ = ident_to_set($1); free($1); }
398 | tokenset '*' tokenset
399 { $$ = setproduct($1,$3); }
400 | tokenset '+' tokenset
401 { $$ = setsum($1,$3); }
402 | tokenset '-' tokenset
403 { $$ = setdiff($1,$3); }
409 : INSTRUCTIONS optcost instdef_list
414 | instdef_list instdef_list_el
417 : IDENT optstring oplist opt_erase_list optcost '.'
418 { n_instr($1,$2,$3,$4,$5); freevi($5); }
425 | oplist_el ',' oplist
426 { $$ = $1; $$->o_next = $3; }
429 : tokenset_no adornlist
430 { NEW($$,struct operand);
434 checkprintformat($1);
440 | ADORNACCESS adornlist
442 error("Only one of :ro,:wo,:rw allowed");
457 | erase_list_el erase_list
458 { $1->vi_next = $2; $$ = $1; }
462 { $$ = make_erase($1); }
464 { NEW($$, struct varinfo);
466 $$->vi_next = VI_NULL;
479 | movedeflist movedeflist_el
483 {startline = lineno; }
507 n_move($3,$5,$8,$10,$13);
513 /* Now the test part */
524 | testdeflist testdeflist_el
528 { startline = lineno;}
555 | stackdeflist stackdeflist_el
559 {startline = lineno;}
566 optexpr TO STACK optuses GEN genlist
568 n_stack($3,$5,$8,$10);
575 { $$ = -1; nallreg=0;}
577 { $$ = $2; nallreg = 1; allreg[0] = $2; }
580 /* Now the one-to-one coercion rules */
590 | coercdeflist coercdeflist_el
594 {startline = lineno; tokpatlen=0; inithall();}
595 STACK allocates generates YIELDS tokeninstance
597 n_coerc(0,0,$4,$5,(struct varinfo *) 0,$7);
602 {startline = lineno;}
610 optexpr allocates generates yields
613 n_coerc($3,$5,$6,$7,$8);
620 /* Now the code part */
630 : PAT {emhere=1;} empattern {emhere=0;} optexpr
634 if (empatlen>maxempatlen)
635 maxempatlen=empatlen;
638 { if (!saferulefound)
639 error("Previous rule impossible on empty stack");
643 { npatterns = 0; saferulefound=0; inproc=1; n_proc($2); }
645 { if (!saferulefound)
646 error("Previous rule impossible on empty stack");
647 outpatterns(); inproc=0;
650 { skipupto(PAT,"pat"); yyerrok; yyclearin; }
655 | EXAMPLE {emhere=1;} empattern {emhere=0;}
659 { empatlen = 1; emmnem[0] = $1; }
661 { NEXT(empatlen,EMPATMAX,"Em pattern");
662 emmnem[empatlen-1] = $2;
672 if (npatterns>maxrule)
675 | CALL IDENT '(' stringlist ')'
676 { register symbol *sy_p;
678 sy_p=lookup($2,symproc,mustexist);
679 callproc=sy_p->sy_value.syv_procoff;
681 if (nprocargs > maxprocargs) maxprocargs = nprocargs;
687 { nprocargs = 1; procarg[0] = strlookup($1); free($1); }
688 | stringlist ',' STRING
689 { NEXT(nprocargs, MAXPROCARG, "Procedure argument list");
690 procarg[nprocargs-1] = strlookup($3); free($3);
695 : { inithall(); startline=lineno;
696 tokpatlen=0; optexact=0; optstack=0;
698 kills allocates generates yields leaving
700 patindex[npatterns++]=codeindex;
702 dopattern(0,$2,$3,$4,$5,$6);
711 : { inithall(); } pattern
712 | morepatterns { inithall(); } pattern
716 : stackpattern kills allocates generates yields leaving
717 { patindex[NEXT(npatterns,MAXPATTERNS,"Patterns")]=codeindex;
718 if (hall() && !optexact) saferulefound=1;
719 dopattern(0,$2,$3,$4,$5,$6);
729 { startline = lineno; }
731 { if (tokpatlen > maxtokpatlen) maxtokpatlen = tokpatlen; }
735 { $$ = optexact = 0; }
737 { $$ = optexact = 1; }
741 { $$ = optstack = 0; }
743 { $$ = optstack = 1; }
749 | setlist tokenset_no
750 { NEXT(tokpatlen,TOKPATMAX,"Stack pattern");
751 tokpatset[tokpatlen-1] = $2;
753 if (l_sets[$2].set_size == 0) {
754 error("Tokenset is empty or has elements with different sizes");
767 | kill_list_el ',' kill_list
768 { $$=$1; $$->vi_next = $3; }
771 : tokenset_no { cursetno=$1; } optexpr
772 { NEW($$,struct varinfo);
779 { NEW($$,struct varinfo);
781 $$->vi_int[0] = -($1.ex_index + 1);
788 { $$ = 0; nallreg=0;}
790 { $$ = $2; setallreg($2); }
794 { prophall($1->vi_int[0]); }
795 | uselist_el ',' uselist
796 { prophall($1->vi_int[0]); $$=$1; $$->vi_next=$3; }
800 { $$=$1; $$->vi_int[1] = 0; }
801 | property '=' tokeninstance
802 { if (!existalmove($3,$$->vi_int[0]))
803 error("No such move defined");
804 $$=$1; $$->vi_int[1] = $3.in_index;
806 | REUSING tokeninstance
807 { NEW($$,struct varinfo);
810 $$->vi_int[1] = $2.in_index;
824 | gen_instruction genlist
826 register struct varinfo *tvip;
828 while (tvip->vi_next!=VI_NULL)
837 : {instline = lineno; } IDENT optstar gen_oplist
838 { saveline =lineno; lineno=instline;
839 $$ = gen_inst($2,$3); free($2);
843 { $$ = gen_tlab($1); }
844 | MOVE tokeninstance ',' tokeninstance
845 { $$ = gen_move($2,$4); }
847 { $$ = gen_test($2);}
849 { $$ = gen_label($2-1); use_tes++; }
851 { $$ = gen_preturn(); }
862 : '.' /* empty gives conflicts */
865 { niops=1;iops[0]=$1; }
866 | gen_oplist ',' tokeninstance
867 { iops[niops++] = $3; }
873 | YIELDS { tokrepllen = 0; } yieldlist
874 { $$ = $3; if (tokrepllen > maxtokrepllen) maxtokrepllen = tokrepllen; }
879 | tokeninstance yieldlist
880 { checkstacking($1.in_set);
881 NEW($$,struct varinfo);
883 $$->vi_int[0] = $1.in_index;
891 | LEAVING {emhere=1; in_em_repl=1; emrepllen = 0; } leavelist
892 { emhere=0; in_em_repl=0; $$ = $3;
893 if (emrepllen > maxemrepllen) maxemrepllen = emrepllen;
898 | leavelist_el leavelist
899 { $$=$1; $$->vi_next=$2; }
903 { NEW($$,struct varinfo);
920 { $$ = $1.ex_index; } /* type checking ? */
925 { $$ = subr_iocc($1,$2); }
927 { $$ = tokm_iocc($1,$3); free($3); }
929 { $$ = ident_iocc($1); free($1);}
931 { $$ = all_iocc($1,$2); }
933 { if (cursetno < 0) {
934 error("%%<ident> not allowed here");
936 $$ = percident_iocc($1);
939 | '{' IDENT attlist '}'
940 { $$ = descr_iocc($2); free($2); }
946 { arexp[narexpr++] = $3; }
951 { if ($1<1 || $1>empatlen)
952 error("Only %d instructions in pattern",empatlen);
960 error("No token references allowed in EM replacement part");
961 if ($1<1 || $1>tokpatlen) {
962 error("Only %d tokens in stackpattern",tokpatlen);
965 if (Xstackflag) $$ = 0;
972 { if ($2<1 || $2>2) {
973 error("Only 2 subregisters allowed");
983 fatal("Only %d registers allocated",nallreg);
990 { $$ = make_expr(TYPINT,EX_CON, (int) ($1 & 0xFFFF), (int) ($1>>16));
993 { $$ = make_expr(argtyp(emmnem[$1-1]),EX_ARG,$1,0); }
995 { $$ = make_expr(TYPADDR,EX_STRING,strlookup($1),0); free($1); }
997 { $$ = ident_expr($1); free($1); }
999 { $$ = subreg_expr($1,$2); }
1001 { $$ = tokm_expr($1,$3); free($3); }
1003 { $$ = all_expr($1,$2); }
1005 { if (cursetno < 0) {
1006 error("%%<ident> not allowed here");
1008 $$ = perc_ident_expr($1);
1011 | DEFINED '(' expr ')'
1012 { $$ = make_expr(TYPBOOL,EX_DEFINED,i_expr($3),0); }
1013 | SAMESIGN '(' expr ',' expr ')'
1014 { $$ = make_expr(TYPBOOL,EX_SAMESIGN,i_expr($3),i_expr($5)); }
1015 | TOPELTSIZE '(' emarg ')'
1016 { $$ = make_expr(TYPINT,EX_TOPELTSIZE,$3-1,0); }
1017 | FALLTHROUGH '(' emarg ')'
1018 { $$ = make_expr(TYPBOOL,EX_FALLTHROUGH,$3-1,0); }
1019 | SFIT '(' expr ',' expr ')'
1020 { $$ = make_expr(TYPBOOL,EX_SFIT,i_expr($3),i_expr($5)); }
1021 | UFIT '(' expr ',' expr ')'
1022 { $$ = make_expr(TYPBOOL,EX_UFIT,i_expr($3),i_expr($5)); }
1023 | ROM '(' emarg ',' NUMBER ')'
1024 { $$ = make_expr(TYPINT,EX_ROM,$3-1,chkincl($5,1,3)-1); }
1025 | ISROM '(' emarg ')'
1026 { $$ = make_expr(TYPBOOL,EX_ISROM,$3-1,0); }
1027 | LOWW '(' emarg ')'
1028 { $$ = make_expr(TYPINT,EX_LOWW,$3-1,0); }
1029 | HIGHW '(' emarg ')'
1030 { $$ = make_expr(TYPINT,EX_HIGHW,$3-1,0); }
1031 /* Excluded, because it causes a shift-reduce conflict
1032 (problems with a tokenset_no followed by an optexpr)
1033 | '-' expr %prec UMINUS
1034 { $$ = make_expr(TYPINT,EX_CON, 0, 0);
1035 $$ = make_expr(TYPINT,EX_MINUS,i_expr($$),i_expr($2));
1041 { $$ = make_expr(TYPBOOL,eq2expr($1,$3),$1.ex_index,$3.ex_index); }
1043 { $$ = make_expr(TYPBOOL,ne2expr($1,$3),$1.ex_index,$3.ex_index); }
1045 { $$ = make_expr(TYPBOOL,EX_NCPLT,i_expr($1),i_expr($3)); }
1047 { $$ = make_expr(TYPBOOL,EX_NCPGT,i_expr($1),i_expr($3)); }
1049 { $$ = make_expr(TYPBOOL,EX_NCPLE,i_expr($1),i_expr($3)); }
1051 { $$ = make_expr(TYPBOOL,EX_NCPGE,i_expr($1),i_expr($3)); }
1053 { $$ = make_expr(TYPBOOL,EX_OR2,b_expr($1),b_expr($3)); }
1055 { $$ = make_expr(TYPBOOL,EX_AND2,b_expr($1),b_expr($3)); }
1057 { $$ = make_expr(TYPINT,EX_OR,i_expr($1),i_expr($3)); }
1059 { $$ = make_expr(TYPINT,EX_XOR,i_expr($1),i_expr($3)); }
1061 { $$ = make_expr(TYPINT,EX_AND,i_expr($1),i_expr($3)); }
1063 { $$ = sum_expr($1,$3); }
1065 { $$ = make_expr(TYPINT,EX_MINUS,i_expr($1),i_expr($3)); }
1067 { $$ = make_expr(TYPINT,EX_TIMES,i_expr($1),i_expr($3)); }
1069 { $$ = make_expr(TYPINT,EX_DIVIDE,i_expr($1),i_expr($3)); }
1071 { $$ = make_expr(TYPINT,EX_MOD,i_expr($1),i_expr($3)); }
1073 { $$ = make_expr(TYPINT,EX_LSHIFT,i_expr($1),i_expr($3)); }
1075 { $$ = make_expr(TYPINT,EX_RSHIFT,i_expr($1),i_expr($3)); }
1077 { $$ = make_expr(TYPBOOL,EX_NOT,b_expr($2),0); }
1079 { $$ = make_expr(TYPINT,EX_COMP,i_expr($2),0); }
1080 | INREG '(' expr ')'
1081 { $$ = make_expr(TYPINT,EX_INREG,i_expr($3),0); }
1083 { $$ = make_expr(TYPINT,EX_CON, $1+1, 0); }
1088 : REGVAR '(' expr optregvartype ')'
1089 { $$ = regvar_expr($3,$4); }