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