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