00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "bconfig.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "errors.h"
00030 #include "gensupport.h"
00031 #include "vec.h"
00032 #include "vecprim.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 typedef char *locstr;
00045
00046 struct extraction
00047 {
00048 unsigned int op_count;
00049 unsigned int dup_count;
00050 locstr *oplocs;
00051 locstr *duplocs;
00052 int *dupnums;
00053 struct code_ptr *insns;
00054 struct extraction *next;
00055 };
00056
00057
00058 struct code_ptr
00059 {
00060 int insn_code;
00061 struct code_ptr *next;
00062 };
00063
00064
00065 static struct extraction *extractions;
00066
00067
00068 static struct code_ptr *peepholes;
00069
00070
00071
00072
00073 DEF_VEC_P(locstr);
00074 DEF_VEC_ALLOC_P(locstr,heap);
00075
00076 struct accum_extract
00077 {
00078 VEC(locstr,heap) *oplocs;
00079 VEC(locstr,heap) *duplocs;
00080 VEC(int,heap) *dupnums;
00081 VEC(char,heap) *pathstr;
00082 };
00083
00084
00085 static void walk_rtx (rtx, struct accum_extract *);
00086
00087 static void
00088 gen_insn (rtx insn, int insn_code_number)
00089 {
00090 int i;
00091 unsigned int op_count, dup_count, j;
00092 struct extraction *p;
00093 struct code_ptr *link;
00094 struct accum_extract acc;
00095
00096 acc.oplocs = VEC_alloc (locstr,heap, 10);
00097 acc.duplocs = VEC_alloc (locstr,heap, 10);
00098 acc.dupnums = VEC_alloc (int,heap, 10);
00099 acc.pathstr = VEC_alloc (char,heap, 20);
00100
00101
00102
00103
00104 if (XVECLEN (insn, 1) == 1)
00105 walk_rtx (XVECEXP (insn, 1, 0), &acc);
00106 else
00107 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
00108 {
00109 VEC_safe_push (char,heap, acc.pathstr, 'a' + i);
00110 walk_rtx (XVECEXP (insn, 1, i), &acc);
00111 VEC_pop (char, acc.pathstr);
00112 }
00113
00114 link = XNEW (struct code_ptr);
00115 link->insn_code = insn_code_number;
00116
00117
00118
00119 op_count = VEC_length (locstr, acc.oplocs);
00120 dup_count = VEC_length (locstr, acc.duplocs);
00121 gcc_assert (dup_count == VEC_length (int, acc.dupnums));
00122
00123 for (p = extractions; p; p = p->next)
00124 {
00125 if (p->op_count != op_count || p->dup_count != dup_count)
00126 continue;
00127
00128 for (j = 0; j < op_count; j++)
00129 {
00130 char *a = p->oplocs[j];
00131 char *b = VEC_index (locstr, acc.oplocs, j);
00132 if (a != b && (!a || !b || strcmp (a, b)))
00133 break;
00134 }
00135
00136 if (j != op_count)
00137 continue;
00138
00139 for (j = 0; j < dup_count; j++)
00140 if (p->dupnums[j] != VEC_index (int, acc.dupnums, j)
00141 || strcmp (p->duplocs[j], VEC_index (locstr, acc.duplocs, j)))
00142 break;
00143
00144 if (j != dup_count)
00145 continue;
00146
00147
00148 link->next = p->insns;
00149 p->insns = link;
00150 goto done;
00151 }
00152
00153
00154
00155
00156 p = xmalloc (sizeof (struct extraction)
00157 + op_count*sizeof (char *)
00158 + dup_count*sizeof (char *)
00159 + dup_count*sizeof (int));
00160 p->op_count = op_count;
00161 p->dup_count = dup_count;
00162 p->next = extractions;
00163 extractions = p;
00164 p->insns = link;
00165 link->next = 0;
00166
00167 p->oplocs = (char **)((char *)p + sizeof (struct extraction));
00168 p->duplocs = p->oplocs + op_count;
00169 p->dupnums = (int *)(p->duplocs + dup_count);
00170
00171 memcpy(p->oplocs, VEC_address(locstr,acc.oplocs), op_count*sizeof(locstr));
00172 memcpy(p->duplocs, VEC_address(locstr,acc.duplocs), dup_count*sizeof(locstr));
00173 memcpy(p->dupnums, VEC_address(int, acc.dupnums), dup_count*sizeof(int));
00174
00175 done:
00176 VEC_free (locstr,heap, acc.oplocs);
00177 VEC_free (locstr,heap, acc.duplocs);
00178 VEC_free (int,heap, acc.dupnums);
00179 VEC_free (char,heap, acc.pathstr);
00180 }
00181
00182
00183
00184
00185
00186 static void
00187 VEC_safe_set_locstr (VEC(locstr,heap) **vp, unsigned int ix, char *str)
00188 {
00189 if (ix < VEC_length (locstr, *vp))
00190 {
00191 gcc_assert (VEC_index (locstr, *vp, ix) == 0);
00192 VEC_replace (locstr, *vp, ix, str);
00193 }
00194 else
00195 {
00196 while (ix > VEC_length (locstr, *vp))
00197 VEC_safe_push (locstr, heap, *vp, 0);
00198 VEC_safe_push (locstr, heap, *vp, str);
00199 }
00200 }
00201
00202
00203
00204 static char *
00205 VEC_char_to_string (VEC(char,heap) *v)
00206 {
00207 size_t n = VEC_length (char, v);
00208 char *s = XNEWVEC (char, n + 1);
00209 memcpy (s, VEC_address (char, v), n);
00210 s[n] = '\0';
00211 return s;
00212 }
00213
00214 static void
00215 walk_rtx (rtx x, struct accum_extract *acc)
00216 {
00217 RTX_CODE code;
00218 int i, len, base;
00219 const char *fmt;
00220
00221 if (x == 0)
00222 return;
00223
00224 code = GET_CODE (x);
00225 switch (code)
00226 {
00227 case PC:
00228 case CC0:
00229 case CONST_INT:
00230 case SYMBOL_REF:
00231 return;
00232
00233 case MATCH_OPERAND:
00234 case MATCH_SCRATCH:
00235 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
00236 VEC_char_to_string (acc->pathstr));
00237 break;
00238
00239 case MATCH_OPERATOR:
00240 case MATCH_PARALLEL:
00241 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
00242 VEC_char_to_string (acc->pathstr));
00243
00244 base = (code == MATCH_OPERATOR ? '0' : 'a');
00245 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
00246 {
00247 VEC_safe_push (char,heap, acc->pathstr, base + i);
00248 walk_rtx (XVECEXP (x, 2, i), acc);
00249 VEC_pop (char, acc->pathstr);
00250 }
00251 return;
00252
00253 case MATCH_DUP:
00254 case MATCH_PAR_DUP:
00255 case MATCH_OP_DUP:
00256 VEC_safe_push (locstr,heap, acc->duplocs,
00257 VEC_char_to_string (acc->pathstr));
00258 VEC_safe_push (int,heap, acc->dupnums, XINT (x, 0));
00259
00260 if (code == MATCH_DUP)
00261 break;
00262
00263 base = (code == MATCH_OP_DUP ? '0' : 'a');
00264 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
00265 {
00266 VEC_safe_push (char,heap, acc->pathstr, base + i);
00267 walk_rtx (XVECEXP (x, 1, i), acc);
00268 VEC_pop (char, acc->pathstr);
00269 }
00270 return;
00271
00272 default:
00273 break;
00274 }
00275
00276 fmt = GET_RTX_FORMAT (code);
00277 len = GET_RTX_LENGTH (code);
00278 for (i = 0; i < len; i++)
00279 {
00280 if (fmt[i] == 'e' || fmt[i] == 'u')
00281 {
00282 VEC_safe_push (char,heap, acc->pathstr, '0' + i);
00283 walk_rtx (XEXP (x, i), acc);
00284 VEC_pop (char, acc->pathstr);
00285 }
00286 else if (fmt[i] == 'E')
00287 {
00288 int j;
00289 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00290 {
00291 VEC_safe_push (char,heap, acc->pathstr, 'a' + j);
00292 walk_rtx (XVECEXP (x, i, j), acc);
00293 VEC_pop (char, acc->pathstr);
00294 }
00295 }
00296 }
00297 }
00298
00299
00300
00301
00302
00303 static void
00304 print_path (const char *path)
00305 {
00306 int len = strlen (path);
00307 int i;
00308
00309 if (len == 0)
00310 {
00311
00312
00313 fputs ("PATTERN (insn)", stdout);
00314 return;
00315 }
00316
00317
00318
00319
00320 for (i = len - 1; i >= 0 ; i--)
00321 {
00322 if (ISLOWER (path[i]))
00323 fputs ("XVECEXP (", stdout);
00324 else if (ISDIGIT (path[i]))
00325 fputs ("XEXP (", stdout);
00326 else
00327 gcc_unreachable ();
00328 }
00329
00330 fputs ("pat", stdout);
00331
00332 for (i = 0; i < len; i++)
00333 {
00334 if (ISLOWER (path[i]))
00335 printf (", 0, %d)", path[i] - 'a');
00336 else if (ISDIGIT(path[i]))
00337 printf (", %d)", path[i] - '0');
00338 else
00339 gcc_unreachable ();
00340 }
00341 }
00342
00343 static void
00344 print_header (void)
00345 {
00346
00347
00348
00349
00350 puts ("\
00351 /* Generated automatically by the program `genextract'\n\
00352 from the machine description file `md'. */\n\
00353 \n\
00354 #include \"config.h\"\n\
00355 #include \"system.h\"\n\
00356 #include \"coretypes.h\"\n\
00357 #include \"tm.h\"\n\
00358 #include \"rtl.h\"\n\
00359 #include \"insn-config.h\"\n\
00360 #include \"recog.h\"\n\
00361 #include \"toplev.h\"\n\
00362 \n\
00363 /* This variable is used as the \"location\" of any missing operand\n\
00364 whose numbers are skipped by a given pattern. */\n\
00365 static rtx junk ATTRIBUTE_UNUSED;\n");
00366
00367 puts ("\
00368 void\n\
00369 insn_extract (rtx insn)\n{\n\
00370 rtx *ro = recog_data.operand;\n\
00371 rtx **ro_loc = recog_data.operand_loc;\n\
00372 rtx pat = PATTERN (insn);\n\
00373 int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\
00374 \n\
00375 #ifdef ENABLE_CHECKING\n\
00376 memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\
00377 memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\
00378 #endif\n");
00379
00380 puts ("\
00381 switch (INSN_CODE (insn))\n\
00382 {\n\
00383 default:\n\
00384 /* Control reaches here if insn_extract has been called with an\n\
00385 unrecognizable insn (code -1), or an insn whose INSN_CODE\n\
00386 corresponds to a DEFINE_EXPAND in the machine description;\n\
00387 either way, a bug. */\n\
00388 if (INSN_CODE (insn) < 0)\n\
00389 fatal_insn (\"unrecognizable insn:\", insn);\n\
00390 else\n\
00391 fatal_insn (\"insn with invalid code number:\", insn);\n");
00392 }
00393
00394 int
00395 main (int argc, char **argv)
00396 {
00397 rtx desc;
00398 unsigned int i;
00399 struct extraction *p;
00400 struct code_ptr *link;
00401 const char *name;
00402 int insn_code_number;
00403 int line_no;
00404
00405 progname = "genextract";
00406
00407 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
00408 return (FATAL_EXIT_CODE);
00409
00410
00411
00412 while ((desc = read_md_rtx (&line_no, &insn_code_number)) != NULL)
00413 {
00414 if (GET_CODE (desc) == DEFINE_INSN)
00415 gen_insn (desc, insn_code_number);
00416
00417 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
00418 {
00419 struct code_ptr *link = XNEW (struct code_ptr);
00420
00421 link->insn_code = insn_code_number;
00422 link->next = peepholes;
00423 peepholes = link;
00424 }
00425 }
00426
00427 print_header ();
00428
00429
00430
00431 if (peepholes)
00432 {
00433 for (link = peepholes; link; link = link->next)
00434 printf (" case %d:\n", link->insn_code);
00435
00436
00437
00438
00439
00440
00441 puts (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n"
00442 " ro[i] = *(ro_loc[i] = &XVECEXP (pat, 0, i));\n"
00443 " break;\n");
00444 }
00445
00446
00447 for (p = extractions; p; p = p->next)
00448 {
00449 for (link = p->insns; link; link = link->next)
00450 {
00451 i = link->insn_code;
00452 name = get_insn_name (i);
00453 if (name)
00454 printf (" case %d: /* %s */\n", i, name);
00455 else
00456 printf (" case %d:\n", i);
00457 }
00458
00459 for (i = 0; i < p->op_count; i++)
00460 {
00461 if (p->oplocs[i] == 0)
00462 {
00463 printf (" ro[%d] = const0_rtx;\n", i);
00464 printf (" ro_loc[%d] = &junk;\n", i);
00465 }
00466 else
00467 {
00468 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
00469 print_path (p->oplocs[i]);
00470 puts (");");
00471 }
00472 }
00473
00474 for (i = 0; i < p->dup_count; i++)
00475 {
00476 printf (" recog_data.dup_loc[%d] = &", i);
00477 print_path (p->duplocs[i]);
00478 puts (";");
00479 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
00480 }
00481
00482 puts (" break;\n");
00483 }
00484
00485 puts (" }\n}");
00486 fflush (stdout);
00487 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
00488 }