File: | jdk/src/hotspot/share/adlc/output_c.cpp |
Warning: | line 1106, column 11 Value stored to 'left_op_base' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | // output_c.cpp - Class CPP file output routines for architecture definition |
26 | |
27 | #include "adlc.hpp" |
28 | |
29 | // Utilities to characterize effect statements |
30 | static bool is_def(int usedef) { |
31 | switch(usedef) { |
32 | case Component::DEF: |
33 | case Component::USE_DEF: return true; break; |
34 | } |
35 | return false; |
36 | } |
37 | |
38 | // Define an array containing the machine register names, strings. |
39 | static void defineRegNames(FILE *fp, RegisterForm *registers) { |
40 | if (registers) { |
41 | fprintf(fp,"\n"); |
42 | fprintf(fp,"// An array of character pointers to machine register names.\n"); |
43 | fprintf(fp,"const char *Matcher::regName[REG_COUNT] = {\n"); |
44 | |
45 | // Output the register name for each register in the allocation classes |
46 | RegDef *reg_def = NULL__null; |
47 | RegDef *next = NULL__null; |
48 | registers->reset_RegDefs(); |
49 | for (reg_def = registers->iter_RegDefs(); reg_def != NULL__null; reg_def = next) { |
50 | next = registers->iter_RegDefs(); |
51 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
52 | fprintf(fp," \"%s\"%s\n", reg_def->_regname, comma); |
53 | } |
54 | |
55 | // Finish defining enumeration |
56 | fprintf(fp,"};\n"); |
57 | |
58 | fprintf(fp,"\n"); |
59 | fprintf(fp,"// An array of character pointers to machine register names.\n"); |
60 | fprintf(fp,"const VMReg OptoReg::opto2vm[REG_COUNT] = {\n"); |
61 | reg_def = NULL__null; |
62 | next = NULL__null; |
63 | registers->reset_RegDefs(); |
64 | for (reg_def = registers->iter_RegDefs(); reg_def != NULL__null; reg_def = next) { |
65 | next = registers->iter_RegDefs(); |
66 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
67 | fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma); |
68 | } |
69 | // Finish defining array |
70 | fprintf(fp,"\t};\n"); |
71 | fprintf(fp,"\n"); |
72 | |
73 | fprintf(fp," OptoReg::Name OptoReg::vm2opto[ConcreteRegisterImpl::number_of_registers];\n"); |
74 | |
75 | } |
76 | } |
77 | |
78 | // Define an array containing the machine register encoding values |
79 | static void defineRegEncodes(FILE *fp, RegisterForm *registers) { |
80 | if (registers) { |
81 | fprintf(fp,"\n"); |
82 | fprintf(fp,"// An array of the machine register encode values\n"); |
83 | fprintf(fp,"const unsigned char Matcher::_regEncode[REG_COUNT] = {\n"); |
84 | |
85 | // Output the register encoding for each register in the allocation classes |
86 | RegDef *reg_def = NULL__null; |
87 | RegDef *next = NULL__null; |
88 | registers->reset_RegDefs(); |
89 | for (reg_def = registers->iter_RegDefs(); reg_def != NULL__null; reg_def = next) { |
90 | next = registers->iter_RegDefs(); |
91 | const char* register_encode = reg_def->register_encode(); |
92 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
93 | int encval; |
94 | if (!ADLParser::is_int_token(register_encode, encval)) { |
95 | fprintf(fp," %s%s // %s\n", register_encode, comma, reg_def->_regname); |
96 | } else { |
97 | // Output known constants in hex char format (backward compatibility). |
98 | assert(encval < 256, "Exceeded supported width for register encoding"){ if (!(encval < 256)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 98, "Exceeded supported width for register encoding"); abort (); }}; |
99 | fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", encval, comma, reg_def->_regname); |
100 | } |
101 | } |
102 | // Finish defining enumeration |
103 | fprintf(fp,"};\n"); |
104 | |
105 | } // Done defining array |
106 | } |
107 | |
108 | // Output an enumeration of register class names |
109 | static void defineRegClassEnum(FILE *fp, RegisterForm *registers) { |
110 | if (registers) { |
111 | // Output an enumeration of register class names |
112 | fprintf(fp,"\n"); |
113 | fprintf(fp,"// Enumeration of register class names\n"); |
114 | fprintf(fp, "enum machRegisterClass {\n"); |
115 | registers->_rclasses.reset(); |
116 | for (const char *class_name = NULL__null; (class_name = registers->_rclasses.iter()) != NULL__null;) { |
117 | const char * class_name_to_upper = toUpper(class_name); |
118 | fprintf(fp," %s,\n", class_name_to_upper); |
119 | delete[] class_name_to_upper; |
120 | } |
121 | // Finish defining enumeration |
122 | fprintf(fp, " _last_Mach_Reg_Class\n"); |
123 | fprintf(fp, "};\n"); |
124 | } |
125 | } |
126 | |
127 | // Declare an enumeration of user-defined register classes |
128 | // and a list of register masks, one for each class. |
129 | void ArchDesc::declare_register_masks(FILE *fp_hpp) { |
130 | const char *rc_name; |
131 | |
132 | if (_register) { |
133 | // Build enumeration of user-defined register classes. |
134 | defineRegClassEnum(fp_hpp, _register); |
135 | |
136 | // Generate a list of register masks, one for each class. |
137 | fprintf(fp_hpp,"\n"); |
138 | fprintf(fp_hpp,"// Register masks, one for each register class.\n"); |
139 | _register->_rclasses.reset(); |
140 | for (rc_name = NULL__null; (rc_name = _register->_rclasses.iter()) != NULL__null;) { |
141 | RegClass *reg_class = _register->getRegClass(rc_name); |
142 | assert(reg_class, "Using an undefined register class"){ if (!(reg_class)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 142, "Using an undefined register class"); abort(); }}; |
143 | reg_class->declare_register_masks(fp_hpp); |
144 | } |
145 | } |
146 | } |
147 | |
148 | // Generate an enumeration of user-defined register classes |
149 | // and a list of register masks, one for each class. |
150 | void ArchDesc::build_register_masks(FILE *fp_cpp) { |
151 | const char *rc_name; |
152 | |
153 | if (_register) { |
154 | // Generate a list of register masks, one for each class. |
155 | fprintf(fp_cpp,"\n"); |
156 | fprintf(fp_cpp,"// Register masks, one for each register class.\n"); |
157 | _register->_rclasses.reset(); |
158 | for (rc_name = NULL__null; (rc_name = _register->_rclasses.iter()) != NULL__null;) { |
159 | RegClass *reg_class = _register->getRegClass(rc_name); |
160 | assert(reg_class, "Using an undefined register class"){ if (!(reg_class)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 160, "Using an undefined register class"); abort(); }}; |
161 | reg_class->build_register_masks(fp_cpp); |
162 | } |
163 | } |
164 | } |
165 | |
166 | // Compute an index for an array in the pipeline_reads_NNN arrays |
167 | static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, PipeClassForm *pipeclass) |
168 | { |
169 | int templen = 1; |
170 | int paramcount = 0; |
171 | const char *paramname; |
172 | |
173 | if (pipeclass->_parameters.count() == 0) |
174 | return -1; |
175 | |
176 | pipeclass->_parameters.reset(); |
177 | paramname = pipeclass->_parameters.iter(); |
178 | const PipeClassOperandForm *pipeopnd = |
179 | (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; |
180 | if (pipeopnd && !pipeopnd->isWrite() && strcmp(pipeopnd->_stage, "Universal")) |
181 | pipeclass->_parameters.reset(); |
182 | |
183 | while ( (paramname = pipeclass->_parameters.iter()) != NULL__null ) { |
184 | const PipeClassOperandForm *tmppipeopnd = |
185 | (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; |
186 | |
187 | if (tmppipeopnd) |
188 | templen += 10 + (int)strlen(tmppipeopnd->_stage); |
189 | else |
190 | templen += 19; |
191 | |
192 | paramcount++; |
193 | } |
194 | |
195 | // See if the count is zero |
196 | if (paramcount == 0) { |
197 | return -1; |
198 | } |
199 | |
200 | char *operand_stages = new char [templen]; |
201 | operand_stages[0] = 0; |
202 | int i = 0; |
203 | templen = 0; |
204 | |
205 | pipeclass->_parameters.reset(); |
206 | paramname = pipeclass->_parameters.iter(); |
207 | pipeopnd = (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; |
208 | if (pipeopnd && !pipeopnd->isWrite() && strcmp(pipeopnd->_stage, "Universal")) |
209 | pipeclass->_parameters.reset(); |
210 | |
211 | while ( (paramname = pipeclass->_parameters.iter()) != NULL__null ) { |
212 | const PipeClassOperandForm *tmppipeopnd = |
213 | (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; |
214 | templen += sprintf(&operand_stages[templen], " stage_%s%c\n", |
215 | tmppipeopnd ? tmppipeopnd->_stage : "undefined", |
216 | (++i < paramcount ? ',' : ' ') ); |
217 | } |
218 | |
219 | // See if the same string is in the table |
220 | int ndx = pipeline_reads.index(operand_stages); |
221 | |
222 | // No, add it to the table |
223 | if (ndx < 0) { |
224 | pipeline_reads.addName(operand_stages); |
225 | ndx = pipeline_reads.index(operand_stages); |
226 | |
227 | fprintf(fp_cpp, "static const enum machPipelineStages pipeline_reads_%03d[%d] = {\n%s};\n\n", |
228 | ndx+1, paramcount, operand_stages); |
229 | } |
230 | else |
231 | delete [] operand_stages; |
232 | |
233 | return (ndx); |
234 | } |
235 | |
236 | // Compute an index for an array in the pipeline_res_stages_NNN arrays |
237 | static int pipeline_res_stages_initializer( |
238 | FILE *fp_cpp, |
239 | PipelineForm *pipeline, |
240 | NameList &pipeline_res_stages, |
241 | PipeClassForm *pipeclass) |
242 | { |
243 | const PipeClassResourceForm *piperesource; |
244 | int * res_stages = new int [pipeline->_rescount]; |
245 | int i; |
246 | |
247 | for (i = 0; i < pipeline->_rescount; i++) |
248 | res_stages[i] = 0; |
249 | |
250 | for (pipeclass->_resUsage.reset(); |
251 | (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL__null; ) { |
252 | int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); |
253 | for (i = 0; i < pipeline->_rescount; i++) |
254 | if ((1 << i) & used_mask) { |
255 | int stage = pipeline->_stages.index(piperesource->_stage); |
256 | if (res_stages[i] < stage+1) |
257 | res_stages[i] = stage+1; |
258 | } |
259 | } |
260 | |
261 | // Compute the length needed for the resource list |
262 | int commentlen = 0; |
263 | int max_stage = 0; |
264 | for (i = 0; i < pipeline->_rescount; i++) { |
265 | if (res_stages[i] == 0) { |
266 | if (max_stage < 9) |
267 | max_stage = 9; |
268 | } |
269 | else { |
270 | int stagelen = (int)strlen(pipeline->_stages.name(res_stages[i]-1)); |
271 | if (max_stage < stagelen) |
272 | max_stage = stagelen; |
273 | } |
274 | |
275 | commentlen += (int)strlen(pipeline->_reslist.name(i)); |
276 | } |
277 | |
278 | int templen = 1 + commentlen + pipeline->_rescount * (max_stage + 14); |
279 | |
280 | // Allocate space for the resource list |
281 | char * resource_stages = new char [templen]; |
282 | |
283 | templen = 0; |
284 | for (i = 0; i < pipeline->_rescount; i++) { |
285 | const char * const resname = |
286 | res_stages[i] == 0 ? "undefined" : pipeline->_stages.name(res_stages[i]-1); |
287 | |
288 | templen += sprintf(&resource_stages[templen], " stage_%s%-*s // %s\n", |
289 | resname, max_stage - (int)strlen(resname) + 1, |
290 | (i < pipeline->_rescount-1) ? "," : "", |
291 | pipeline->_reslist.name(i)); |
292 | } |
293 | |
294 | // See if the same string is in the table |
295 | int ndx = pipeline_res_stages.index(resource_stages); |
296 | |
297 | // No, add it to the table |
298 | if (ndx < 0) { |
299 | pipeline_res_stages.addName(resource_stages); |
300 | ndx = pipeline_res_stages.index(resource_stages); |
301 | |
302 | fprintf(fp_cpp, "static const enum machPipelineStages pipeline_res_stages_%03d[%d] = {\n%s};\n\n", |
303 | ndx+1, pipeline->_rescount, resource_stages); |
304 | } |
305 | else |
306 | delete [] resource_stages; |
307 | |
308 | delete [] res_stages; |
309 | |
310 | return (ndx); |
311 | } |
312 | |
313 | // Compute an index for an array in the pipeline_res_cycles_NNN arrays |
314 | static int pipeline_res_cycles_initializer( |
315 | FILE *fp_cpp, |
316 | PipelineForm *pipeline, |
317 | NameList &pipeline_res_cycles, |
318 | PipeClassForm *pipeclass) |
319 | { |
320 | const PipeClassResourceForm *piperesource; |
321 | int * res_cycles = new int [pipeline->_rescount]; |
322 | int i; |
323 | |
324 | for (i = 0; i < pipeline->_rescount; i++) |
325 | res_cycles[i] = 0; |
326 | |
327 | for (pipeclass->_resUsage.reset(); |
328 | (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL__null; ) { |
329 | int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); |
330 | for (i = 0; i < pipeline->_rescount; i++) |
331 | if ((1 << i) & used_mask) { |
332 | int cycles = piperesource->_cycles; |
333 | if (res_cycles[i] < cycles) |
334 | res_cycles[i] = cycles; |
335 | } |
336 | } |
337 | |
338 | // Pre-compute the string length |
339 | int templen; |
340 | int cyclelen = 0, commentlen = 0; |
341 | int max_cycles = 0; |
342 | char temp[32]; |
343 | |
344 | for (i = 0; i < pipeline->_rescount; i++) { |
345 | if (max_cycles < res_cycles[i]) |
346 | max_cycles = res_cycles[i]; |
347 | templen = sprintf(temp, "%d", res_cycles[i]); |
348 | if (cyclelen < templen) |
349 | cyclelen = templen; |
350 | commentlen += (int)strlen(pipeline->_reslist.name(i)); |
351 | } |
352 | |
353 | templen = 1 + commentlen + (cyclelen + 8) * pipeline->_rescount; |
354 | |
355 | // Allocate space for the resource list |
356 | char * resource_cycles = new char [templen]; |
357 | |
358 | templen = 0; |
359 | |
360 | for (i = 0; i < pipeline->_rescount; i++) { |
361 | templen += sprintf(&resource_cycles[templen], " %*d%c // %s\n", |
362 | cyclelen, res_cycles[i], (i < pipeline->_rescount-1) ? ',' : ' ', pipeline->_reslist.name(i)); |
363 | } |
364 | |
365 | // See if the same string is in the table |
366 | int ndx = pipeline_res_cycles.index(resource_cycles); |
367 | |
368 | // No, add it to the table |
369 | if (ndx < 0) { |
370 | pipeline_res_cycles.addName(resource_cycles); |
371 | ndx = pipeline_res_cycles.index(resource_cycles); |
372 | |
373 | fprintf(fp_cpp, "static const uint pipeline_res_cycles_%03d[%d] = {\n%s};\n\n", |
374 | ndx+1, pipeline->_rescount, resource_cycles); |
375 | } |
376 | else |
377 | delete [] resource_cycles; |
378 | |
379 | delete [] res_cycles; |
380 | |
381 | return (ndx); |
382 | } |
383 | |
384 | //typedef unsigned long long uint64_t; |
385 | |
386 | // Compute an index for an array in the pipeline_res_mask_NNN arrays |
387 | static int pipeline_res_mask_initializer( |
388 | FILE *fp_cpp, |
389 | PipelineForm *pipeline, |
390 | NameList &pipeline_res_mask, |
391 | NameList &pipeline_res_args, |
392 | PipeClassForm *pipeclass) |
393 | { |
394 | const PipeClassResourceForm *piperesource; |
395 | const uintunsigned int rescount = pipeline->_rescount; |
396 | const uintunsigned int maxcycleused = pipeline->_maxcycleused; |
397 | const uintunsigned int cyclemasksize = (maxcycleused + 31) >> 5; |
398 | |
399 | int i, j; |
400 | int element_count = 0; |
401 | uintunsigned int *res_mask = new uintunsigned int [cyclemasksize]; |
402 | uintunsigned int resources_used = 0; |
403 | uintunsigned int resources_used_exclusively = 0; |
404 | |
405 | for (pipeclass->_resUsage.reset(); |
406 | (piperesource = (const PipeClassResourceForm*)pipeclass->_resUsage.iter()) != NULL__null; ) { |
407 | element_count++; |
408 | } |
409 | |
410 | // Pre-compute the string length |
411 | int templen; |
412 | int commentlen = 0; |
413 | int max_cycles = 0; |
414 | |
415 | int cyclelen = ((maxcycleused + 3) >> 2); |
416 | int masklen = (rescount + 3) >> 2; |
417 | |
418 | int cycledigit = 0; |
419 | for (i = maxcycleused; i > 0; i /= 10) |
420 | cycledigit++; |
421 | |
422 | int maskdigit = 0; |
423 | for (i = rescount; i > 0; i /= 10) |
424 | maskdigit++; |
425 | |
426 | static const char* pipeline_use_cycle_mask = "Pipeline_Use_Cycle_Mask"; |
427 | static const char* pipeline_use_element = "Pipeline_Use_Element"; |
428 | |
429 | templen = 1 + |
430 | (int)(strlen(pipeline_use_cycle_mask) + (int)strlen(pipeline_use_element) + |
431 | (cyclemasksize * 12) + masklen + (cycledigit * 2) + 30) * element_count; |
432 | |
433 | // Allocate space for the resource list |
434 | char * resource_mask = new char [templen]; |
435 | char * last_comma = NULL__null; |
436 | |
437 | templen = 0; |
438 | |
439 | for (pipeclass->_resUsage.reset(); |
440 | (piperesource = (const PipeClassResourceForm*)pipeclass->_resUsage.iter()) != NULL__null; ) { |
441 | int used_mask = pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); |
442 | |
443 | if (!used_mask) { |
444 | fprintf(stderrstderr, "*** used_mask is 0 ***\n"); |
445 | } |
446 | |
447 | resources_used |= used_mask; |
448 | |
449 | uintunsigned int lb, ub; |
450 | |
451 | for (lb = 0; (used_mask & (1 << lb)) == 0; lb++); |
452 | for (ub = 31; (used_mask & (1 << ub)) == 0; ub--); |
453 | |
454 | if (lb == ub) { |
455 | resources_used_exclusively |= used_mask; |
456 | } |
457 | |
458 | int formatlen = |
459 | sprintf(&resource_mask[templen], " %s(0x%0*x, %*d, %*d, %s %s(", |
460 | pipeline_use_element, |
461 | masklen, used_mask, |
462 | cycledigit, lb, cycledigit, ub, |
463 | ((used_mask & (used_mask-1)) != 0) ? "true, " : "false,", |
464 | pipeline_use_cycle_mask); |
465 | |
466 | templen += formatlen; |
467 | |
468 | memset(res_mask, 0, cyclemasksize * sizeof(uintunsigned int)); |
469 | |
470 | int cycles = piperesource->_cycles; |
471 | uintunsigned int stage = pipeline->_stages.index(piperesource->_stage); |
472 | if ((uintunsigned int)NameList::Not_in_list == stage) { |
473 | fprintf(stderrstderr, |
474 | "pipeline_res_mask_initializer: " |
475 | "semantic error: " |
476 | "pipeline stage undeclared: %s\n", |
477 | piperesource->_stage); |
478 | exit(1); |
479 | } |
480 | uintunsigned int upper_limit = stage + cycles - 1; |
481 | uintunsigned int lower_limit = stage - 1; |
482 | uintunsigned int upper_idx = upper_limit >> 5; |
483 | uintunsigned int lower_idx = lower_limit >> 5; |
484 | uintunsigned int upper_position = upper_limit & 0x1f; |
485 | uintunsigned int lower_position = lower_limit & 0x1f; |
486 | |
487 | uintunsigned int mask = (((uintunsigned int)1) << upper_position) - 1; |
488 | |
489 | while (upper_idx > lower_idx) { |
490 | res_mask[upper_idx--] |= mask; |
491 | mask = (uintunsigned int)-1; |
492 | } |
493 | |
494 | mask -= (((uintunsigned int)1) << lower_position) - 1; |
495 | res_mask[upper_idx] |= mask; |
496 | |
497 | for (j = cyclemasksize-1; j >= 0; j--) { |
498 | formatlen = |
499 | sprintf(&resource_mask[templen], "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); |
500 | templen += formatlen; |
501 | } |
502 | |
503 | resource_mask[templen++] = ')'; |
504 | resource_mask[templen++] = ')'; |
505 | last_comma = &resource_mask[templen]; |
506 | resource_mask[templen++] = ','; |
507 | resource_mask[templen++] = '\n'; |
508 | } |
509 | |
510 | resource_mask[templen] = 0; |
511 | if (last_comma) { |
512 | last_comma[0] = ' '; |
513 | } |
514 | |
515 | // See if the same string is in the table |
516 | int ndx = pipeline_res_mask.index(resource_mask); |
517 | |
518 | // No, add it to the table |
519 | if (ndx < 0) { |
520 | pipeline_res_mask.addName(resource_mask); |
521 | ndx = pipeline_res_mask.index(resource_mask); |
522 | |
523 | if (strlen(resource_mask) > 0) |
524 | fprintf(fp_cpp, "static const Pipeline_Use_Element pipeline_res_mask_%03d[%d] = {\n%s};\n\n", |
525 | ndx+1, element_count, resource_mask); |
526 | |
527 | char* args = new char [9 + 2*masklen + maskdigit]; |
528 | |
529 | sprintf(args, "0x%0*x, 0x%0*x, %*d", |
530 | masklen, resources_used, |
531 | masklen, resources_used_exclusively, |
532 | maskdigit, element_count); |
533 | |
534 | pipeline_res_args.addName(args); |
535 | } |
536 | else { |
537 | delete [] resource_mask; |
538 | } |
539 | |
540 | delete [] res_mask; |
541 | //delete [] res_masks; |
542 | |
543 | return (ndx); |
544 | } |
545 | |
546 | void ArchDesc::build_pipe_classes(FILE *fp_cpp) { |
547 | const char *classname; |
548 | const char *resourcename; |
549 | int resourcenamelen = 0; |
550 | NameList pipeline_reads; |
551 | NameList pipeline_res_stages; |
552 | NameList pipeline_res_cycles; |
553 | NameList pipeline_res_masks; |
554 | NameList pipeline_res_args; |
555 | const int default_latency = 1; |
556 | const int non_operand_latency = 0; |
557 | const int node_latency = 0; |
558 | |
559 | if (!_pipeline) { |
560 | fprintf(fp_cpp, "uint Node::latency(uint i) const {\n"); |
561 | fprintf(fp_cpp, " // assert(false, \"pipeline functionality is not defined\");\n"); |
562 | fprintf(fp_cpp, " return %d;\n", non_operand_latency); |
563 | fprintf(fp_cpp, "}\n"); |
564 | return; |
565 | } |
566 | |
567 | fprintf(fp_cpp, "\n"); |
568 | fprintf(fp_cpp, "//------------------Pipeline Methods-----------------------------------------\n"); |
569 | fprintf(fp_cpp, "#ifndef PRODUCT\n"); |
570 | fprintf(fp_cpp, "const char * Pipeline::stageName(uint s) {\n"); |
571 | fprintf(fp_cpp, " static const char * const _stage_names[] = {\n"); |
572 | fprintf(fp_cpp, " \"undefined\""); |
573 | |
574 | for (int s = 0; s < _pipeline->_stagecnt; s++) |
575 | fprintf(fp_cpp, ", \"%s\"", _pipeline->_stages.name(s)); |
576 | |
577 | fprintf(fp_cpp, "\n };\n\n"); |
578 | fprintf(fp_cpp, " return (s <= %d ? _stage_names[s] : \"???\");\n", |
579 | _pipeline->_stagecnt); |
580 | fprintf(fp_cpp, "}\n"); |
581 | fprintf(fp_cpp, "#endif\n\n"); |
582 | |
583 | fprintf(fp_cpp, "uint Pipeline::functional_unit_latency(uint start, const Pipeline *pred) const {\n"); |
584 | fprintf(fp_cpp, " // See if the functional units overlap\n"); |
585 | #if 0 |
586 | fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); |
587 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
588 | fprintf(fp_cpp, " tty->print(\"# functional_unit_latency: start == %%d, this->exclusively == 0x%%03x, pred->exclusively == 0x%%03x\\n\", start, resourcesUsedExclusively(), pred->resourcesUsedExclusively());\n"); |
589 | fprintf(fp_cpp, " }\n"); |
590 | fprintf(fp_cpp, "#endif\n\n"); |
591 | #endif |
592 | fprintf(fp_cpp, " uint mask = resourcesUsedExclusively() & pred->resourcesUsedExclusively();\n"); |
593 | fprintf(fp_cpp, " if (mask == 0)\n return (start);\n\n"); |
594 | #if 0 |
595 | fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); |
596 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
597 | fprintf(fp_cpp, " tty->print(\"# functional_unit_latency: mask == 0x%%x\\n\", mask);\n"); |
598 | fprintf(fp_cpp, " }\n"); |
599 | fprintf(fp_cpp, "#endif\n\n"); |
600 | #endif |
601 | fprintf(fp_cpp, " for (uint i = 0; i < pred->resourceUseCount(); i++) {\n"); |
602 | fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred->resourceUseElement(i);\n"); |
603 | fprintf(fp_cpp, " if (predUse->multiple())\n"); |
604 | fprintf(fp_cpp, " continue;\n\n"); |
605 | fprintf(fp_cpp, " for (uint j = 0; j < resourceUseCount(); j++) {\n"); |
606 | fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = resourceUseElement(j);\n"); |
607 | fprintf(fp_cpp, " if (currUse->multiple())\n"); |
608 | fprintf(fp_cpp, " continue;\n\n"); |
609 | fprintf(fp_cpp, " if (predUse->used() & currUse->used()) {\n"); |
610 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->mask();\n"); |
611 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->mask();\n\n"); |
612 | fprintf(fp_cpp, " for ( y <<= start; x.overlaps(y); start++ )\n"); |
613 | fprintf(fp_cpp, " y <<= 1;\n"); |
614 | fprintf(fp_cpp, " }\n"); |
615 | fprintf(fp_cpp, " }\n"); |
616 | fprintf(fp_cpp, " }\n\n"); |
617 | fprintf(fp_cpp, " // There is the potential for overlap\n"); |
618 | fprintf(fp_cpp, " return (start);\n"); |
619 | fprintf(fp_cpp, "}\n\n"); |
620 | fprintf(fp_cpp, "// The following two routines assume that the root Pipeline_Use entity\n"); |
621 | fprintf(fp_cpp, "// consists of exactly 1 element for each functional unit\n"); |
622 | fprintf(fp_cpp, "// start is relative to the current cycle; used for latency-based info\n"); |
623 | fprintf(fp_cpp, "uint Pipeline_Use::full_latency(uint delay, const Pipeline_Use &pred) const {\n"); |
624 | fprintf(fp_cpp, " for (uint i = 0; i < pred._count; i++) {\n"); |
625 | fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred.element(i);\n"); |
626 | fprintf(fp_cpp, " if (predUse->_multiple) {\n"); |
627 | fprintf(fp_cpp, " uint min_delay = %d;\n", |
628 | _pipeline->_maxcycleused+1); |
629 | fprintf(fp_cpp, " // Multiple possible functional units, choose first unused one\n"); |
630 | fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); |
631 | fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = element(j);\n"); |
632 | fprintf(fp_cpp, " uint curr_delay = delay;\n"); |
633 | fprintf(fp_cpp, " if (predUse->_used & currUse->_used) {\n"); |
634 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->_mask;\n"); |
635 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->_mask;\n\n"); |
636 | fprintf(fp_cpp, " for ( y <<= curr_delay; x.overlaps(y); curr_delay++ )\n"); |
637 | fprintf(fp_cpp, " y <<= 1;\n"); |
638 | fprintf(fp_cpp, " }\n"); |
639 | fprintf(fp_cpp, " if (min_delay > curr_delay)\n min_delay = curr_delay;\n"); |
640 | fprintf(fp_cpp, " }\n"); |
641 | fprintf(fp_cpp, " if (delay < min_delay)\n delay = min_delay;\n"); |
642 | fprintf(fp_cpp, " }\n"); |
643 | fprintf(fp_cpp, " else {\n"); |
644 | fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); |
645 | fprintf(fp_cpp, " const Pipeline_Use_Element *currUse = element(j);\n"); |
646 | fprintf(fp_cpp, " if (predUse->_used & currUse->_used) {\n"); |
647 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask x = predUse->_mask;\n"); |
648 | fprintf(fp_cpp, " Pipeline_Use_Cycle_Mask y = currUse->_mask;\n\n"); |
649 | fprintf(fp_cpp, " for ( y <<= delay; x.overlaps(y); delay++ )\n"); |
650 | fprintf(fp_cpp, " y <<= 1;\n"); |
651 | fprintf(fp_cpp, " }\n"); |
652 | fprintf(fp_cpp, " }\n"); |
653 | fprintf(fp_cpp, " }\n"); |
654 | fprintf(fp_cpp, " }\n\n"); |
655 | fprintf(fp_cpp, " return (delay);\n"); |
656 | fprintf(fp_cpp, "}\n\n"); |
657 | fprintf(fp_cpp, "void Pipeline_Use::add_usage(const Pipeline_Use &pred) {\n"); |
658 | fprintf(fp_cpp, " for (uint i = 0; i < pred._count; i++) {\n"); |
659 | fprintf(fp_cpp, " const Pipeline_Use_Element *predUse = pred.element(i);\n"); |
660 | fprintf(fp_cpp, " if (predUse->_multiple) {\n"); |
661 | fprintf(fp_cpp, " // Multiple possible functional units, choose first unused one\n"); |
662 | fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); |
663 | fprintf(fp_cpp, " Pipeline_Use_Element *currUse = element(j);\n"); |
664 | fprintf(fp_cpp, " if ( !predUse->_mask.overlaps(currUse->_mask) ) {\n"); |
665 | fprintf(fp_cpp, " currUse->_used |= (1 << j);\n"); |
666 | fprintf(fp_cpp, " _resources_used |= (1 << j);\n"); |
667 | fprintf(fp_cpp, " currUse->_mask.Or(predUse->_mask);\n"); |
668 | fprintf(fp_cpp, " break;\n"); |
669 | fprintf(fp_cpp, " }\n"); |
670 | fprintf(fp_cpp, " }\n"); |
671 | fprintf(fp_cpp, " }\n"); |
672 | fprintf(fp_cpp, " else {\n"); |
673 | fprintf(fp_cpp, " for (uint j = predUse->_lb; j <= predUse->_ub; j++) {\n"); |
674 | fprintf(fp_cpp, " Pipeline_Use_Element *currUse = element(j);\n"); |
675 | fprintf(fp_cpp, " currUse->_used |= (1 << j);\n"); |
676 | fprintf(fp_cpp, " _resources_used |= (1 << j);\n"); |
677 | fprintf(fp_cpp, " currUse->_mask.Or(predUse->_mask);\n"); |
678 | fprintf(fp_cpp, " }\n"); |
679 | fprintf(fp_cpp, " }\n"); |
680 | fprintf(fp_cpp, " }\n"); |
681 | fprintf(fp_cpp, "}\n\n"); |
682 | |
683 | fprintf(fp_cpp, "uint Pipeline::operand_latency(uint opnd, const Pipeline *pred) const {\n"); |
684 | fprintf(fp_cpp, " int const default_latency = 1;\n"); |
685 | fprintf(fp_cpp, "\n"); |
686 | #if 0 |
687 | fprintf(fp_cpp, "#ifndef PRODUCT\n"); |
688 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
689 | fprintf(fp_cpp, " tty->print(\"# operand_latency(%%d), _read_stage_count = %%d\\n\", opnd, _read_stage_count);\n"); |
690 | fprintf(fp_cpp, " }\n"); |
691 | fprintf(fp_cpp, "#endif\n\n"); |
692 | #endif |
693 | fprintf(fp_cpp, " assert(this, \"NULL pipeline info\");\n"); |
694 | fprintf(fp_cpp, " assert(pred, \"NULL predecessor pipline info\");\n\n"); |
695 | fprintf(fp_cpp, " if (pred->hasFixedLatency())\n return (pred->fixedLatency());\n\n"); |
696 | fprintf(fp_cpp, " // If this is not an operand, then assume a dependence with 0 latency\n"); |
697 | fprintf(fp_cpp, " if (opnd > _read_stage_count)\n return (0);\n\n"); |
698 | fprintf(fp_cpp, " uint writeStage = pred->_write_stage;\n"); |
699 | fprintf(fp_cpp, " uint readStage = _read_stages[opnd-1];\n"); |
700 | #if 0 |
701 | fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); |
702 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
703 | fprintf(fp_cpp, " tty->print(\"# operand_latency: writeStage=%%s readStage=%%s, opnd=%%d\\n\", stageName(writeStage), stageName(readStage), opnd);\n"); |
704 | fprintf(fp_cpp, " }\n"); |
705 | fprintf(fp_cpp, "#endif\n\n"); |
706 | #endif |
707 | fprintf(fp_cpp, "\n"); |
708 | fprintf(fp_cpp, " if (writeStage == stage_undefined || readStage == stage_undefined)\n"); |
709 | fprintf(fp_cpp, " return (default_latency);\n"); |
710 | fprintf(fp_cpp, "\n"); |
711 | fprintf(fp_cpp, " int delta = writeStage - readStage;\n"); |
712 | fprintf(fp_cpp, " if (delta < 0) delta = 0;\n\n"); |
713 | #if 0 |
714 | fprintf(fp_cpp, "\n#ifndef PRODUCT\n"); |
715 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
716 | fprintf(fp_cpp, " tty->print(\"# operand_latency: delta=%%d\\n\", delta);\n"); |
717 | fprintf(fp_cpp, " }\n"); |
718 | fprintf(fp_cpp, "#endif\n\n"); |
719 | #endif |
720 | fprintf(fp_cpp, " return (delta);\n"); |
721 | fprintf(fp_cpp, "}\n\n"); |
722 | |
723 | if (!_pipeline) |
724 | /* Do Nothing */; |
725 | |
726 | else if (_pipeline->_maxcycleused <= 32) { |
727 | fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); |
728 | fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask(in1._mask & in2._mask);\n"); |
729 | fprintf(fp_cpp, "}\n\n"); |
730 | fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); |
731 | fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask(in1._mask | in2._mask);\n"); |
732 | fprintf(fp_cpp, "}\n\n"); |
733 | } |
734 | else { |
735 | uintunsigned int l; |
736 | uintunsigned int masklen = (_pipeline->_maxcycleused + 31) >> 5; |
737 | fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); |
738 | fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask("); |
739 | for (l = 1; l <= masklen; l++) |
740 | fprintf(fp_cpp, "in1._mask%d & in2._mask%d%s\n", l, l, l < masklen ? ", " : ""); |
741 | fprintf(fp_cpp, ");\n"); |
742 | fprintf(fp_cpp, "}\n\n"); |
743 | fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n"); |
744 | fprintf(fp_cpp, " return Pipeline_Use_Cycle_Mask("); |
745 | for (l = 1; l <= masklen; l++) |
746 | fprintf(fp_cpp, "in1._mask%d | in2._mask%d%s", l, l, l < masklen ? ", " : ""); |
747 | fprintf(fp_cpp, ");\n"); |
748 | fprintf(fp_cpp, "}\n\n"); |
749 | fprintf(fp_cpp, "void Pipeline_Use_Cycle_Mask::Or(const Pipeline_Use_Cycle_Mask &in2) {\n "); |
750 | for (l = 1; l <= masklen; l++) |
751 | fprintf(fp_cpp, " _mask%d |= in2._mask%d;", l, l); |
752 | fprintf(fp_cpp, "\n}\n\n"); |
753 | } |
754 | |
755 | /* Get the length of all the resource names */ |
756 | for (_pipeline->_reslist.reset(), resourcenamelen = 0; |
757 | (resourcename = _pipeline->_reslist.iter()) != NULL__null; |
758 | resourcenamelen += (int)strlen(resourcename)); |
759 | |
760 | // Create the pipeline class description |
761 | |
762 | fprintf(fp_cpp, "static const Pipeline pipeline_class_Zero_Instructions(0, 0, true, 0, 0, false, false, false, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n"); |
763 | fprintf(fp_cpp, "static const Pipeline pipeline_class_Unknown_Instructions(0, 0, true, 0, 0, false, true, true, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n"); |
764 | |
765 | fprintf(fp_cpp, "const Pipeline_Use_Element Pipeline_Use::elaborated_elements[%d] = {\n", _pipeline->_rescount); |
766 | for (int i1 = 0; i1 < _pipeline->_rescount; i1++) { |
767 | fprintf(fp_cpp, " Pipeline_Use_Element(0, %d, %d, false, Pipeline_Use_Cycle_Mask(", i1, i1); |
768 | uintunsigned int masklen = (_pipeline->_maxcycleused + 31) >> 5; |
769 | for (int i2 = masklen-1; i2 >= 0; i2--) |
770 | fprintf(fp_cpp, "0%s", i2 > 0 ? ", " : ""); |
771 | fprintf(fp_cpp, "))%s\n", i1 < (_pipeline->_rescount-1) ? "," : ""); |
772 | } |
773 | fprintf(fp_cpp, "};\n\n"); |
774 | |
775 | fprintf(fp_cpp, "const Pipeline_Use Pipeline_Use::elaborated_use(0, 0, %d, (Pipeline_Use_Element *)&elaborated_elements[0]);\n\n", |
776 | _pipeline->_rescount); |
777 | |
778 | for (_pipeline->_classlist.reset(); (classname = _pipeline->_classlist.iter()) != NULL__null; ) { |
779 | fprintf(fp_cpp, "\n"); |
780 | fprintf(fp_cpp, "// Pipeline Class \"%s\"\n", classname); |
781 | PipeClassForm *pipeclass = _pipeline->_classdict[classname]->is_pipeclass(); |
782 | int maxWriteStage = -1; |
783 | int maxMoreInstrs = 0; |
784 | int paramcount = 0; |
785 | int i = 0; |
786 | const char *paramname; |
787 | int resource_count = (_pipeline->_rescount + 3) >> 2; |
788 | |
789 | // Scan the operands, looking for last output stage and number of inputs |
790 | for (pipeclass->_parameters.reset(); (paramname = pipeclass->_parameters.iter()) != NULL__null; ) { |
791 | const PipeClassOperandForm *pipeopnd = |
792 | (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; |
793 | if (pipeopnd) { |
794 | if (pipeopnd->_iswrite) { |
795 | int stagenum = _pipeline->_stages.index(pipeopnd->_stage); |
796 | int moreinsts = pipeopnd->_more_instrs; |
797 | if ((maxWriteStage+maxMoreInstrs) < (stagenum+moreinsts)) { |
798 | maxWriteStage = stagenum; |
799 | maxMoreInstrs = moreinsts; |
800 | } |
801 | } |
802 | } |
803 | |
804 | if (i++ > 0 || (pipeopnd && !pipeopnd->isWrite())) |
805 | paramcount++; |
806 | } |
807 | |
808 | // Create the list of stages for the operands that are read |
809 | // Note that we will build a NameList to reduce the number of copies |
810 | |
811 | int pipeline_reads_index = pipeline_reads_initializer(fp_cpp, pipeline_reads, pipeclass); |
812 | |
813 | int pipeline_res_stages_index = pipeline_res_stages_initializer( |
814 | fp_cpp, _pipeline, pipeline_res_stages, pipeclass); |
815 | |
816 | int pipeline_res_cycles_index = pipeline_res_cycles_initializer( |
817 | fp_cpp, _pipeline, pipeline_res_cycles, pipeclass); |
818 | |
819 | int pipeline_res_mask_index = pipeline_res_mask_initializer( |
820 | fp_cpp, _pipeline, pipeline_res_masks, pipeline_res_args, pipeclass); |
821 | |
822 | #if 0 |
823 | // Process the Resources |
824 | const PipeClassResourceForm *piperesource; |
825 | |
826 | unsigned resources_used = 0; |
827 | unsigned exclusive_resources_used = 0; |
828 | unsigned resource_groups = 0; |
829 | for (pipeclass->_resUsage.reset(); |
830 | (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL__null; ) { |
831 | int used_mask = _pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); |
832 | if (used_mask) |
833 | resource_groups++; |
834 | resources_used |= used_mask; |
835 | if ((used_mask & (used_mask-1)) == 0) |
836 | exclusive_resources_used |= used_mask; |
837 | } |
838 | |
839 | if (resource_groups > 0) { |
840 | fprintf(fp_cpp, "static const uint pipeline_res_or_masks_%03d[%d] = {", |
841 | pipeclass->_num, resource_groups); |
842 | for (pipeclass->_resUsage.reset(), i = 1; |
843 | (piperesource = (const PipeClassResourceForm *)pipeclass->_resUsage.iter()) != NULL__null; |
844 | i++ ) { |
845 | int used_mask = _pipeline->_resdict[piperesource->_resource]->is_resource()->mask(); |
846 | if (used_mask) { |
847 | fprintf(fp_cpp, " 0x%0*x%c", resource_count, used_mask, i < (int)resource_groups ? ',' : ' '); |
848 | } |
849 | } |
850 | fprintf(fp_cpp, "};\n\n"); |
851 | } |
852 | #endif |
853 | |
854 | // Create the pipeline class description |
855 | fprintf(fp_cpp, "static const Pipeline pipeline_class_%03d(", |
856 | pipeclass->_num); |
857 | if (maxWriteStage < 0) |
858 | fprintf(fp_cpp, "(uint)stage_undefined"); |
859 | else if (maxMoreInstrs == 0) |
860 | fprintf(fp_cpp, "(uint)stage_%s", _pipeline->_stages.name(maxWriteStage)); |
861 | else |
862 | fprintf(fp_cpp, "((uint)stage_%s)+%d", _pipeline->_stages.name(maxWriteStage), maxMoreInstrs); |
863 | fprintf(fp_cpp, ", %d, %s, %d, %d, %s, %s, %s, %s,\n", |
864 | paramcount, |
865 | pipeclass->hasFixedLatency() ? "true" : "false", |
866 | pipeclass->fixedLatency(), |
867 | pipeclass->InstructionCount(), |
868 | pipeclass->hasBranchDelay() ? "true" : "false", |
869 | pipeclass->hasMultipleBundles() ? "true" : "false", |
870 | pipeclass->forceSerialization() ? "true" : "false", |
871 | pipeclass->mayHaveNoCode() ? "true" : "false" ); |
872 | if (paramcount > 0) { |
873 | fprintf(fp_cpp, "\n (enum machPipelineStages * const) pipeline_reads_%03d,\n ", |
874 | pipeline_reads_index+1); |
875 | } |
876 | else |
877 | fprintf(fp_cpp, " NULL,"); |
878 | fprintf(fp_cpp, " (enum machPipelineStages * const) pipeline_res_stages_%03d,\n", |
879 | pipeline_res_stages_index+1); |
880 | fprintf(fp_cpp, " (uint * const) pipeline_res_cycles_%03d,\n", |
881 | pipeline_res_cycles_index+1); |
882 | fprintf(fp_cpp, " Pipeline_Use(%s, (Pipeline_Use_Element *)", |
883 | pipeline_res_args.name(pipeline_res_mask_index)); |
884 | if (strlen(pipeline_res_masks.name(pipeline_res_mask_index)) > 0) |
885 | fprintf(fp_cpp, "&pipeline_res_mask_%03d[0]", |
886 | pipeline_res_mask_index+1); |
887 | else |
888 | fprintf(fp_cpp, "NULL"); |
889 | fprintf(fp_cpp, "));\n"); |
890 | } |
891 | |
892 | // Generate the Node::latency method if _pipeline defined |
893 | fprintf(fp_cpp, "\n"); |
894 | fprintf(fp_cpp, "//------------------Inter-Instruction Latency--------------------------------\n"); |
895 | fprintf(fp_cpp, "uint Node::latency(uint i) {\n"); |
896 | if (_pipeline) { |
897 | #if 0 |
898 | fprintf(fp_cpp, "#ifndef PRODUCT\n"); |
899 | fprintf(fp_cpp, " if (TraceOptoOutput) {\n"); |
900 | fprintf(fp_cpp, " tty->print(\"# %%4d->latency(%%d)\\n\", _idx, i);\n"); |
901 | fprintf(fp_cpp, " }\n"); |
902 | fprintf(fp_cpp, "#endif\n"); |
903 | #endif |
904 | fprintf(fp_cpp, " uint j;\n"); |
905 | fprintf(fp_cpp, " // verify in legal range for inputs\n"); |
906 | fprintf(fp_cpp, " assert(i < len(), \"index not in range\");\n\n"); |
907 | fprintf(fp_cpp, " // verify input is not null\n"); |
908 | fprintf(fp_cpp, " Node *pred = in(i);\n"); |
909 | fprintf(fp_cpp, " if (!pred)\n return %d;\n\n", |
910 | non_operand_latency); |
911 | fprintf(fp_cpp, " if (pred->is_Proj())\n pred = pred->in(0);\n\n"); |
912 | fprintf(fp_cpp, " // if either node does not have pipeline info, use default\n"); |
913 | fprintf(fp_cpp, " const Pipeline *predpipe = pred->pipeline();\n"); |
914 | fprintf(fp_cpp, " assert(predpipe, \"no predecessor pipeline info\");\n\n"); |
915 | fprintf(fp_cpp, " if (predpipe->hasFixedLatency())\n return predpipe->fixedLatency();\n\n"); |
916 | fprintf(fp_cpp, " const Pipeline *currpipe = pipeline();\n"); |
917 | fprintf(fp_cpp, " assert(currpipe, \"no pipeline info\");\n\n"); |
918 | fprintf(fp_cpp, " if (!is_Mach())\n return %d;\n\n", |
919 | node_latency); |
920 | fprintf(fp_cpp, " const MachNode *m = as_Mach();\n"); |
921 | fprintf(fp_cpp, " j = m->oper_input_base();\n"); |
922 | fprintf(fp_cpp, " if (i < j)\n return currpipe->functional_unit_latency(%d, predpipe);\n\n", |
923 | non_operand_latency); |
924 | fprintf(fp_cpp, " // determine which operand this is in\n"); |
925 | fprintf(fp_cpp, " uint n = m->num_opnds();\n"); |
926 | fprintf(fp_cpp, " int delta = %d;\n\n", |
927 | non_operand_latency); |
928 | fprintf(fp_cpp, " uint k;\n"); |
929 | fprintf(fp_cpp, " for (k = 1; k < n; k++) {\n"); |
930 | fprintf(fp_cpp, " j += m->_opnds[k]->num_edges();\n"); |
931 | fprintf(fp_cpp, " if (i < j)\n"); |
932 | fprintf(fp_cpp, " break;\n"); |
933 | fprintf(fp_cpp, " }\n"); |
934 | fprintf(fp_cpp, " if (k < n)\n"); |
935 | fprintf(fp_cpp, " delta = currpipe->operand_latency(k,predpipe);\n\n"); |
936 | fprintf(fp_cpp, " return currpipe->functional_unit_latency(delta, predpipe);\n"); |
937 | } |
938 | else { |
939 | fprintf(fp_cpp, " // assert(false, \"pipeline functionality is not defined\");\n"); |
940 | fprintf(fp_cpp, " return %d;\n", |
941 | non_operand_latency); |
942 | } |
943 | fprintf(fp_cpp, "}\n\n"); |
944 | |
945 | // Output the list of nop nodes |
946 | fprintf(fp_cpp, "// Descriptions for emitting different functional unit nops\n"); |
947 | const char *nop; |
948 | int nopcnt = 0; |
949 | for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL__null; nopcnt++ ); |
950 | |
951 | fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d]) {\n", nopcnt); |
952 | int i = 0; |
953 | for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL__null; i++ ) { |
954 | fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new %sNode();\n", i, nop); |
955 | } |
956 | fprintf(fp_cpp, "};\n\n"); |
957 | fprintf(fp_cpp, "#ifndef PRODUCT\n"); |
958 | fprintf(fp_cpp, "void Bundle::dump(outputStream *st) const {\n"); |
959 | fprintf(fp_cpp, " static const char * bundle_flags[] = {\n"); |
960 | fprintf(fp_cpp, " \"\",\n"); |
961 | fprintf(fp_cpp, " \"use nop delay\",\n"); |
962 | fprintf(fp_cpp, " \"use unconditional delay\",\n"); |
963 | fprintf(fp_cpp, " \"use conditional delay\",\n"); |
964 | fprintf(fp_cpp, " \"used in conditional delay\",\n"); |
965 | fprintf(fp_cpp, " \"used in unconditional delay\",\n"); |
966 | fprintf(fp_cpp, " \"used in all conditional delays\",\n"); |
967 | fprintf(fp_cpp, " };\n\n"); |
968 | |
969 | fprintf(fp_cpp, " static const char *resource_names[%d] = {", _pipeline->_rescount); |
970 | for (i = 0; i < _pipeline->_rescount; i++) |
971 | fprintf(fp_cpp, " \"%s\"%c", _pipeline->_reslist.name(i), i < _pipeline->_rescount-1 ? ',' : ' '); |
972 | fprintf(fp_cpp, "};\n\n"); |
973 | |
974 | // See if the same string is in the table |
975 | fprintf(fp_cpp, " bool needs_comma = false;\n\n"); |
976 | fprintf(fp_cpp, " if (_flags) {\n"); |
977 | fprintf(fp_cpp, " st->print(\"%%s\", bundle_flags[_flags]);\n"); |
978 | fprintf(fp_cpp, " needs_comma = true;\n"); |
979 | fprintf(fp_cpp, " };\n"); |
980 | fprintf(fp_cpp, " if (instr_count()) {\n"); |
981 | fprintf(fp_cpp, " st->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n"); |
982 | fprintf(fp_cpp, " needs_comma = true;\n"); |
983 | fprintf(fp_cpp, " };\n"); |
984 | fprintf(fp_cpp, " uint r = resources_used();\n"); |
985 | fprintf(fp_cpp, " if (r) {\n"); |
986 | fprintf(fp_cpp, " st->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n"); |
987 | fprintf(fp_cpp, " for (uint i = 0; i < %d; i++)\n", _pipeline->_rescount); |
988 | fprintf(fp_cpp, " if ((r & (1 << i)) != 0)\n"); |
989 | fprintf(fp_cpp, " st->print(\" %%s\", resource_names[i]);\n"); |
990 | fprintf(fp_cpp, " needs_comma = true;\n"); |
991 | fprintf(fp_cpp, " };\n"); |
992 | fprintf(fp_cpp, " st->print(\"\\n\");\n"); |
993 | fprintf(fp_cpp, "}\n"); |
994 | fprintf(fp_cpp, "#endif\n"); |
995 | } |
996 | |
997 | // --------------------------------------------------------------------------- |
998 | //------------------------------Utilities to build Instruction Classes-------- |
999 | // --------------------------------------------------------------------------- |
1000 | |
1001 | static void defineOut_RegMask(FILE *fp, const char *node, const char *regMask) { |
1002 | fprintf(fp,"const RegMask &%sNode::out_RegMask() const { return (%s); }\n", |
1003 | node, regMask); |
1004 | } |
1005 | |
1006 | static void print_block_index(FILE *fp, int inst_position) { |
1007 | assert( inst_position >= 0, "Instruction number less than zero"){ if (!(inst_position >= 0)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1007, "Instruction number less than zero"); abort(); }}; |
1008 | fprintf(fp, "block_index"); |
1009 | if( inst_position != 0 ) { |
1010 | fprintf(fp, " - %d", inst_position); |
1011 | } |
1012 | } |
1013 | |
1014 | // Scan the peepmatch and output a test for each instruction |
1015 | static void check_peepmatch_instruction_sequence(FILE *fp, PeepMatch *pmatch, PeepConstraint *pconstraint) { |
1016 | int parent = -1; |
1017 | int inst_position = 0; |
1018 | const char* inst_name = NULL__null; |
1019 | int input = 0; |
1020 | fprintf(fp, " // Check instruction sub-tree\n"); |
1021 | pmatch->reset(); |
1022 | for( pmatch->next_instruction( parent, inst_position, inst_name, input ); |
1023 | inst_name != NULL__null; |
1024 | pmatch->next_instruction( parent, inst_position, inst_name, input ) ) { |
1025 | // If this is not a placeholder |
1026 | if( ! pmatch->is_placeholder() ) { |
1027 | // Define temporaries 'inst#', based on parent and parent's input index |
1028 | if( parent != -1 ) { // root was initialized |
1029 | fprintf(fp, " // Identify previous instruction if inside this block\n"); |
1030 | fprintf(fp, " if( "); |
1031 | print_block_index(fp, inst_position); |
1032 | fprintf(fp, " > 0 ) {\n Node *n = block->get_node("); |
1033 | print_block_index(fp, inst_position); |
1034 | fprintf(fp, ");\n inst%d = (n->is_Mach()) ? ", inst_position); |
1035 | fprintf(fp, "n->as_Mach() : NULL;\n }\n"); |
1036 | } |
1037 | |
1038 | // When not the root |
1039 | // Test we have the correct instruction by comparing the rule. |
1040 | if( parent != -1 ) { |
1041 | fprintf(fp, " matches = matches && (inst%d != NULL) && (inst%d->rule() == %s_rule);\n", |
1042 | inst_position, inst_position, inst_name); |
1043 | } |
1044 | } else { |
1045 | // Check that user did not try to constrain a placeholder |
1046 | assert( ! pconstraint->constrains_instruction(inst_position),{ if (!(! pconstraint->constrains_instruction(inst_position ))) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1047, "fatal(): Can not constrain a placeholder instruction" ); abort(); }} |
1047 | "fatal(): Can not constrain a placeholder instruction"){ if (!(! pconstraint->constrains_instruction(inst_position ))) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1047, "fatal(): Can not constrain a placeholder instruction" ); abort(); }}; |
1048 | } |
1049 | } |
1050 | } |
1051 | |
1052 | // Build mapping for register indices, num_edges to input |
1053 | static void build_instruction_index_mapping( FILE *fp, FormDict &globals, PeepMatch *pmatch ) { |
1054 | int parent = -1; |
1055 | int inst_position = 0; |
1056 | const char* inst_name = NULL__null; |
1057 | int input = 0; |
1058 | fprintf(fp, " // Build map to register info\n"); |
1059 | pmatch->reset(); |
1060 | for( pmatch->next_instruction( parent, inst_position, inst_name, input ); |
1061 | inst_name != NULL__null; |
1062 | pmatch->next_instruction( parent, inst_position, inst_name, input ) ) { |
1063 | // If this is not a placeholder |
1064 | if( ! pmatch->is_placeholder() ) { |
1065 | // Define temporaries 'inst#', based on self's inst_position |
1066 | InstructForm *inst = globals[inst_name]->is_instruction(); |
1067 | if( inst != NULL__null ) { |
1068 | char inst_prefix[] = "instXXXX_"; |
1069 | sprintf(inst_prefix, "inst%d_", inst_position); |
1070 | char receiver[] = "instXXXX->"; |
1071 | sprintf(receiver, "inst%d->", inst_position); |
1072 | inst->index_temps( fp, globals, inst_prefix, receiver ); |
1073 | } |
1074 | } |
1075 | } |
1076 | } |
1077 | |
1078 | // Generate tests for the constraints |
1079 | static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint) { |
1080 | fprintf(fp, "\n"); |
1081 | fprintf(fp, " // Check constraints on sub-tree-leaves\n"); |
1082 | |
1083 | // Build mapping from num_edges to local variables |
1084 | build_instruction_index_mapping( fp, globals, pmatch ); |
1085 | |
1086 | // Build constraint tests |
1087 | if( pconstraint != NULL__null ) { |
1088 | fprintf(fp, " matches = matches &&"); |
1089 | bool first_constraint = true; |
1090 | while( pconstraint != NULL__null ) { |
1091 | // indentation and connecting '&&' |
1092 | const char *indentation = " "; |
1093 | fprintf(fp, "\n%s%s", indentation, (!first_constraint ? "&& " : " ")); |
1094 | |
1095 | // Only have '==' relation implemented |
1096 | if( strcmp(pconstraint->_relation,"==") != 0 ) { |
1097 | assert( false, "Unimplemented()" ){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1097, "Unimplemented()"); abort(); }}; |
1098 | } |
1099 | |
1100 | // LEFT |
1101 | int left_index = pconstraint->_left_inst; |
1102 | const char *left_op = pconstraint->_left_op; |
1103 | // Access info on the instructions whose operands are compared |
1104 | InstructForm *inst_left = globals[pmatch->instruction_name(left_index)]->is_instruction(); |
1105 | assert( inst_left, "Parser should guaranty this is an instruction"){ if (!(inst_left)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1105, "Parser should guaranty this is an instruction"); abort (); }}; |
1106 | int left_op_base = inst_left->oper_input_base(globals); |
Value stored to 'left_op_base' during its initialization is never read | |
1107 | // Access info on the operands being compared |
1108 | int left_op_index = inst_left->operand_position(left_op, Component::USE); |
1109 | if( left_op_index == -1 ) { |
1110 | left_op_index = inst_left->operand_position(left_op, Component::DEF); |
1111 | if( left_op_index == -1 ) { |
1112 | left_op_index = inst_left->operand_position(left_op, Component::USE_DEF); |
1113 | } |
1114 | } |
1115 | assert( left_op_index != NameList::Not_in_list, "Did not find operand in instruction"){ if (!(left_op_index != NameList::Not_in_list)) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1115, "Did not find operand in instruction"); abort(); }}; |
1116 | ComponentList components_left = inst_left->_components; |
1117 | const char *left_comp_type = components_left.at(left_op_index)->_type; |
1118 | OpClassForm *left_opclass = globals[left_comp_type]->is_opclass(); |
1119 | Form::InterfaceType left_interface_type = left_opclass->interface_type(globals); |
1120 | |
1121 | |
1122 | // RIGHT |
1123 | int right_op_index = -1; |
1124 | int right_index = pconstraint->_right_inst; |
1125 | const char *right_op = pconstraint->_right_op; |
1126 | if( right_index != -1 ) { // Match operand |
1127 | // Access info on the instructions whose operands are compared |
1128 | InstructForm *inst_right = globals[pmatch->instruction_name(right_index)]->is_instruction(); |
1129 | assert( inst_right, "Parser should guaranty this is an instruction"){ if (!(inst_right)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1129, "Parser should guaranty this is an instruction"); abort (); }}; |
1130 | int right_op_base = inst_right->oper_input_base(globals); |
1131 | // Access info on the operands being compared |
1132 | right_op_index = inst_right->operand_position(right_op, Component::USE); |
1133 | if( right_op_index == -1 ) { |
1134 | right_op_index = inst_right->operand_position(right_op, Component::DEF); |
1135 | if( right_op_index == -1 ) { |
1136 | right_op_index = inst_right->operand_position(right_op, Component::USE_DEF); |
1137 | } |
1138 | } |
1139 | assert( right_op_index != NameList::Not_in_list, "Did not find operand in instruction"){ if (!(right_op_index != NameList::Not_in_list)) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1139, "Did not find operand in instruction"); abort(); }}; |
1140 | ComponentList components_right = inst_right->_components; |
1141 | const char *right_comp_type = components_right.at(right_op_index)->_type; |
1142 | OpClassForm *right_opclass = globals[right_comp_type]->is_opclass(); |
1143 | Form::InterfaceType right_interface_type = right_opclass->interface_type(globals); |
1144 | assert( right_interface_type == left_interface_type, "Both must be same interface"){ if (!(right_interface_type == left_interface_type)) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1144, "Both must be same interface"); abort(); }}; |
1145 | |
1146 | } else { // Else match register |
1147 | // assert( false, "should be a register" ); |
1148 | } |
1149 | |
1150 | // |
1151 | // Check for equivalence |
1152 | // |
1153 | // fprintf(fp, "(inst%d->_opnds[%d]->reg(ra_,inst%d%s) /* %d.%s */ == /* %d.%s */ inst%d->_opnds[%d]->reg(ra_,inst%d%s)", |
1154 | // left_index, left_op_index, left_index, left_reg_index, left_index, left_op |
1155 | // right_index, right_op, right_index, right_op_index, right_index, right_reg_index); |
1156 | // fprintf(fp, ")"); |
1157 | // |
1158 | switch( left_interface_type ) { |
1159 | case Form::register_interface: { |
1160 | // Check that they are allocated to the same register |
1161 | // Need parameter for index position if not result operand |
1162 | char left_reg_index[] = ",instXXXX_idxXXXX"; |
1163 | if( left_op_index != 0 ) { |
1164 | assert( (left_index <= 9999) && (left_op_index <= 9999), "exceed string size"){ if (!((left_index <= 9999) && (left_op_index <= 9999))) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1164, "exceed string size"); abort(); }}; |
1165 | // Must have index into operands |
1166 | sprintf(left_reg_index,",inst%d_idx%d", (int)left_index, left_op_index); |
1167 | } else { |
1168 | strcpy(left_reg_index, ""); |
1169 | } |
1170 | fprintf(fp, "(inst%d->_opnds[%d]->reg(ra_,inst%d%s) /* %d.%s */", |
1171 | left_index, left_op_index, left_index, left_reg_index, left_index, left_op ); |
1172 | fprintf(fp, " == "); |
1173 | |
1174 | if( right_index != -1 ) { |
1175 | char right_reg_index[18] = ",instXXXX_idxXXXX"; |
1176 | if( right_op_index != 0 ) { |
1177 | assert( (right_index <= 9999) && (right_op_index <= 9999), "exceed string size"){ if (!((right_index <= 9999) && (right_op_index <= 9999))) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1177, "exceed string size"); abort(); }}; |
1178 | // Must have index into operands |
1179 | sprintf(right_reg_index,",inst%d_idx%d", (int)right_index, right_op_index); |
1180 | } else { |
1181 | strcpy(right_reg_index, ""); |
1182 | } |
1183 | fprintf(fp, "/* %d.%s */ inst%d->_opnds[%d]->reg(ra_,inst%d%s)", |
1184 | right_index, right_op, right_index, right_op_index, right_index, right_reg_index ); |
1185 | } else { |
1186 | fprintf(fp, "%s_enc", right_op ); |
1187 | } |
1188 | fprintf(fp,")"); |
1189 | break; |
1190 | } |
1191 | case Form::constant_interface: { |
1192 | // Compare the '->constant()' values |
1193 | fprintf(fp, "(inst%d->_opnds[%d]->constant() /* %d.%s */", |
1194 | left_index, left_op_index, left_index, left_op ); |
1195 | fprintf(fp, " == "); |
1196 | fprintf(fp, "/* %d.%s */ inst%d->_opnds[%d]->constant())", |
1197 | right_index, right_op, right_index, right_op_index ); |
1198 | break; |
1199 | } |
1200 | case Form::memory_interface: { |
1201 | // Compare 'base', 'index', 'scale', and 'disp' |
1202 | // base |
1203 | fprintf(fp, "( \n"); |
1204 | fprintf(fp, " (inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d) /* %d.%s$$base */", |
1205 | left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); |
1206 | fprintf(fp, " == "); |
1207 | fprintf(fp, "/* %d.%s$$base */ inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d)) &&\n", |
1208 | right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); |
1209 | // index |
1210 | fprintf(fp, " (inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d) /* %d.%s$$index */", |
1211 | left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); |
1212 | fprintf(fp, " == "); |
1213 | fprintf(fp, "/* %d.%s$$index */ inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d)) &&\n", |
1214 | right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); |
1215 | // scale |
1216 | fprintf(fp, " (inst%d->_opnds[%d]->scale() /* %d.%s$$scale */", |
1217 | left_index, left_op_index, left_index, left_op ); |
1218 | fprintf(fp, " == "); |
1219 | fprintf(fp, "/* %d.%s$$scale */ inst%d->_opnds[%d]->scale()) &&\n", |
1220 | right_index, right_op, right_index, right_op_index ); |
1221 | // disp |
1222 | fprintf(fp, " (inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d) /* %d.%s$$disp */", |
1223 | left_index, left_op_index, left_index, left_index, left_op_index, left_index, left_op ); |
1224 | fprintf(fp, " == "); |
1225 | fprintf(fp, "/* %d.%s$$disp */ inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d))\n", |
1226 | right_index, right_op, right_index, right_op_index, right_index, right_index, right_op_index ); |
1227 | fprintf(fp, ") \n"); |
1228 | break; |
1229 | } |
1230 | case Form::conditional_interface: { |
1231 | // Compare the condition code being tested |
1232 | assert( false, "Unimplemented()" ){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1232, "Unimplemented()"); abort(); }}; |
1233 | break; |
1234 | } |
1235 | default: { |
1236 | assert( false, "ShouldNotReachHere()" ){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1236, "ShouldNotReachHere()"); abort(); }}; |
1237 | break; |
1238 | } |
1239 | } |
1240 | |
1241 | // Advance to next constraint |
1242 | pconstraint = pconstraint->next(); |
1243 | first_constraint = false; |
1244 | } |
1245 | |
1246 | fprintf(fp, ";\n"); |
1247 | } |
1248 | } |
1249 | |
1250 | // // EXPERIMENTAL -- TEMPORARY code |
1251 | // static Form::DataType get_operand_type(FormDict &globals, InstructForm *instr, const char *op_name ) { |
1252 | // int op_index = instr->operand_position(op_name, Component::USE); |
1253 | // if( op_index == -1 ) { |
1254 | // op_index = instr->operand_position(op_name, Component::DEF); |
1255 | // if( op_index == -1 ) { |
1256 | // op_index = instr->operand_position(op_name, Component::USE_DEF); |
1257 | // } |
1258 | // } |
1259 | // assert( op_index != NameList::Not_in_list, "Did not find operand in instruction"); |
1260 | // |
1261 | // ComponentList components_right = instr->_components; |
1262 | // char *right_comp_type = components_right.at(op_index)->_type; |
1263 | // OpClassForm *right_opclass = globals[right_comp_type]->is_opclass(); |
1264 | // Form::InterfaceType right_interface_type = right_opclass->interface_type(globals); |
1265 | // |
1266 | // return; |
1267 | // } |
1268 | |
1269 | // Construct the new sub-tree |
1270 | static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint, PeepReplace *preplace, int max_position ) { |
1271 | fprintf(fp, " // IF instructions and constraints matched\n"); |
1272 | fprintf(fp, " if( matches ) {\n"); |
1273 | fprintf(fp, " // generate the new sub-tree\n"); |
1274 | fprintf(fp, " assert( true, \"Debug stopping point\");\n"); |
1275 | if( preplace != NULL__null ) { |
1276 | // Get the root of the new sub-tree |
1277 | const char *root_inst = NULL__null; |
1278 | preplace->next_instruction(root_inst); |
1279 | InstructForm *root_form = globals[root_inst]->is_instruction(); |
1280 | assert( root_form != NULL, "Replacement instruction was not previously defined"){ if (!(root_form != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1280, "Replacement instruction was not previously defined") ; abort(); }}; |
1281 | fprintf(fp, " %sNode *root = new %sNode();\n", root_inst, root_inst); |
1282 | |
1283 | int inst_num; |
1284 | const char *op_name; |
1285 | int opnds_index = 0; // define result operand |
1286 | // Then install the use-operands for the new sub-tree |
1287 | // preplace->reset(); // reset breaks iteration |
1288 | for( preplace->next_operand( inst_num, op_name ); |
1289 | op_name != NULL__null; |
1290 | preplace->next_operand( inst_num, op_name ) ) { |
1291 | InstructForm *inst_form; |
1292 | inst_form = globals[pmatch->instruction_name(inst_num)]->is_instruction(); |
1293 | assert( inst_form, "Parser should guaranty this is an instruction"){ if (!(inst_form)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1293, "Parser should guaranty this is an instruction"); abort (); }}; |
1294 | int inst_op_num = inst_form->operand_position(op_name, Component::USE); |
1295 | if( inst_op_num == NameList::Not_in_list ) |
1296 | inst_op_num = inst_form->operand_position(op_name, Component::USE_DEF); |
1297 | assert( inst_op_num != NameList::Not_in_list, "Did not find operand as USE"){ if (!(inst_op_num != NameList::Not_in_list)) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1297, "Did not find operand as USE"); abort(); }}; |
1298 | // find the name of the OperandForm from the local name |
1299 | const Form *form = inst_form->_localNames[op_name]; |
1300 | OperandForm *op_form = form->is_operand(); |
1301 | if( opnds_index == 0 ) { |
1302 | // Initial setup of new instruction |
1303 | fprintf(fp, " // ----- Initial setup -----\n"); |
1304 | // |
1305 | // Add control edge for this node |
1306 | fprintf(fp, " root->add_req(_in[0]); // control edge\n"); |
1307 | // Add unmatched edges from root of match tree |
1308 | int op_base = root_form->oper_input_base(globals); |
1309 | for( int unmatched_edge = 1; unmatched_edge < op_base; ++unmatched_edge ) { |
1310 | fprintf(fp, " root->add_req(inst%d->in(%d)); // unmatched ideal edge\n", |
1311 | inst_num, unmatched_edge); |
1312 | } |
1313 | // If new instruction captures bottom type |
1314 | if( root_form->captures_bottom_type(globals) ) { |
1315 | // Get bottom type from instruction whose result we are replacing |
1316 | fprintf(fp, " root->_bottom_type = inst%d->bottom_type();\n", inst_num); |
1317 | } |
1318 | // Define result register and result operand |
1319 | fprintf(fp, " ra_->add_reference(root, inst%d);\n", inst_num); |
1320 | fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num); |
1321 | fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num); |
1322 | fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(); // result\n", inst_num); |
1323 | fprintf(fp, " // ----- Done with initial setup -----\n"); |
1324 | } else { |
1325 | if( (op_form == NULL__null) || (op_form->is_base_constant(globals) == Form::none) ) { |
1326 | // Do not have ideal edges for constants after matching |
1327 | fprintf(fp, " for( unsigned x%d = inst%d_idx%d; x%d < inst%d_idx%d; x%d++ )\n", |
1328 | inst_op_num, inst_num, inst_op_num, |
1329 | inst_op_num, inst_num, inst_op_num+1, inst_op_num ); |
1330 | fprintf(fp, " root->add_req( inst%d->in(x%d) );\n", |
1331 | inst_num, inst_op_num ); |
1332 | } else { |
1333 | fprintf(fp, " // no ideal edge for constants after matching\n"); |
1334 | } |
1335 | fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone();\n", |
1336 | opnds_index, inst_num, inst_op_num ); |
1337 | } |
1338 | ++opnds_index; |
1339 | } |
1340 | }else { |
1341 | // Replacing subtree with empty-tree |
1342 | assert( false, "ShouldNotReachHere();"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1342, "ShouldNotReachHere();"); abort(); }}; |
1343 | } |
1344 | |
1345 | for (int i = 0; i <= max_position; i++) { |
1346 | fprintf(fp, " inst%d->set_removed();\n", i); |
1347 | } |
1348 | // Return the new sub-tree |
1349 | fprintf(fp, " deleted = %d;\n", max_position+1 /*zero to one based*/); |
1350 | fprintf(fp, " return root; // return new root;\n"); |
1351 | fprintf(fp, " }\n"); |
1352 | } |
1353 | |
1354 | |
1355 | // Define the Peephole method for an instruction node |
1356 | void ArchDesc::definePeephole(FILE *fp, InstructForm *node) { |
1357 | // Generate Peephole function header |
1358 | fprintf(fp, "MachNode *%sNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {\n", node->_ident); |
1359 | fprintf(fp, " bool matches = true;\n"); |
1360 | |
1361 | // Identify the maximum instruction position, |
1362 | // generate temporaries that hold current instruction |
1363 | // |
1364 | // MachNode *inst0 = NULL; |
1365 | // ... |
1366 | // MachNode *instMAX = NULL; |
1367 | // |
1368 | int max_position = 0; |
1369 | Peephole *peep; |
1370 | for( peep = node->peepholes(); peep != NULL__null; peep = peep->next() ) { |
1371 | PeepMatch *pmatch = peep->match(); |
1372 | assert( pmatch != NULL, "fatal(), missing peepmatch rule"){ if (!(pmatch != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1372, "fatal(), missing peepmatch rule"); abort(); }}; |
1373 | if( max_position < pmatch->max_position() ) max_position = pmatch->max_position(); |
1374 | } |
1375 | for( int i = 0; i <= max_position; ++i ) { |
1376 | if( i == 0 ) { |
1377 | fprintf(fp, " MachNode *inst0 = this;\n"); |
1378 | } else { |
1379 | fprintf(fp, " MachNode *inst%d = NULL;\n", i); |
1380 | } |
1381 | } |
1382 | |
1383 | // For each peephole rule in architecture description |
1384 | // Construct a test for the desired instruction sub-tree |
1385 | // then check the constraints |
1386 | // If these match, Generate the new subtree |
1387 | for( peep = node->peepholes(); peep != NULL__null; peep = peep->next() ) { |
1388 | int peephole_number = peep->peephole_number(); |
1389 | PeepMatch *pmatch = peep->match(); |
1390 | PeepConstraint *pconstraint = peep->constraints(); |
1391 | PeepReplace *preplace = peep->replacement(); |
1392 | |
1393 | // Root of this peephole is the current MachNode |
1394 | assert( true, // %%name?%% strcmp( node->_ident, pmatch->name(0) ) == 0,{ if (!(true)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1395, "root of PeepMatch does not match instruction"); abort (); }} |
1395 | "root of PeepMatch does not match instruction"){ if (!(true)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1395, "root of PeepMatch does not match instruction"); abort (); }}; |
1396 | |
1397 | // Make each peephole rule individually selectable |
1398 | fprintf(fp, " if( (OptoPeepholeAt == -1) || (OptoPeepholeAt==%d) ) {\n", peephole_number); |
1399 | fprintf(fp, " matches = true;\n"); |
1400 | // Scan the peepmatch and output a test for each instruction |
1401 | check_peepmatch_instruction_sequence( fp, pmatch, pconstraint ); |
1402 | |
1403 | // Check constraints and build replacement inside scope |
1404 | fprintf(fp, " // If instruction subtree matches\n"); |
1405 | fprintf(fp, " if( matches ) {\n"); |
1406 | |
1407 | // Generate tests for the constraints |
1408 | check_peepconstraints( fp, _globalNames, pmatch, pconstraint ); |
1409 | |
1410 | // Construct the new sub-tree |
1411 | generate_peepreplace( fp, _globalNames, pmatch, pconstraint, preplace, max_position ); |
1412 | |
1413 | // End of scope for this peephole's constraints |
1414 | fprintf(fp, " }\n"); |
1415 | // Closing brace '}' to make each peephole rule individually selectable |
1416 | fprintf(fp, " } // end of peephole rule #%d\n", peephole_number); |
1417 | fprintf(fp, "\n"); |
1418 | } |
1419 | |
1420 | fprintf(fp, " return NULL; // No peephole rules matched\n"); |
1421 | fprintf(fp, "}\n"); |
1422 | fprintf(fp, "\n"); |
1423 | } |
1424 | |
1425 | // Define the Expand method for an instruction node |
1426 | void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { |
1427 | unsigned cnt = 0; // Count nodes we have expand into |
1428 | unsigned i; |
1429 | |
1430 | // Generate Expand function header |
1431 | fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident); |
1432 | fprintf(fp, " Compile* C = Compile::current();\n"); |
1433 | // Generate expand code |
1434 | if( node->expands() ) { |
1435 | const char *opid; |
1436 | int new_pos, exp_pos; |
1437 | const char *new_id = NULL__null; |
1438 | const Form *frm = NULL__null; |
1439 | InstructForm *new_inst = NULL__null; |
1440 | OperandForm *new_oper = NULL__null; |
1441 | unsigned numo = node->num_opnds() + |
1442 | node->_exprule->_newopers.count(); |
1443 | |
1444 | // If necessary, generate any operands created in expand rule |
1445 | if (node->_exprule->_newopers.count()) { |
1446 | for(node->_exprule->_newopers.reset(); |
1447 | (new_id = node->_exprule->_newopers.iter()) != NULL__null; cnt++) { |
1448 | frm = node->_localNames[new_id]; |
1449 | assert(frm, "Invalid entry in new operands list of expand rule"){ if (!(frm)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1449, "Invalid entry in new operands list of expand rule"); abort(); }}; |
1450 | new_oper = frm->is_operand(); |
1451 | char *tmp = (char *)node->_exprule->_newopconst[new_id]; |
1452 | if (tmp == NULL__null) { |
1453 | fprintf(fp," MachOper *op%d = new %sOper();\n", |
1454 | cnt, new_oper->_ident); |
1455 | } |
1456 | else { |
1457 | fprintf(fp," MachOper *op%d = new %sOper(%s);\n", |
1458 | cnt, new_oper->_ident, tmp); |
1459 | } |
1460 | } |
1461 | } |
1462 | cnt = 0; |
1463 | // Generate the temps to use for DAG building |
1464 | for(i = 0; i < numo; i++) { |
1465 | if (i < node->num_opnds()) { |
1466 | fprintf(fp," MachNode *tmp%d = this;\n", i); |
1467 | } |
1468 | else { |
1469 | fprintf(fp," MachNode *tmp%d = NULL;\n", i); |
1470 | } |
1471 | } |
1472 | // Build mapping from num_edges to local variables |
1473 | fprintf(fp," unsigned num0 = 0;\n"); |
1474 | for( i = 1; i < node->num_opnds(); i++ ) { |
1475 | fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();\n",i,i); |
1476 | } |
1477 | |
1478 | // Build a mapping from operand index to input edges |
1479 | fprintf(fp," unsigned idx0 = oper_input_base();\n"); |
1480 | |
1481 | // The order in which the memory input is added to a node is very |
1482 | // strange. Store nodes get a memory input before Expand is |
1483 | // called and other nodes get it afterwards or before depending on |
1484 | // match order so oper_input_base is wrong during expansion. This |
1485 | // code adjusts it so that expansion will work correctly. |
1486 | int has_memory_edge = node->_matrule->needs_ideal_memory_edge(_globalNames); |
1487 | if (has_memory_edge) { |
1488 | fprintf(fp," if (mem == (Node*)1) {\n"); |
1489 | fprintf(fp," idx0--; // Adjust base because memory edge hasn't been inserted yet\n"); |
1490 | fprintf(fp," }\n"); |
1491 | } |
1492 | |
1493 | for( i = 0; i < node->num_opnds(); i++ ) { |
1494 | fprintf(fp," unsigned idx%d = idx%d + num%d;\n", |
1495 | i+1,i,i); |
1496 | } |
1497 | |
1498 | // Declare variable to hold root of expansion |
1499 | fprintf(fp," MachNode *result = NULL;\n"); |
1500 | |
1501 | // Iterate over the instructions 'node' expands into |
1502 | ExpandRule *expand = node->_exprule; |
1503 | NameAndList *expand_instr = NULL__null; |
1504 | for (expand->reset_instructions(); |
1505 | (expand_instr = expand->iter_instructions()) != NULL__null; cnt++) { |
1506 | new_id = expand_instr->name(); |
1507 | |
1508 | InstructForm* expand_instruction = (InstructForm*)globalAD->globalNames()[new_id]; |
1509 | |
1510 | if (!expand_instruction) { |
1511 | globalAD->syntax_err(node->_linenum, "In %s: instruction %s used in expand not declared\n", |
1512 | node->_ident, new_id); |
1513 | continue; |
1514 | } |
1515 | |
1516 | // Build the node for the instruction |
1517 | fprintf(fp,"\n %sNode *n%d = new %sNode();\n", new_id, cnt, new_id); |
1518 | // Add control edge for this node |
1519 | fprintf(fp," n%d->add_req(_in[0]);\n", cnt); |
1520 | // Build the operand for the value this node defines. |
1521 | Form *form = (Form*)_globalNames[new_id]; |
1522 | assert(form, "'new_id' must be a defined form name"){ if (!(form)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1522, "'new_id' must be a defined form name"); abort(); }}; |
1523 | // Grab the InstructForm for the new instruction |
1524 | new_inst = form->is_instruction(); |
1525 | assert(new_inst, "'new_id' must be an instruction name"){ if (!(new_inst)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1525, "'new_id' must be an instruction name"); abort(); }}; |
1526 | if (node->is_ideal_if() && new_inst->is_ideal_if()) { |
1527 | fprintf(fp, " ((MachIfNode*)n%d)->_prob = _prob;\n", cnt); |
1528 | fprintf(fp, " ((MachIfNode*)n%d)->_fcnt = _fcnt;\n", cnt); |
1529 | } |
1530 | |
1531 | if (node->is_ideal_fastlock() && new_inst->is_ideal_fastlock()) { |
1532 | fprintf(fp, " ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n", cnt); |
1533 | fprintf(fp, " ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n", cnt); |
1534 | } |
1535 | |
1536 | // Fill in the bottom_type where requested |
1537 | if (node->captures_bottom_type(_globalNames) && |
1538 | new_inst->captures_bottom_type(_globalNames)) { |
1539 | fprintf(fp, " ((MachTypeNode*)n%d)->_bottom_type = bottom_type();\n", cnt); |
1540 | } |
1541 | |
1542 | const char *resultOper = new_inst->reduce_result(); |
1543 | fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n", |
1544 | cnt, machOperEnum(resultOper)); |
1545 | |
1546 | // get the formal operand NameList |
1547 | NameList *formal_lst = &new_inst->_parameters; |
1548 | formal_lst->reset(); |
1549 | |
1550 | // Handle any memory operand |
1551 | int memory_operand = new_inst->memory_operand(_globalNames); |
1552 | if( memory_operand != InstructForm::NO_MEMORY_OPERAND ) { |
1553 | int node_mem_op = node->memory_operand(_globalNames); |
1554 | assert( node_mem_op != InstructForm::NO_MEMORY_OPERAND,{ if (!(node_mem_op != InstructForm::NO_MEMORY_OPERAND)) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1555, "expand rule member needs memory but top-level inst doesn't have any" ); abort(); }} |
1555 | "expand rule member needs memory but top-level inst doesn't have any" ){ if (!(node_mem_op != InstructForm::NO_MEMORY_OPERAND)) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1555, "expand rule member needs memory but top-level inst doesn't have any" ); abort(); }}; |
1556 | if (has_memory_edge) { |
1557 | // Copy memory edge |
1558 | fprintf(fp," if (mem != (Node*)1) {\n"); |
1559 | fprintf(fp," n%d->add_req(_in[1]);\t// Add memory edge\n", cnt); |
1560 | fprintf(fp," }\n"); |
1561 | } |
1562 | } |
1563 | |
1564 | // Iterate over the new instruction's operands |
1565 | int prev_pos = -1; |
1566 | for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL__null; ) { |
1567 | // Use 'parameter' at current position in list of new instruction's formals |
1568 | // instead of 'opid' when looking up info internal to new_inst |
1569 | const char *parameter = formal_lst->iter(); |
1570 | if (!parameter) { |
1571 | globalAD->syntax_err(node->_linenum, "Operand %s of expand instruction %s has" |
1572 | " no equivalent in new instruction %s.", |
1573 | opid, node->_ident, new_inst->_ident); |
1574 | assert(0, "Wrong expand"){ if (!(0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1574, "Wrong expand"); abort(); }}; |
1575 | } |
1576 | |
1577 | // Check for an operand which is created in the expand rule |
1578 | if ((exp_pos = node->_exprule->_newopers.index(opid)) != -1) { |
1579 | new_pos = new_inst->operand_position(parameter,Component::USE); |
1580 | exp_pos += node->num_opnds(); |
1581 | // If there is no use of the created operand, just skip it |
1582 | if (new_pos != NameList::Not_in_list) { |
1583 | //Copy the operand from the original made above |
1584 | fprintf(fp," n%d->set_opnd_array(%d, op%d->clone()); // %s\n", |
1585 | cnt, new_pos, exp_pos-node->num_opnds(), opid); |
1586 | // Check for who defines this operand & add edge if needed |
1587 | fprintf(fp," if(tmp%d != NULL)\n", exp_pos); |
1588 | fprintf(fp," n%d->add_req(tmp%d);\n", cnt, exp_pos); |
1589 | } |
1590 | } |
1591 | else { |
1592 | // Use operand name to get an index into instruction component list |
1593 | // ins = (InstructForm *) _globalNames[new_id]; |
1594 | exp_pos = node->operand_position_format(opid); |
1595 | assert(exp_pos != -1, "Bad expand rule"){ if (!(exp_pos != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1595, "Bad expand rule"); abort(); }}; |
1596 | if (prev_pos > exp_pos && expand_instruction->_matrule != NULL__null) { |
1597 | // For the add_req calls below to work correctly they need |
1598 | // to added in the same order that a match would add them. |
1599 | // This means that they would need to be in the order of |
1600 | // the components list instead of the formal parameters. |
1601 | // This is a sort of hidden invariant that previously |
1602 | // wasn't checked and could lead to incorrectly |
1603 | // constructed nodes. |
1604 | syntax_err(node->_linenum, "For expand in %s to work, parameter declaration order in %s must follow matchrule\n", |
1605 | node->_ident, new_inst->_ident); |
1606 | } |
1607 | prev_pos = exp_pos; |
1608 | |
1609 | new_pos = new_inst->operand_position(parameter,Component::USE); |
1610 | if (new_pos != -1) { |
1611 | // Copy the operand from the ExpandNode to the new node |
1612 | fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", |
1613 | cnt, new_pos, exp_pos, opid); |
1614 | // For each operand add appropriate input edges by looking at tmp's |
1615 | fprintf(fp," if(tmp%d == this) {\n", exp_pos); |
1616 | // Grab corresponding edges from ExpandNode and insert them here |
1617 | fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", exp_pos); |
1618 | fprintf(fp," n%d->add_req(_in[i + idx%d]);\n", cnt, exp_pos); |
1619 | fprintf(fp," }\n"); |
1620 | fprintf(fp," }\n"); |
1621 | // This value is generated by one of the new instructions |
1622 | fprintf(fp," else n%d->add_req(tmp%d);\n", cnt, exp_pos); |
1623 | } |
1624 | } |
1625 | |
1626 | // Update the DAG tmp's for values defined by this instruction |
1627 | int new_def_pos = new_inst->operand_position(parameter,Component::DEF); |
1628 | Effect *eform = (Effect *)new_inst->_effects[parameter]; |
1629 | // If this operand is a definition in either an effects rule |
1630 | // or a match rule |
1631 | if((eform) && (is_def(eform->_use_def))) { |
1632 | // Update the temp associated with this operand |
1633 | fprintf(fp," tmp%d = n%d;\n", exp_pos, cnt); |
1634 | } |
1635 | else if( new_def_pos != -1 ) { |
1636 | // Instruction defines a value but user did not declare it |
1637 | // in the 'effect' clause |
1638 | fprintf(fp," tmp%d = n%d;\n", exp_pos, cnt); |
1639 | } |
1640 | } // done iterating over a new instruction's operands |
1641 | |
1642 | // Fix number of operands, as we do not generate redundant ones. |
1643 | // The matcher generates some redundant operands, which are removed |
1644 | // in the expand function (of the node we generate here). We don't |
1645 | // generate the redundant operands here, so set the correct _num_opnds. |
1646 | if (expand_instruction->num_opnds() != expand_instruction->num_unique_opnds()) { |
1647 | fprintf(fp, " n%d->_num_opnds = %d; // Only unique opnds generated.\n", |
1648 | cnt, expand_instruction->num_unique_opnds()); |
1649 | } |
1650 | |
1651 | // Invoke Expand() for the newly created instruction. |
1652 | fprintf(fp," result = n%d->Expand( state, proj_list, mem );\n", cnt); |
1653 | assert( !new_inst->expands(), "Do not have complete support for recursive expansion"){ if (!(!new_inst->expands())) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1653, "Do not have complete support for recursive expansion" ); abort(); }}; |
1654 | } // done iterating over new instructions |
1655 | fprintf(fp,"\n"); |
1656 | } // done generating expand rule |
1657 | |
1658 | // Generate projections for instruction's additional DEFs and KILLs |
1659 | if( ! node->expands() && (node->needs_projections() || node->has_temps())) { |
1660 | // Get string representing the MachNode that projections point at |
1661 | const char *machNode = "this"; |
1662 | // Generate the projections |
1663 | fprintf(fp," // Add projection edges for additional defs or kills\n"); |
1664 | |
1665 | // Examine each component to see if it is a DEF or KILL |
1666 | node->_components.reset(); |
1667 | // Skip the first component, if already handled as (SET dst (...)) |
1668 | Component *comp = NULL__null; |
1669 | // For kills, the choice of projection numbers is arbitrary |
1670 | int proj_no = 1; |
1671 | bool declared_def = false; |
1672 | bool declared_kill = false; |
1673 | |
1674 | while ((comp = node->_components.iter()) != NULL__null) { |
1675 | // Lookup register class associated with operand type |
1676 | Form *form = (Form*)_globalNames[comp->_type]; |
1677 | assert(form, "component type must be a defined form"){ if (!(form)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1677, "component type must be a defined form"); abort(); }}; |
1678 | OperandForm *op = form->is_operand(); |
1679 | |
1680 | if (comp->is(Component::TEMP) || |
1681 | comp->is(Component::TEMP_DEF)) { |
1682 | fprintf(fp, " // TEMP %s\n", comp->_name); |
1683 | if (!declared_def) { |
1684 | // Define the variable "def" to hold new MachProjNodes |
1685 | fprintf(fp, " MachTempNode *def;\n"); |
1686 | declared_def = true; |
1687 | } |
1688 | if (op && op->_interface && op->_interface->is_RegInterface()) { |
1689 | fprintf(fp," def = new MachTempNode(state->MachOperGenerator(%s));\n", |
1690 | machOperEnum(op->_ident)); |
1691 | fprintf(fp," add_req(def);\n"); |
1692 | // The operand for TEMP is already constructed during |
1693 | // this mach node construction, see buildMachNode(). |
1694 | // |
1695 | // int idx = node->operand_position_format(comp->_name); |
1696 | // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator(%s));\n", |
1697 | // idx, machOperEnum(op->_ident)); |
1698 | } else { |
1699 | assert(false, "can't have temps which aren't registers"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1699, "can't have temps which aren't registers"); abort(); } }; |
1700 | } |
1701 | } else if (comp->isa(Component::KILL)) { |
1702 | fprintf(fp, " // DEF/KILL %s\n", comp->_name); |
1703 | |
1704 | if (!declared_kill) { |
1705 | // Define the variable "kill" to hold new MachProjNodes |
1706 | fprintf(fp, " MachProjNode *kill;\n"); |
1707 | declared_kill = true; |
1708 | } |
1709 | |
1710 | assert(op, "Support additional KILLS for base operands"){ if (!(op)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1710, "Support additional KILLS for base operands"); abort( ); }}; |
1711 | const char *regmask = reg_mask(*op); |
1712 | const char *ideal_type = op->ideal_type(_globalNames, _register); |
1713 | |
1714 | if (!op->is_bound_register()) { |
1715 | syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n", |
1716 | node->_ident, comp->_type, comp->_name); |
1717 | } |
1718 | |
1719 | fprintf(fp," kill = "); |
1720 | fprintf(fp,"new MachProjNode( %s, %d, (%s), Op_%s );\n", |
1721 | machNode, proj_no++, regmask, ideal_type); |
1722 | fprintf(fp," proj_list.push(kill);\n"); |
1723 | } |
1724 | } |
1725 | } |
1726 | |
1727 | if( !node->expands() && node->_matrule != NULL__null ) { |
1728 | // Remove duplicated operands and inputs which use the same name. |
1729 | // Search through match operands for the same name usage. |
1730 | // The matcher generates these non-unique operands. If the node |
1731 | // was constructed by an expand rule, there are no unique operands. |
1732 | uintunsigned int cur_num_opnds = node->num_opnds(); |
1733 | if (cur_num_opnds > 1 && cur_num_opnds != node->num_unique_opnds()) { |
1734 | Component *comp = NULL__null; |
1735 | fprintf(fp, " // Remove duplicated operands and inputs which use the same name.\n"); |
1736 | fprintf(fp, " if (num_opnds() == %d) {\n", cur_num_opnds); |
1737 | // Build mapping from num_edges to local variables |
1738 | fprintf(fp," unsigned num0 = 0;\n"); |
1739 | for (i = 1; i < cur_num_opnds; i++) { |
1740 | fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();", i, i); |
1741 | fprintf(fp, " \t// %s\n", node->opnd_ident(i)); |
1742 | } |
1743 | // Build a mapping from operand index to input edges |
1744 | fprintf(fp," unsigned idx0 = oper_input_base();\n"); |
1745 | for (i = 0; i < cur_num_opnds; i++) { |
1746 | fprintf(fp," unsigned idx%d = idx%d + num%d;\n", i+1, i, i); |
1747 | } |
1748 | |
1749 | uintunsigned int new_num_opnds = 1; |
1750 | node->_components.reset(); |
1751 | // Skip first unique operands. |
1752 | for (i = 1; i < cur_num_opnds; i++) { |
1753 | comp = node->_components.iter(); |
1754 | if (i != node->unique_opnds_idx(i)) { |
1755 | break; |
1756 | } |
1757 | new_num_opnds++; |
1758 | } |
1759 | // Replace not unique operands with next unique operands. |
1760 | for ( ; i < cur_num_opnds; i++) { |
1761 | comp = node->_components.iter(); |
1762 | uintunsigned int j = node->unique_opnds_idx(i); |
1763 | // unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique. |
1764 | if (j != node->unique_opnds_idx(j)) { |
1765 | fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", |
1766 | new_num_opnds, i, comp->_name); |
1767 | // Delete not unique edges here. |
1768 | fprintf(fp," for (unsigned i = 0; i < num%d; i++) {\n", i); |
1769 | fprintf(fp," set_req(i + idx%d, _in[i + idx%d]);\n", new_num_opnds, i); |
1770 | fprintf(fp," }\n"); |
1771 | fprintf(fp," num%d = num%d;\n", new_num_opnds, i); |
1772 | fprintf(fp," idx%d = idx%d + num%d;\n", new_num_opnds+1, new_num_opnds, new_num_opnds); |
1773 | new_num_opnds++; |
1774 | } |
1775 | } |
1776 | // Delete the rest of edges. |
1777 | fprintf(fp," for (int i = idx%d - 1; i >= (int)idx%d; i--) {\n", cur_num_opnds, new_num_opnds); |
1778 | fprintf(fp," del_req(i);\n"); |
1779 | fprintf(fp," }\n"); |
1780 | fprintf(fp," _num_opnds = %d;\n", new_num_opnds); |
1781 | assert(new_num_opnds == node->num_unique_opnds(), "what?"){ if (!(new_num_opnds == node->num_unique_opnds())) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1781, "what?"); abort(); }}; |
1782 | fprintf(fp, " } else {\n"); |
1783 | fprintf(fp, " assert(_num_opnds == %d, \"There should be either %d or %d operands.\");\n", |
1784 | new_num_opnds, new_num_opnds, cur_num_opnds); |
1785 | fprintf(fp, " }\n"); |
1786 | } |
1787 | } |
1788 | |
1789 | // If the node is a MachConstantNode, insert the MachConstantBaseNode edge. |
1790 | // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input). |
1791 | // There are nodes that don't use $constantablebase, but still require that it |
1792 | // is an input to the node. Example: divF_reg_immN, Repl32B_imm on x86_64. |
1793 | if (node->is_mach_constant() || node->needs_constant_base()) { |
1794 | if (node->is_ideal_call() != Form::invalid_type && |
1795 | node->is_ideal_call() != Form::JAVA_LEAF) { |
1796 | fprintf(fp, " // MachConstantBaseNode added in matcher.\n"); |
1797 | _needs_deep_clone_jvms = true; |
1798 | } else { |
1799 | fprintf(fp, " add_req(C->mach_constant_base_node());\n"); |
1800 | } |
1801 | } |
1802 | |
1803 | fprintf(fp, "\n"); |
1804 | if (node->expands()) { |
1805 | fprintf(fp, " return result;\n"); |
1806 | } else { |
1807 | fprintf(fp, " return this;\n"); |
1808 | } |
1809 | fprintf(fp, "}\n"); |
1810 | fprintf(fp, "\n"); |
1811 | } |
1812 | |
1813 | |
1814 | //------------------------------Emit Routines---------------------------------- |
1815 | // Special classes and routines for defining node emit routines which output |
1816 | // target specific instruction object encodings. |
1817 | // Define the ___Node::emit() routine |
1818 | // |
1819 | // (1) void ___Node::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { |
1820 | // (2) // ... encoding defined by user |
1821 | // (3) |
1822 | // (4) } |
1823 | // |
1824 | |
1825 | class DefineEmitState { |
1826 | private: |
1827 | enum reloc_format { RELOC_NONE = -1, |
1828 | RELOC_IMMEDIATE = 0, |
1829 | RELOC_DISP = 1, |
1830 | RELOC_CALL_DISP = 2 }; |
1831 | enum literal_status{ LITERAL_NOT_SEEN = 0, |
1832 | LITERAL_SEEN = 1, |
1833 | LITERAL_ACCESSED = 2, |
1834 | LITERAL_OUTPUT = 3 }; |
1835 | // Temporaries that describe current operand |
1836 | bool _cleared; |
1837 | OpClassForm *_opclass; |
1838 | OperandForm *_operand; |
1839 | int _operand_idx; |
1840 | const char *_local_name; |
1841 | const char *_operand_name; |
1842 | bool _doing_disp; |
1843 | bool _doing_constant; |
1844 | Form::DataType _constant_type; |
1845 | DefineEmitState::literal_status _constant_status; |
1846 | DefineEmitState::literal_status _reg_status; |
1847 | bool _doing_emit8; |
1848 | bool _doing_emit_d32; |
1849 | bool _doing_emit_d16; |
1850 | bool _doing_emit_hi; |
1851 | bool _doing_emit_lo; |
1852 | bool _may_reloc; |
1853 | reloc_format _reloc_form; |
1854 | const char * _reloc_type; |
1855 | bool _processing_noninput; |
1856 | |
1857 | NameList _strings_to_emit; |
1858 | |
1859 | // Stable state, set by constructor |
1860 | ArchDesc &_AD; |
1861 | FILE *_fp; |
1862 | EncClass &_encoding; |
1863 | InsEncode &_ins_encode; |
1864 | InstructForm &_inst; |
1865 | |
1866 | public: |
1867 | DefineEmitState(FILE *fp, ArchDesc &AD, EncClass &encoding, |
1868 | InsEncode &ins_encode, InstructForm &inst) |
1869 | : _AD(AD), _fp(fp), _encoding(encoding), _ins_encode(ins_encode), _inst(inst) { |
1870 | clear(); |
1871 | } |
1872 | |
1873 | void clear() { |
1874 | _cleared = true; |
1875 | _opclass = NULL__null; |
1876 | _operand = NULL__null; |
1877 | _operand_idx = 0; |
1878 | _local_name = ""; |
1879 | _operand_name = ""; |
1880 | _doing_disp = false; |
1881 | _doing_constant= false; |
1882 | _constant_type = Form::none; |
1883 | _constant_status = LITERAL_NOT_SEEN; |
1884 | _reg_status = LITERAL_NOT_SEEN; |
1885 | _doing_emit8 = false; |
1886 | _doing_emit_d32= false; |
1887 | _doing_emit_d16= false; |
1888 | _doing_emit_hi = false; |
1889 | _doing_emit_lo = false; |
1890 | _may_reloc = false; |
1891 | _reloc_form = RELOC_NONE; |
1892 | _reloc_type = AdlcVMDeps::none_reloc_type(); |
1893 | _strings_to_emit.clear(); |
1894 | } |
1895 | |
1896 | // Track necessary state when identifying a replacement variable |
1897 | // @arg rep_var: The formal parameter of the encoding. |
1898 | void update_state(const char *rep_var) { |
1899 | // A replacement variable or one of its subfields |
1900 | // Obtain replacement variable from list |
1901 | if ( (*rep_var) != '$' ) { |
1902 | // A replacement variable, '$' prefix |
1903 | // check_rep_var( rep_var ); |
1904 | if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { |
1905 | // No state needed. |
1906 | assert( _opclass == NULL,{ if (!(_opclass == __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1907, "'primary', 'secondary' and 'tertiary' don't follow operand." ); abort(); }} |
1907 | "'primary', 'secondary' and 'tertiary' don't follow operand."){ if (!(_opclass == __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1907, "'primary', 'secondary' and 'tertiary' don't follow operand." ); abort(); }}; |
1908 | } |
1909 | else if ((strcmp(rep_var, "constanttablebase") == 0) || |
1910 | (strcmp(rep_var, "constantoffset") == 0) || |
1911 | (strcmp(rep_var, "constantaddress") == 0)) { |
1912 | if (!(_inst.is_mach_constant() || _inst.needs_constant_base())) { |
1913 | _AD.syntax_err(_encoding._linenum, |
1914 | "Replacement variable %s not allowed in instruct %s (only in MachConstantNode or MachCall).\n", |
1915 | rep_var, _encoding._name); |
1916 | } |
1917 | } |
1918 | else { |
1919 | // Lookup its position in (formal) parameter list of encoding |
1920 | int param_no = _encoding.rep_var_index(rep_var); |
1921 | if ( param_no == -1 ) { |
1922 | _AD.syntax_err( _encoding._linenum, |
1923 | "Replacement variable %s not found in enc_class %s.\n", |
1924 | rep_var, _encoding._name); |
1925 | } |
1926 | |
1927 | // Lookup the corresponding ins_encode parameter |
1928 | // This is the argument (actual parameter) to the encoding. |
1929 | const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no); |
1930 | if (inst_rep_var == NULL__null) { |
1931 | _AD.syntax_err( _ins_encode._linenum, |
1932 | "Parameter %s not passed to enc_class %s from instruct %s.\n", |
1933 | rep_var, _encoding._name, _inst._ident); |
1934 | assert(false, "inst_rep_var == NULL, cannot continue."){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1934, "inst_rep_var == NULL, cannot continue."); abort(); } }; |
1935 | } |
1936 | |
1937 | // Check if instruction's actual parameter is a local name in the instruction |
1938 | const Form *local = _inst._localNames[inst_rep_var]; |
1939 | OpClassForm *opc = (local != NULL__null) ? local->is_opclass() : NULL__null; |
1940 | // Note: assert removed to allow constant and symbolic parameters |
1941 | // assert( opc, "replacement variable was not found in local names"); |
1942 | // Lookup the index position iff the replacement variable is a localName |
1943 | int idx = (opc != NULL__null) ? _inst.operand_position_format(inst_rep_var) : -1; |
1944 | |
1945 | if ( idx != -1 ) { |
1946 | // This is a local in the instruction |
1947 | // Update local state info. |
1948 | _opclass = opc; |
1949 | _operand_idx = idx; |
1950 | _local_name = rep_var; |
1951 | _operand_name = inst_rep_var; |
1952 | |
1953 | // !!!!! |
1954 | // Do not support consecutive operands. |
1955 | assert( _operand == NULL, "Unimplemented()"){ if (!(_operand == __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1955, "Unimplemented()"); abort(); }}; |
1956 | _operand = opc->is_operand(); |
1957 | } |
1958 | else if( ADLParser::is_literal_constant(inst_rep_var) ) { |
1959 | // Instruction provided a constant expression |
1960 | // Check later that encoding specifies $$$constant to resolve as constant |
1961 | _constant_status = LITERAL_SEEN; |
1962 | } |
1963 | else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { |
1964 | // Instruction provided an opcode: "primary", "secondary", "tertiary" |
1965 | // Check later that encoding specifies $$$constant to resolve as constant |
1966 | _constant_status = LITERAL_SEEN; |
1967 | } |
1968 | else if((_AD.get_registers() != NULL__null ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL__null)) { |
1969 | // Instruction provided a literal register name for this parameter |
1970 | // Check that encoding specifies $$$reg to resolve.as register. |
1971 | _reg_status = LITERAL_SEEN; |
1972 | } |
1973 | else { |
1974 | // Check for unimplemented functionality before hard failure |
1975 | assert(opc != NULL && strcmp(opc->_ident, "label") == 0, "Unimplemented Label"){ if (!(opc != __null && strcmp(opc->_ident, "label" ) == 0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1975, "Unimplemented Label"); abort(); }}; |
1976 | assert(false, "ShouldNotReachHere()"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1976, "ShouldNotReachHere()"); abort(); }}; |
1977 | } |
1978 | } // done checking which operand this is. |
1979 | } else { |
1980 | // |
1981 | // A subfield variable, '$$' prefix |
1982 | // Check for fields that may require relocation information. |
1983 | // Then check that literal register parameters are accessed with 'reg' or 'constant' |
1984 | // |
1985 | if ( strcmp(rep_var,"$disp") == 0 ) { |
1986 | _doing_disp = true; |
1987 | assert( _opclass, "Must use operand or operand class before '$disp'"){ if (!(_opclass)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1987, "Must use operand or operand class before '$disp'"); abort (); }}; |
1988 | if( _operand == NULL__null ) { |
1989 | // Only have an operand class, generate run-time check for relocation |
1990 | _may_reloc = true; |
1991 | _reloc_form = RELOC_DISP; |
1992 | _reloc_type = AdlcVMDeps::oop_reloc_type(); |
1993 | } else { |
1994 | // Do precise check on operand: is it a ConP or not |
1995 | // |
1996 | // Check interface for value of displacement |
1997 | assert( ( _operand->_interface != NULL ),{ if (!(( _operand->_interface != __null ))) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1998, "$disp can only follow memory interface operand"); abort (); }} |
1998 | "$disp can only follow memory interface operand"){ if (!(( _operand->_interface != __null ))) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 1998, "$disp can only follow memory interface operand"); abort (); }}; |
1999 | MemInterface *mem_interface= _operand->_interface->is_MemInterface(); |
2000 | assert( mem_interface != NULL,{ if (!(mem_interface != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2001, "$disp can only follow memory interface operand"); abort (); }} |
2001 | "$disp can only follow memory interface operand"){ if (!(mem_interface != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2001, "$disp can only follow memory interface operand"); abort (); }}; |
2002 | const char *disp = mem_interface->_disp; |
2003 | |
2004 | if( disp != NULL__null && (*disp == '$') ) { |
2005 | // MemInterface::disp contains a replacement variable, |
2006 | // Check if this matches a ConP |
2007 | // |
2008 | // Lookup replacement variable, in operand's component list |
2009 | const char *rep_var_name = disp + 1; // Skip '$' |
2010 | const Component *comp = _operand->_components.search(rep_var_name); |
2011 | assert( comp != NULL,"Replacement variable not found in components"){ if (!(comp != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2011, "Replacement variable not found in components"); abort (); }}; |
2012 | const char *type = comp->_type; |
2013 | // Lookup operand form for replacement variable's type |
2014 | const Form *form = _AD.globalNames()[type]; |
2015 | assert( form != NULL, "Replacement variable's type not found"){ if (!(form != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2015, "Replacement variable's type not found"); abort(); }}; |
2016 | OperandForm *op = form->is_operand(); |
2017 | assert( op, "Attempting to emit a non-register or non-constant"){ if (!(op)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2017, "Attempting to emit a non-register or non-constant"); abort(); }}; |
2018 | // Check if this is a constant |
2019 | if (op->_matrule && op->_matrule->is_base_constant(_AD.globalNames())) { |
2020 | // Check which constant this name maps to: _c0, _c1, ..., _cn |
2021 | // const int idx = _operand.constant_position(_AD.globalNames(), comp); |
2022 | // assert( idx != -1, "Constant component not found in operand"); |
2023 | Form::DataType dtype = op->is_base_constant(_AD.globalNames()); |
2024 | if ( dtype == Form::idealP ) { |
2025 | _may_reloc = true; |
2026 | // No longer true that idealP is always an oop |
2027 | _reloc_form = RELOC_DISP; |
2028 | _reloc_type = AdlcVMDeps::oop_reloc_type(); |
2029 | } |
2030 | } |
2031 | |
2032 | else if( _operand->is_user_name_for_sReg() != Form::none ) { |
2033 | // The only non-constant allowed access to disp is an operand sRegX in a stackSlotX |
2034 | assert( op->ideal_to_sReg_type(type) != Form::none, "StackSlots access displacements using 'sRegs'"){ if (!(op->ideal_to_sReg_type(type) != Form::none)) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2034, "StackSlots access displacements using 'sRegs'"); abort (); }}; |
2035 | _may_reloc = false; |
2036 | } else { |
2037 | assert( false, "fatal(); Only stackSlots can access a non-constant using 'disp'"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2037, "fatal(); Only stackSlots can access a non-constant using 'disp'" ); abort(); }}; |
2038 | } |
2039 | } |
2040 | } // finished with precise check of operand for relocation. |
2041 | } // finished with subfield variable |
2042 | else if ( strcmp(rep_var,"$constant") == 0 ) { |
2043 | _doing_constant = true; |
2044 | if ( _constant_status == LITERAL_NOT_SEEN ) { |
2045 | // Check operand for type of constant |
2046 | assert( _operand, "Must use operand before '$$constant'"){ if (!(_operand)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2046, "Must use operand before '$$constant'"); abort(); }}; |
2047 | Form::DataType dtype = _operand->is_base_constant(_AD.globalNames()); |
2048 | _constant_type = dtype; |
2049 | if ( dtype == Form::idealP ) { |
2050 | _may_reloc = true; |
2051 | // No longer true that idealP is always an oop |
2052 | // // _must_reloc = true; |
2053 | _reloc_form = RELOC_IMMEDIATE; |
2054 | _reloc_type = AdlcVMDeps::oop_reloc_type(); |
2055 | } else { |
2056 | // No relocation information needed |
2057 | } |
2058 | } else { |
2059 | // User-provided literals may not require relocation information !!!!! |
2060 | assert( _constant_status == LITERAL_SEEN, "Must know we are processing a user-provided literal"){ if (!(_constant_status == LITERAL_SEEN)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2060, "Must know we are processing a user-provided literal" ); abort(); }}; |
2061 | } |
2062 | } |
2063 | else if ( strcmp(rep_var,"$label") == 0 ) { |
2064 | // Calls containing labels require relocation |
2065 | if ( _inst.is_ideal_call() ) { |
2066 | _may_reloc = true; |
2067 | // !!!!! !!!!! |
2068 | _reloc_type = AdlcVMDeps::none_reloc_type(); |
2069 | } |
2070 | } |
2071 | |
2072 | // literal register parameter must be accessed as a 'reg' field. |
2073 | if ( _reg_status != LITERAL_NOT_SEEN ) { |
2074 | assert( _reg_status == LITERAL_SEEN, "Must have seen register literal before now"){ if (!(_reg_status == LITERAL_SEEN)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2074, "Must have seen register literal before now"); abort( ); }}; |
2075 | if (strcmp(rep_var,"$reg") == 0 || reg_conversion(rep_var) != NULL__null) { |
2076 | _reg_status = LITERAL_ACCESSED; |
2077 | } else { |
2078 | _AD.syntax_err(_encoding._linenum, |
2079 | "Invalid access to literal register parameter '%s' in %s.\n", |
2080 | rep_var, _encoding._name); |
2081 | assert( false, "invalid access to literal register parameter"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2081, "invalid access to literal register parameter"); abort (); }}; |
2082 | } |
2083 | } |
2084 | // literal constant parameters must be accessed as a 'constant' field |
2085 | if (_constant_status != LITERAL_NOT_SEEN) { |
2086 | assert(_constant_status == LITERAL_SEEN, "Must have seen constant literal before now"){ if (!(_constant_status == LITERAL_SEEN)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2086, "Must have seen constant literal before now"); abort( ); }}; |
2087 | if (strcmp(rep_var,"$constant") == 0) { |
2088 | _constant_status = LITERAL_ACCESSED; |
2089 | } else { |
2090 | _AD.syntax_err(_encoding._linenum, |
2091 | "Invalid access to literal constant parameter '%s' in %s.\n", |
2092 | rep_var, _encoding._name); |
2093 | } |
2094 | } |
2095 | } // end replacement and/or subfield |
2096 | |
2097 | } |
2098 | |
2099 | void add_rep_var(const char *rep_var) { |
2100 | // Handle subfield and replacement variables. |
2101 | if ( ( *rep_var == '$' ) && ( *(rep_var+1) == '$' ) ) { |
2102 | // Check for emit prefix, '$$emit32' |
2103 | assert( _cleared, "Can not nest $$$emit32"){ if (!(_cleared)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2103, "Can not nest $$$emit32"); abort(); }}; |
2104 | if ( strcmp(rep_var,"$$emit32") == 0 ) { |
2105 | _doing_emit_d32 = true; |
2106 | } |
2107 | else if ( strcmp(rep_var,"$$emit16") == 0 ) { |
2108 | _doing_emit_d16 = true; |
2109 | } |
2110 | else if ( strcmp(rep_var,"$$emit_hi") == 0 ) { |
2111 | _doing_emit_hi = true; |
2112 | } |
2113 | else if ( strcmp(rep_var,"$$emit_lo") == 0 ) { |
2114 | _doing_emit_lo = true; |
2115 | } |
2116 | else if ( strcmp(rep_var,"$$emit8") == 0 ) { |
2117 | _doing_emit8 = true; |
2118 | } |
2119 | else { |
2120 | _AD.syntax_err(_encoding._linenum, "Unsupported $$operation '%s'\n",rep_var); |
2121 | assert( false, "fatal();"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2121, "fatal();"); abort(); }}; |
2122 | } |
2123 | } |
2124 | else { |
2125 | // Update state for replacement variables |
2126 | update_state( rep_var ); |
2127 | _strings_to_emit.addName(rep_var); |
2128 | } |
2129 | _cleared = false; |
2130 | } |
2131 | |
2132 | void emit_replacement() { |
2133 | // A replacement variable or one of its subfields |
2134 | // Obtain replacement variable from list |
2135 | // const char *ec_rep_var = encoding->_rep_vars.iter(); |
2136 | const char *rep_var; |
2137 | _strings_to_emit.reset(); |
2138 | while ( (rep_var = _strings_to_emit.iter()) != NULL__null ) { |
2139 | |
2140 | if ( (*rep_var) == '$' ) { |
2141 | // A subfield variable, '$$' prefix |
2142 | emit_field( rep_var ); |
2143 | } else { |
2144 | if (_strings_to_emit.peek() != NULL__null && |
2145 | strcmp(_strings_to_emit.peek(), "$Address") == 0) { |
2146 | fprintf(_fp, "Address::make_raw("); |
2147 | |
2148 | emit_rep_var( rep_var ); |
2149 | fprintf(_fp,"->base(ra_,this,idx%d), ", _operand_idx); |
2150 | |
2151 | _reg_status = LITERAL_ACCESSED; |
2152 | emit_rep_var( rep_var ); |
2153 | fprintf(_fp,"->index(ra_,this,idx%d), ", _operand_idx); |
2154 | |
2155 | _reg_status = LITERAL_ACCESSED; |
2156 | emit_rep_var( rep_var ); |
2157 | fprintf(_fp,"->scale(), "); |
2158 | |
2159 | _reg_status = LITERAL_ACCESSED; |
2160 | emit_rep_var( rep_var ); |
2161 | Form::DataType stack_type = _operand ? _operand->is_user_name_for_sReg() : Form::none; |
2162 | if( _operand && _operand_idx==0 && stack_type != Form::none ) { |
2163 | fprintf(_fp,"->disp(ra_,this,0), "); |
2164 | } else { |
2165 | fprintf(_fp,"->disp(ra_,this,idx%d), ", _operand_idx); |
2166 | } |
2167 | |
2168 | _reg_status = LITERAL_ACCESSED; |
2169 | emit_rep_var( rep_var ); |
2170 | fprintf(_fp,"->disp_reloc())"); |
2171 | |
2172 | // skip trailing $Address |
2173 | _strings_to_emit.iter(); |
2174 | } else { |
2175 | // A replacement variable, '$' prefix |
2176 | const char* next = _strings_to_emit.peek(); |
2177 | const char* next2 = _strings_to_emit.peek(2); |
2178 | if (next != NULL__null && next2 != NULL__null && strcmp(next2, "$Register") == 0 && |
2179 | (strcmp(next, "$base") == 0 || strcmp(next, "$index") == 0)) { |
2180 | // handle $rev_var$$base$$Register and $rev_var$$index$$Register by |
2181 | // producing as_Register(opnd_array(#)->base(ra_,this,idx1)). |
2182 | fprintf(_fp, "as_Register("); |
2183 | // emit the operand reference |
2184 | emit_rep_var( rep_var ); |
2185 | rep_var = _strings_to_emit.iter(); |
2186 | assert(strcmp(rep_var, "$base") == 0 || strcmp(rep_var, "$index") == 0, "bad pattern"){ if (!(strcmp(rep_var, "$base") == 0 || strcmp(rep_var, "$index" ) == 0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2186, "bad pattern"); abort(); }}; |
2187 | // handle base or index |
2188 | emit_field(rep_var); |
2189 | rep_var = _strings_to_emit.iter(); |
2190 | assert(strcmp(rep_var, "$Register") == 0, "bad pattern"){ if (!(strcmp(rep_var, "$Register") == 0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2190, "bad pattern"); abort(); }}; |
2191 | // close up the parens |
2192 | fprintf(_fp, ")"); |
2193 | } else { |
2194 | emit_rep_var( rep_var ); |
2195 | } |
2196 | } |
2197 | } // end replacement and/or subfield |
2198 | } |
2199 | } |
2200 | |
2201 | void emit_reloc_type(const char* type) { |
2202 | fprintf(_fp, "%s", type) |
2203 | ; |
2204 | } |
2205 | |
2206 | |
2207 | void emit() { |
2208 | // |
2209 | // "emit_d32_reloc(" or "emit_hi_reloc" or "emit_lo_reloc" |
2210 | // |
2211 | // Emit the function name when generating an emit function |
2212 | if ( _doing_emit_d32 || _doing_emit_hi || _doing_emit_lo ) { |
2213 | const char *d32_hi_lo = _doing_emit_d32 ? "d32" : (_doing_emit_hi ? "hi" : "lo"); |
2214 | // In general, relocatable isn't known at compiler compile time. |
2215 | // Check results of prior scan |
2216 | if ( ! _may_reloc ) { |
2217 | // Definitely don't need relocation information |
2218 | fprintf( _fp, "emit_%s(cbuf, ", d32_hi_lo ); |
2219 | emit_replacement(); fprintf(_fp, ")"); |
2220 | } |
2221 | else { |
2222 | // Emit RUNTIME CHECK to see if value needs relocation info |
2223 | // If emitting a relocatable address, use 'emit_d32_reloc' |
2224 | const char *disp_constant = _doing_disp ? "disp" : _doing_constant ? "constant" : "INVALID"; |
2225 | assert( (_doing_disp || _doing_constant){ if (!((_doing_disp || _doing_constant) && !(_doing_disp && _doing_constant))) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2227, "Must be emitting either a displacement or a constant" ); abort(); }} |
2226 | && !(_doing_disp && _doing_constant),{ if (!((_doing_disp || _doing_constant) && !(_doing_disp && _doing_constant))) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2227, "Must be emitting either a displacement or a constant" ); abort(); }} |
2227 | "Must be emitting either a displacement or a constant"){ if (!((_doing_disp || _doing_constant) && !(_doing_disp && _doing_constant))) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2227, "Must be emitting either a displacement or a constant" ); abort(); }}; |
2228 | fprintf(_fp,"\n"); |
2229 | fprintf(_fp,"if ( opnd_array(%d)->%s_reloc() != relocInfo::none ) {\n", |
2230 | _operand_idx, disp_constant); |
2231 | fprintf(_fp," "); |
2232 | fprintf(_fp,"emit_%s_reloc(cbuf, ", d32_hi_lo ); |
2233 | emit_replacement(); fprintf(_fp,", "); |
2234 | fprintf(_fp,"opnd_array(%d)->%s_reloc(), ", |
2235 | _operand_idx, disp_constant); |
2236 | fprintf(_fp, "%d", _reloc_form);fprintf(_fp, ");"); |
2237 | fprintf(_fp,"\n"); |
2238 | fprintf(_fp,"} else {\n"); |
2239 | fprintf(_fp," emit_%s(cbuf, ", d32_hi_lo); |
2240 | emit_replacement(); fprintf(_fp, ");\n"); fprintf(_fp,"}"); |
2241 | } |
2242 | } |
2243 | else if ( _doing_emit_d16 ) { |
2244 | // Relocation of 16-bit values is not supported |
2245 | fprintf(_fp,"emit_d16(cbuf, "); |
2246 | emit_replacement(); fprintf(_fp, ")"); |
2247 | // No relocation done for 16-bit values |
2248 | } |
2249 | else if ( _doing_emit8 ) { |
2250 | // Relocation of 8-bit values is not supported |
2251 | fprintf(_fp,"emit_d8(cbuf, "); |
2252 | emit_replacement(); fprintf(_fp, ")"); |
2253 | // No relocation done for 8-bit values |
2254 | } |
2255 | else { |
2256 | // Not an emit# command, just output the replacement string. |
2257 | emit_replacement(); |
2258 | } |
2259 | |
2260 | // Get ready for next state collection. |
2261 | clear(); |
2262 | } |
2263 | |
2264 | private: |
2265 | |
2266 | // recognizes names which represent MacroAssembler register types |
2267 | // and return the conversion function to build them from OptoReg |
2268 | const char* reg_conversion(const char* rep_var) { |
2269 | if (strcmp(rep_var,"$Register") == 0) return "as_Register"; |
2270 | if (strcmp(rep_var,"$KRegister") == 0) return "as_KRegister"; |
2271 | if (strcmp(rep_var,"$FloatRegister") == 0) return "as_FloatRegister"; |
2272 | #if defined(IA32) || defined(AMD641) |
2273 | if (strcmp(rep_var,"$XMMRegister") == 0) return "as_XMMRegister"; |
2274 | #endif |
2275 | if (strcmp(rep_var,"$CondRegister") == 0) return "as_ConditionRegister"; |
2276 | #if defined(PPC64) |
2277 | if (strcmp(rep_var,"$VectorRegister") == 0) return "as_VectorRegister"; |
2278 | if (strcmp(rep_var,"$VectorSRegister") == 0) return "as_VectorSRegister"; |
2279 | #endif |
2280 | return NULL__null; |
2281 | } |
2282 | |
2283 | void emit_field(const char *rep_var) { |
2284 | const char* reg_convert = reg_conversion(rep_var); |
2285 | |
2286 | // A subfield variable, '$$subfield' |
2287 | if ( strcmp(rep_var, "$reg") == 0 || reg_convert != NULL__null) { |
2288 | // $reg form or the $Register MacroAssembler type conversions |
2289 | assert( _operand_idx != -1,{ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2290, "Must use this subfield after operand"); abort(); }} |
2290 | "Must use this subfield after operand"){ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2290, "Must use this subfield after operand"); abort(); }}; |
2291 | if( _reg_status == LITERAL_NOT_SEEN ) { |
2292 | if (_processing_noninput) { |
2293 | const Form *local = _inst._localNames[_operand_name]; |
2294 | OperandForm *oper = local->is_operand(); |
2295 | const RegDef* first = oper->get_RegClass()->find_first_elem(); |
2296 | if (reg_convert != NULL__null) { |
2297 | fprintf(_fp, "%s(%s_enc)", reg_convert, first->_regname); |
2298 | } else { |
2299 | fprintf(_fp, "%s_enc", first->_regname); |
2300 | } |
2301 | } else { |
2302 | fprintf(_fp,"->%s(ra_,this", reg_convert != NULL__null ? reg_convert : "reg"); |
2303 | // Add parameter for index position, if not result operand |
2304 | if( _operand_idx != 0 ) fprintf(_fp,",idx%d", _operand_idx); |
2305 | fprintf(_fp,")"); |
2306 | fprintf(_fp, "/* %s */", _operand_name); |
2307 | } |
2308 | } else { |
2309 | assert( _reg_status == LITERAL_OUTPUT, "should have output register literal in emit_rep_var"){ if (!(_reg_status == LITERAL_OUTPUT)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2309, "should have output register literal in emit_rep_var" ); abort(); }}; |
2310 | // Register literal has already been sent to output file, nothing more needed |
2311 | } |
2312 | } |
2313 | else if ( strcmp(rep_var,"$base") == 0 ) { |
2314 | assert( _operand_idx != -1,{ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2315, "Must use this subfield after operand"); abort(); }} |
2315 | "Must use this subfield after operand"){ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2315, "Must use this subfield after operand"); abort(); }}; |
2316 | assert( ! _may_reloc, "UnImplemented()"){ if (!(! _may_reloc)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2316, "UnImplemented()"); abort(); }}; |
2317 | fprintf(_fp,"->base(ra_,this,idx%d)", _operand_idx); |
2318 | } |
2319 | else if ( strcmp(rep_var,"$index") == 0 ) { |
2320 | assert( _operand_idx != -1,{ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2321, "Must use this subfield after operand"); abort(); }} |
2321 | "Must use this subfield after operand"){ if (!(_operand_idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2321, "Must use this subfield after operand"); abort(); }}; |
2322 | assert( ! _may_reloc, "UnImplemented()"){ if (!(! _may_reloc)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2322, "UnImplemented()"); abort(); }}; |
2323 | fprintf(_fp,"->index(ra_,this,idx%d)", _operand_idx); |
2324 | } |
2325 | else if ( strcmp(rep_var,"$scale") == 0 ) { |
2326 | assert( ! _may_reloc, "UnImplemented()"){ if (!(! _may_reloc)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2326, "UnImplemented()"); abort(); }}; |
2327 | fprintf(_fp,"->scale()"); |
2328 | } |
2329 | else if ( strcmp(rep_var,"$cmpcode") == 0 ) { |
2330 | assert( ! _may_reloc, "UnImplemented()"){ if (!(! _may_reloc)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2330, "UnImplemented()"); abort(); }}; |
2331 | fprintf(_fp,"->ccode()"); |
2332 | } |
2333 | else if ( strcmp(rep_var,"$constant") == 0 ) { |
2334 | if( _constant_status == LITERAL_NOT_SEEN ) { |
2335 | if ( _constant_type == Form::idealD ) { |
2336 | fprintf(_fp,"->constantD()"); |
2337 | } else if ( _constant_type == Form::idealF ) { |
2338 | fprintf(_fp,"->constantF()"); |
2339 | } else if ( _constant_type == Form::idealL ) { |
2340 | fprintf(_fp,"->constantL()"); |
2341 | } else { |
2342 | fprintf(_fp,"->constant()"); |
2343 | } |
2344 | } else { |
2345 | assert( _constant_status == LITERAL_OUTPUT, "should have output constant literal in emit_rep_var"){ if (!(_constant_status == LITERAL_OUTPUT)) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2345, "should have output constant literal in emit_rep_var" ); abort(); }}; |
2346 | // Constant literal has already been sent to output file, nothing more needed |
2347 | } |
2348 | } |
2349 | else if ( strcmp(rep_var,"$disp") == 0 ) { |
2350 | Form::DataType stack_type = _operand ? _operand->is_user_name_for_sReg() : Form::none; |
2351 | if( _operand && _operand_idx==0 && stack_type != Form::none ) { |
2352 | fprintf(_fp,"->disp(ra_,this,0)"); |
2353 | } else { |
2354 | fprintf(_fp,"->disp(ra_,this,idx%d)", _operand_idx); |
2355 | } |
2356 | } |
2357 | else if ( strcmp(rep_var,"$label") == 0 ) { |
2358 | fprintf(_fp,"->label()"); |
2359 | } |
2360 | else if ( strcmp(rep_var,"$method") == 0 ) { |
2361 | fprintf(_fp,"->method()"); |
2362 | } |
2363 | else { |
2364 | printf("emit_field: %s\n",rep_var); |
2365 | globalAD->syntax_err(_inst._linenum, "Unknown replacement variable %s in format statement of %s.", |
2366 | rep_var, _inst._ident); |
2367 | assert( false, "UnImplemented()"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2367, "UnImplemented()"); abort(); }}; |
2368 | } |
2369 | } |
2370 | |
2371 | |
2372 | void emit_rep_var(const char *rep_var) { |
2373 | _processing_noninput = false; |
2374 | // A replacement variable, originally '$' |
2375 | if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { |
2376 | if ((_inst._opcode == NULL__null) || !_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) )) { |
2377 | // Missing opcode |
2378 | _AD.syntax_err( _inst._linenum, |
2379 | "Missing $%s opcode definition in %s, used by encoding %s\n", |
2380 | rep_var, _inst._ident, _encoding._name); |
2381 | } |
2382 | } |
2383 | else if (strcmp(rep_var, "constanttablebase") == 0) { |
2384 | fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))"); |
2385 | } |
2386 | else if (strcmp(rep_var, "constantoffset") == 0) { |
2387 | fprintf(_fp, "constant_offset()"); |
2388 | } |
2389 | else if (strcmp(rep_var, "constantaddress") == 0) { |
2390 | fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())"); |
2391 | } |
2392 | else { |
2393 | // Lookup its position in parameter list |
2394 | int param_no = _encoding.rep_var_index(rep_var); |
2395 | if ( param_no == -1 ) { |
2396 | _AD.syntax_err( _encoding._linenum, |
2397 | "Replacement variable %s not found in enc_class %s.\n", |
2398 | rep_var, _encoding._name); |
2399 | } |
2400 | // Lookup the corresponding ins_encode parameter |
2401 | const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no); |
2402 | |
2403 | // Check if instruction's actual parameter is a local name in the instruction |
2404 | const Form *local = _inst._localNames[inst_rep_var]; |
2405 | OpClassForm *opc = (local != NULL__null) ? local->is_opclass() : NULL__null; |
2406 | // Note: assert removed to allow constant and symbolic parameters |
2407 | // assert( opc, "replacement variable was not found in local names"); |
2408 | // Lookup the index position iff the replacement variable is a localName |
2409 | int idx = (opc != NULL__null) ? _inst.operand_position_format(inst_rep_var) : -1; |
2410 | if( idx != -1 ) { |
2411 | if (_inst.is_noninput_operand(idx)) { |
2412 | // This operand isn't a normal input so printing it is done |
2413 | // specially. |
2414 | _processing_noninput = true; |
2415 | } else { |
2416 | // Output the emit code for this operand |
2417 | fprintf(_fp,"opnd_array(%d)",idx); |
2418 | } |
2419 | assert( _operand == opc->is_operand(),{ if (!(_operand == opc->is_operand())) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2420, "Previous emit $operand does not match current"); abort (); }} |
2420 | "Previous emit $operand does not match current"){ if (!(_operand == opc->is_operand())) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2420, "Previous emit $operand does not match current"); abort (); }}; |
2421 | } |
2422 | else if( ADLParser::is_literal_constant(inst_rep_var) ) { |
2423 | // else check if it is a constant expression |
2424 | // Removed following assert to allow primitive C types as arguments to encodings |
2425 | // assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); |
2426 | fprintf(_fp,"(%s)", inst_rep_var); |
2427 | _constant_status = LITERAL_OUTPUT; |
2428 | } |
2429 | else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { |
2430 | // else check if "primary", "secondary", "tertiary" |
2431 | assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"){ if (!(_constant_status == LITERAL_ACCESSED)) { fprintf(stderr , "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2431, "Must be processing a literal constant parameter"); abort (); }}; |
2432 | if ((_inst._opcode == NULL__null) || !_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) )) { |
2433 | // Missing opcode |
2434 | _AD.syntax_err( _inst._linenum, |
2435 | "Missing $%s opcode definition in %s\n", |
2436 | rep_var, _inst._ident); |
2437 | |
2438 | } |
2439 | _constant_status = LITERAL_OUTPUT; |
2440 | } |
2441 | else if((_AD.get_registers() != NULL__null ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL__null)) { |
2442 | // Instruction provided a literal register name for this parameter |
2443 | // Check that encoding specifies $$$reg to resolve.as register. |
2444 | assert( _reg_status == LITERAL_ACCESSED, "Must be processing a literal register parameter"){ if (!(_reg_status == LITERAL_ACCESSED)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2444, "Must be processing a literal register parameter"); abort (); }}; |
2445 | fprintf(_fp,"(%s_enc)", inst_rep_var); |
2446 | _reg_status = LITERAL_OUTPUT; |
2447 | } |
2448 | else { |
2449 | // Check for unimplemented functionality before hard failure |
2450 | assert(opc != NULL && strcmp(opc->_ident, "label") == 0, "Unimplemented Label"){ if (!(opc != __null && strcmp(opc->_ident, "label" ) == 0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2450, "Unimplemented Label"); abort(); }}; |
2451 | assert(false, "ShouldNotReachHere()"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2451, "ShouldNotReachHere()"); abort(); }}; |
2452 | } |
2453 | // all done |
2454 | } |
2455 | } |
2456 | |
2457 | }; // end class DefineEmitState |
2458 | |
2459 | |
2460 | void ArchDesc::defineSize(FILE *fp, InstructForm &inst) { |
2461 | |
2462 | //(1) |
2463 | // Output instruction's emit prototype |
2464 | fprintf(fp,"uint %sNode::size(PhaseRegAlloc *ra_) const {\n", |
2465 | inst._ident); |
2466 | |
2467 | fprintf(fp, " assert(VerifyOops || MachNode::size(ra_) <= %s, \"bad fixed size\");\n", inst._size); |
2468 | |
2469 | //(2) |
2470 | // Print the size |
2471 | fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size); |
2472 | |
2473 | // (3) and (4) |
2474 | fprintf(fp,"}\n\n"); |
2475 | } |
2476 | |
2477 | // Emit postalloc expand function. |
2478 | void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { |
2479 | InsEncode *ins_encode = inst._insencode; |
2480 | |
2481 | // Output instruction's postalloc_expand prototype. |
2482 | fprintf(fp, "void %sNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {\n", |
2483 | inst._ident); |
2484 | |
2485 | assert((_encode != NULL) && (ins_encode != NULL), "You must define an encode section."){ if (!((_encode != __null) && (ins_encode != __null) )) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2485, "You must define an encode section."); abort(); }}; |
2486 | |
2487 | // Output each operand's offset into the array of registers. |
2488 | inst.index_temps(fp, _globalNames); |
2489 | |
2490 | // Output variables "unsigned idx_<par_name>", Node *n_<par_name> and "MachOpnd *op_<par_name>" |
2491 | // for each parameter <par_name> specified in the encoding. |
2492 | ins_encode->reset(); |
2493 | const char *ec_name = ins_encode->encode_class_iter(); |
2494 | assert(ec_name != NULL, "Postalloc expand must specify an encoding."){ if (!(ec_name != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2494, "Postalloc expand must specify an encoding."); abort( ); }}; |
2495 | |
2496 | EncClass *encoding = _encode->encClass(ec_name); |
2497 | if (encoding == NULL__null) { |
2498 | fprintf(stderrstderr, "User did not define contents of this encode_class: %s\n", ec_name); |
2499 | abort(); |
2500 | } |
2501 | if (ins_encode->current_encoding_num_args() != encoding->num_args()) { |
2502 | globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", |
2503 | inst._ident, ins_encode->current_encoding_num_args(), |
2504 | ec_name, encoding->num_args()); |
2505 | } |
2506 | |
2507 | fprintf(fp, " // Access to ins and operands for postalloc expand.\n"); |
2508 | const int buflen = 2000; |
2509 | char idxbuf[buflen]; char *ib = idxbuf; idxbuf[0] = '\0'; |
2510 | char nbuf [buflen]; char *nb = nbuf; nbuf[0] = '\0'; |
2511 | char opbuf [buflen]; char *ob = opbuf; opbuf[0] = '\0'; |
2512 | |
2513 | encoding->_parameter_type.reset(); |
2514 | encoding->_parameter_name.reset(); |
2515 | const char *type = encoding->_parameter_type.iter(); |
2516 | const char *name = encoding->_parameter_name.iter(); |
2517 | int param_no = 0; |
2518 | for (; (type != NULL__null) && (name != NULL__null); |
2519 | (type = encoding->_parameter_type.iter()), (name = encoding->_parameter_name.iter())) { |
2520 | const char* arg_name = ins_encode->rep_var_name(inst, param_no); |
2521 | int idx = inst.operand_position_format(arg_name); |
2522 | if (strcmp(arg_name, "constanttablebase") == 0) { |
2523 | ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", |
2524 | name, type, arg_name); |
2525 | nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); |
2526 | // There is no operand for the constanttablebase. |
2527 | } else if (inst.is_noninput_operand(idx)) { |
2528 | globalAD->syntax_err(inst._linenum, |
2529 | "In %s: you can not pass the non-input %s to a postalloc expand encoding.\n", |
2530 | inst._ident, arg_name); |
2531 | } else { |
2532 | ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", |
2533 | name, idx, type, arg_name); |
2534 | nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); |
2535 | ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); |
2536 | } |
2537 | param_no++; |
2538 | } |
2539 | assert(ib < &idxbuf[buflen-1] && nb < &nbuf[buflen-1] && ob < &opbuf[buflen-1], "buffer overflow"){ if (!(ib < &idxbuf[buflen-1] && nb < & nbuf[buflen-1] && ob < &opbuf[buflen-1])) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2539, "buffer overflow"); abort(); }}; |
2540 | |
2541 | fprintf(fp, "%s", idxbuf); |
2542 | fprintf(fp, " Node *n_region = lookup(0);\n"); |
2543 | fprintf(fp, "%s%s", nbuf, opbuf); |
2544 | fprintf(fp, " Compile *C = ra_->C;\n"); |
2545 | |
2546 | // Output this instruction's encodings. |
2547 | fprintf(fp, " {"); |
2548 | const char *ec_code = NULL__null; |
2549 | const char *ec_rep_var = NULL__null; |
2550 | assert(encoding == _encode->encClass(ec_name), ""){ if (!(encoding == _encode->encClass(ec_name))) { fprintf (stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2550, ""); abort(); }}; |
2551 | |
2552 | DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst); |
2553 | encoding->_code.reset(); |
2554 | encoding->_rep_vars.reset(); |
2555 | // Process list of user-defined strings, |
2556 | // and occurrences of replacement variables. |
2557 | // Replacement Vars are pushed into a list and then output. |
2558 | while ((ec_code = encoding->_code.iter()) != NULL__null) { |
2559 | if (! encoding->_code.is_signal(ec_code)) { |
2560 | // Emit pending code. |
2561 | pending.emit(); |
2562 | pending.clear(); |
2563 | // Emit this code section. |
2564 | fprintf(fp, "%s", ec_code); |
2565 | } else { |
2566 | // A replacement variable or one of its subfields. |
2567 | // Obtain replacement variable from list. |
2568 | ec_rep_var = encoding->_rep_vars.iter(); |
2569 | pending.add_rep_var(ec_rep_var); |
2570 | } |
2571 | } |
2572 | // Emit pending code. |
2573 | pending.emit(); |
2574 | pending.clear(); |
2575 | fprintf(fp, " }\n"); |
2576 | |
2577 | fprintf(fp, "}\n\n"); |
2578 | |
2579 | ec_name = ins_encode->encode_class_iter(); |
2580 | assert(ec_name == NULL, "Postalloc expand may only have one encoding."){ if (!(ec_name == __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2580, "Postalloc expand may only have one encoding."); abort (); }}; |
2581 | } |
2582 | |
2583 | // defineEmit ----------------------------------------------------------------- |
2584 | void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) { |
2585 | InsEncode* encode = inst._insencode; |
2586 | |
2587 | // (1) |
2588 | // Output instruction's emit prototype |
2589 | fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident); |
2590 | |
2591 | // If user did not define an encode section, |
2592 | // provide stub that does not generate any machine code. |
2593 | if( (_encode == NULL__null) || (encode == NULL__null) ) { |
2594 | fprintf(fp, " // User did not define an encode section.\n"); |
2595 | fprintf(fp, "}\n"); |
2596 | return; |
2597 | } |
2598 | |
2599 | // Save current instruction's starting address (helps with relocation). |
2600 | fprintf(fp, " cbuf.set_insts_mark();\n"); |
2601 | |
2602 | // For MachConstantNodes which are ideal jump nodes, fill the jump table. |
2603 | if (inst.is_mach_constant() && inst.is_ideal_jump()) { |
2604 | fprintf(fp, " ra_->C->output()->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n"); |
2605 | } |
2606 | |
2607 | // Output each operand's offset into the array of registers. |
2608 | inst.index_temps(fp, _globalNames); |
2609 | |
2610 | // Output this instruction's encodings |
2611 | const char *ec_name; |
2612 | bool user_defined = false; |
2613 | encode->reset(); |
2614 | while ((ec_name = encode->encode_class_iter()) != NULL__null) { |
2615 | fprintf(fp, " {\n"); |
2616 | // Output user-defined encoding |
2617 | user_defined = true; |
2618 | |
2619 | const char *ec_code = NULL__null; |
2620 | const char *ec_rep_var = NULL__null; |
2621 | EncClass *encoding = _encode->encClass(ec_name); |
2622 | if (encoding == NULL__null) { |
2623 | fprintf(stderrstderr, "User did not define contents of this encode_class: %s\n", ec_name); |
2624 | abort(); |
2625 | } |
2626 | |
2627 | if (encode->current_encoding_num_args() != encoding->num_args()) { |
2628 | globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", |
2629 | inst._ident, encode->current_encoding_num_args(), |
2630 | ec_name, encoding->num_args()); |
2631 | } |
2632 | |
2633 | DefineEmitState pending(fp, *this, *encoding, *encode, inst); |
2634 | encoding->_code.reset(); |
2635 | encoding->_rep_vars.reset(); |
2636 | // Process list of user-defined strings, |
2637 | // and occurrences of replacement variables. |
2638 | // Replacement Vars are pushed into a list and then output |
2639 | while ((ec_code = encoding->_code.iter()) != NULL__null) { |
2640 | if (!encoding->_code.is_signal(ec_code)) { |
2641 | // Emit pending code |
2642 | pending.emit(); |
2643 | pending.clear(); |
2644 | // Emit this code section |
2645 | fprintf(fp, "%s", ec_code); |
2646 | } else { |
2647 | // A replacement variable or one of its subfields |
2648 | // Obtain replacement variable from list |
2649 | ec_rep_var = encoding->_rep_vars.iter(); |
2650 | pending.add_rep_var(ec_rep_var); |
2651 | } |
2652 | } |
2653 | // Emit pending code |
2654 | pending.emit(); |
2655 | pending.clear(); |
2656 | fprintf(fp, " }\n"); |
2657 | } // end while instruction's encodings |
2658 | |
2659 | // Check if user stated which encoding to user |
2660 | if ( user_defined == false ) { |
2661 | fprintf(fp, " // User did not define which encode class to use.\n"); |
2662 | } |
2663 | |
2664 | // (3) and (4) |
2665 | fprintf(fp, "}\n\n"); |
2666 | } |
2667 | |
2668 | // defineEvalConstant --------------------------------------------------------- |
2669 | void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) { |
2670 | InsEncode* encode = inst._constant; |
2671 | |
2672 | // (1) |
2673 | // Output instruction's emit prototype |
2674 | fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident); |
2675 | |
2676 | // For ideal jump nodes, add a jump-table entry. |
2677 | if (inst.is_ideal_jump()) { |
2678 | fprintf(fp, " _constant = C->output()->constant_table().add_jump_table(this);\n"); |
2679 | } |
2680 | |
2681 | // If user did not define an encode section, |
2682 | // provide stub that does not generate any machine code. |
2683 | if ((_encode == NULL__null) || (encode == NULL__null)) { |
2684 | fprintf(fp, " // User did not define an encode section.\n"); |
2685 | fprintf(fp, "}\n"); |
2686 | return; |
2687 | } |
2688 | |
2689 | // Output this instruction's encodings |
2690 | const char *ec_name; |
2691 | bool user_defined = false; |
2692 | encode->reset(); |
2693 | while ((ec_name = encode->encode_class_iter()) != NULL__null) { |
2694 | fprintf(fp, " {\n"); |
2695 | // Output user-defined encoding |
2696 | user_defined = true; |
2697 | |
2698 | const char *ec_code = NULL__null; |
2699 | const char *ec_rep_var = NULL__null; |
2700 | EncClass *encoding = _encode->encClass(ec_name); |
2701 | if (encoding == NULL__null) { |
2702 | fprintf(stderrstderr, "User did not define contents of this encode_class: %s\n", ec_name); |
2703 | abort(); |
2704 | } |
2705 | |
2706 | if (encode->current_encoding_num_args() != encoding->num_args()) { |
2707 | globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", |
2708 | inst._ident, encode->current_encoding_num_args(), |
2709 | ec_name, encoding->num_args()); |
2710 | } |
2711 | |
2712 | DefineEmitState pending(fp, *this, *encoding, *encode, inst); |
2713 | encoding->_code.reset(); |
2714 | encoding->_rep_vars.reset(); |
2715 | // Process list of user-defined strings, |
2716 | // and occurrences of replacement variables. |
2717 | // Replacement Vars are pushed into a list and then output |
2718 | while ((ec_code = encoding->_code.iter()) != NULL__null) { |
2719 | if (!encoding->_code.is_signal(ec_code)) { |
2720 | // Emit pending code |
2721 | pending.emit(); |
2722 | pending.clear(); |
2723 | // Emit this code section |
2724 | fprintf(fp, "%s", ec_code); |
2725 | } else { |
2726 | // A replacement variable or one of its subfields |
2727 | // Obtain replacement variable from list |
2728 | ec_rep_var = encoding->_rep_vars.iter(); |
2729 | pending.add_rep_var(ec_rep_var); |
2730 | } |
2731 | } |
2732 | // Emit pending code |
2733 | pending.emit(); |
2734 | pending.clear(); |
2735 | fprintf(fp, " }\n"); |
2736 | } // end while instruction's encodings |
2737 | |
2738 | // Check if user stated which encoding to user |
2739 | if (user_defined == false) { |
2740 | fprintf(fp, " // User did not define which encode class to use.\n"); |
2741 | } |
2742 | |
2743 | // (3) and (4) |
2744 | fprintf(fp, "}\n"); |
2745 | } |
2746 | |
2747 | // --------------------------------------------------------------------------- |
2748 | //--------Utilities to build MachOper and MachNode derived Classes------------ |
2749 | // --------------------------------------------------------------------------- |
2750 | |
2751 | //------------------------------Utilities to build Operand Classes------------ |
2752 | static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) { |
2753 | uintunsigned int num_edges = oper.num_edges(globals); |
2754 | if( num_edges != 0 ) { |
2755 | // Method header |
2756 | fprintf(fp, "const RegMask *%sOper::in_RegMask(int index) const {\n", |
2757 | oper._ident); |
2758 | |
2759 | // Assert that the index is in range. |
2760 | fprintf(fp, " assert(0 <= index && index < %d, \"index out of range\");\n", |
2761 | num_edges); |
2762 | |
2763 | // Figure out if all RegMasks are the same. |
2764 | const char* first_reg_class = oper.in_reg_class(0, globals); |
2765 | bool all_same = true; |
2766 | assert(first_reg_class != NULL, "did not find register mask"){ if (!(first_reg_class != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2766, "did not find register mask"); abort(); }}; |
2767 | |
2768 | for (uintunsigned int index = 1; all_same && index < num_edges; index++) { |
2769 | const char* some_reg_class = oper.in_reg_class(index, globals); |
2770 | assert(some_reg_class != NULL, "did not find register mask"){ if (!(some_reg_class != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2770, "did not find register mask"); abort(); }}; |
2771 | if (strcmp(first_reg_class, some_reg_class) != 0) { |
2772 | all_same = false; |
2773 | } |
2774 | } |
2775 | |
2776 | if (all_same) { |
2777 | // Return the sole RegMask. |
2778 | if (strcmp(first_reg_class, "stack_slots") == 0) { |
2779 | fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); |
2780 | } else if (strcmp(first_reg_class, "dynamic") == 0) { |
2781 | fprintf(fp," return &RegMask::Empty;\n"); |
2782 | } else { |
2783 | const char* first_reg_class_to_upper = toUpper(first_reg_class); |
2784 | fprintf(fp," return &%s_mask();\n", first_reg_class_to_upper); |
2785 | delete[] first_reg_class_to_upper; |
2786 | } |
2787 | } else { |
2788 | // Build a switch statement to return the desired mask. |
2789 | fprintf(fp," switch (index) {\n"); |
2790 | |
2791 | for (uintunsigned int index = 0; index < num_edges; index++) { |
2792 | const char *reg_class = oper.in_reg_class(index, globals); |
2793 | assert(reg_class != NULL, "did not find register mask"){ if (!(reg_class != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2793, "did not find register mask"); abort(); }}; |
2794 | if( !strcmp(reg_class, "stack_slots") ) { |
2795 | fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); |
2796 | } else { |
2797 | const char* reg_class_to_upper = toUpper(reg_class); |
2798 | fprintf(fp, " case %d: return &%s_mask();\n", index, reg_class_to_upper); |
2799 | delete[] reg_class_to_upper; |
2800 | } |
2801 | } |
2802 | fprintf(fp," }\n"); |
2803 | fprintf(fp," ShouldNotReachHere();\n"); |
2804 | fprintf(fp," return NULL;\n"); |
2805 | } |
2806 | |
2807 | // Method close |
2808 | fprintf(fp, "}\n\n"); |
2809 | } |
2810 | } |
2811 | |
2812 | // generate code to create a clone for a class derived from MachOper |
2813 | // |
2814 | // (0) MachOper *MachOperXOper::clone() const { |
2815 | // (1) return new MachXOper( _ccode, _c0, _c1, ..., _cn); |
2816 | // (2) } |
2817 | // |
2818 | static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) { |
2819 | fprintf(fp,"MachOper *%sOper::clone() const {\n", oper._ident); |
2820 | // Check for constants that need to be copied over |
2821 | const int num_consts = oper.num_consts(globalNames); |
2822 | const bool is_ideal_bool = oper.is_ideal_bool(); |
2823 | if( (num_consts > 0) ) { |
2824 | fprintf(fp," return new %sOper(", oper._ident); |
2825 | // generate parameters for constants |
2826 | int i = 0; |
2827 | fprintf(fp,"_c%d", i); |
2828 | for( i = 1; i < num_consts; ++i) { |
2829 | fprintf(fp,", _c%d", i); |
2830 | } |
2831 | // finish line (1) |
2832 | fprintf(fp,");\n"); |
2833 | } |
2834 | else { |
2835 | assert( num_consts == 0, "Currently support zero or one constant per operand clone function"){ if (!(num_consts == 0)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2835, "Currently support zero or one constant per operand clone function" ); abort(); }}; |
2836 | fprintf(fp," return new %sOper();\n", oper._ident); |
2837 | } |
2838 | // finish method |
2839 | fprintf(fp,"}\n"); |
2840 | } |
2841 | |
2842 | // Helper functions for bug 4796752, abstracted with minimal modification |
2843 | // from define_oper_interface() |
2844 | OperandForm *rep_var_to_operand(const char *encoding, OperandForm &oper, FormDict &globals) { |
2845 | OperandForm *op = NULL__null; |
2846 | // Check for replacement variable |
2847 | if( *encoding == '$' ) { |
2848 | // Replacement variable |
2849 | const char *rep_var = encoding + 1; |
2850 | // Lookup replacement variable, rep_var, in operand's component list |
2851 | const Component *comp = oper._components.search(rep_var); |
2852 | assert( comp != NULL, "Replacement variable not found in components"){ if (!(comp != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2852, "Replacement variable not found in components"); abort (); }}; |
2853 | // Lookup operand form for replacement variable's type |
2854 | const char *type = comp->_type; |
2855 | Form *form = (Form*)globals[type]; |
2856 | assert( form != NULL, "Replacement variable's type not found"){ if (!(form != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2856, "Replacement variable's type not found"); abort(); }}; |
2857 | op = form->is_operand(); |
2858 | assert( op, "Attempting to emit a non-register or non-constant"){ if (!(op)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2858, "Attempting to emit a non-register or non-constant"); abort(); }}; |
2859 | } |
2860 | |
2861 | return op; |
2862 | } |
2863 | |
2864 | int rep_var_to_constant_index(const char *encoding, OperandForm &oper, FormDict &globals) { |
2865 | int idx = -1; |
2866 | // Check for replacement variable |
2867 | if( *encoding == '$' ) { |
2868 | // Replacement variable |
2869 | const char *rep_var = encoding + 1; |
2870 | // Lookup replacement variable, rep_var, in operand's component list |
2871 | const Component *comp = oper._components.search(rep_var); |
2872 | assert( comp != NULL, "Replacement variable not found in components"){ if (!(comp != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2872, "Replacement variable not found in components"); abort (); }}; |
2873 | // Lookup operand form for replacement variable's type |
2874 | const char *type = comp->_type; |
2875 | Form *form = (Form*)globals[type]; |
2876 | assert( form != NULL, "Replacement variable's type not found"){ if (!(form != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2876, "Replacement variable's type not found"); abort(); }}; |
2877 | OperandForm *op = form->is_operand(); |
2878 | assert( op, "Attempting to emit a non-register or non-constant"){ if (!(op)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2878, "Attempting to emit a non-register or non-constant"); abort(); }}; |
2879 | // Check that this is a constant and find constant's index: |
2880 | if (op->_matrule && op->_matrule->is_base_constant(globals)) { |
2881 | idx = oper.constant_position(globals, comp); |
2882 | } |
2883 | } |
2884 | |
2885 | return idx; |
2886 | } |
2887 | |
2888 | bool is_regI(const char *encoding, OperandForm &oper, FormDict &globals ) { |
2889 | bool is_regI = false; |
2890 | |
2891 | OperandForm *op = rep_var_to_operand(encoding, oper, globals); |
2892 | if( op != NULL__null ) { |
2893 | // Check that this is a register |
2894 | if ( (op->_matrule && op->_matrule->is_base_register(globals)) ) { |
2895 | // Register |
2896 | const char* ideal = op->ideal_type(globals); |
2897 | is_regI = (ideal && (op->ideal_to_Reg_type(ideal) == Form::idealI)); |
2898 | } |
2899 | } |
2900 | |
2901 | return is_regI; |
2902 | } |
2903 | |
2904 | bool is_conP(const char *encoding, OperandForm &oper, FormDict &globals ) { |
2905 | bool is_conP = false; |
2906 | |
2907 | OperandForm *op = rep_var_to_operand(encoding, oper, globals); |
2908 | if( op != NULL__null ) { |
2909 | // Check that this is a constant pointer |
2910 | if (op->_matrule && op->_matrule->is_base_constant(globals)) { |
2911 | // Constant |
2912 | Form::DataType dtype = op->is_base_constant(globals); |
2913 | is_conP = (dtype == Form::idealP); |
2914 | } |
2915 | } |
2916 | |
2917 | return is_conP; |
2918 | } |
2919 | |
2920 | |
2921 | // Define a MachOper interface methods |
2922 | void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals, |
2923 | const char *name, const char *encoding) { |
2924 | bool emit_position = false; |
2925 | int position = -1; |
2926 | |
2927 | fprintf(fp," virtual int %s", name); |
2928 | // Generate access method for base, index, scale, disp, ... |
2929 | if( (strcmp(name,"base") == 0) || (strcmp(name,"index") == 0) ) { |
2930 | fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); |
2931 | emit_position = true; |
2932 | } else if ( (strcmp(name,"disp") == 0) ) { |
2933 | fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); |
2934 | } else { |
2935 | fprintf(fp, "() const {\n"); |
2936 | } |
2937 | |
2938 | // Check for hexadecimal value OR replacement variable |
2939 | if( *encoding == '$' ) { |
2940 | // Replacement variable |
2941 | const char *rep_var = encoding + 1; |
2942 | fprintf(fp," // Replacement variable: %s\n", encoding+1); |
2943 | // Lookup replacement variable, rep_var, in operand's component list |
2944 | const Component *comp = oper._components.search(rep_var); |
2945 | assert( comp != NULL, "Replacement variable not found in components"){ if (!(comp != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2945, "Replacement variable not found in components"); abort (); }}; |
2946 | // Lookup operand form for replacement variable's type |
2947 | const char *type = comp->_type; |
2948 | Form *form = (Form*)globals[type]; |
2949 | assert( form != NULL, "Replacement variable's type not found"){ if (!(form != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2949, "Replacement variable's type not found"); abort(); }}; |
2950 | OperandForm *op = form->is_operand(); |
2951 | assert( op, "Attempting to emit a non-register or non-constant"){ if (!(op)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2951, "Attempting to emit a non-register or non-constant"); abort(); }}; |
2952 | // Check that this is a register or a constant and generate code: |
2953 | if ( (op->_matrule && op->_matrule->is_base_register(globals)) ) { |
2954 | // Register |
2955 | int idx_offset = oper.register_position( globals, rep_var); |
2956 | position = idx_offset; |
2957 | fprintf(fp," return (int)ra_->get_encode(node->in(idx"); |
2958 | if ( idx_offset > 0 ) fprintf(fp, "+%d",idx_offset); |
2959 | fprintf(fp,"));\n"); |
2960 | } else if ( op->ideal_to_sReg_type(op->_ident) != Form::none ) { |
2961 | // StackSlot for an sReg comes either from input node or from self, when idx==0 |
2962 | fprintf(fp," if( idx != 0 ) {\n"); |
2963 | fprintf(fp," // Access stack offset (register number) for input operand\n"); |
2964 | fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node->in(idx)));/* sReg */\n"); |
2965 | fprintf(fp," }\n"); |
2966 | fprintf(fp," // Access stack offset (register number) from myself\n"); |
2967 | fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node));/* sReg */\n"); |
2968 | } else if (op->_matrule && op->_matrule->is_base_constant(globals)) { |
2969 | // Constant |
2970 | // Check which constant this name maps to: _c0, _c1, ..., _cn |
2971 | const int idx = oper.constant_position(globals, comp); |
2972 | assert( idx != -1, "Constant component not found in operand"){ if (!(idx != -1)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2972, "Constant component not found in operand"); abort(); } }; |
2973 | // Output code for this constant, type dependent. |
2974 | fprintf(fp," return (int)" ); |
2975 | oper.access_constant(fp, globals, (uintunsigned int)idx /* , const_type */); |
2976 | fprintf(fp,";\n"); |
2977 | } else { |
2978 | assert( false, "Attempting to emit a non-register or non-constant"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2978, "Attempting to emit a non-register or non-constant"); abort(); }}; |
2979 | } |
2980 | } |
2981 | else if( *encoding == '0' && *(encoding+1) == 'x' ) { |
2982 | // Hex value |
2983 | fprintf(fp," return %s;\n", encoding); |
2984 | } else { |
2985 | globalAD->syntax_err(oper._linenum, "In operand %s: Do not support this encode constant: '%s' for %s.", |
2986 | oper._ident, encoding, name); |
2987 | assert( false, "Do not support octal or decimal encode constants"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 2987, "Do not support octal or decimal encode constants"); abort (); }}; |
2988 | } |
2989 | fprintf(fp," }\n"); |
2990 | |
2991 | if( emit_position && (position != -1) && (oper.num_edges(globals) > 0) ) { |
2992 | fprintf(fp," virtual int %s_position() const { return %d; }\n", name, position); |
2993 | MemInterface *mem_interface = oper._interface->is_MemInterface(); |
2994 | const char *base = mem_interface->_base; |
2995 | const char *disp = mem_interface->_disp; |
2996 | if( emit_position && (strcmp(name,"base") == 0) |
2997 | && base != NULL__null && is_regI(base, oper, globals) |
2998 | && disp != NULL__null && is_conP(disp, oper, globals) ) { |
2999 | // Found a memory access using a constant pointer for a displacement |
3000 | // and a base register containing an integer offset. |
3001 | // In this case the base and disp are reversed with respect to what |
3002 | // is expected by MachNode::get_base_and_disp() and MachNode::adr_type(). |
3003 | // Provide a non-NULL return for disp_as_type() that will allow adr_type() |
3004 | // to correctly compute the access type for alias analysis. |
3005 | // |
3006 | // See BugId 4796752, operand indOffset32X in x86_32.ad |
3007 | int idx = rep_var_to_constant_index(disp, oper, globals); |
3008 | fprintf(fp," virtual const TypePtr *disp_as_type() const { return _c%d; }\n", idx); |
3009 | } |
3010 | } |
3011 | } |
3012 | |
3013 | // |
3014 | // Construct the method to copy _idx, inputs and operands to new node. |
3015 | static void define_fill_new_machnode(bool used, FILE *fp_cpp) { |
3016 | fprintf(fp_cpp, "\n"); |
3017 | fprintf(fp_cpp, "// Copy _idx, inputs and operands to new node\n"); |
3018 | fprintf(fp_cpp, "void MachNode::fill_new_machnode(MachNode* node) const {\n"); |
3019 | if( !used ) { |
3020 | fprintf(fp_cpp, " // This architecture does not have cisc or short branch instructions\n"); |
3021 | fprintf(fp_cpp, " ShouldNotCallThis();\n"); |
3022 | fprintf(fp_cpp, "}\n"); |
3023 | } else { |
3024 | // New node must use same node index for access through allocator's tables |
3025 | fprintf(fp_cpp, " // New node must use same node index\n"); |
3026 | fprintf(fp_cpp, " node->set_idx( _idx );\n"); |
3027 | // Copy machine-independent inputs |
3028 | fprintf(fp_cpp, " // Copy machine-independent inputs\n"); |
3029 | fprintf(fp_cpp, " for( uint j = 0; j < req(); j++ ) {\n"); |
3030 | fprintf(fp_cpp, " node->add_req(in(j));\n"); |
3031 | fprintf(fp_cpp, " }\n"); |
3032 | // Copy machine operands to new MachNode |
3033 | fprintf(fp_cpp, " // Copy my operands, except for cisc position\n"); |
3034 | fprintf(fp_cpp, " int nopnds = num_opnds();\n"); |
3035 | fprintf(fp_cpp, " assert( node->num_opnds() == (uint)nopnds, \"Must have same number of operands\");\n"); |
3036 | fprintf(fp_cpp, " MachOper **to = node->_opnds;\n"); |
3037 | fprintf(fp_cpp, " for( int i = 0; i < nopnds; i++ ) {\n"); |
3038 | fprintf(fp_cpp, " if( i != cisc_operand() ) \n"); |
3039 | fprintf(fp_cpp, " to[i] = _opnds[i]->clone();\n"); |
3040 | fprintf(fp_cpp, " }\n"); |
3041 | fprintf(fp_cpp, "}\n"); |
3042 | } |
3043 | fprintf(fp_cpp, "\n"); |
3044 | } |
3045 | |
3046 | //------------------------------defineClasses---------------------------------- |
3047 | // Define members of MachNode and MachOper classes based on |
3048 | // operand and instruction lists |
3049 | void ArchDesc::defineClasses(FILE *fp) { |
3050 | |
3051 | // Define the contents of an array containing the machine register names |
3052 | defineRegNames(fp, _register); |
3053 | // Define an array containing the machine register encoding values |
3054 | defineRegEncodes(fp, _register); |
3055 | // Generate an enumeration of user-defined register classes |
3056 | // and a list of register masks, one for each class. |
3057 | // Only define the RegMask value objects in the expand file. |
3058 | // Declare each as an extern const RegMask ...; in ad_<arch>.hpp |
3059 | declare_register_masks(_HPP_file._fp); |
3060 | // build_register_masks(fp); |
3061 | build_register_masks(_CPP_EXPAND_file._fp); |
3062 | // Define the pipe_classes |
3063 | build_pipe_classes(_CPP_PIPELINE_file._fp); |
3064 | |
3065 | // Generate Machine Classes for each operand defined in AD file |
3066 | fprintf(fp,"\n"); |
3067 | fprintf(fp,"\n"); |
3068 | fprintf(fp,"//------------------Define classes derived from MachOper---------------------\n"); |
3069 | // Iterate through all operands |
3070 | _operands.reset(); |
3071 | OperandForm *oper; |
3072 | for( ; (oper = (OperandForm*)_operands.iter()) != NULL__null; ) { |
3073 | // Ensure this is a machine-world instruction |
3074 | if ( oper->ideal_only() ) continue; |
3075 | // !!!!! |
3076 | // The declaration of labelOper is in machine-independent file: machnode |
3077 | if ( strcmp(oper->_ident,"label") == 0 ) { |
3078 | defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); |
3079 | |
3080 | fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); |
3081 | fprintf(fp," return new %sOper(_label, _block_num);\n", oper->_ident); |
3082 | fprintf(fp,"}\n"); |
3083 | |
3084 | fprintf(fp,"uint %sOper::opcode() const { return %s; }\n", |
3085 | oper->_ident, machOperEnum(oper->_ident)); |
3086 | // // Currently all XXXOper::Hash() methods are identical (990820) |
3087 | // define_hash(fp, oper->_ident); |
3088 | // // Currently all XXXOper::Cmp() methods are identical (990820) |
3089 | // define_cmp(fp, oper->_ident); |
3090 | fprintf(fp,"\n"); |
3091 | |
3092 | continue; |
3093 | } |
3094 | |
3095 | // The declaration of methodOper is in machine-independent file: machnode |
3096 | if ( strcmp(oper->_ident,"method") == 0 ) { |
3097 | defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); |
3098 | |
3099 | fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); |
3100 | fprintf(fp," return new %sOper(_method);\n", oper->_ident); |
3101 | fprintf(fp,"}\n"); |
3102 | |
3103 | fprintf(fp,"uint %sOper::opcode() const { return %s; }\n", |
3104 | oper->_ident, machOperEnum(oper->_ident)); |
3105 | // // Currently all XXXOper::Hash() methods are identical (990820) |
3106 | // define_hash(fp, oper->_ident); |
3107 | // // Currently all XXXOper::Cmp() methods are identical (990820) |
3108 | // define_cmp(fp, oper->_ident); |
3109 | fprintf(fp,"\n"); |
3110 | |
3111 | continue; |
3112 | } |
3113 | |
3114 | defineIn_RegMask(fp, _globalNames, *oper); |
3115 | defineClone(_CPP_CLONE_file._fp, _globalNames, *oper); |
3116 | // // Currently all XXXOper::Hash() methods are identical (990820) |
3117 | // define_hash(fp, oper->_ident); |
3118 | // // Currently all XXXOper::Cmp() methods are identical (990820) |
3119 | // define_cmp(fp, oper->_ident); |
3120 | |
3121 | // side-call to generate output that used to be in the header file: |
3122 | extern void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_file); |
3123 | gen_oper_format(_CPP_FORMAT_file._fp, _globalNames, *oper, true); |
3124 | |
3125 | } |
3126 | |
3127 | |
3128 | // Generate Machine Classes for each instruction defined in AD file |
3129 | fprintf(fp,"//------------------Define members for classes derived from MachNode----------\n"); |
3130 | // Output the definitions for out_RegMask() // & kill_RegMask() |
3131 | _instructions.reset(); |
3132 | InstructForm *instr; |
3133 | MachNodeForm *machnode; |
3134 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3135 | // Ensure this is a machine-world instruction |
3136 | if ( instr->ideal_only() ) continue; |
3137 | |
3138 | defineOut_RegMask(_CPP_MISC_file._fp, instr->_ident, reg_mask(*instr)); |
3139 | } |
3140 | |
3141 | bool used = false; |
3142 | // Output the definitions for expand rules & peephole rules |
3143 | _instructions.reset(); |
3144 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3145 | // Ensure this is a machine-world instruction |
3146 | if ( instr->ideal_only() ) continue; |
3147 | // If there are multiple defs/kills, or an explicit expand rule, build rule |
3148 | if( instr->expands() || instr->needs_projections() || |
3149 | instr->has_temps() || |
3150 | instr->is_mach_constant() || |
3151 | instr->needs_constant_base() || |
3152 | (instr->_matrule != NULL__null && |
3153 | instr->num_opnds() != instr->num_unique_opnds()) ) |
3154 | defineExpand(_CPP_EXPAND_file._fp, instr); |
3155 | // If there is an explicit peephole rule, build it |
3156 | if ( instr->peepholes() ) |
3157 | definePeephole(_CPP_PEEPHOLE_file._fp, instr); |
3158 | |
3159 | // Output code to convert to the cisc version, if applicable |
3160 | used |= instr->define_cisc_version(*this, fp); |
3161 | |
3162 | // Output code to convert to the short branch version, if applicable |
3163 | used |= instr->define_short_branch_methods(*this, fp); |
3164 | } |
3165 | |
3166 | // Construct the method called by cisc_version() to copy inputs and operands. |
3167 | define_fill_new_machnode(used, fp); |
3168 | |
3169 | // Output the definitions for labels |
3170 | _instructions.reset(); |
3171 | while( (instr = (InstructForm*)_instructions.iter()) != NULL__null ) { |
3172 | // Ensure this is a machine-world instruction |
3173 | if ( instr->ideal_only() ) continue; |
3174 | |
3175 | // Access the fields for operand Label |
3176 | int label_position = instr->label_position(); |
3177 | if( label_position != -1 ) { |
3178 | // Set the label |
3179 | fprintf(fp,"void %sNode::label_set( Label* label, uint block_num ) {\n", instr->_ident); |
3180 | fprintf(fp," labelOper* oper = (labelOper*)(opnd_array(%d));\n", |
3181 | label_position ); |
3182 | fprintf(fp," oper->_label = label;\n"); |
3183 | fprintf(fp," oper->_block_num = block_num;\n"); |
3184 | fprintf(fp,"}\n"); |
3185 | // Save the label |
3186 | fprintf(fp,"void %sNode::save_label( Label** label, uint* block_num ) {\n", instr->_ident); |
3187 | fprintf(fp," labelOper* oper = (labelOper*)(opnd_array(%d));\n", |
3188 | label_position ); |
3189 | fprintf(fp," *label = oper->_label;\n"); |
3190 | fprintf(fp," *block_num = oper->_block_num;\n"); |
3191 | fprintf(fp,"}\n"); |
3192 | } |
3193 | } |
3194 | |
3195 | // Output the definitions for methods |
3196 | _instructions.reset(); |
3197 | while( (instr = (InstructForm*)_instructions.iter()) != NULL__null ) { |
3198 | // Ensure this is a machine-world instruction |
3199 | if ( instr->ideal_only() ) continue; |
3200 | |
3201 | // Access the fields for operand Label |
3202 | int method_position = instr->method_position(); |
3203 | if( method_position != -1 ) { |
3204 | // Access the method's address |
3205 | fprintf(fp,"void %sNode::method_set( intptr_t method ) {\n", instr->_ident); |
3206 | fprintf(fp," ((methodOper*)opnd_array(%d))->_method = method;\n", |
3207 | method_position ); |
3208 | fprintf(fp,"}\n"); |
3209 | fprintf(fp,"\n"); |
3210 | } |
3211 | } |
3212 | |
3213 | // Define this instruction's number of relocation entries, base is '0' |
3214 | _instructions.reset(); |
3215 | while( (instr = (InstructForm*)_instructions.iter()) != NULL__null ) { |
3216 | // Output the definition for number of relocation entries |
3217 | uintunsigned int reloc_size = instr->reloc(_globalNames); |
3218 | if ( reloc_size != 0 ) { |
3219 | fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident); |
3220 | fprintf(fp," return %d;\n", reloc_size); |
3221 | fprintf(fp,"}\n"); |
3222 | fprintf(fp,"\n"); |
3223 | } |
3224 | } |
3225 | fprintf(fp,"\n"); |
3226 | |
3227 | // Output the definitions for code generation |
3228 | // |
3229 | // address ___Node::emit(address ptr, PhaseRegAlloc *ra_) const { |
3230 | // // ... encoding defined by user |
3231 | // return ptr; |
3232 | // } |
3233 | // |
3234 | _instructions.reset(); |
3235 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3236 | // Ensure this is a machine-world instruction |
3237 | if ( instr->ideal_only() ) continue; |
3238 | |
3239 | if (instr->_insencode) { |
3240 | if (instr->postalloc_expands()) { |
3241 | // Don't write this to _CPP_EXPAND_file, as the code generated calls C-code |
3242 | // from code sections in ad file that is dumped to fp. |
3243 | define_postalloc_expand(fp, *instr); |
3244 | } else { |
3245 | defineEmit(fp, *instr); |
3246 | } |
3247 | } |
3248 | if (instr->is_mach_constant()) defineEvalConstant(fp, *instr); |
3249 | if (instr->_size) defineSize (fp, *instr); |
3250 | |
3251 | // side-call to generate output that used to be in the header file: |
3252 | extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file); |
3253 | gen_inst_format(_CPP_FORMAT_file._fp, _globalNames, *instr, true); |
3254 | } |
3255 | |
3256 | // Output the definitions for alias analysis |
3257 | _instructions.reset(); |
3258 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3259 | // Ensure this is a machine-world instruction |
3260 | if ( instr->ideal_only() ) continue; |
3261 | |
3262 | // Analyze machine instructions that either USE or DEF memory. |
3263 | int memory_operand = instr->memory_operand(_globalNames); |
3264 | |
3265 | if ( memory_operand != InstructForm::NO_MEMORY_OPERAND ) { |
3266 | if( memory_operand == InstructForm::MANY_MEMORY_OPERANDS ) { |
3267 | fprintf(fp,"const TypePtr *%sNode::adr_type() const { return TypePtr::BOTTOM; }\n", instr->_ident); |
3268 | fprintf(fp,"const MachOper* %sNode::memory_operand() const { return (MachOper*)-1; }\n", instr->_ident); |
3269 | } else { |
3270 | fprintf(fp,"const MachOper* %sNode::memory_operand() const { return _opnds[%d]; }\n", instr->_ident, memory_operand); |
3271 | } |
3272 | } |
3273 | } |
3274 | |
3275 | // Get the length of the longest identifier |
3276 | int max_ident_len = 0; |
3277 | _instructions.reset(); |
3278 | |
3279 | for ( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3280 | if (instr->_ins_pipe && _pipeline->_classlist.search(instr->_ins_pipe)) { |
3281 | int ident_len = (int)strlen(instr->_ident); |
3282 | if( max_ident_len < ident_len ) |
3283 | max_ident_len = ident_len; |
3284 | } |
3285 | } |
3286 | |
3287 | // Emit specifically for Node(s) |
3288 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline_class() { return %s; }\n", |
3289 | max_ident_len, "Node", _pipeline ? "(&pipeline_class_Zero_Instructions)" : "NULL"); |
3290 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline() const { return %s; }\n", |
3291 | max_ident_len, "Node", _pipeline ? "(&pipeline_class_Zero_Instructions)" : "NULL"); |
3292 | fprintf(_CPP_PIPELINE_file._fp, "\n"); |
3293 | |
3294 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline_class() { return %s; }\n", |
3295 | max_ident_len, "MachNode", _pipeline ? "(&pipeline_class_Unknown_Instructions)" : "NULL"); |
3296 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline() const { return pipeline_class(); }\n", |
3297 | max_ident_len, "MachNode"); |
3298 | fprintf(_CPP_PIPELINE_file._fp, "\n"); |
3299 | |
3300 | // Output the definitions for machine node specific pipeline data |
3301 | _machnodes.reset(); |
3302 | |
3303 | if (_pipeline != NULL__null) { |
3304 | for ( ; (machnode = (MachNodeForm*)_machnodes.iter()) != NULL__null; ) { |
3305 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %sNode::pipeline() const { return (&pipeline_class_%03d); }\n", |
3306 | machnode->_ident, ((class PipeClassForm *)_pipeline->_classdict[machnode->_machnode_pipe])->_num); |
3307 | } |
3308 | } |
3309 | |
3310 | fprintf(_CPP_PIPELINE_file._fp, "\n"); |
3311 | |
3312 | // Output the definitions for instruction pipeline static data references |
3313 | _instructions.reset(); |
3314 | |
3315 | if (_pipeline != NULL__null) { |
3316 | for ( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3317 | if (instr->_ins_pipe && _pipeline->_classlist.search(instr->_ins_pipe)) { |
3318 | fprintf(_CPP_PIPELINE_file._fp, "\n"); |
3319 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline_class() { return (&pipeline_class_%03d); }\n", |
3320 | max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num); |
3321 | fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline() const { return (&pipeline_class_%03d); }\n", |
3322 | max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num); |
3323 | } |
3324 | } |
3325 | } |
3326 | } |
3327 | |
3328 | |
3329 | // -------------------------------- maps ------------------------------------ |
3330 | |
3331 | // Information needed to generate the ReduceOp mapping for the DFA |
3332 | class OutputReduceOp : public OutputMap { |
3333 | public: |
3334 | OutputReduceOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3335 | : OutputMap(hpp, cpp, globals, AD, "reduceOp") {}; |
3336 | |
3337 | void declaration() { fprintf(_hpp, "extern const int reduceOp[];\n"); } |
3338 | void definition() { fprintf(_cpp, "const int reduceOp[] = {\n"); } |
3339 | void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); |
3340 | OutputMap::closing(); |
3341 | } |
3342 | void map(OpClassForm &opc) { |
3343 | const char *reduce = opc._ident; |
3344 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3345 | else fprintf(_cpp, " 0"); |
3346 | } |
3347 | void map(OperandForm &oper) { |
3348 | // Most operands without match rules, e.g. eFlagsReg, do not have a result operand |
3349 | const char *reduce = (oper._matrule ? oper.reduce_result() : NULL__null); |
3350 | // operand stackSlot does not have a match rule, but produces a stackSlot |
3351 | if( oper.is_user_name_for_sReg() != Form::none ) reduce = oper.reduce_result(); |
3352 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3353 | else fprintf(_cpp, " 0"); |
3354 | } |
3355 | void map(InstructForm &inst) { |
3356 | const char *reduce = (inst._matrule ? inst.reduce_result() : NULL__null); |
3357 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3358 | else fprintf(_cpp, " 0"); |
3359 | } |
3360 | void map(char *reduce) { |
3361 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3362 | else fprintf(_cpp, " 0"); |
3363 | } |
3364 | }; |
3365 | |
3366 | // Information needed to generate the LeftOp mapping for the DFA |
3367 | class OutputLeftOp : public OutputMap { |
3368 | public: |
3369 | OutputLeftOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3370 | : OutputMap(hpp, cpp, globals, AD, "leftOp") {}; |
3371 | |
3372 | void declaration() { fprintf(_hpp, "extern const int leftOp[];\n"); } |
3373 | void definition() { fprintf(_cpp, "const int leftOp[] = {\n"); } |
3374 | void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); |
3375 | OutputMap::closing(); |
3376 | } |
3377 | void map(OpClassForm &opc) { fprintf(_cpp, " 0"); } |
3378 | void map(OperandForm &oper) { |
3379 | const char *reduce = oper.reduce_left(_globals); |
3380 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3381 | else fprintf(_cpp, " 0"); |
3382 | } |
3383 | void map(char *name) { |
3384 | const char *reduce = _AD.reduceLeft(name); |
3385 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3386 | else fprintf(_cpp, " 0"); |
3387 | } |
3388 | void map(InstructForm &inst) { |
3389 | const char *reduce = inst.reduce_left(_globals); |
3390 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3391 | else fprintf(_cpp, " 0"); |
3392 | } |
3393 | }; |
3394 | |
3395 | |
3396 | // Information needed to generate the RightOp mapping for the DFA |
3397 | class OutputRightOp : public OutputMap { |
3398 | public: |
3399 | OutputRightOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3400 | : OutputMap(hpp, cpp, globals, AD, "rightOp") {}; |
3401 | |
3402 | void declaration() { fprintf(_hpp, "extern const int rightOp[];\n"); } |
3403 | void definition() { fprintf(_cpp, "const int rightOp[] = {\n"); } |
3404 | void closing() { fprintf(_cpp, " 0 // no trailing comma\n"); |
3405 | OutputMap::closing(); |
3406 | } |
3407 | void map(OpClassForm &opc) { fprintf(_cpp, " 0"); } |
3408 | void map(OperandForm &oper) { |
3409 | const char *reduce = oper.reduce_right(_globals); |
3410 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3411 | else fprintf(_cpp, " 0"); |
3412 | } |
3413 | void map(char *name) { |
3414 | const char *reduce = _AD.reduceRight(name); |
3415 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3416 | else fprintf(_cpp, " 0"); |
3417 | } |
3418 | void map(InstructForm &inst) { |
3419 | const char *reduce = inst.reduce_right(_globals); |
3420 | if( reduce ) fprintf(_cpp, " %s_rule", reduce); |
3421 | else fprintf(_cpp, " 0"); |
3422 | } |
3423 | }; |
3424 | |
3425 | |
3426 | // Information needed to generate the Rule names for the DFA |
3427 | class OutputRuleName : public OutputMap { |
3428 | public: |
3429 | OutputRuleName(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3430 | : OutputMap(hpp, cpp, globals, AD, "ruleName") {}; |
3431 | |
3432 | void declaration() { fprintf(_hpp, "extern const char *ruleName[];\n"); } |
3433 | void definition() { fprintf(_cpp, "const char *ruleName[] = {\n"); } |
3434 | void closing() { fprintf(_cpp, " \"invalid rule name\" // no trailing comma\n"); |
3435 | OutputMap::closing(); |
3436 | } |
3437 | void map(OpClassForm &opc) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(opc._ident) ); } |
3438 | void map(OperandForm &oper) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(oper._ident) ); } |
3439 | void map(char *name) { fprintf(_cpp, " \"%s\"", name ? name : "0"); } |
3440 | void map(InstructForm &inst){ fprintf(_cpp, " \"%s\"", inst._ident ? inst._ident : "0"); } |
3441 | }; |
3442 | |
3443 | |
3444 | // Information needed to generate the swallowed mapping for the DFA |
3445 | class OutputSwallowed : public OutputMap { |
3446 | public: |
3447 | OutputSwallowed(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3448 | : OutputMap(hpp, cpp, globals, AD, "swallowed") {}; |
3449 | |
3450 | void declaration() { fprintf(_hpp, "extern const bool swallowed[];\n"); } |
3451 | void definition() { fprintf(_cpp, "const bool swallowed[] = {\n"); } |
3452 | void closing() { fprintf(_cpp, " false // no trailing comma\n"); |
3453 | OutputMap::closing(); |
3454 | } |
3455 | void map(OperandForm &oper) { // Generate the entry for this opcode |
3456 | const char *swallowed = oper.swallowed(_globals) ? "true" : "false"; |
3457 | fprintf(_cpp, " %s", swallowed); |
3458 | } |
3459 | void map(OpClassForm &opc) { fprintf(_cpp, " false"); } |
3460 | void map(char *name) { fprintf(_cpp, " false"); } |
3461 | void map(InstructForm &inst){ fprintf(_cpp, " false"); } |
3462 | }; |
3463 | |
3464 | |
3465 | // Information needed to generate the decision array for instruction chain rule |
3466 | class OutputInstChainRule : public OutputMap { |
3467 | public: |
3468 | OutputInstChainRule(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) |
3469 | : OutputMap(hpp, cpp, globals, AD, "instruction_chain_rule") {}; |
3470 | |
3471 | void declaration() { fprintf(_hpp, "extern const bool instruction_chain_rule[];\n"); } |
3472 | void definition() { fprintf(_cpp, "const bool instruction_chain_rule[] = {\n"); } |
3473 | void closing() { fprintf(_cpp, " false // no trailing comma\n"); |
3474 | OutputMap::closing(); |
3475 | } |
3476 | void map(OpClassForm &opc) { fprintf(_cpp, " false"); } |
3477 | void map(OperandForm &oper) { fprintf(_cpp, " false"); } |
3478 | void map(char *name) { fprintf(_cpp, " false"); } |
3479 | void map(InstructForm &inst) { // Check for simple chain rule |
3480 | const char *chain = inst.is_simple_chain_rule(_globals) ? "true" : "false"; |
3481 | fprintf(_cpp, " %s", chain); |
3482 | } |
3483 | }; |
3484 | |
3485 | |
3486 | //---------------------------build_map------------------------------------ |
3487 | // Build mapping from enumeration for densely packed operands |
3488 | // TO result and child types. |
3489 | void ArchDesc::build_map(OutputMap &map) { |
3490 | FILE *fp_hpp = map.decl_file(); |
3491 | FILE *fp_cpp = map.def_file(); |
3492 | int idx = 0; |
3493 | OperandForm *op; |
3494 | OpClassForm *opc; |
3495 | InstructForm *inst; |
3496 | |
3497 | // Construct this mapping |
3498 | map.declaration(); |
3499 | fprintf(fp_cpp,"\n"); |
3500 | map.definition(); |
3501 | |
3502 | // Output the mapping for operands |
3503 | map.record_position(OutputMap::BEGIN_OPERANDS, idx ); |
3504 | _operands.reset(); |
3505 | for(; (op = (OperandForm*)_operands.iter()) != NULL__null; ) { |
3506 | // Ensure this is a machine-world instruction |
3507 | if ( op->ideal_only() ) continue; |
3508 | |
3509 | // Generate the entry for this opcode |
3510 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*op); fprintf(fp_cpp, ",\n"); |
3511 | ++idx; |
3512 | }; |
3513 | fprintf(fp_cpp, " // last operand\n"); |
3514 | |
3515 | // Place all user-defined operand classes into the mapping |
3516 | map.record_position(OutputMap::BEGIN_OPCLASSES, idx ); |
3517 | _opclass.reset(); |
3518 | for(; (opc = (OpClassForm*)_opclass.iter()) != NULL__null; ) { |
3519 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*opc); fprintf(fp_cpp, ",\n"); |
3520 | ++idx; |
3521 | }; |
3522 | fprintf(fp_cpp, " // last operand class\n"); |
3523 | |
3524 | // Place all internally defined operands into the mapping |
3525 | map.record_position(OutputMap::BEGIN_INTERNALS, idx ); |
3526 | _internalOpNames.reset(); |
3527 | char *name = NULL__null; |
3528 | for(; (name = (char *)_internalOpNames.iter()) != NULL__null; ) { |
3529 | fprintf(fp_cpp, " /* %4d */", idx); map.map(name); fprintf(fp_cpp, ",\n"); |
3530 | ++idx; |
3531 | }; |
3532 | fprintf(fp_cpp, " // last internally defined operand\n"); |
3533 | |
3534 | // Place all user-defined instructions into the mapping |
3535 | if( map.do_instructions() ) { |
3536 | map.record_position(OutputMap::BEGIN_INSTRUCTIONS, idx ); |
3537 | // Output all simple instruction chain rules first |
3538 | map.record_position(OutputMap::BEGIN_INST_CHAIN_RULES, idx ); |
3539 | { |
3540 | _instructions.reset(); |
3541 | for(; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3542 | // Ensure this is a machine-world instruction |
3543 | if ( inst->ideal_only() ) continue; |
3544 | if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; |
3545 | if ( inst->rematerialize(_globalNames, get_registers()) ) continue; |
3546 | |
3547 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n"); |
3548 | ++idx; |
3549 | }; |
3550 | map.record_position(OutputMap::BEGIN_REMATERIALIZE, idx ); |
3551 | _instructions.reset(); |
3552 | for(; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3553 | // Ensure this is a machine-world instruction |
3554 | if ( inst->ideal_only() ) continue; |
3555 | if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; |
3556 | if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; |
3557 | |
3558 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n"); |
3559 | ++idx; |
3560 | }; |
3561 | map.record_position(OutputMap::END_INST_CHAIN_RULES, idx ); |
3562 | } |
3563 | // Output all instructions that are NOT simple chain rules |
3564 | { |
3565 | _instructions.reset(); |
3566 | for(; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3567 | // Ensure this is a machine-world instruction |
3568 | if ( inst->ideal_only() ) continue; |
3569 | if ( inst->is_simple_chain_rule(_globalNames) ) continue; |
3570 | if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; |
3571 | |
3572 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n"); |
3573 | ++idx; |
3574 | }; |
3575 | map.record_position(OutputMap::END_REMATERIALIZE, idx ); |
3576 | _instructions.reset(); |
3577 | for(; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
3578 | // Ensure this is a machine-world instruction |
3579 | if ( inst->ideal_only() ) continue; |
3580 | if ( inst->is_simple_chain_rule(_globalNames) ) continue; |
3581 | if ( inst->rematerialize(_globalNames, get_registers()) ) continue; |
3582 | |
3583 | fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n"); |
3584 | ++idx; |
3585 | }; |
3586 | } |
3587 | fprintf(fp_cpp, " // last instruction\n"); |
3588 | map.record_position(OutputMap::END_INSTRUCTIONS, idx ); |
3589 | } |
3590 | // Finish defining table |
3591 | map.closing(); |
3592 | }; |
3593 | |
3594 | |
3595 | // Helper function for buildReduceMaps |
3596 | char reg_save_policy(const char *calling_convention) { |
3597 | char callconv; |
3598 | |
3599 | if (!strcmp(calling_convention, "NS")) callconv = 'N'; |
3600 | else if (!strcmp(calling_convention, "SOE")) callconv = 'E'; |
3601 | else if (!strcmp(calling_convention, "SOC")) callconv = 'C'; |
3602 | else if (!strcmp(calling_convention, "AS")) callconv = 'A'; |
3603 | else callconv = 'Z'; |
3604 | |
3605 | return callconv; |
3606 | } |
3607 | |
3608 | void ArchDesc::generate_needs_deep_clone_jvms(FILE *fp_cpp) { |
3609 | fprintf(fp_cpp, "bool Compile::needs_deep_clone_jvms() { return %s; }\n\n", |
3610 | _needs_deep_clone_jvms ? "true" : "false"); |
3611 | } |
3612 | |
3613 | //---------------------------generate_assertion_checks------------------- |
3614 | void ArchDesc::generate_adlc_verification(FILE *fp_cpp) { |
3615 | fprintf(fp_cpp, "\n"); |
3616 | |
3617 | fprintf(fp_cpp, "#ifndef PRODUCT\n"); |
3618 | fprintf(fp_cpp, "void Compile::adlc_verification() {\n"); |
3619 | globalDefs().print_asserts(fp_cpp); |
3620 | fprintf(fp_cpp, "}\n"); |
3621 | fprintf(fp_cpp, "#endif\n"); |
3622 | fprintf(fp_cpp, "\n"); |
3623 | } |
3624 | |
3625 | //---------------------------addSourceBlocks----------------------------- |
3626 | void ArchDesc::addSourceBlocks(FILE *fp_cpp) { |
3627 | if (_source.count() > 0) |
3628 | _source.output(fp_cpp); |
3629 | |
3630 | generate_adlc_verification(fp_cpp); |
3631 | } |
3632 | //---------------------------addHeaderBlocks----------------------------- |
3633 | void ArchDesc::addHeaderBlocks(FILE *fp_hpp) { |
3634 | if (_header.count() > 0) |
3635 | _header.output(fp_hpp); |
3636 | } |
3637 | //-------------------------addPreHeaderBlocks---------------------------- |
3638 | void ArchDesc::addPreHeaderBlocks(FILE *fp_hpp) { |
3639 | // Output #defines from definition block |
3640 | globalDefs().print_defines(fp_hpp); |
3641 | |
3642 | if (_pre_header.count() > 0) |
3643 | _pre_header.output(fp_hpp); |
3644 | } |
3645 | |
3646 | //---------------------------buildReduceMaps----------------------------- |
3647 | // Build mapping from enumeration for densely packed operands |
3648 | // TO result and child types. |
3649 | void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) { |
3650 | RegDef *rdef; |
3651 | RegDef *next; |
3652 | |
3653 | // The emit bodies currently require functions defined in the source block. |
3654 | |
3655 | // Build external declarations for mappings |
3656 | fprintf(fp_hpp, "\n"); |
3657 | fprintf(fp_hpp, "extern const char register_save_policy[];\n"); |
3658 | fprintf(fp_hpp, "extern const char c_reg_save_policy[];\n"); |
3659 | fprintf(fp_hpp, "extern const int register_save_type[];\n"); |
3660 | fprintf(fp_hpp, "\n"); |
3661 | |
3662 | // Construct Save-Policy array |
3663 | fprintf(fp_cpp, "// Map from machine-independent register number to register_save_policy\n"); |
3664 | fprintf(fp_cpp, "const char register_save_policy[] = {\n"); |
3665 | _register->reset_RegDefs(); |
3666 | for( rdef = _register->iter_RegDefs(); rdef != NULL__null; rdef = next ) { |
3667 | next = _register->iter_RegDefs(); |
3668 | char policy = reg_save_policy(rdef->_callconv); |
3669 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
3670 | fprintf(fp_cpp, " '%c'%s // %s\n", policy, comma, rdef->_regname); |
3671 | } |
3672 | fprintf(fp_cpp, "};\n\n"); |
3673 | |
3674 | // Construct Native Save-Policy array |
3675 | fprintf(fp_cpp, "// Map from machine-independent register number to c_reg_save_policy\n"); |
3676 | fprintf(fp_cpp, "const char c_reg_save_policy[] = {\n"); |
3677 | _register->reset_RegDefs(); |
3678 | for( rdef = _register->iter_RegDefs(); rdef != NULL__null; rdef = next ) { |
3679 | next = _register->iter_RegDefs(); |
3680 | char policy = reg_save_policy(rdef->_c_conv); |
3681 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
3682 | fprintf(fp_cpp, " '%c'%s // %s\n", policy, comma, rdef->_regname); |
3683 | } |
3684 | fprintf(fp_cpp, "};\n\n"); |
3685 | |
3686 | // Construct Register Save Type array |
3687 | fprintf(fp_cpp, "// Map from machine-independent register number to register_save_type\n"); |
3688 | fprintf(fp_cpp, "const int register_save_type[] = {\n"); |
3689 | _register->reset_RegDefs(); |
3690 | for( rdef = _register->iter_RegDefs(); rdef != NULL__null; rdef = next ) { |
3691 | next = _register->iter_RegDefs(); |
3692 | const char *comma = (next != NULL__null) ? "," : " // no trailing comma"; |
3693 | fprintf(fp_cpp, " %s%s\n", rdef->_idealtype, comma); |
3694 | } |
3695 | fprintf(fp_cpp, "};\n\n"); |
3696 | |
3697 | // Construct the table for reduceOp |
3698 | OutputReduceOp output_reduce_op(fp_hpp, fp_cpp, _globalNames, *this); |
3699 | build_map(output_reduce_op); |
3700 | // Construct the table for leftOp |
3701 | OutputLeftOp output_left_op(fp_hpp, fp_cpp, _globalNames, *this); |
3702 | build_map(output_left_op); |
3703 | // Construct the table for rightOp |
3704 | OutputRightOp output_right_op(fp_hpp, fp_cpp, _globalNames, *this); |
3705 | build_map(output_right_op); |
3706 | // Construct the table of rule names |
3707 | OutputRuleName output_rule_name(fp_hpp, fp_cpp, _globalNames, *this); |
3708 | build_map(output_rule_name); |
3709 | // Construct the boolean table for subsumed operands |
3710 | OutputSwallowed output_swallowed(fp_hpp, fp_cpp, _globalNames, *this); |
3711 | build_map(output_swallowed); |
3712 | // // // Preserve in case we decide to use this table instead of another |
3713 | //// Construct the boolean table for instruction chain rules |
3714 | //OutputInstChainRule output_inst_chain(fp_hpp, fp_cpp, _globalNames, *this); |
3715 | //build_map(output_inst_chain); |
3716 | |
3717 | } |
3718 | |
3719 | |
3720 | //---------------------------buildMachOperGenerator--------------------------- |
3721 | |
3722 | // Recurse through match tree, building path through corresponding state tree, |
3723 | // Until we reach the constant we are looking for. |
3724 | static void path_to_constant(FILE *fp, FormDict &globals, |
3725 | MatchNode *mnode, uintunsigned int idx) { |
3726 | if ( ! mnode) return; |
3727 | |
3728 | unsigned position = 0; |
3729 | const char *result = NULL__null; |
3730 | const char *name = NULL__null; |
3731 | const char *optype = NULL__null; |
3732 | |
3733 | // Base Case: access constant in ideal node linked to current state node |
3734 | // Each type of constant has its own access function |
3735 | if ( (mnode->_lChild == NULL__null) && (mnode->_rChild == NULL__null) |
3736 | && mnode->base_operand(position, globals, result, name, optype) ) { |
3737 | if ( strcmp(optype,"ConI") == 0 ) { |
3738 | fprintf(fp, "_leaf->get_int()"); |
3739 | } else if ( (strcmp(optype,"ConP") == 0) ) { |
3740 | fprintf(fp, "_leaf->bottom_type()->is_ptr()"); |
3741 | } else if ( (strcmp(optype,"ConN") == 0) ) { |
3742 | fprintf(fp, "_leaf->bottom_type()->is_narrowoop()"); |
3743 | } else if ( (strcmp(optype,"ConNKlass") == 0) ) { |
3744 | fprintf(fp, "_leaf->bottom_type()->is_narrowklass()"); |
3745 | } else if ( (strcmp(optype,"ConF") == 0) ) { |
3746 | fprintf(fp, "_leaf->getf()"); |
3747 | } else if ( (strcmp(optype,"ConD") == 0) ) { |
3748 | fprintf(fp, "_leaf->getd()"); |
3749 | } else if ( (strcmp(optype,"ConL") == 0) ) { |
3750 | fprintf(fp, "_leaf->get_long()"); |
3751 | } else if ( (strcmp(optype,"Con")==0) ) { |
3752 | // !!!!! - Update if adding a machine-independent constant type |
3753 | fprintf(fp, "_leaf->get_int()"); |
3754 | assert( false, "Unsupported constant type, pointer or indefinite"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3754, "Unsupported constant type, pointer or indefinite"); abort (); }}; |
3755 | } else if ( (strcmp(optype,"Bool") == 0) ) { |
3756 | fprintf(fp, "_leaf->as_Bool()->_test._test"); |
3757 | } else { |
3758 | assert( false, "Unsupported constant type"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3758, "Unsupported constant type"); abort(); }}; |
3759 | } |
3760 | return; |
3761 | } |
3762 | |
3763 | // If constant is in left child, build path and recurse |
3764 | uintunsigned int lConsts = (mnode->_lChild) ? (mnode->_lChild->num_consts(globals) ) : 0; |
3765 | uintunsigned int rConsts = (mnode->_rChild) ? (mnode->_rChild->num_consts(globals) ) : 0; |
3766 | if ( (mnode->_lChild) && (lConsts > idx) ) { |
3767 | fprintf(fp, "_kids[0]->"); |
3768 | path_to_constant(fp, globals, mnode->_lChild, idx); |
3769 | return; |
3770 | } |
3771 | // If constant is in right child, build path and recurse |
3772 | if ( (mnode->_rChild) && (rConsts > (idx - lConsts) ) ) { |
3773 | idx = idx - lConsts; |
3774 | fprintf(fp, "_kids[1]->"); |
3775 | path_to_constant(fp, globals, mnode->_rChild, idx); |
3776 | return; |
3777 | } |
3778 | assert( false, "ShouldNotReachHere()"){ if (!(false)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3778, "ShouldNotReachHere()"); abort(); }}; |
3779 | } |
3780 | |
3781 | // Generate code that is executed when generating a specific Machine Operand |
3782 | static void genMachOperCase(FILE *fp, FormDict &globalNames, ArchDesc &AD, |
3783 | OperandForm &op) { |
3784 | const char *opName = op._ident; |
3785 | const char *opEnumName = AD.machOperEnum(opName); |
3786 | uintunsigned int num_consts = op.num_consts(globalNames); |
3787 | |
3788 | // Generate the case statement for this opcode |
3789 | fprintf(fp, " case %s:", opEnumName); |
3790 | fprintf(fp, "\n return new %sOper(", opName); |
3791 | // Access parameters for constructor from the stat object |
3792 | // |
3793 | // Build access to condition code value |
3794 | if ( (num_consts > 0) ) { |
3795 | uintunsigned int i = 0; |
3796 | path_to_constant(fp, globalNames, op._matrule, i); |
3797 | for ( i = 1; i < num_consts; ++i ) { |
3798 | fprintf(fp, ", "); |
3799 | path_to_constant(fp, globalNames, op._matrule, i); |
3800 | } |
3801 | } |
3802 | fprintf(fp, " );\n"); |
3803 | } |
3804 | |
3805 | |
3806 | // Build switch to invoke "new" MachNode or MachOper |
3807 | void ArchDesc::buildMachOperGenerator(FILE *fp_cpp) { |
3808 | int idx = 0; |
3809 | |
3810 | // Build switch to invoke 'new' for a specific MachOper |
3811 | fprintf(fp_cpp, "\n"); |
3812 | fprintf(fp_cpp, "\n"); |
3813 | fprintf(fp_cpp, |
3814 | "//------------------------- MachOper Generator ---------------\n"); |
3815 | fprintf(fp_cpp, |
3816 | "// A switch statement on the dense-packed user-defined type system\n" |
3817 | "// that invokes 'new' on the corresponding class constructor.\n"); |
3818 | fprintf(fp_cpp, "\n"); |
3819 | fprintf(fp_cpp, "MachOper *State::MachOperGenerator"); |
3820 | fprintf(fp_cpp, "(int opcode)"); |
3821 | fprintf(fp_cpp, "{\n"); |
3822 | fprintf(fp_cpp, "\n"); |
3823 | fprintf(fp_cpp, " switch(opcode) {\n"); |
3824 | |
3825 | // Place all user-defined operands into the mapping |
3826 | _operands.reset(); |
3827 | int opIndex = 0; |
3828 | OperandForm *op; |
3829 | for( ; (op = (OperandForm*)_operands.iter()) != NULL__null; ) { |
3830 | // Ensure this is a machine-world instruction |
3831 | if ( op->ideal_only() ) continue; |
3832 | |
3833 | genMachOperCase(fp_cpp, _globalNames, *this, *op); |
3834 | }; |
3835 | |
3836 | // Do not iterate over operand classes for the operand generator!!! |
3837 | |
3838 | // Place all internal operands into the mapping |
3839 | _internalOpNames.reset(); |
3840 | const char *iopn; |
3841 | for( ; (iopn = _internalOpNames.iter()) != NULL__null; ) { |
3842 | const char *opEnumName = machOperEnum(iopn); |
3843 | // Generate the case statement for this opcode |
3844 | fprintf(fp_cpp, " case %s:", opEnumName); |
3845 | fprintf(fp_cpp, " return NULL;\n"); |
3846 | }; |
3847 | |
3848 | // Generate the default case for switch(opcode) |
3849 | fprintf(fp_cpp, " \n"); |
3850 | fprintf(fp_cpp, " default:\n"); |
3851 | fprintf(fp_cpp, " fprintf(stderr, \"Default MachOper Generator invoked for: \\n\");\n"); |
3852 | fprintf(fp_cpp, " fprintf(stderr, \" opcode = %cd\\n\", opcode);\n", '%'); |
3853 | fprintf(fp_cpp, " break;\n"); |
3854 | fprintf(fp_cpp, " }\n"); |
3855 | |
3856 | // Generate the closing for method Matcher::MachOperGenerator |
3857 | fprintf(fp_cpp, " return NULL;\n"); |
3858 | fprintf(fp_cpp, "};\n"); |
3859 | } |
3860 | |
3861 | |
3862 | //---------------------------buildMachNode------------------------------------- |
3863 | // Build a new MachNode, for MachNodeGenerator or cisc-spilling |
3864 | void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *indent) { |
3865 | const char *opType = NULL__null; |
3866 | const char *opClass = inst->_ident; |
3867 | |
3868 | // Create the MachNode object |
3869 | fprintf(fp_cpp, "%s %sNode *node = new %sNode();\n",indent, opClass,opClass); |
3870 | |
3871 | if ( (inst->num_post_match_opnds() != 0) ) { |
3872 | // Instruction that contains operands which are not in match rule. |
3873 | // |
3874 | // Check if the first post-match component may be an interesting def |
3875 | bool dont_care = false; |
3876 | ComponentList &comp_list = inst->_components; |
3877 | Component *comp = NULL__null; |
3878 | comp_list.reset(); |
3879 | if ( comp_list.match_iter() != NULL__null ) dont_care = true; |
3880 | |
3881 | // Insert operands that are not in match-rule. |
3882 | // Only insert a DEF if the do_care flag is set |
3883 | comp_list.reset(); |
3884 | while ( (comp = comp_list.post_match_iter()) ) { |
3885 | // Check if we don't care about DEFs or KILLs that are not USEs |
3886 | if ( dont_care && (! comp->isa(Component::USE)) ) { |
3887 | continue; |
3888 | } |
3889 | dont_care = true; |
3890 | // For each operand not in the match rule, call MachOperGenerator |
3891 | // with the enum for the opcode that needs to be built. |
3892 | ComponentList clist = inst->_components; |
3893 | int index = clist.operand_position(comp->_name, comp->_usedef, inst); |
3894 | const char *opcode = machOperEnum(comp->_type); |
3895 | fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); |
3896 | fprintf(fp_cpp, "MachOperGenerator(%s));\n", opcode); |
3897 | } |
3898 | } |
3899 | else if ( inst->is_chain_of_constant(_globalNames, opType) ) { |
3900 | // An instruction that chains from a constant! |
3901 | // In this case, we need to subsume the constant into the node |
3902 | // at operand position, oper_input_base(). |
3903 | // |
3904 | // Fill in the constant |
3905 | fprintf(fp_cpp, "%s node->_opnd_array[%d] = ", indent, |
3906 | inst->oper_input_base(_globalNames)); |
3907 | // ##### |
3908 | // Check for multiple constants and then fill them in. |
3909 | // Just like MachOperGenerator |
3910 | const char *opName = inst->_matrule->_rChild->_opType; |
3911 | fprintf(fp_cpp, "new %sOper(", opName); |
3912 | // Grab operand form |
3913 | OperandForm *op = (_globalNames[opName])->is_operand(); |
3914 | // Look up the number of constants |
3915 | uintunsigned int num_consts = op->num_consts(_globalNames); |
3916 | if ( (num_consts > 0) ) { |
3917 | uintunsigned int i = 0; |
3918 | path_to_constant(fp_cpp, _globalNames, op->_matrule, i); |
3919 | for ( i = 1; i < num_consts; ++i ) { |
3920 | fprintf(fp_cpp, ", "); |
3921 | path_to_constant(fp_cpp, _globalNames, op->_matrule, i); |
3922 | } |
3923 | } |
3924 | fprintf(fp_cpp, " );\n"); |
3925 | // ##### |
3926 | } |
3927 | |
3928 | // Fill in the bottom_type where requested |
3929 | if (inst->captures_bottom_type(_globalNames)) { |
3930 | if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall"))) { |
3931 | fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); |
3932 | } |
3933 | } |
3934 | if( inst->is_ideal_if() ) { |
3935 | fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent); |
3936 | fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent); |
3937 | } |
3938 | if (inst->is_ideal_halt()) { |
3939 | fprintf(fp_cpp, "%s node->_halt_reason = _leaf->as_Halt()->_halt_reason;\n", indent); |
3940 | fprintf(fp_cpp, "%s node->_reachable = _leaf->as_Halt()->_reachable;\n", indent); |
3941 | } |
3942 | if (inst->is_ideal_jump()) { |
3943 | fprintf(fp_cpp, "%s node->_probs = _leaf->as_Jump()->_probs;\n", indent); |
3944 | } |
3945 | if( inst->is_ideal_fastlock() ) { |
3946 | fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent); |
3947 | fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent); |
3948 | } |
3949 | |
3950 | } |
3951 | |
3952 | //---------------------------declare_cisc_version------------------------------ |
3953 | // Build CISC version of this instruction |
3954 | void InstructForm::declare_cisc_version(ArchDesc &AD, FILE *fp_hpp) { |
3955 | if( AD.can_cisc_spill() ) { |
3956 | InstructForm *inst_cisc = cisc_spill_alternate(); |
3957 | if (inst_cisc != NULL__null) { |
3958 | fprintf(fp_hpp, " virtual int cisc_operand() const { return %d; }\n", cisc_spill_operand()); |
3959 | fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset);\n"); |
3960 | fprintf(fp_hpp, " virtual void use_cisc_RegMask();\n"); |
3961 | fprintf(fp_hpp, " virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n"); |
3962 | } |
3963 | } |
3964 | } |
3965 | |
3966 | //---------------------------define_cisc_version------------------------------- |
3967 | // Build CISC version of this instruction |
3968 | bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) { |
3969 | InstructForm *inst_cisc = this->cisc_spill_alternate(); |
3970 | if( AD.can_cisc_spill() && (inst_cisc != NULL__null) ) { |
3971 | const char *name = inst_cisc->_ident; |
3972 | assert( inst_cisc->num_opnds() == this->num_opnds(), "Must have same number of operands"){ if (!(inst_cisc->num_opnds() == this->num_opnds())) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3972, "Must have same number of operands"); abort(); }}; |
3973 | OperandForm *cisc_oper = AD.cisc_spill_operand(); |
3974 | assert( cisc_oper != NULL, "insanity check"){ if (!(cisc_oper != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3974, "insanity check"); abort(); }}; |
3975 | const char *cisc_oper_name = cisc_oper->_ident; |
3976 | assert( cisc_oper_name != NULL, "insanity check"){ if (!(cisc_oper_name != __null)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/output_c.cpp" , 3976, "insanity check"); abort(); }}; |
3977 | // |
3978 | // Set the correct reg_mask_or_stack for the cisc operand |
3979 | fprintf(fp_cpp, "\n"); |
3980 | fprintf(fp_cpp, "void %sNode::use_cisc_RegMask() {\n", this->_ident); |
3981 | // Lookup the correct reg_mask_or_stack |
3982 | const char *reg_mask_name = cisc_reg_mask_name(); |
3983 | fprintf(fp_cpp, " _cisc_RegMask = &STACK_OR_%s;\n", reg_mask_name); |
3984 | fprintf(fp_cpp, "}\n"); |
3985 | // |
3986 | // Construct CISC version of this instruction |
3987 | fprintf(fp_cpp, "\n"); |
3988 | fprintf(fp_cpp, "// Build CISC version of this instruction\n"); |
3989 | fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident); |
3990 | // Create the MachNode object |
3991 | fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); |
3992 | // Fill in the bottom_type where requested |
3993 | if ( this->captures_bottom_type(AD.globalNames()) ) { |
3994 | fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); |
3995 | } |
3996 | |
3997 | uintunsigned int cur_num_opnds = num_opnds(); |
3998 | if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) { |
3999 | fprintf(fp_cpp," node->_num_opnds = %d;\n", num_unique_opnds()); |
4000 | } |
4001 | |
4002 | fprintf(fp_cpp, "\n"); |
4003 | fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); |
4004 | fprintf(fp_cpp, " fill_new_machnode(node);\n"); |
4005 | // Construct operand to access [stack_pointer + offset] |
4006 | fprintf(fp_cpp, " // Construct operand to access [stack_pointer + offset]\n"); |
4007 | fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new %sOper(offset));\n", cisc_oper_name); |
4008 | fprintf(fp_cpp, "\n"); |
4009 | |
4010 | // Return result and exit scope |
4011 | fprintf(fp_cpp, " return node;\n"); |
4012 | fprintf(fp_cpp, "}\n"); |
4013 | fprintf(fp_cpp, "\n"); |
4014 | return true; |
4015 | } |
4016 | return false; |
4017 | } |
4018 | |
4019 | //---------------------------declare_short_branch_methods---------------------- |
4020 | // Build prototypes for short branch methods |
4021 | void InstructForm::declare_short_branch_methods(FILE *fp_hpp) { |
4022 | if (has_short_branch_form()) { |
4023 | fprintf(fp_hpp, " virtual MachNode *short_branch_version();\n"); |
4024 | } |
4025 | } |
4026 | |
4027 | //---------------------------define_short_branch_methods----------------------- |
4028 | // Build definitions for short branch methods |
4029 | bool InstructForm::define_short_branch_methods(ArchDesc &AD, FILE *fp_cpp) { |
4030 | if (has_short_branch_form()) { |
4031 | InstructForm *short_branch = short_branch_form(); |
4032 | const char *name = short_branch->_ident; |
4033 | |
4034 | // Construct short_branch_version() method. |
4035 | fprintf(fp_cpp, "// Build short branch version of this instruction\n"); |
4036 | fprintf(fp_cpp, "MachNode *%sNode::short_branch_version() {\n", this->_ident); |
4037 | // Create the MachNode object |
4038 | fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); |
4039 | if( is_ideal_if() ) { |
4040 | fprintf(fp_cpp, " node->_prob = _prob;\n"); |
4041 | fprintf(fp_cpp, " node->_fcnt = _fcnt;\n"); |
4042 | } |
4043 | // Fill in the bottom_type where requested |
4044 | if ( this->captures_bottom_type(AD.globalNames()) ) { |
4045 | fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); |
4046 | } |
4047 | |
4048 | fprintf(fp_cpp, "\n"); |
4049 | // Short branch version must use same node index for access |
4050 | // through allocator's tables |
4051 | fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); |
4052 | fprintf(fp_cpp, " fill_new_machnode(node);\n"); |
4053 | |
4054 | // Return result and exit scope |
4055 | fprintf(fp_cpp, " return node;\n"); |
4056 | fprintf(fp_cpp, "}\n"); |
4057 | fprintf(fp_cpp,"\n"); |
4058 | return true; |
4059 | } |
4060 | return false; |
4061 | } |
4062 | |
4063 | |
4064 | //---------------------------buildMachNodeGenerator---------------------------- |
4065 | // Build switch to invoke appropriate "new" MachNode for an opcode |
4066 | void ArchDesc::buildMachNodeGenerator(FILE *fp_cpp) { |
4067 | |
4068 | // Build switch to invoke 'new' for a specific MachNode |
4069 | fprintf(fp_cpp, "\n"); |
4070 | fprintf(fp_cpp, "\n"); |
4071 | fprintf(fp_cpp, |
4072 | "//------------------------- MachNode Generator ---------------\n"); |
4073 | fprintf(fp_cpp, |
4074 | "// A switch statement on the dense-packed user-defined type system\n" |
4075 | "// that invokes 'new' on the corresponding class constructor.\n"); |
4076 | fprintf(fp_cpp, "\n"); |
4077 | fprintf(fp_cpp, "MachNode *State::MachNodeGenerator"); |
4078 | fprintf(fp_cpp, "(int opcode)"); |
4079 | fprintf(fp_cpp, "{\n"); |
4080 | fprintf(fp_cpp, " switch(opcode) {\n"); |
4081 | |
4082 | // Provide constructor for all user-defined instructions |
4083 | _instructions.reset(); |
4084 | int opIndex = operandFormCount(); |
4085 | InstructForm *inst; |
4086 | for( ; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
4087 | // Ensure that matrule is defined. |
4088 | if ( inst->_matrule == NULL__null ) continue; |
4089 | |
4090 | int opcode = opIndex++; |
4091 | const char *opClass = inst->_ident; |
4092 | char *opType = NULL__null; |
4093 | |
4094 | // Generate the case statement for this instruction |
4095 | fprintf(fp_cpp, " case %s_rule:", opClass); |
4096 | |
4097 | // Start local scope |
4098 | fprintf(fp_cpp, " {\n"); |
4099 | // Generate code to construct the new MachNode |
4100 | buildMachNode(fp_cpp, inst, " "); |
4101 | // Return result and exit scope |
4102 | fprintf(fp_cpp, " return node;\n"); |
4103 | fprintf(fp_cpp, " }\n"); |
4104 | } |
4105 | |
4106 | // Generate the default case for switch(opcode) |
4107 | fprintf(fp_cpp, " \n"); |
4108 | fprintf(fp_cpp, " default:\n"); |
4109 | fprintf(fp_cpp, " fprintf(stderr, \"Default MachNode Generator invoked for: \\n\");\n"); |
4110 | fprintf(fp_cpp, " fprintf(stderr, \" opcode = %cd\\n\", opcode);\n", '%'); |
4111 | fprintf(fp_cpp, " break;\n"); |
4112 | fprintf(fp_cpp, " };\n"); |
4113 | |
4114 | // Generate the closing for method Matcher::MachNodeGenerator |
4115 | fprintf(fp_cpp, " return NULL;\n"); |
4116 | fprintf(fp_cpp, "}\n"); |
4117 | } |
4118 | |
4119 | |
4120 | //---------------------------buildInstructMatchCheck-------------------------- |
4121 | // Output the method to Matcher which checks whether or not a specific |
4122 | // instruction has a matching rule for the host architecture. |
4123 | void ArchDesc::buildInstructMatchCheck(FILE *fp_cpp) const { |
4124 | fprintf(fp_cpp, "\n\n"); |
4125 | fprintf(fp_cpp, "const bool Matcher::has_match_rule(int opcode) {\n"); |
4126 | fprintf(fp_cpp, " assert(_last_machine_leaf < opcode && opcode < _last_opcode, \"opcode in range\");\n"); |
4127 | fprintf(fp_cpp, " return _hasMatchRule[opcode];\n"); |
4128 | fprintf(fp_cpp, "}\n\n"); |
4129 | |
4130 | fprintf(fp_cpp, "const bool Matcher::_hasMatchRule[_last_opcode] = {\n"); |
4131 | int i; |
4132 | for (i = 0; i < _last_opcode - 1; i++) { |
4133 | fprintf(fp_cpp, " %-5s, // %s\n", |
4134 | _has_match_rule[i] ? "true" : "false", |
4135 | NodeClassNames[i]); |
4136 | } |
4137 | fprintf(fp_cpp, " %-5s // %s\n", |
4138 | _has_match_rule[i] ? "true" : "false", |
4139 | NodeClassNames[i]); |
4140 | fprintf(fp_cpp, "};\n"); |
4141 | } |
4142 | |
4143 | //---------------------------buildFrameMethods--------------------------------- |
4144 | // Output the methods to Matcher which specify frame behavior |
4145 | void ArchDesc::buildFrameMethods(FILE *fp_cpp) { |
4146 | fprintf(fp_cpp,"\n\n"); |
4147 | // Sync Stack Slots |
4148 | fprintf(fp_cpp,"int Compile::sync_stack_slots() const { return %s; }\n\n", |
4149 | _frame->_sync_stack_slots); |
4150 | // Java Stack Alignment |
4151 | fprintf(fp_cpp,"uint Matcher::stack_alignment_in_bytes() { return %s; }\n\n", |
4152 | _frame->_alignment); |
4153 | // Java Return Address Location |
4154 | fprintf(fp_cpp,"OptoReg::Name Matcher::return_addr() const {"); |
4155 | if (_frame->_return_addr_loc) { |
4156 | fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", |
4157 | _frame->_return_addr); |
4158 | } |
4159 | else { |
4160 | fprintf(fp_cpp," return OptoReg::stack2reg(%s); }\n\n", |
4161 | _frame->_return_addr); |
4162 | } |
4163 | // varargs C out slots killed |
4164 | fprintf(fp_cpp,"uint Compile::varargs_C_out_slots_killed() const "); |
4165 | fprintf(fp_cpp,"{ return %s; }\n\n", _frame->_varargs_C_out_slots_killed); |
4166 | // Java Return Value Location |
4167 | fprintf(fp_cpp,"OptoRegPair Matcher::return_value(uint ideal_reg) {\n"); |
4168 | fprintf(fp_cpp,"%s\n", _frame->_return_value); |
4169 | fprintf(fp_cpp,"}\n\n"); |
4170 | // Native Return Value Location |
4171 | fprintf(fp_cpp,"OptoRegPair Matcher::c_return_value(uint ideal_reg) {\n"); |
4172 | fprintf(fp_cpp,"%s\n", _frame->_c_return_value); |
4173 | fprintf(fp_cpp,"}\n\n"); |
4174 | |
4175 | // Inline Cache Register, mask definition, and encoding |
4176 | fprintf(fp_cpp,"OptoReg::Name Matcher::inline_cache_reg() {"); |
4177 | fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", |
4178 | _frame->_inline_cache_reg); |
4179 | fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {"); |
4180 | fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n"); |
4181 | |
4182 | // Interpreter's Frame Pointer Register |
4183 | fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_frame_pointer_reg() {"); |
4184 | if (_frame->_interpreter_frame_pointer_reg == NULL__null) |
4185 | fprintf(fp_cpp," return OptoReg::Bad; }\n\n"); |
4186 | else |
4187 | fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", |
4188 | _frame->_interpreter_frame_pointer_reg); |
4189 | |
4190 | // Frame Pointer definition |
4191 | /* CNC - I can not contemplate having a different frame pointer between |
4192 | Java and native code; makes my head hurt to think about it. |
4193 | fprintf(fp_cpp,"OptoReg::Name Matcher::frame_pointer() const {"); |
4194 | fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", |
4195 | _frame->_frame_pointer); |
4196 | */ |
4197 | // (Native) Frame Pointer definition |
4198 | fprintf(fp_cpp,"OptoReg::Name Matcher::c_frame_pointer() const {"); |
4199 | fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", |
4200 | _frame->_frame_pointer); |
4201 | |
4202 | // Number of callee-save + always-save registers for calling convention |
4203 | fprintf(fp_cpp, "// Number of callee-save + always-save registers\n"); |
4204 | fprintf(fp_cpp, "int Matcher::number_of_saved_registers() {\n"); |
4205 | RegDef *rdef; |
4206 | int nof_saved_registers = 0; |
4207 | _register->reset_RegDefs(); |
4208 | while( (rdef = _register->iter_RegDefs()) != NULL__null ) { |
4209 | if( !strcmp(rdef->_callconv, "SOE") || !strcmp(rdef->_callconv, "AS") ) |
4210 | ++nof_saved_registers; |
4211 | } |
4212 | fprintf(fp_cpp, " return %d;\n", nof_saved_registers); |
4213 | fprintf(fp_cpp, "};\n\n"); |
4214 | } |
4215 | |
4216 | |
4217 | |
4218 | |
4219 | static int PrintAdlcCisc = 0; |
4220 | //---------------------------identify_cisc_spilling---------------------------- |
4221 | // Get info for the CISC_oracle and MachNode::cisc_version() |
4222 | void ArchDesc::identify_cisc_spill_instructions() { |
4223 | |
4224 | if (_frame == NULL__null) |
4225 | return; |
4226 | |
4227 | // Find the user-defined operand for cisc-spilling |
4228 | if( _frame->_cisc_spilling_operand_name != NULL__null ) { |
4229 | const Form *form = _globalNames[_frame->_cisc_spilling_operand_name]; |
4230 | OperandForm *oper = form ? form->is_operand() : NULL__null; |
4231 | // Verify the user's suggestion |
4232 | if( oper != NULL__null ) { |
4233 | // Ensure that match field is defined. |
4234 | if ( oper->_matrule != NULL__null ) { |
4235 | MatchRule &mrule = *oper->_matrule; |
4236 | if( strcmp(mrule._opType,"AddP") == 0 ) { |
4237 | MatchNode *left = mrule._lChild; |
4238 | MatchNode *right= mrule._rChild; |
4239 | if( left != NULL__null && right != NULL__null ) { |
4240 | const Form *left_op = _globalNames[left->_opType]->is_operand(); |
4241 | const Form *right_op = _globalNames[right->_opType]->is_operand(); |
4242 | if( (left_op != NULL__null && right_op != NULL__null) |
4243 | && (left_op->interface_type(_globalNames) == Form::register_interface) |
4244 | && (right_op->interface_type(_globalNames) == Form::constant_interface) ) { |
4245 | // Successfully verified operand |
4246 | set_cisc_spill_operand( oper ); |
4247 | if( _cisc_spill_debug ) { |
4248 | fprintf(stderrstderr, "\n\nVerified CISC-spill operand %s\n\n", oper->_ident); |
4249 | } |
4250 | } |
4251 | } |
4252 | } |
4253 | } |
4254 | } |
4255 | } |
4256 | |
4257 | if( cisc_spill_operand() != NULL__null ) { |
4258 | // N^2 comparison of instructions looking for a cisc-spilling version |
4259 | _instructions.reset(); |
4260 | InstructForm *instr; |
4261 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
4262 | // Ensure that match field is defined. |
4263 | if ( instr->_matrule == NULL__null ) continue; |
4264 | |
4265 | MatchRule &mrule = *instr->_matrule; |
4266 | Predicate *pred = instr->build_predicate(); |
4267 | |
4268 | // Grab the machine type of the operand |
4269 | const char *rootOp = instr->_ident; |
4270 | mrule._machType = rootOp; |
4271 | |
4272 | // Find result type for match |
4273 | const char *result = instr->reduce_result(); |
4274 | |
4275 | if( PrintAdlcCisc ) fprintf(stderrstderr, " new instruction %s \n", instr->_ident ? instr->_ident : " "); |
4276 | bool found_cisc_alternate = false; |
4277 | _instructions.reset2(); |
4278 | InstructForm *instr2; |
4279 | for( ; !found_cisc_alternate && (instr2 = (InstructForm*)_instructions.iter2()) != NULL__null; ) { |
4280 | // Ensure that match field is defined. |
4281 | if( PrintAdlcCisc ) fprintf(stderrstderr, " instr2 == %s \n", instr2->_ident ? instr2->_ident : " "); |
4282 | if ( instr2->_matrule != NULL__null |
4283 | && (instr != instr2 ) // Skip self |
4284 | && (instr2->reduce_result() != NULL__null) // want same result |
4285 | && (strcmp(result, instr2->reduce_result()) == 0)) { |
4286 | MatchRule &mrule2 = *instr2->_matrule; |
4287 | Predicate *pred2 = instr2->build_predicate(); |
4288 | found_cisc_alternate = instr->cisc_spills_to(*this, instr2); |
4289 | } |
4290 | } |
4291 | } |
4292 | } |
4293 | } |
4294 | |
4295 | //---------------------------build_cisc_spilling------------------------------- |
4296 | // Get info for the CISC_oracle and MachNode::cisc_version() |
4297 | void ArchDesc::build_cisc_spill_instructions(FILE *fp_hpp, FILE *fp_cpp) { |
4298 | // Output the table for cisc spilling |
4299 | fprintf(fp_cpp, "// The following instructions can cisc-spill\n"); |
4300 | _instructions.reset(); |
4301 | InstructForm *inst = NULL__null; |
4302 | for(; (inst = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
4303 | // Ensure this is a machine-world instruction |
4304 | if ( inst->ideal_only() ) continue; |
4305 | const char *inst_name = inst->_ident; |
4306 | int operand = inst->cisc_spill_operand(); |
4307 | if( operand != AdlcVMDeps::Not_cisc_spillable ) { |
4308 | InstructForm *inst2 = inst->cisc_spill_alternate(); |
4309 | fprintf(fp_cpp, "// %s can cisc-spill operand %d to %s\n", inst->_ident, operand, inst2->_ident); |
4310 | } |
4311 | } |
4312 | fprintf(fp_cpp, "\n\n"); |
4313 | } |
4314 | |
4315 | //---------------------------identify_short_branches---------------------------- |
4316 | // Get info for our short branch replacement oracle. |
4317 | void ArchDesc::identify_short_branches() { |
4318 | // Walk over all instructions, checking to see if they match a short |
4319 | // branching alternate. |
4320 | _instructions.reset(); |
4321 | InstructForm *instr; |
4322 | while( (instr = (InstructForm*)_instructions.iter()) != NULL__null ) { |
4323 | // The instruction must have a match rule. |
4324 | if (instr->_matrule != NULL__null && |
4325 | instr->is_short_branch()) { |
4326 | |
4327 | _instructions.reset2(); |
4328 | InstructForm *instr2; |
4329 | while( (instr2 = (InstructForm*)_instructions.iter2()) != NULL__null ) { |
4330 | instr2->check_branch_variant(*this, instr); |
4331 | } |
4332 | } |
4333 | } |
4334 | } |
4335 | |
4336 | |
4337 | //---------------------------identify_unique_operands--------------------------- |
4338 | // Identify unique operands. |
4339 | void ArchDesc::identify_unique_operands() { |
4340 | // Walk over all instructions. |
4341 | _instructions.reset(); |
4342 | InstructForm *instr; |
4343 | while( (instr = (InstructForm*)_instructions.iter()) != NULL__null ) { |
4344 | // Ensure this is a machine-world instruction |
4345 | if (!instr->ideal_only()) { |
4346 | instr->set_unique_opnds(); |
4347 | } |
4348 | } |
4349 | } |