genextract.c revision 50397
1/* Generate code from machine description to extract operands from insn as rtl. 2 Copyright (C) 1987, 91, 92, 93, 97, 1998 Free Software Foundation, Inc. 3 4This file is part of GNU CC. 5 6GNU CC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU CC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU CC; see the file COPYING. If not, write to 18the Free Software Foundation, 59 Temple Place - Suite 330, 19Boston, MA 02111-1307, USA. */ 20 21 22#include "hconfig.h" 23#ifdef __STDC__ 24#include <stdarg.h> 25#else 26#include <varargs.h> 27#endif 28#include "system.h" 29#include "rtl.h" 30#include "obstack.h" 31#include "insn-config.h" 32 33static struct obstack obstack; 34struct obstack *rtl_obstack = &obstack; 35 36#define obstack_chunk_alloc xmalloc 37#define obstack_chunk_free free 38 39/* Names for patterns. Need to allow linking with print-rtl. */ 40char **insn_name_ptr; 41 42/* This structure contains all the information needed to describe one 43 set of extractions methods. Each method may be used by more than 44 one pattern if the operands are in the same place. 45 46 The string for each operand describes that path to the operand and 47 contains `0' through `9' when going into an expression and `a' through 48 `z' when going into a vector. We assume here that only the first operand 49 of an rtl expression is a vector. genrecog.c makes the same assumption 50 (and uses the same representation) and it is currently true. */ 51 52struct extraction 53{ 54 int op_count; 55 char *oplocs[MAX_RECOG_OPERANDS]; 56 int dup_count; 57 char *duplocs[MAX_DUP_OPERANDS]; 58 int dupnums[MAX_DUP_OPERANDS]; 59 struct code_ptr *insns; 60 struct extraction *next; 61}; 62 63/* Holds a single insn code that use an extraction method. */ 64 65struct code_ptr 66{ 67 int insn_code; 68 struct code_ptr *next; 69}; 70 71static struct extraction *extractions; 72 73/* Number instruction patterns handled, starting at 0 for first one. */ 74 75static int insn_code_number; 76 77/* Records the large operand number in this insn. */ 78 79static int op_count; 80 81/* Records the location of any operands using the string format described 82 above. */ 83 84static char *oplocs[MAX_RECOG_OPERANDS]; 85 86/* Number the occurrences of MATCH_DUP in each instruction, 87 starting at 0 for the first occurrence. */ 88 89static int dup_count; 90 91/* Records the location of any MATCH_DUP operands. */ 92 93static char *duplocs[MAX_DUP_OPERANDS]; 94 95/* Record the operand number of any MATCH_DUPs. */ 96 97static int dupnums[MAX_DUP_OPERANDS]; 98 99/* Record the list of insn_codes for peepholes. */ 100 101static struct code_ptr *peepholes; 102 103static void gen_insn PROTO ((rtx)); 104static void walk_rtx PROTO ((rtx, char *)); 105static void print_path PROTO ((char *)); 106char *xmalloc PROTO ((unsigned)); 107char *xrealloc PROTO ((char *, unsigned)); 108static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1; 109static char *copystr PROTO ((char *)); 110static void mybzero (); 111void fancy_abort PROTO ((void)); 112 113static void 114gen_insn (insn) 115 rtx insn; 116{ 117 register int i; 118 register struct extraction *p; 119 register struct code_ptr *link; 120 121 op_count = 0; 122 dup_count = 0; 123 124 /* No operands seen so far in this pattern. */ 125 mybzero (oplocs, sizeof oplocs); 126 127 /* Walk the insn's pattern, remembering at all times the path 128 down to the walking point. */ 129 130 if (XVECLEN (insn, 1) == 1) 131 walk_rtx (XVECEXP (insn, 1, 0), ""); 132 else 133 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) 134 { 135 char *path = (char *) alloca (2); 136 137 path[0] = 'a' + i; 138 path[1] = 0; 139 140 walk_rtx (XVECEXP (insn, 1, i), path); 141 } 142 143 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr)); 144 link->insn_code = insn_code_number; 145 146 /* See if we find something that already had this extraction method. */ 147 148 for (p = extractions; p; p = p->next) 149 { 150 if (p->op_count != op_count || p->dup_count != dup_count) 151 continue; 152 153 for (i = 0; i < op_count; i++) 154 if (p->oplocs[i] != oplocs[i] 155 && ! (p->oplocs[i] != 0 && oplocs[i] != 0 156 && ! strcmp (p->oplocs[i], oplocs[i]))) 157 break; 158 159 if (i != op_count) 160 continue; 161 162 for (i = 0; i < dup_count; i++) 163 if (p->dupnums[i] != dupnums[i] 164 || strcmp (p->duplocs[i], duplocs[i])) 165 break; 166 167 if (i != dup_count) 168 continue; 169 170 /* This extraction is the same as ours. Just link us in. */ 171 link->next = p->insns; 172 p->insns = link; 173 return; 174 } 175 176 /* Otherwise, make a new extraction method. */ 177 178 p = (struct extraction *) xmalloc (sizeof (struct extraction)); 179 p->op_count = op_count; 180 p->dup_count = dup_count; 181 p->next = extractions; 182 extractions = p; 183 p->insns = link; 184 link->next = 0; 185 186 for (i = 0; i < op_count; i++) 187 p->oplocs[i] = oplocs[i]; 188 189 for (i = 0; i < dup_count; i++) 190 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i]; 191} 192 193static void 194walk_rtx (x, path) 195 rtx x; 196 char *path; 197{ 198 register RTX_CODE code; 199 register int i; 200 register int len; 201 register char *fmt; 202 int depth = strlen (path); 203 char *newpath; 204 205 if (x == 0) 206 return; 207 208 code = GET_CODE (x); 209 210 switch (code) 211 { 212 case PC: 213 case CC0: 214 case CONST_INT: 215 case SYMBOL_REF: 216 return; 217 218 case MATCH_OPERAND: 219 case MATCH_SCRATCH: 220 oplocs[XINT (x, 0)] = copystr (path); 221 op_count = MAX (op_count, XINT (x, 0) + 1); 222 break; 223 224 case MATCH_DUP: 225 case MATCH_PAR_DUP: 226 duplocs[dup_count] = copystr (path); 227 dupnums[dup_count] = XINT (x, 0); 228 dup_count++; 229 break; 230 231 case MATCH_OP_DUP: 232 duplocs[dup_count] = copystr (path); 233 dupnums[dup_count] = XINT (x, 0); 234 dup_count++; 235 236 newpath = (char *) alloca (depth + 2); 237 strcpy (newpath, path); 238 newpath[depth + 1] = 0; 239 240 for (i = XVECLEN (x, 1) - 1; i >= 0; i--) 241 { 242 newpath[depth] = '0' + i; 243 walk_rtx (XVECEXP (x, 1, i), newpath); 244 } 245 return; 246 247 case MATCH_OPERATOR: 248 oplocs[XINT (x, 0)] = copystr (path); 249 op_count = MAX (op_count, XINT (x, 0) + 1); 250 251 newpath = (char *) alloca (depth + 2); 252 strcpy (newpath, path); 253 newpath[depth + 1] = 0; 254 255 for (i = XVECLEN (x, 2) - 1; i >= 0; i--) 256 { 257 newpath[depth] = '0' + i; 258 walk_rtx (XVECEXP (x, 2, i), newpath); 259 } 260 return; 261 262 case MATCH_PARALLEL: 263 oplocs[XINT (x, 0)] = copystr (path); 264 op_count = MAX (op_count, XINT (x, 0) + 1); 265 266 newpath = (char *) alloca (depth + 2); 267 strcpy (newpath, path); 268 newpath[depth + 1] = 0; 269 270 for (i = XVECLEN (x, 2) - 1; i >= 0; i--) 271 { 272 newpath[depth] = 'a' + i; 273 walk_rtx (XVECEXP (x, 2, i), newpath); 274 } 275 return; 276 277 case ADDRESS: 278 walk_rtx (XEXP (x, 0), path); 279 return; 280 281 default: 282 break; 283 } 284 285 newpath = (char *) alloca (depth + 2); 286 strcpy (newpath, path); 287 newpath[depth + 1] = 0; 288 289 fmt = GET_RTX_FORMAT (code); 290 len = GET_RTX_LENGTH (code); 291 for (i = 0; i < len; i++) 292 { 293 if (fmt[i] == 'e' || fmt[i] == 'u') 294 { 295 newpath[depth] = '0' + i; 296 walk_rtx (XEXP (x, i), newpath); 297 } 298 else if (fmt[i] == 'E') 299 { 300 int j; 301 for (j = XVECLEN (x, i) - 1; j >= 0; j--) 302 { 303 newpath[depth] = 'a' + j; 304 walk_rtx (XVECEXP (x, i, j), newpath); 305 } 306 } 307 } 308} 309 310/* Given a PATH, representing a path down the instruction's 311 pattern from the root to a certain point, output code to 312 evaluate to the rtx at that point. */ 313 314static void 315print_path (path) 316 char *path; 317{ 318 register int len = strlen (path); 319 register int i; 320 321 if (len == 0) 322 { 323 /* Don't emit "pat", since we may try to take the address of it, 324 which isn't what is intended. */ 325 printf("PATTERN (insn)"); 326 return; 327 } 328 329 /* We first write out the operations (XEXP or XVECEXP) in reverse 330 order, then write "insn", then the indices in forward order. */ 331 332 for (i = len - 1; i >=0 ; i--) 333 { 334 if (path[i] >= 'a' && path[i] <= 'z') 335 printf ("XVECEXP ("); 336 else if (path[i] >= '0' && path[i] <= '9') 337 printf ("XEXP ("); 338 else 339 abort (); 340 } 341 342 printf ("pat"); 343 344 for (i = 0; i < len; i++) 345 { 346 if (path[i] >= 'a' && path[i] <= 'z') 347 printf (", 0, %d)", path[i] - 'a'); 348 else if (path[i] >= '0' && path[i] <= '9') 349 printf (", %d)", path[i] - '0'); 350 else 351 abort (); 352 } 353} 354 355char * 356xmalloc (size) 357 unsigned size; 358{ 359 register char *val = (char *) malloc (size); 360 361 if (val == 0) 362 fatal ("virtual memory exhausted"); 363 return val; 364} 365 366char * 367xrealloc (ptr, size) 368 char *ptr; 369 unsigned size; 370{ 371 char *result = (char *) realloc (ptr, size); 372 if (!result) 373 fatal ("virtual memory exhausted"); 374 return result; 375} 376 377static void 378fatal VPROTO ((char *format, ...)) 379{ 380#ifndef __STDC__ 381 char *format; 382#endif 383 va_list ap; 384 385 VA_START (ap, format); 386 387#ifndef __STDC__ 388 format = va_arg (ap, char *); 389#endif 390 391 fprintf (stderr, "genextract: "); 392 vfprintf (stderr, format, ap); 393 va_end (ap); 394 fprintf (stderr, "\n"); 395 exit (FATAL_EXIT_CODE); 396} 397 398/* More 'friendly' abort that prints the line and file. 399 config.h can #define abort fancy_abort if you like that sort of thing. */ 400 401void 402fancy_abort () 403{ 404 fatal ("Internal gcc abort."); 405} 406 407static char * 408copystr (s1) 409 char *s1; 410{ 411 register char *tem; 412 413 if (s1 == 0) 414 return 0; 415 416 tem = (char *) xmalloc (strlen (s1) + 1); 417 strcpy (tem, s1); 418 419 return tem; 420} 421 422static void 423mybzero (b, length) 424 register char *b; 425 register unsigned length; 426{ 427 while (length-- > 0) 428 *b++ = 0; 429} 430 431int 432main (argc, argv) 433 int argc; 434 char **argv; 435{ 436 rtx desc; 437 FILE *infile; 438 register int c, i; 439 struct extraction *p; 440 struct code_ptr *link; 441 442 obstack_init (rtl_obstack); 443 444 if (argc <= 1) 445 fatal ("No input file name."); 446 447 infile = fopen (argv[1], "r"); 448 if (infile == 0) 449 { 450 perror (argv[1]); 451 exit (FATAL_EXIT_CODE); 452 } 453 454 init_rtl (); 455 456 /* Assign sequential codes to all entries in the machine description 457 in parallel with the tables in insn-output.c. */ 458 459 insn_code_number = 0; 460 461 printf ("/* Generated automatically by the program `genextract'\n\ 462from the machine description file `md'. */\n\n"); 463 464 printf ("#include \"config.h\"\n"); 465 printf ("#include \"system.h\"\n"); 466 printf ("#include \"rtl.h\"\n\n"); 467 468 /* This variable exists only so it can be the "location" 469 of any missing operand whose numbers are skipped by a given pattern. */ 470 printf ("static rtx junk ATTRIBUTE_UNUSED;\n"); 471 472 printf ("extern rtx recog_operand[];\n"); 473 printf ("extern rtx *recog_operand_loc[];\n"); 474 printf ("extern rtx *recog_dup_loc[];\n"); 475 printf ("extern char recog_dup_num[];\n"); 476 477 printf ("void\ninsn_extract (insn)\n"); 478 printf (" rtx insn;\n"); 479 printf ("{\n"); 480 printf (" register rtx *ro = recog_operand;\n"); 481 printf (" register rtx **ro_loc = recog_operand_loc;\n"); 482 printf (" rtx pat = PATTERN (insn);\n"); 483 printf (" int i ATTRIBUTE_UNUSED;\n\n"); 484 printf (" switch (INSN_CODE (insn))\n"); 485 printf (" {\n"); 486 printf (" case -1:\n"); 487 printf (" fatal_insn_not_found (insn);\n\n"); 488 489 /* Read the machine description. */ 490 491 while (1) 492 { 493 c = read_skip_spaces (infile); 494 if (c == EOF) 495 break; 496 ungetc (c, infile); 497 498 desc = read_rtx (infile); 499 if (GET_CODE (desc) == DEFINE_INSN) 500 { 501 gen_insn (desc); 502 ++insn_code_number; 503 } 504 505 else if (GET_CODE (desc) == DEFINE_PEEPHOLE) 506 { 507 struct code_ptr *link 508 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr)); 509 510 link->insn_code = insn_code_number; 511 link->next = peepholes; 512 peepholes = link; 513 ++insn_code_number; 514 } 515 516 else if (GET_CODE (desc) == DEFINE_EXPAND 517 || GET_CODE (desc) == DEFINE_SPLIT) 518 ++insn_code_number; 519 } 520 521 /* Write out code to handle peepholes and the insn_codes that it should 522 be called for. */ 523 if (peepholes) 524 { 525 for (link = peepholes; link; link = link->next) 526 printf (" case %d:\n", link->insn_code); 527 528 /* The vector in the insn says how many operands it has. 529 And all it contains are operands. In fact, the vector was 530 created just for the sake of this function. */ 531 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n"); 532 printf (" ro[i] = XVECEXP (pat, 0, i);\n"); 533 printf (" break;\n\n"); 534 } 535 536 /* Write out all the ways to extract insn operands. */ 537 for (p = extractions; p; p = p->next) 538 { 539 for (link = p->insns; link; link = link->next) 540 printf (" case %d:\n", link->insn_code); 541 542 for (i = 0; i < p->op_count; i++) 543 { 544 if (p->oplocs[i] == 0) 545 { 546 printf (" ro[%d] = const0_rtx;\n", i); 547 printf (" ro_loc[%d] = &junk;\n", i); 548 } 549 else 550 { 551 printf (" ro[%d] = *(ro_loc[%d] = &", i, i); 552 print_path (p->oplocs[i]); 553 printf (");\n"); 554 } 555 } 556 557 for (i = 0; i < p->dup_count; i++) 558 { 559 printf (" recog_dup_loc[%d] = &", i); 560 print_path (p->duplocs[i]); 561 printf (";\n"); 562 printf (" recog_dup_num[%d] = %d;\n", i, p->dupnums[i]); 563 } 564 565 printf (" break;\n\n"); 566 } 567 568 /* This should never be reached. Note that we would also reach this abort 569 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or 570 DEFINE_SPLIT, but that is correct. */ 571 printf (" default:\n abort ();\n"); 572 573 printf (" }\n}\n"); 574 575 fflush (stdout); 576 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 577 /* NOTREACHED */ 578 return 0; 579} 580