Mercurial > hg > CbC > CbC_gcc
comparison gcc/genextract.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Generate code from machine description to extract operands from insn as rtl. | 1 /* Generate code from machine description to extract operands from insn as rtl. |
2 Copyright (C) 1987, 1991, 1992, 1993, 1997, 1998, 1999, 2000, 2003, | 2 Copyright (C) 1987-2017 Free Software Foundation, Inc. |
3 2004, 2005, 2007, 2008, 2009, 2010 | |
4 Free Software Foundation, Inc. | |
5 | 3 |
6 This file is part of GCC. | 4 This file is part of GCC. |
7 | 5 |
8 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
9 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
26 #include "tm.h" | 24 #include "tm.h" |
27 #include "rtl.h" | 25 #include "rtl.h" |
28 #include "errors.h" | 26 #include "errors.h" |
29 #include "read-md.h" | 27 #include "read-md.h" |
30 #include "gensupport.h" | 28 #include "gensupport.h" |
31 #include "vec.h" | |
32 #include "vecprim.h" | |
33 | 29 |
34 /* This structure contains all the information needed to describe one | 30 /* This structure contains all the information needed to describe one |
35 set of extractions methods. Each method may be used by more than | 31 set of extractions methods. Each method may be used by more than |
36 one pattern if the operands are in the same place. | 32 one pattern if the operands are in the same place. |
37 | 33 |
68 static struct code_ptr *peepholes; | 64 static struct code_ptr *peepholes; |
69 | 65 |
70 /* This structure is used by gen_insn and walk_rtx to accumulate the | 66 /* This structure is used by gen_insn and walk_rtx to accumulate the |
71 data that will be used to produce an extractions structure. */ | 67 data that will be used to produce an extractions structure. */ |
72 | 68 |
73 DEF_VEC_P(locstr); | |
74 DEF_VEC_ALLOC_P(locstr,heap); | |
75 | 69 |
76 struct accum_extract | 70 struct accum_extract |
77 { | 71 { |
78 VEC(locstr,heap) *oplocs; | 72 accum_extract () : oplocs (10), duplocs (10), dupnums (10), pathstr (20) {} |
79 VEC(locstr,heap) *duplocs; | 73 |
80 VEC(int,heap) *dupnums; | 74 auto_vec<locstr> oplocs; |
81 VEC(char,heap) *pathstr; | 75 auto_vec<locstr> duplocs; |
76 auto_vec<int> dupnums; | |
77 auto_vec<char> pathstr; | |
82 }; | 78 }; |
83 | 79 |
84 int line_no; | |
85 | |
86 /* Forward declarations. */ | 80 /* Forward declarations. */ |
87 static void walk_rtx (rtx, struct accum_extract *); | 81 static void walk_rtx (md_rtx_info *, rtx, struct accum_extract *); |
88 | 82 |
89 static void | 83 static void |
90 gen_insn (rtx insn, int insn_code_number) | 84 gen_insn (md_rtx_info *info) |
91 { | 85 { |
92 int i; | 86 int i; |
93 unsigned int op_count, dup_count, j; | 87 unsigned int op_count, dup_count, j; |
94 struct extraction *p; | 88 struct extraction *p; |
95 struct code_ptr *link; | 89 struct code_ptr *link; |
96 struct accum_extract acc; | 90 struct accum_extract acc; |
97 | 91 |
98 acc.oplocs = VEC_alloc (locstr,heap, 10); | |
99 acc.duplocs = VEC_alloc (locstr,heap, 10); | |
100 acc.dupnums = VEC_alloc (int,heap, 10); | |
101 acc.pathstr = VEC_alloc (char,heap, 20); | |
102 | |
103 /* Walk the insn's pattern, remembering at all times the path | 92 /* Walk the insn's pattern, remembering at all times the path |
104 down to the walking point. */ | 93 down to the walking point. */ |
105 | 94 |
95 rtx insn = info->def; | |
106 if (XVECLEN (insn, 1) == 1) | 96 if (XVECLEN (insn, 1) == 1) |
107 walk_rtx (XVECEXP (insn, 1, 0), &acc); | 97 walk_rtx (info, XVECEXP (insn, 1, 0), &acc); |
108 else | 98 else |
109 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) | 99 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--) |
110 { | 100 { |
111 VEC_safe_push (char,heap, acc.pathstr, 'a' + i); | 101 acc.pathstr.safe_push ('a' + i); |
112 walk_rtx (XVECEXP (insn, 1, i), &acc); | 102 walk_rtx (info, XVECEXP (insn, 1, i), &acc); |
113 VEC_pop (char, acc.pathstr); | 103 acc.pathstr.pop (); |
114 } | 104 } |
115 | 105 |
116 link = XNEW (struct code_ptr); | 106 link = XNEW (struct code_ptr); |
117 link->insn_code = insn_code_number; | 107 link->insn_code = info->index; |
118 | 108 |
119 /* See if we find something that already had this extraction method. */ | 109 /* See if we find something that already had this extraction method. */ |
120 | 110 |
121 op_count = VEC_length (locstr, acc.oplocs); | 111 op_count = acc.oplocs.length (); |
122 dup_count = VEC_length (locstr, acc.duplocs); | 112 dup_count = acc.duplocs.length (); |
123 gcc_assert (dup_count == VEC_length (int, acc.dupnums)); | 113 gcc_assert (dup_count == acc.dupnums.length ()); |
124 | 114 |
125 for (p = extractions; p; p = p->next) | 115 for (p = extractions; p; p = p->next) |
126 { | 116 { |
127 if (p->op_count != op_count || p->dup_count != dup_count) | 117 if (p->op_count != op_count || p->dup_count != dup_count) |
128 continue; | 118 continue; |
129 | 119 |
130 for (j = 0; j < op_count; j++) | 120 for (j = 0; j < op_count; j++) |
131 { | 121 { |
132 char *a = p->oplocs[j]; | 122 char *a = p->oplocs[j]; |
133 char *b = VEC_index (locstr, acc.oplocs, j); | 123 char *b = acc.oplocs[j]; |
134 if (a != b && (!a || !b || strcmp (a, b))) | 124 if (a != b && (!a || !b || strcmp (a, b))) |
135 break; | 125 break; |
136 } | 126 } |
137 | 127 |
138 if (j != op_count) | 128 if (j != op_count) |
139 continue; | 129 continue; |
140 | 130 |
141 for (j = 0; j < dup_count; j++) | 131 for (j = 0; j < dup_count; j++) |
142 if (p->dupnums[j] != VEC_index (int, acc.dupnums, j) | 132 if (p->dupnums[j] != acc.dupnums[j] |
143 || strcmp (p->duplocs[j], VEC_index (locstr, acc.duplocs, j))) | 133 || strcmp (p->duplocs[j], acc.duplocs[j])) |
144 break; | 134 break; |
145 | 135 |
146 if (j != dup_count) | 136 if (j != dup_count) |
147 continue; | 137 continue; |
148 | 138 |
149 /* This extraction is the same as ours. Just link us in. */ | 139 /* This extraction is the same as ours. Just link us in. */ |
150 link->next = p->insns; | 140 link->next = p->insns; |
151 p->insns = link; | 141 p->insns = link; |
152 goto done; | 142 return; |
153 } | 143 } |
154 | 144 |
155 /* Otherwise, make a new extraction method. We stash the arrays | 145 /* Otherwise, make a new extraction method. We stash the arrays |
156 after the extraction structure in memory. */ | 146 after the extraction structure in memory. */ |
157 | 147 |
168 | 158 |
169 p->oplocs = (char **)((char *)p + sizeof (struct extraction)); | 159 p->oplocs = (char **)((char *)p + sizeof (struct extraction)); |
170 p->duplocs = p->oplocs + op_count; | 160 p->duplocs = p->oplocs + op_count; |
171 p->dupnums = (int *)(p->duplocs + dup_count); | 161 p->dupnums = (int *)(p->duplocs + dup_count); |
172 | 162 |
173 memcpy(p->oplocs, VEC_address(locstr,acc.oplocs), op_count*sizeof(locstr)); | 163 memcpy (p->oplocs, acc.oplocs.address (), op_count * sizeof (locstr)); |
174 memcpy(p->duplocs, VEC_address(locstr,acc.duplocs), dup_count*sizeof(locstr)); | 164 memcpy (p->duplocs, acc.duplocs.address (), dup_count * sizeof (locstr)); |
175 memcpy(p->dupnums, VEC_address(int, acc.dupnums), dup_count*sizeof(int)); | 165 memcpy (p->dupnums, acc.dupnums.address (), dup_count * sizeof (int)); |
176 | |
177 done: | |
178 VEC_free (locstr,heap, acc.oplocs); | |
179 VEC_free (locstr,heap, acc.duplocs); | |
180 VEC_free (int,heap, acc.dupnums); | |
181 VEC_free (char,heap, acc.pathstr); | |
182 } | 166 } |
183 | 167 |
184 /* Helper subroutine of walk_rtx: given a VEC(locstr), an index, and a | 168 /* Helper subroutine of walk_rtx: given a vec<locstr>, an index, and a |
185 string, insert the string at the index, which should either already | 169 string, insert the string at the index, which should either already |
186 exist and be NULL, or not yet exist within the vector. In the latter | 170 exist and be NULL, or not yet exist within the vector. In the latter |
187 case the vector is enlarged as appropriate. */ | 171 case the vector is enlarged as appropriate. INFO describes the |
172 containing define_* expression. */ | |
188 static void | 173 static void |
189 VEC_safe_set_locstr (VEC(locstr,heap) **vp, unsigned int ix, char *str) | 174 VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp, |
190 { | 175 unsigned int ix, char *str) |
191 if (ix < VEC_length (locstr, *vp)) | 176 { |
192 { | 177 if (ix < (*vp).length ()) |
193 if (VEC_index (locstr, *vp, ix)) | 178 { |
194 { | 179 if ((*vp)[ix]) |
195 message_with_line (line_no, "repeated operand number %d", ix); | 180 { |
181 message_at (info->loc, "repeated operand number %d", ix); | |
196 have_error = 1; | 182 have_error = 1; |
197 } | 183 } |
198 else | 184 else |
199 VEC_replace (locstr, *vp, ix, str); | 185 (*vp)[ix] = str; |
200 } | 186 } |
201 else | 187 else |
202 { | 188 { |
203 while (ix > VEC_length (locstr, *vp)) | 189 while (ix > (*vp).length ()) |
204 VEC_safe_push (locstr, heap, *vp, 0); | 190 vp->safe_push (NULL); |
205 VEC_safe_push (locstr, heap, *vp, str); | 191 vp->safe_push (str); |
206 } | 192 } |
207 } | 193 } |
208 | 194 |
209 /* Another helper subroutine of walk_rtx: given a VEC(char), convert it | 195 /* Another helper subroutine of walk_rtx: given a vec<char>, convert it |
210 to a NUL-terminated string in malloc memory. */ | 196 to a NUL-terminated string in malloc memory. */ |
211 static char * | 197 static char * |
212 VEC_char_to_string (VEC(char,heap) *v) | 198 VEC_char_to_string (vec<char> v) |
213 { | 199 { |
214 size_t n = VEC_length (char, v); | 200 size_t n = v.length (); |
215 char *s = XNEWVEC (char, n + 1); | 201 char *s = XNEWVEC (char, n + 1); |
216 memcpy (s, VEC_address (char, v), n); | 202 memcpy (s, v.address (), n); |
217 s[n] = '\0'; | 203 s[n] = '\0'; |
218 return s; | 204 return s; |
219 } | 205 } |
220 | 206 |
221 static void | 207 static void |
222 walk_rtx (rtx x, struct accum_extract *acc) | 208 walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) |
223 { | 209 { |
224 RTX_CODE code; | 210 RTX_CODE code; |
225 int i, len, base; | 211 int i, len, base; |
226 const char *fmt; | 212 const char *fmt; |
227 | 213 |
237 case SYMBOL_REF: | 223 case SYMBOL_REF: |
238 return; | 224 return; |
239 | 225 |
240 case MATCH_OPERAND: | 226 case MATCH_OPERAND: |
241 case MATCH_SCRATCH: | 227 case MATCH_SCRATCH: |
242 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0), | 228 VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0), |
243 VEC_char_to_string (acc->pathstr)); | 229 VEC_char_to_string (acc->pathstr)); |
244 break; | 230 break; |
245 | 231 |
246 case MATCH_OPERATOR: | 232 case MATCH_OPERATOR: |
247 case MATCH_PARALLEL: | 233 case MATCH_PARALLEL: |
248 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0), | 234 VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0), |
249 VEC_char_to_string (acc->pathstr)); | 235 VEC_char_to_string (acc->pathstr)); |
250 | 236 |
251 base = (code == MATCH_OPERATOR ? '0' : 'a'); | 237 base = (code == MATCH_OPERATOR ? '0' : 'a'); |
252 for (i = XVECLEN (x, 2) - 1; i >= 0; i--) | 238 for (i = XVECLEN (x, 2) - 1; i >= 0; i--) |
253 { | 239 { |
254 VEC_safe_push (char,heap, acc->pathstr, base + i); | 240 acc->pathstr.safe_push (base + i); |
255 walk_rtx (XVECEXP (x, 2, i), acc); | 241 walk_rtx (info, XVECEXP (x, 2, i), acc); |
256 VEC_pop (char, acc->pathstr); | 242 acc->pathstr.pop (); |
257 } | 243 } |
258 return; | 244 return; |
259 | 245 |
260 case MATCH_DUP: | 246 case MATCH_DUP: |
261 case MATCH_PAR_DUP: | 247 case MATCH_PAR_DUP: |
262 case MATCH_OP_DUP: | 248 case MATCH_OP_DUP: |
263 VEC_safe_push (locstr,heap, acc->duplocs, | 249 acc->duplocs.safe_push (VEC_char_to_string (acc->pathstr)); |
264 VEC_char_to_string (acc->pathstr)); | 250 acc->dupnums.safe_push (XINT (x, 0)); |
265 VEC_safe_push (int,heap, acc->dupnums, XINT (x, 0)); | |
266 | 251 |
267 if (code == MATCH_DUP) | 252 if (code == MATCH_DUP) |
268 break; | 253 break; |
269 | 254 |
270 base = (code == MATCH_OP_DUP ? '0' : 'a'); | 255 base = (code == MATCH_OP_DUP ? '0' : 'a'); |
271 for (i = XVECLEN (x, 1) - 1; i >= 0; i--) | 256 for (i = XVECLEN (x, 1) - 1; i >= 0; i--) |
272 { | 257 { |
273 VEC_safe_push (char,heap, acc->pathstr, base + i); | 258 acc->pathstr.safe_push (base + i); |
274 walk_rtx (XVECEXP (x, 1, i), acc); | 259 walk_rtx (info, XVECEXP (x, 1, i), acc); |
275 VEC_pop (char, acc->pathstr); | 260 acc->pathstr.pop (); |
276 } | 261 } |
277 return; | 262 return; |
278 | 263 |
279 default: | 264 default: |
280 break; | 265 break; |
284 len = GET_RTX_LENGTH (code); | 269 len = GET_RTX_LENGTH (code); |
285 for (i = 0; i < len; i++) | 270 for (i = 0; i < len; i++) |
286 { | 271 { |
287 if (fmt[i] == 'e' || fmt[i] == 'u') | 272 if (fmt[i] == 'e' || fmt[i] == 'u') |
288 { | 273 { |
289 VEC_safe_push (char,heap, acc->pathstr, '0' + i); | 274 acc->pathstr.safe_push ('0' + i); |
290 walk_rtx (XEXP (x, i), acc); | 275 walk_rtx (info, XEXP (x, i), acc); |
291 VEC_pop (char, acc->pathstr); | 276 acc->pathstr.pop (); |
292 } | 277 } |
293 else if (fmt[i] == 'E') | 278 else if (fmt[i] == 'E') |
294 { | 279 { |
295 int j; | 280 int j; |
296 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | 281 for (j = XVECLEN (x, i) - 1; j >= 0; j--) |
297 { | 282 { |
298 VEC_safe_push (char,heap, acc->pathstr, 'a' + j); | 283 acc->pathstr.safe_push ('a' + j); |
299 walk_rtx (XVECEXP (x, i, j), acc); | 284 walk_rtx (info, XVECEXP (x, i, j), acc); |
300 VEC_pop (char, acc->pathstr); | 285 acc->pathstr.pop (); |
301 } | 286 } |
302 } | 287 } |
303 } | 288 } |
304 } | 289 } |
305 | 290 |
338 | 323 |
339 for (i = 0; i < len; i++) | 324 for (i = 0; i < len; i++) |
340 { | 325 { |
341 if (ISLOWER (path[i])) | 326 if (ISLOWER (path[i])) |
342 printf (", 0, %d)", path[i] - 'a'); | 327 printf (", 0, %d)", path[i] - 'a'); |
343 else if (ISDIGIT(path[i])) | 328 else if (ISDIGIT (path[i])) |
344 printf (", %d)", path[i] - '0'); | 329 printf (", %d)", path[i] - '0'); |
345 else | 330 else |
346 gcc_unreachable (); | 331 gcc_unreachable (); |
347 } | 332 } |
348 } | 333 } |
371 whose numbers are skipped by a given pattern. */\n\ | 356 whose numbers are skipped by a given pattern. */\n\ |
372 static rtx junk ATTRIBUTE_UNUSED;\n"); | 357 static rtx junk ATTRIBUTE_UNUSED;\n"); |
373 | 358 |
374 puts ("\ | 359 puts ("\ |
375 void\n\ | 360 void\n\ |
376 insn_extract (rtx insn)\n{\n\ | 361 insn_extract (rtx_insn *insn)\n{\n\ |
377 rtx *ro = recog_data.operand;\n\ | 362 rtx *ro = recog_data.operand;\n\ |
378 rtx **ro_loc = recog_data.operand_loc;\n\ | 363 rtx **ro_loc = recog_data.operand_loc;\n\ |
379 rtx pat = PATTERN (insn);\n\ | 364 rtx pat = PATTERN (insn);\n\ |
380 int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\ | 365 int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\ |
381 \n\ | 366 \n\ |
382 #ifdef ENABLE_CHECKING\n\ | 367 if (flag_checking)\n\ |
383 memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\ | 368 {\n\ |
384 memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\ | 369 memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\ |
385 #endif\n"); | 370 memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\ |
371 }\n"); | |
386 | 372 |
387 puts ("\ | 373 puts ("\ |
388 switch (INSN_CODE (insn))\n\ | 374 switch (INSN_CODE (insn))\n\ |
389 {\n\ | 375 {\n\ |
390 default:\n\ | 376 default:\n\ |
397 else\n\ | 383 else\n\ |
398 fatal_insn (\"insn with invalid code number:\", insn);\n"); | 384 fatal_insn (\"insn with invalid code number:\", insn);\n"); |
399 } | 385 } |
400 | 386 |
401 int | 387 int |
402 main (int argc, char **argv) | 388 main (int argc, const char **argv) |
403 { | 389 { |
404 rtx desc; | |
405 unsigned int i; | 390 unsigned int i; |
406 struct extraction *p; | 391 struct extraction *p; |
407 struct code_ptr *link; | 392 struct code_ptr *link; |
408 const char *name; | 393 const char *name; |
409 int insn_code_number; | |
410 | 394 |
411 progname = "genextract"; | 395 progname = "genextract"; |
412 | 396 |
413 if (!init_rtx_reader_args (argc, argv)) | 397 if (!init_rtx_reader_args (argc, argv)) |
414 return (FATAL_EXIT_CODE); | 398 return (FATAL_EXIT_CODE); |
415 | 399 |
416 /* Read the machine description. */ | 400 /* Read the machine description. */ |
417 | 401 |
418 while ((desc = read_md_rtx (&line_no, &insn_code_number)) != NULL) | 402 md_rtx_info info; |
419 { | 403 while (read_md_rtx (&info)) |
420 if (GET_CODE (desc) == DEFINE_INSN) | 404 switch (GET_CODE (info.def)) |
421 gen_insn (desc, insn_code_number); | 405 { |
422 | 406 case DEFINE_INSN: |
423 else if (GET_CODE (desc) == DEFINE_PEEPHOLE) | 407 gen_insn (&info); |
408 break; | |
409 | |
410 case DEFINE_PEEPHOLE: | |
424 { | 411 { |
425 struct code_ptr *link = XNEW (struct code_ptr); | 412 struct code_ptr *link = XNEW (struct code_ptr); |
426 | 413 |
427 link->insn_code = insn_code_number; | 414 link->insn_code = info.index; |
428 link->next = peepholes; | 415 link->next = peepholes; |
429 peepholes = link; | 416 peepholes = link; |
430 } | 417 } |
418 break; | |
419 | |
420 default: | |
421 break; | |
431 } | 422 } |
432 | 423 |
433 if (have_error) | 424 if (have_error) |
434 return FATAL_EXIT_CODE; | 425 return FATAL_EXIT_CODE; |
435 | 426 |