Mercurial > hg > truffle
annotate src/share/vm/adlc/output_h.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | 2f644f85485d |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
diff
changeset
|
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // output_h.cpp - Class HPP file output routines for architecture definition | |
26 #include "adlc.hpp" | |
27 | |
28 | |
29 // Generate the #define that describes the number of registers. | |
30 static void defineRegCount(FILE *fp, RegisterForm *registers) { | |
31 if (registers) { | |
32 int regCount = AdlcVMDeps::Physical + registers->_rdefs.count(); | |
33 fprintf(fp,"\n"); | |
34 fprintf(fp,"// the number of reserved registers + machine registers.\n"); | |
35 fprintf(fp,"#define REG_COUNT %d\n", regCount); | |
36 } | |
37 } | |
38 | |
39 // Output enumeration of machine register numbers | |
40 // (1) | |
41 // // Enumerate machine registers starting after reserved regs. | |
42 // // in the order of occurrence in the register block. | |
43 // enum MachRegisterNumbers { | |
44 // EAX_num = 0, | |
45 // ... | |
46 // _last_Mach_Reg | |
47 // } | |
48 void ArchDesc::buildMachRegisterNumbers(FILE *fp_hpp) { | |
49 if (_register) { | |
50 RegDef *reg_def = NULL; | |
51 | |
52 // Output a #define for the number of machine registers | |
53 defineRegCount(fp_hpp, _register); | |
54 | |
55 // Count all the Save_On_Entry and Always_Save registers | |
56 int saved_on_entry = 0; | |
57 int c_saved_on_entry = 0; | |
58 _register->reset_RegDefs(); | |
59 while( (reg_def = _register->iter_RegDefs()) != NULL ) { | |
60 if( strcmp(reg_def->_callconv,"SOE") == 0 || | |
61 strcmp(reg_def->_callconv,"AS") == 0 ) ++saved_on_entry; | |
62 if( strcmp(reg_def->_c_conv,"SOE") == 0 || | |
63 strcmp(reg_def->_c_conv,"AS") == 0 ) ++c_saved_on_entry; | |
64 } | |
65 fprintf(fp_hpp, "\n"); | |
66 fprintf(fp_hpp, "// the number of save_on_entry + always_saved registers.\n"); | |
67 fprintf(fp_hpp, "#define MAX_SAVED_ON_ENTRY_REG_COUNT %d\n", max(saved_on_entry,c_saved_on_entry)); | |
68 fprintf(fp_hpp, "#define SAVED_ON_ENTRY_REG_COUNT %d\n", saved_on_entry); | |
69 fprintf(fp_hpp, "#define C_SAVED_ON_ENTRY_REG_COUNT %d\n", c_saved_on_entry); | |
70 | |
71 // (1) | |
72 // Build definition for enumeration of register numbers | |
73 fprintf(fp_hpp, "\n"); | |
74 fprintf(fp_hpp, "// Enumerate machine register numbers starting after reserved regs.\n"); | |
75 fprintf(fp_hpp, "// in the order of occurrence in the register block.\n"); | |
76 fprintf(fp_hpp, "enum MachRegisterNumbers {\n"); | |
77 | |
78 // Output the register number for each register in the allocation classes | |
79 _register->reset_RegDefs(); | |
80 int i = 0; | |
81 while( (reg_def = _register->iter_RegDefs()) != NULL ) { | |
82 fprintf(fp_hpp," %s_num,\t\t// %d\n", reg_def->_regname, i++); | |
83 } | |
84 // Finish defining enumeration | |
85 fprintf(fp_hpp, " _last_Mach_Reg\t// %d\n", i); | |
86 fprintf(fp_hpp, "};\n"); | |
87 } | |
88 | |
89 fprintf(fp_hpp, "\n// Size of register-mask in ints\n"); | |
90 fprintf(fp_hpp, "#define RM_SIZE %d\n",RegisterForm::RegMask_Size()); | |
91 fprintf(fp_hpp, "// Unroll factor for loops over the data in a RegMask\n"); | |
92 fprintf(fp_hpp, "#define FORALL_BODY "); | |
93 int len = RegisterForm::RegMask_Size(); | |
94 for( int i = 0; i < len; i++ ) | |
95 fprintf(fp_hpp, "BODY(%d) ",i); | |
96 fprintf(fp_hpp, "\n\n"); | |
97 | |
98 fprintf(fp_hpp,"class RegMask;\n"); | |
99 // All RegMasks are declared "extern const ..." in ad_<arch>.hpp | |
100 // fprintf(fp_hpp,"extern RegMask STACK_OR_STACK_SLOTS_mask;\n\n"); | |
101 } | |
102 | |
103 | |
104 // Output enumeration of machine register encodings | |
105 // (2) | |
106 // // Enumerate machine registers starting after reserved regs. | |
107 // // in the order of occurrence in the alloc_class(es). | |
108 // enum MachRegisterEncodes { | |
109 // EAX_enc = 0x00, | |
110 // ... | |
111 // } | |
112 void ArchDesc::buildMachRegisterEncodes(FILE *fp_hpp) { | |
113 if (_register) { | |
114 RegDef *reg_def = NULL; | |
115 RegDef *reg_def_next = NULL; | |
116 | |
117 // (2) | |
118 // Build definition for enumeration of encode values | |
119 fprintf(fp_hpp, "\n"); | |
120 fprintf(fp_hpp, "// Enumerate machine registers starting after reserved regs.\n"); | |
121 fprintf(fp_hpp, "// in the order of occurrence in the alloc_class(es).\n"); | |
122 fprintf(fp_hpp, "enum MachRegisterEncodes {\n"); | |
123 | |
124 // Output the register encoding for each register in the allocation classes | |
125 _register->reset_RegDefs(); | |
126 reg_def_next = _register->iter_RegDefs(); | |
127 while( (reg_def = reg_def_next) != NULL ) { | |
128 reg_def_next = _register->iter_RegDefs(); | |
129 fprintf(fp_hpp," %s_enc = %s%s\n", | |
130 reg_def->_regname, reg_def->register_encode(), reg_def_next == NULL? "" : "," ); | |
131 } | |
132 // Finish defining enumeration | |
133 fprintf(fp_hpp, "};\n"); | |
134 | |
135 } // Done with register form | |
136 } | |
137 | |
138 | |
139 // Declare an array containing the machine register names, strings. | |
140 static void declareRegNames(FILE *fp, RegisterForm *registers) { | |
141 if (registers) { | |
142 // fprintf(fp,"\n"); | |
143 // fprintf(fp,"// An array of character pointers to machine register names.\n"); | |
144 // fprintf(fp,"extern const char *regName[];\n"); | |
145 } | |
146 } | |
147 | |
148 // Declare an array containing the machine register sizes in 32-bit words. | |
149 void ArchDesc::declareRegSizes(FILE *fp) { | |
150 // regSize[] is not used | |
151 } | |
152 | |
153 // Declare an array containing the machine register encoding values | |
154 static void declareRegEncodes(FILE *fp, RegisterForm *registers) { | |
155 if (registers) { | |
156 // // // | |
157 // fprintf(fp,"\n"); | |
158 // fprintf(fp,"// An array containing the machine register encode values\n"); | |
159 // fprintf(fp,"extern const char regEncode[];\n"); | |
160 } | |
161 } | |
162 | |
163 | |
164 // --------------------------------------------------------------------------- | |
165 //------------------------------Utilities to build Instruction Classes-------- | |
166 // --------------------------------------------------------------------------- | |
167 static void out_RegMask(FILE *fp) { | |
168 fprintf(fp," virtual const RegMask &out_RegMask() const;\n"); | |
169 } | |
170 | |
171 // --------------------------------------------------------------------------- | |
172 //--------Utilities to build MachOper and MachNode derived Classes------------ | |
173 // --------------------------------------------------------------------------- | |
174 | |
175 //------------------------------Utilities to build Operand Classes------------ | |
176 static void in_RegMask(FILE *fp) { | |
177 fprintf(fp," virtual const RegMask *in_RegMask(int index) const;\n"); | |
178 } | |
179 | |
180 static void declare_hash(FILE *fp) { | |
181 fprintf(fp," virtual uint hash() const;\n"); | |
182 } | |
183 | |
184 static void declare_cmp(FILE *fp) { | |
185 fprintf(fp," virtual uint cmp( const MachOper &oper ) const;\n"); | |
186 } | |
187 | |
188 static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) { | |
189 int i = 0; | |
190 Component *comp; | |
191 | |
192 if (oper->num_consts(globals) == 0) return; | |
193 // Iterate over the component list looking for constants | |
194 oper->_components.reset(); | |
195 if ((comp = oper->_components.iter()) == NULL) { | |
196 assert(oper->num_consts(globals) == 1, "Bad component list detected.\n"); | |
197 const char *type = oper->ideal_type(globals); | |
198 if (!strcmp(type, "ConI")) { | |
199 if (i > 0) fprintf(fp,", "); | |
200 fprintf(fp," int32 _c%d;\n", i); | |
201 } | |
202 else if (!strcmp(type, "ConP")) { | |
203 if (i > 0) fprintf(fp,", "); | |
204 fprintf(fp," const TypePtr *_c%d;\n", i); | |
205 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
206 else if (!strcmp(type, "ConN")) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
207 if (i > 0) fprintf(fp,", "); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
208 fprintf(fp," const TypeNarrowOop *_c%d;\n", i); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
209 } |
0 | 210 else if (!strcmp(type, "ConL")) { |
211 if (i > 0) fprintf(fp,", "); | |
212 fprintf(fp," jlong _c%d;\n", i); | |
213 } | |
214 else if (!strcmp(type, "ConF")) { | |
215 if (i > 0) fprintf(fp,", "); | |
216 fprintf(fp," jfloat _c%d;\n", i); | |
217 } | |
218 else if (!strcmp(type, "ConD")) { | |
219 if (i > 0) fprintf(fp,", "); | |
220 fprintf(fp," jdouble _c%d;\n", i); | |
221 } | |
222 else if (!strcmp(type, "Bool")) { | |
223 fprintf(fp,"private:\n"); | |
224 fprintf(fp," BoolTest::mask _c%d;\n", i); | |
225 fprintf(fp,"public:\n"); | |
226 } | |
227 else { | |
228 assert(0, "Non-constant operand lacks component list."); | |
229 } | |
230 } // end if NULL | |
231 else { | |
232 oper->_components.reset(); | |
233 while ((comp = oper->_components.iter()) != NULL) { | |
234 if (!strcmp(comp->base_type(globals), "ConI")) { | |
235 fprintf(fp," jint _c%d;\n", i); | |
236 i++; | |
237 } | |
238 else if (!strcmp(comp->base_type(globals), "ConP")) { | |
239 fprintf(fp," const TypePtr *_c%d;\n", i); | |
240 i++; | |
241 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
242 else if (!strcmp(comp->base_type(globals), "ConN")) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
243 fprintf(fp," const TypePtr *_c%d;\n", i); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
244 i++; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
245 } |
0 | 246 else if (!strcmp(comp->base_type(globals), "ConL")) { |
247 fprintf(fp," jlong _c%d;\n", i); | |
248 i++; | |
249 } | |
250 else if (!strcmp(comp->base_type(globals), "ConF")) { | |
251 fprintf(fp," jfloat _c%d;\n", i); | |
252 i++; | |
253 } | |
254 else if (!strcmp(comp->base_type(globals), "ConD")) { | |
255 fprintf(fp," jdouble _c%d;\n", i); | |
256 i++; | |
257 } | |
258 } | |
259 } | |
260 } | |
261 | |
262 // Declare constructor. | |
263 // Parameters start with condition code, then all other constants | |
264 // | |
265 // (0) public: | |
266 // (1) MachXOper(int32 ccode, int32 c0, int32 c1, ..., int32 cn) | |
267 // (2) : _ccode(ccode), _c0(c0), _c1(c1), ..., _cn(cn) { } | |
268 // | |
269 static void defineConstructor(FILE *fp, const char *name, uint num_consts, | |
270 ComponentList &lst, bool is_ideal_bool, | |
271 Form::DataType constant_type, FormDict &globals) { | |
272 fprintf(fp,"public:\n"); | |
273 // generate line (1) | |
274 fprintf(fp," %sOper(", name); | |
275 if( num_consts == 0 ) { | |
276 fprintf(fp,") {}\n"); | |
277 return; | |
278 } | |
279 | |
280 // generate parameters for constants | |
281 uint i = 0; | |
282 Component *comp; | |
283 lst.reset(); | |
284 if ((comp = lst.iter()) == NULL) { | |
285 assert(num_consts == 1, "Bad component list detected.\n"); | |
286 switch( constant_type ) { | |
287 case Form::idealI : { | |
288 fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32 c%d", i); | |
289 break; | |
290 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
291 case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; } |
0 | 292 case Form::idealP : { fprintf(fp,"const TypePtr *c%d", i); break; } |
293 case Form::idealL : { fprintf(fp,"jlong c%d", i); break; } | |
294 case Form::idealF : { fprintf(fp,"jfloat c%d", i); break; } | |
295 case Form::idealD : { fprintf(fp,"jdouble c%d", i); break; } | |
296 default: | |
297 assert(!is_ideal_bool, "Non-constant operand lacks component list."); | |
298 break; | |
299 } | |
300 } // end if NULL | |
301 else { | |
302 lst.reset(); | |
303 while((comp = lst.iter()) != NULL) { | |
304 if (!strcmp(comp->base_type(globals), "ConI")) { | |
305 if (i > 0) fprintf(fp,", "); | |
306 fprintf(fp,"int32 c%d", i); | |
307 i++; | |
308 } | |
309 else if (!strcmp(comp->base_type(globals), "ConP")) { | |
310 if (i > 0) fprintf(fp,", "); | |
311 fprintf(fp,"const TypePtr *c%d", i); | |
312 i++; | |
313 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
314 else if (!strcmp(comp->base_type(globals), "ConN")) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
315 if (i > 0) fprintf(fp,", "); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
316 fprintf(fp,"const TypePtr *c%d", i); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
317 i++; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
318 } |
0 | 319 else if (!strcmp(comp->base_type(globals), "ConL")) { |
320 if (i > 0) fprintf(fp,", "); | |
321 fprintf(fp,"jlong c%d", i); | |
322 i++; | |
323 } | |
324 else if (!strcmp(comp->base_type(globals), "ConF")) { | |
325 if (i > 0) fprintf(fp,", "); | |
326 fprintf(fp,"jfloat c%d", i); | |
327 i++; | |
328 } | |
329 else if (!strcmp(comp->base_type(globals), "ConD")) { | |
330 if (i > 0) fprintf(fp,", "); | |
331 fprintf(fp,"jdouble c%d", i); | |
332 i++; | |
333 } | |
334 else if (!strcmp(comp->base_type(globals), "Bool")) { | |
335 if (i > 0) fprintf(fp,", "); | |
336 fprintf(fp,"BoolTest::mask c%d", i); | |
337 i++; | |
338 } | |
339 } | |
340 } | |
341 // finish line (1) and start line (2) | |
342 fprintf(fp,") : "); | |
343 // generate initializers for constants | |
344 i = 0; | |
345 fprintf(fp,"_c%d(c%d)", i, i); | |
346 for( i = 1; i < num_consts; ++i) { | |
347 fprintf(fp,", _c%d(c%d)", i, i); | |
348 } | |
349 // The body for the constructor is empty | |
350 fprintf(fp," {}\n"); | |
351 } | |
352 | |
353 // --------------------------------------------------------------------------- | |
354 // Utilities to generate format rules for machine operands and instructions | |
355 // --------------------------------------------------------------------------- | |
356 | |
357 // Generate the format rule for condition codes | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
358 static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
359 assert(oper != NULL, "what"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
360 CondInterface* cond = oper->_interface->is_CondInterface(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
361 fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
362 fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
363 fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
364 fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
365 fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
366 fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format); |
0 | 367 } |
368 | |
369 // Output code that dumps constant values, increment "i" if type is constant | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
370 static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) { |
0 | 371 if (!strcmp(ideal_type, "ConI")) { |
372 fprintf(fp," st->print(\"#%%d\", _c%d);\n", i); | |
373 ++i; | |
374 } | |
375 else if (!strcmp(ideal_type, "ConP")) { | |
376 fprintf(fp," _c%d->dump_on(st);\n", i); | |
377 ++i; | |
378 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
379 else if (!strcmp(ideal_type, "ConN")) { |
417 | 380 fprintf(fp," _c%d->dump_on(st);\n", i); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
381 ++i; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
382 } |
0 | 383 else if (!strcmp(ideal_type, "ConL")) { |
384 fprintf(fp," st->print(\"#\" INT64_FORMAT, _c%d);\n", i); | |
385 ++i; | |
386 } | |
387 else if (!strcmp(ideal_type, "ConF")) { | |
388 fprintf(fp," st->print(\"#%%f\", _c%d);\n", i); | |
389 ++i; | |
390 } | |
391 else if (!strcmp(ideal_type, "ConD")) { | |
392 fprintf(fp," st->print(\"#%%f\", _c%d);\n", i); | |
393 ++i; | |
394 } | |
395 else if (!strcmp(ideal_type, "Bool")) { | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
396 defineCCodeDump(oper, fp,i); |
0 | 397 ++i; |
398 } | |
399 | |
400 return i; | |
401 } | |
402 | |
403 // Generate the format rule for an operand | |
404 void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_file = false) { | |
405 if (!for_c_file) { | |
406 // invoked after output #ifndef PRODUCT to ad_<arch>.hpp | |
407 // compile the bodies separately, to cut down on recompilations | |
408 fprintf(fp," virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const;\n"); | |
409 fprintf(fp," virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const;\n"); | |
410 return; | |
411 } | |
412 | |
413 // Local pointer indicates remaining part of format rule | |
414 uint idx = 0; // position of operand in match rule | |
415 | |
416 // Generate internal format function, used when stored locally | |
417 fprintf(fp, "\n#ifndef PRODUCT\n"); | |
418 fprintf(fp,"void %sOper::int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const {\n", oper._ident); | |
419 // Generate the user-defined portion of the format | |
420 if (oper._format) { | |
421 if ( oper._format->_strings.count() != 0 ) { | |
422 // No initialization code for int_format | |
423 | |
424 // Build the format from the entries in strings and rep_vars | |
425 const char *string = NULL; | |
426 oper._format->_rep_vars.reset(); | |
427 oper._format->_strings.reset(); | |
428 while ( (string = oper._format->_strings.iter()) != NULL ) { | |
429 fprintf(fp," "); | |
430 | |
431 // Check if this is a standard string or a replacement variable | |
432 if ( string != NameList::_signal ) { | |
433 // Normal string | |
434 // Pass through to st->print | |
435 fprintf(fp,"st->print(\"%s\");\n", string); | |
436 } else { | |
437 // Replacement variable | |
438 const char *rep_var = oper._format->_rep_vars.iter(); | |
439 // Check that it is a local name, and an operand | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
440 const Form* form = oper._localNames[rep_var]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
441 if (form == NULL) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
442 globalAD->syntax_err(oper._linenum, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
443 "\'%s\' not found in format for %s\n", rep_var, oper._ident); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
444 assert(form, "replacement variable was not found in local names"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
445 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
446 OperandForm *op = form->is_operand(); |
0 | 447 // Get index if register or constant |
448 if ( op->_matrule && op->_matrule->is_base_register(globals) ) { | |
449 idx = oper.register_position( globals, rep_var); | |
450 } | |
451 else if (op->_matrule && op->_matrule->is_base_constant(globals)) { | |
452 idx = oper.constant_position( globals, rep_var); | |
453 } else { | |
454 idx = 0; | |
455 } | |
456 | |
457 // output invocation of "$..."s format function | |
458 if ( op != NULL ) op->int_format(fp, globals, idx); | |
459 | |
460 if ( idx == -1 ) { | |
461 fprintf(stderr, | |
462 "Using a name, %s, that isn't in match rule\n", rep_var); | |
463 assert( strcmp(op->_ident,"label")==0, "Unimplemented"); | |
464 } | |
465 } // Done with a replacement variable | |
466 } // Done with all format strings | |
467 } else { | |
468 // Default formats for base operands (RegI, RegP, ConI, ConP, ...) | |
469 oper.int_format(fp, globals, 0); | |
470 } | |
471 | |
472 } else { // oper._format == NULL | |
473 // Provide a few special case formats where the AD writer cannot. | |
474 if ( strcmp(oper._ident,"Universe")==0 ) { | |
475 fprintf(fp, " st->print(\"$$univ\");\n"); | |
476 } | |
477 // labelOper::int_format is defined in ad_<...>.cpp | |
478 } | |
479 // ALWAYS! Provide a special case output for condition codes. | |
480 if( oper.is_ideal_bool() ) { | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
481 defineCCodeDump(&oper, fp,0); |
0 | 482 } |
483 fprintf(fp,"}\n"); | |
484 | |
485 // Generate external format function, when data is stored externally | |
486 fprintf(fp,"void %sOper::ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const {\n", oper._ident); | |
487 // Generate the user-defined portion of the format | |
488 if (oper._format) { | |
489 if ( oper._format->_strings.count() != 0 ) { | |
490 | |
491 // Check for a replacement string "$..." | |
492 if ( oper._format->_rep_vars.count() != 0 ) { | |
493 // Initialization code for ext_format | |
494 } | |
495 | |
496 // Build the format from the entries in strings and rep_vars | |
497 const char *string = NULL; | |
498 oper._format->_rep_vars.reset(); | |
499 oper._format->_strings.reset(); | |
500 while ( (string = oper._format->_strings.iter()) != NULL ) { | |
501 fprintf(fp," "); | |
502 | |
503 // Check if this is a standard string or a replacement variable | |
504 if ( string != NameList::_signal ) { | |
505 // Normal string | |
506 // Pass through to st->print | |
507 fprintf(fp,"st->print(\"%s\");\n", string); | |
508 } else { | |
509 // Replacement variable | |
510 const char *rep_var = oper._format->_rep_vars.iter(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
511 // Check that it is a local name, and an operand |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
512 const Form* form = oper._localNames[rep_var]; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
513 if (form == NULL) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
514 globalAD->syntax_err(oper._linenum, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
515 "\'%s\' not found in format for %s\n", rep_var, oper._ident); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
516 assert(form, "replacement variable was not found in local names"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
517 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
518 OperandForm *op = form->is_operand(); |
0 | 519 // Get index if register or constant |
520 if ( op->_matrule && op->_matrule->is_base_register(globals) ) { | |
521 idx = oper.register_position( globals, rep_var); | |
522 } | |
523 else if (op->_matrule && op->_matrule->is_base_constant(globals)) { | |
524 idx = oper.constant_position( globals, rep_var); | |
525 } else { | |
526 idx = 0; | |
527 } | |
528 // output invocation of "$..."s format function | |
529 if ( op != NULL ) op->ext_format(fp, globals, idx); | |
530 | |
531 // Lookup the index position of the replacement variable | |
532 idx = oper._components.operand_position_format(rep_var); | |
533 if ( idx == -1 ) { | |
534 fprintf(stderr, | |
535 "Using a name, %s, that isn't in match rule\n", rep_var); | |
536 assert( strcmp(op->_ident,"label")==0, "Unimplemented"); | |
537 } | |
538 } // Done with a replacement variable | |
539 } // Done with all format strings | |
540 | |
541 } else { | |
542 // Default formats for base operands (RegI, RegP, ConI, ConP, ...) | |
543 oper.ext_format(fp, globals, 0); | |
544 } | |
545 } else { // oper._format == NULL | |
546 // Provide a few special case formats where the AD writer cannot. | |
547 if ( strcmp(oper._ident,"Universe")==0 ) { | |
548 fprintf(fp, " st->print(\"$$univ\");\n"); | |
549 } | |
550 // labelOper::ext_format is defined in ad_<...>.cpp | |
551 } | |
552 // ALWAYS! Provide a special case output for condition codes. | |
553 if( oper.is_ideal_bool() ) { | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
554 defineCCodeDump(&oper, fp,0); |
0 | 555 } |
556 fprintf(fp, "}\n"); | |
557 fprintf(fp, "#endif\n"); | |
558 } | |
559 | |
560 | |
561 // Generate the format rule for an instruction | |
562 void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c_file = false) { | |
563 if (!for_c_file) { | |
564 // compile the bodies separately, to cut down on recompilations | |
565 // #ifndef PRODUCT region generated by caller | |
566 fprintf(fp," virtual void format(PhaseRegAlloc *ra, outputStream *st) const;\n"); | |
567 return; | |
568 } | |
569 | |
570 // Define the format function | |
571 fprintf(fp, "#ifndef PRODUCT\n"); | |
572 fprintf(fp, "void %sNode::format(PhaseRegAlloc *ra, outputStream *st) const {\n", inst._ident); | |
573 | |
574 // Generate the user-defined portion of the format | |
575 if( inst._format ) { | |
576 // If there are replacement variables, | |
605 | 577 // Generate index values needed for determining the operand position |
0 | 578 if( inst._format->_rep_vars.count() ) |
579 inst.index_temps(fp, globals); | |
580 | |
581 // Build the format from the entries in strings and rep_vars | |
582 const char *string = NULL; | |
583 inst._format->_rep_vars.reset(); | |
584 inst._format->_strings.reset(); | |
585 while( (string = inst._format->_strings.iter()) != NULL ) { | |
586 fprintf(fp," "); | |
587 // Check if this is a standard string or a replacement variable | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
588 if( string == NameList::_signal ) { // Replacement variable |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
589 const char* rep_var = inst._format->_rep_vars.iter(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
590 inst.rep_var_format( fp, rep_var); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
591 } else if( string == NameList::_signal3 ) { // Replacement variable in raw text |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
592 const char* rep_var = inst._format->_rep_vars.iter(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
593 const Form *form = inst._localNames[rep_var]; |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
594 if (form == NULL) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
595 fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
596 assert(false, "ShouldNotReachHere()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
597 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
598 OpClassForm *opc = form->is_opclass(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
599 assert( opc, "replacement variable was not found in local names"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
600 // Lookup the index position of the replacement variable |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
601 int idx = inst.operand_position_format(rep_var); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
602 if ( idx == -1 ) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
603 assert( strcmp(opc->_ident,"label")==0, "Unimplemented"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
604 assert( false, "ShouldNotReachHere()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
605 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
606 |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
607 if (inst.is_noninput_operand(idx)) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
608 assert( false, "ShouldNotReachHere()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
609 } else { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
610 // Output the format call for this operand |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
611 fprintf(fp,"opnd_array(%d)",idx); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
612 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
613 rep_var = inst._format->_rep_vars.iter(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
614 inst._format->_strings.iter(); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
615 if ( strcmp(rep_var,"$constant") == 0 && opc->is_operand()) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
616 Form::DataType constant_type = form->is_operand()->is_base_constant(globals); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
617 if ( constant_type == Form::idealD ) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
618 fprintf(fp,"->constantD()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
619 } else if ( constant_type == Form::idealF ) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
620 fprintf(fp,"->constantF()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
621 } else if ( constant_type == Form::idealL ) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
622 fprintf(fp,"->constantL()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
623 } else { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
624 fprintf(fp,"->constant()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
625 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
626 } else if ( strcmp(rep_var,"$cmpcode") == 0) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
627 fprintf(fp,"->ccode()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
628 } else { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
629 assert( false, "ShouldNotReachHere()"); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
630 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
631 } else if( string == NameList::_signal2 ) // Raw program text |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
632 fputs(inst._format->_strings.iter(), fp); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
633 else |
0 | 634 fprintf(fp,"st->print(\"%s\");\n", string); |
635 } // Done with all format strings | |
636 } // Done generating the user-defined portion of the format | |
637 | |
638 // Add call debug info automatically | |
639 Form::CallType call_type = inst.is_ideal_call(); | |
640 if( call_type != Form::invalid_type ) { | |
641 switch( call_type ) { | |
642 case Form::JAVA_DYNAMIC: | |
643 fprintf(fp," _method->print_short_name();\n"); | |
644 break; | |
645 case Form::JAVA_STATIC: | |
646 fprintf(fp," if( _method ) _method->print_short_name(st); else st->print(\" wrapper for: %%s\", _name);\n"); | |
647 fprintf(fp," if( !_method ) dump_trap_args(st);\n"); | |
648 break; | |
649 case Form::JAVA_COMPILED: | |
650 case Form::JAVA_INTERP: | |
651 break; | |
652 case Form::JAVA_RUNTIME: | |
653 case Form::JAVA_LEAF: | |
654 case Form::JAVA_NATIVE: | |
655 fprintf(fp," st->print(\" %%s\", _name);"); | |
656 break; | |
657 default: | |
658 assert(0,"ShouldNotReacHere"); | |
659 } | |
660 fprintf(fp, " st->print_cr(\"\");\n" ); | |
661 fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" ); | |
662 fprintf(fp, " st->print(\" # \");\n" ); | |
663 fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\n"); | |
664 } | |
665 else if(inst.is_ideal_safepoint()) { | |
666 fprintf(fp, " st->print(\"\");\n" ); | |
667 fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" ); | |
668 fprintf(fp, " st->print(\" # \");\n" ); | |
669 fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\n"); | |
670 } | |
671 else if( inst.is_ideal_if() ) { | |
672 fprintf(fp, " st->print(\" P=%%f C=%%f\",_prob,_fcnt);\n" ); | |
673 } | |
674 else if( inst.is_ideal_mem() ) { | |
675 // Print out the field name if available to improve readability | |
676 fprintf(fp, " if (ra->C->alias_type(adr_type())->field() != NULL) {\n"); | |
677 fprintf(fp, " st->print(\" ! Field \");\n"); | |
678 fprintf(fp, " if( ra->C->alias_type(adr_type())->is_volatile() )\n"); | |
679 fprintf(fp, " st->print(\" Volatile\");\n"); | |
680 fprintf(fp, " ra->C->alias_type(adr_type())->field()->holder()->name()->print_symbol_on(st);\n"); | |
681 fprintf(fp, " st->print(\".\");\n"); | |
682 fprintf(fp, " ra->C->alias_type(adr_type())->field()->name()->print_symbol_on(st);\n"); | |
683 fprintf(fp, " } else\n"); | |
684 // Make sure 'Volatile' gets printed out | |
685 fprintf(fp, " if( ra->C->alias_type(adr_type())->is_volatile() )\n"); | |
686 fprintf(fp, " st->print(\" Volatile!\");\n"); | |
687 } | |
688 | |
689 // Complete the definition of the format function | |
690 fprintf(fp, " }\n#endif\n"); | |
691 } | |
692 | |
693 static bool is_non_constant(char* x) { | |
694 // Tells whether the string (part of an operator interface) is non-constant. | |
695 // Simply detect whether there is an occurrence of a formal parameter, | |
696 // which will always begin with '$'. | |
697 return strchr(x, '$') == 0; | |
698 } | |
699 | |
700 void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { | |
701 if (!_pipeline) | |
702 return; | |
703 | |
704 fprintf(fp_hpp, "\n"); | |
705 fprintf(fp_hpp, "// Pipeline_Use_Cycle_Mask Class\n"); | |
706 fprintf(fp_hpp, "class Pipeline_Use_Cycle_Mask {\n"); | |
707 | |
708 if (_pipeline->_maxcycleused <= | |
709 #ifdef SPARC | |
710 64 | |
711 #else | |
712 32 | |
713 #endif | |
714 ) { | |
715 fprintf(fp_hpp, "protected:\n"); | |
716 fprintf(fp_hpp, " %s _mask;\n\n", _pipeline->_maxcycleused <= 32 ? "uint" : "uint64_t" ); | |
717 fprintf(fp_hpp, "public:\n"); | |
718 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask() : _mask(0) {}\n\n"); | |
719 if (_pipeline->_maxcycleused <= 32) | |
720 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint mask) : _mask(mask) {}\n\n"); | |
721 else { | |
722 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint mask1, uint mask2) : _mask((((uint64_t)mask1) << 32) | mask2) {}\n\n"); | |
723 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint64_t mask) : _mask(mask) {}\n\n"); | |
724 } | |
725 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator=(const Pipeline_Use_Cycle_Mask &in) {\n"); | |
726 fprintf(fp_hpp, " _mask = in._mask;\n"); | |
727 fprintf(fp_hpp, " return *this;\n"); | |
728 fprintf(fp_hpp, " }\n\n"); | |
729 fprintf(fp_hpp, " bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n"); | |
730 fprintf(fp_hpp, " return ((_mask & in2._mask) != 0);\n"); | |
731 fprintf(fp_hpp, " }\n\n"); | |
732 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n"); | |
733 fprintf(fp_hpp, " _mask <<= n;\n"); | |
734 fprintf(fp_hpp, " return *this;\n"); | |
735 fprintf(fp_hpp, " }\n\n"); | |
736 fprintf(fp_hpp, " void Or(const Pipeline_Use_Cycle_Mask &in2) {\n"); | |
737 fprintf(fp_hpp, " _mask |= in2._mask;\n"); | |
738 fprintf(fp_hpp, " }\n\n"); | |
739 fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n"); | |
740 fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n"); | |
741 } | |
742 else { | |
743 fprintf(fp_hpp, "protected:\n"); | |
744 uint masklen = (_pipeline->_maxcycleused + 31) >> 5; | |
745 uint l; | |
746 fprintf(fp_hpp, " uint "); | |
747 for (l = 1; l <= masklen; l++) | |
748 fprintf(fp_hpp, "_mask%d%s", l, l < masklen ? ", " : ";\n\n"); | |
749 fprintf(fp_hpp, "public:\n"); | |
750 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask() : "); | |
751 for (l = 1; l <= masklen; l++) | |
752 fprintf(fp_hpp, "_mask%d(0)%s", l, l < masklen ? ", " : " {}\n\n"); | |
753 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask("); | |
754 for (l = 1; l <= masklen; l++) | |
755 fprintf(fp_hpp, "uint mask%d%s", l, l < masklen ? ", " : ") : "); | |
756 for (l = 1; l <= masklen; l++) | |
757 fprintf(fp_hpp, "_mask%d(mask%d)%s", l, l, l < masklen ? ", " : " {}\n\n"); | |
758 | |
759 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator=(const Pipeline_Use_Cycle_Mask &in) {\n"); | |
760 for (l = 1; l <= masklen; l++) | |
761 fprintf(fp_hpp, " _mask%d = in._mask%d;\n", l, l); | |
762 fprintf(fp_hpp, " return *this;\n"); | |
763 fprintf(fp_hpp, " }\n\n"); | |
764 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask intersect(const Pipeline_Use_Cycle_Mask &in2) {\n"); | |
765 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask out;\n"); | |
766 for (l = 1; l <= masklen; l++) | |
767 fprintf(fp_hpp, " out._mask%d = _mask%d & in2._mask%d;\n", l, l, l); | |
768 fprintf(fp_hpp, " return out;\n"); | |
769 fprintf(fp_hpp, " }\n\n"); | |
770 fprintf(fp_hpp, " bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n"); | |
771 fprintf(fp_hpp, " return ("); | |
772 for (l = 1; l <= masklen; l++) | |
773 fprintf(fp_hpp, "((_mask%d & in2._mask%d) != 0)%s", l, l, l < masklen ? " || " : ""); | |
774 fprintf(fp_hpp, ") ? true : false;\n"); | |
775 fprintf(fp_hpp, " }\n\n"); | |
776 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n"); | |
777 fprintf(fp_hpp, " if (n >= 32)\n"); | |
778 fprintf(fp_hpp, " do {\n "); | |
779 for (l = masklen; l > 1; l--) | |
780 fprintf(fp_hpp, " _mask%d = _mask%d;", l, l-1); | |
781 fprintf(fp_hpp, " _mask%d = 0;\n", 1); | |
782 fprintf(fp_hpp, " } while ((n -= 32) >= 32);\n\n"); | |
783 fprintf(fp_hpp, " if (n > 0) {\n"); | |
784 fprintf(fp_hpp, " uint m = 32 - n;\n"); | |
785 fprintf(fp_hpp, " uint mask = (1 << n) - 1;\n"); | |
786 fprintf(fp_hpp, " uint temp%d = mask & (_mask%d >> m); _mask%d <<= n;\n", 2, 1, 1); | |
787 for (l = 2; l < masklen; l++) { | |
788 fprintf(fp_hpp, " uint temp%d = mask & (_mask%d >> m); _mask%d <<= n; _mask%d |= temp%d;\n", l+1, l, l, l, l); | |
789 } | |
790 fprintf(fp_hpp, " _mask%d <<= n; _mask%d |= temp%d;\n", masklen, masklen, masklen); | |
791 fprintf(fp_hpp, " }\n"); | |
792 | |
793 fprintf(fp_hpp, " return *this;\n"); | |
794 fprintf(fp_hpp, " }\n\n"); | |
795 fprintf(fp_hpp, " void Or(const Pipeline_Use_Cycle_Mask &);\n\n"); | |
796 fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n"); | |
797 fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n"); | |
798 } | |
799 | |
800 fprintf(fp_hpp, " friend class Pipeline_Use;\n\n"); | |
801 fprintf(fp_hpp, " friend class Pipeline_Use_Element;\n\n"); | |
802 fprintf(fp_hpp, "};\n\n"); | |
803 | |
804 uint rescount = 0; | |
805 const char *resource; | |
806 | |
807 for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) { | |
808 int mask = _pipeline->_resdict[resource]->is_resource()->mask(); | |
809 if ((mask & (mask-1)) == 0) | |
810 rescount++; | |
811 } | |
812 | |
813 fprintf(fp_hpp, "// Pipeline_Use_Element Class\n"); | |
814 fprintf(fp_hpp, "class Pipeline_Use_Element {\n"); | |
815 fprintf(fp_hpp, "protected:\n"); | |
816 fprintf(fp_hpp, " // Mask of used functional units\n"); | |
817 fprintf(fp_hpp, " uint _used;\n\n"); | |
818 fprintf(fp_hpp, " // Lower and upper bound of functional unit number range\n"); | |
819 fprintf(fp_hpp, " uint _lb, _ub;\n\n"); | |
820 fprintf(fp_hpp, " // Indicates multiple functionals units available\n"); | |
821 fprintf(fp_hpp, " bool _multiple;\n\n"); | |
822 fprintf(fp_hpp, " // Mask of specific used cycles\n"); | |
823 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask _mask;\n\n"); | |
824 fprintf(fp_hpp, "public:\n"); | |
825 fprintf(fp_hpp, " Pipeline_Use_Element() {}\n\n"); | |
826 fprintf(fp_hpp, " Pipeline_Use_Element(uint used, uint lb, uint ub, bool multiple, Pipeline_Use_Cycle_Mask mask)\n"); | |
827 fprintf(fp_hpp, " : _used(used), _lb(lb), _ub(ub), _multiple(multiple), _mask(mask) {}\n\n"); | |
828 fprintf(fp_hpp, " uint used() const { return _used; }\n\n"); | |
829 fprintf(fp_hpp, " uint lowerBound() const { return _lb; }\n\n"); | |
830 fprintf(fp_hpp, " uint upperBound() const { return _ub; }\n\n"); | |
831 fprintf(fp_hpp, " bool multiple() const { return _multiple; }\n\n"); | |
832 fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask mask() const { return _mask; }\n\n"); | |
833 fprintf(fp_hpp, " bool overlaps(const Pipeline_Use_Element &in2) const {\n"); | |
834 fprintf(fp_hpp, " return ((_used & in2._used) != 0 && _mask.overlaps(in2._mask));\n"); | |
835 fprintf(fp_hpp, " }\n\n"); | |
836 fprintf(fp_hpp, " void step(uint cycles) {\n"); | |
837 fprintf(fp_hpp, " _used = 0;\n"); | |
838 fprintf(fp_hpp, " _mask <<= cycles;\n"); | |
839 fprintf(fp_hpp, " }\n\n"); | |
840 fprintf(fp_hpp, " friend class Pipeline_Use;\n"); | |
841 fprintf(fp_hpp, "};\n\n"); | |
842 | |
843 fprintf(fp_hpp, "// Pipeline_Use Class\n"); | |
844 fprintf(fp_hpp, "class Pipeline_Use {\n"); | |
845 fprintf(fp_hpp, "protected:\n"); | |
846 fprintf(fp_hpp, " // These resources can be used\n"); | |
847 fprintf(fp_hpp, " uint _resources_used;\n\n"); | |
848 fprintf(fp_hpp, " // These resources are used; excludes multiple choice functional units\n"); | |
849 fprintf(fp_hpp, " uint _resources_used_exclusively;\n\n"); | |
850 fprintf(fp_hpp, " // Number of elements\n"); | |
851 fprintf(fp_hpp, " uint _count;\n\n"); | |
852 fprintf(fp_hpp, " // This is the array of Pipeline_Use_Elements\n"); | |
853 fprintf(fp_hpp, " Pipeline_Use_Element * _elements;\n\n"); | |
854 fprintf(fp_hpp, "public:\n"); | |
855 fprintf(fp_hpp, " Pipeline_Use(uint resources_used, uint resources_used_exclusively, uint count, Pipeline_Use_Element *elements)\n"); | |
856 fprintf(fp_hpp, " : _resources_used(resources_used)\n"); | |
857 fprintf(fp_hpp, " , _resources_used_exclusively(resources_used_exclusively)\n"); | |
858 fprintf(fp_hpp, " , _count(count)\n"); | |
859 fprintf(fp_hpp, " , _elements(elements)\n"); | |
860 fprintf(fp_hpp, " {}\n\n"); | |
861 fprintf(fp_hpp, " uint resourcesUsed() const { return _resources_used; }\n\n"); | |
862 fprintf(fp_hpp, " uint resourcesUsedExclusively() const { return _resources_used_exclusively; }\n\n"); | |
863 fprintf(fp_hpp, " uint count() const { return _count; }\n\n"); | |
864 fprintf(fp_hpp, " Pipeline_Use_Element * element(uint i) const { return &_elements[i]; }\n\n"); | |
865 fprintf(fp_hpp, " uint full_latency(uint delay, const Pipeline_Use &pred) const;\n\n"); | |
866 fprintf(fp_hpp, " void add_usage(const Pipeline_Use &pred);\n\n"); | |
867 fprintf(fp_hpp, " void reset() {\n"); | |
868 fprintf(fp_hpp, " _resources_used = _resources_used_exclusively = 0;\n"); | |
869 fprintf(fp_hpp, " };\n\n"); | |
870 fprintf(fp_hpp, " void step(uint cycles) {\n"); | |
871 fprintf(fp_hpp, " reset();\n"); | |
872 fprintf(fp_hpp, " for (uint i = 0; i < %d; i++)\n", | |
873 rescount); | |
874 fprintf(fp_hpp, " (&_elements[i])->step(cycles);\n"); | |
875 fprintf(fp_hpp, " };\n\n"); | |
876 fprintf(fp_hpp, " static const Pipeline_Use elaborated_use;\n"); | |
877 fprintf(fp_hpp, " static const Pipeline_Use_Element elaborated_elements[%d];\n\n", | |
878 rescount); | |
879 fprintf(fp_hpp, " friend class Pipeline;\n"); | |
880 fprintf(fp_hpp, "};\n\n"); | |
881 | |
882 fprintf(fp_hpp, "// Pipeline Class\n"); | |
883 fprintf(fp_hpp, "class Pipeline {\n"); | |
884 fprintf(fp_hpp, "public:\n"); | |
885 | |
886 fprintf(fp_hpp, " static bool enabled() { return %s; }\n\n", | |
887 _pipeline ? "true" : "false" ); | |
888 | |
889 assert( _pipeline->_maxInstrsPerBundle && | |
890 ( _pipeline->_instrUnitSize || _pipeline->_bundleUnitSize) && | |
891 _pipeline->_instrFetchUnitSize && | |
892 _pipeline->_instrFetchUnits, | |
893 "unspecified pipeline architecture units"); | |
894 | |
895 uint unitSize = _pipeline->_instrUnitSize ? _pipeline->_instrUnitSize : _pipeline->_bundleUnitSize; | |
896 | |
897 fprintf(fp_hpp, " enum {\n"); | |
898 fprintf(fp_hpp, " _variable_size_instructions = %d,\n", | |
899 _pipeline->_variableSizeInstrs ? 1 : 0); | |
900 fprintf(fp_hpp, " _fixed_size_instructions = %d,\n", | |
901 _pipeline->_variableSizeInstrs ? 0 : 1); | |
902 fprintf(fp_hpp, " _branch_has_delay_slot = %d,\n", | |
903 _pipeline->_branchHasDelaySlot ? 1 : 0); | |
904 fprintf(fp_hpp, " _max_instrs_per_bundle = %d,\n", | |
905 _pipeline->_maxInstrsPerBundle); | |
906 fprintf(fp_hpp, " _max_bundles_per_cycle = %d,\n", | |
907 _pipeline->_maxBundlesPerCycle); | |
908 fprintf(fp_hpp, " _max_instrs_per_cycle = %d\n", | |
909 _pipeline->_maxBundlesPerCycle * _pipeline->_maxInstrsPerBundle); | |
910 fprintf(fp_hpp, " };\n\n"); | |
911 | |
912 fprintf(fp_hpp, " static bool instr_has_unit_size() { return %s; }\n\n", | |
913 _pipeline->_instrUnitSize != 0 ? "true" : "false" ); | |
914 if( _pipeline->_bundleUnitSize != 0 ) | |
915 if( _pipeline->_instrUnitSize != 0 ) | |
916 fprintf(fp_hpp, "// Individual Instructions may be bundled together by the hardware\n\n"); | |
917 else | |
918 fprintf(fp_hpp, "// Instructions exist only in bundles\n\n"); | |
919 else | |
920 fprintf(fp_hpp, "// Bundling is not supported\n\n"); | |
921 if( _pipeline->_instrUnitSize != 0 ) | |
922 fprintf(fp_hpp, " // Size of an instruction\n"); | |
923 else | |
924 fprintf(fp_hpp, " // Size of an individual instruction does not exist - unsupported\n"); | |
925 fprintf(fp_hpp, " static uint instr_unit_size() {"); | |
926 if( _pipeline->_instrUnitSize == 0 ) | |
927 fprintf(fp_hpp, " assert( false, \"Instructions are only in bundles\" );"); | |
928 fprintf(fp_hpp, " return %d; };\n\n", _pipeline->_instrUnitSize); | |
929 | |
930 if( _pipeline->_bundleUnitSize != 0 ) | |
931 fprintf(fp_hpp, " // Size of a bundle\n"); | |
932 else | |
933 fprintf(fp_hpp, " // Bundles do not exist - unsupported\n"); | |
934 fprintf(fp_hpp, " static uint bundle_unit_size() {"); | |
935 if( _pipeline->_bundleUnitSize == 0 ) | |
936 fprintf(fp_hpp, " assert( false, \"Bundles are not supported\" );"); | |
937 fprintf(fp_hpp, " return %d; };\n\n", _pipeline->_bundleUnitSize); | |
938 | |
939 fprintf(fp_hpp, " static bool requires_bundling() { return %s; }\n\n", | |
940 _pipeline->_bundleUnitSize != 0 && _pipeline->_instrUnitSize == 0 ? "true" : "false" ); | |
941 | |
942 fprintf(fp_hpp, "private:\n"); | |
943 fprintf(fp_hpp, " Pipeline(); // Not a legal constructor\n"); | |
944 fprintf(fp_hpp, "\n"); | |
945 fprintf(fp_hpp, " const unsigned char _read_stage_count;\n"); | |
946 fprintf(fp_hpp, " const unsigned char _write_stage;\n"); | |
947 fprintf(fp_hpp, " const unsigned char _fixed_latency;\n"); | |
948 fprintf(fp_hpp, " const unsigned char _instruction_count;\n"); | |
949 fprintf(fp_hpp, " const bool _has_fixed_latency;\n"); | |
950 fprintf(fp_hpp, " const bool _has_branch_delay;\n"); | |
951 fprintf(fp_hpp, " const bool _has_multiple_bundles;\n"); | |
952 fprintf(fp_hpp, " const bool _force_serialization;\n"); | |
953 fprintf(fp_hpp, " const bool _may_have_no_code;\n"); | |
954 fprintf(fp_hpp, " const enum machPipelineStages * const _read_stages;\n"); | |
955 fprintf(fp_hpp, " const enum machPipelineStages * const _resource_stage;\n"); | |
956 fprintf(fp_hpp, " const uint * const _resource_cycles;\n"); | |
957 fprintf(fp_hpp, " const Pipeline_Use _resource_use;\n"); | |
958 fprintf(fp_hpp, "\n"); | |
959 fprintf(fp_hpp, "public:\n"); | |
960 fprintf(fp_hpp, " Pipeline(uint write_stage,\n"); | |
961 fprintf(fp_hpp, " uint count,\n"); | |
962 fprintf(fp_hpp, " bool has_fixed_latency,\n"); | |
963 fprintf(fp_hpp, " uint fixed_latency,\n"); | |
964 fprintf(fp_hpp, " uint instruction_count,\n"); | |
965 fprintf(fp_hpp, " bool has_branch_delay,\n"); | |
966 fprintf(fp_hpp, " bool has_multiple_bundles,\n"); | |
967 fprintf(fp_hpp, " bool force_serialization,\n"); | |
968 fprintf(fp_hpp, " bool may_have_no_code,\n"); | |
969 fprintf(fp_hpp, " enum machPipelineStages * const dst,\n"); | |
970 fprintf(fp_hpp, " enum machPipelineStages * const stage,\n"); | |
971 fprintf(fp_hpp, " uint * const cycles,\n"); | |
972 fprintf(fp_hpp, " Pipeline_Use resource_use)\n"); | |
973 fprintf(fp_hpp, " : _write_stage(write_stage)\n"); | |
974 fprintf(fp_hpp, " , _read_stage_count(count)\n"); | |
975 fprintf(fp_hpp, " , _has_fixed_latency(has_fixed_latency)\n"); | |
976 fprintf(fp_hpp, " , _fixed_latency(fixed_latency)\n"); | |
977 fprintf(fp_hpp, " , _read_stages(dst)\n"); | |
978 fprintf(fp_hpp, " , _resource_stage(stage)\n"); | |
979 fprintf(fp_hpp, " , _resource_cycles(cycles)\n"); | |
980 fprintf(fp_hpp, " , _resource_use(resource_use)\n"); | |
981 fprintf(fp_hpp, " , _instruction_count(instruction_count)\n"); | |
982 fprintf(fp_hpp, " , _has_branch_delay(has_branch_delay)\n"); | |
983 fprintf(fp_hpp, " , _has_multiple_bundles(has_multiple_bundles)\n"); | |
984 fprintf(fp_hpp, " , _force_serialization(force_serialization)\n"); | |
985 fprintf(fp_hpp, " , _may_have_no_code(may_have_no_code)\n"); | |
986 fprintf(fp_hpp, " {};\n"); | |
987 fprintf(fp_hpp, "\n"); | |
988 fprintf(fp_hpp, " uint writeStage() const {\n"); | |
989 fprintf(fp_hpp, " return (_write_stage);\n"); | |
990 fprintf(fp_hpp, " }\n"); | |
991 fprintf(fp_hpp, "\n"); | |
992 fprintf(fp_hpp, " enum machPipelineStages readStage(int ndx) const {\n"); | |
993 fprintf(fp_hpp, " return (ndx < _read_stage_count ? _read_stages[ndx] : stage_undefined);"); | |
994 fprintf(fp_hpp, " }\n\n"); | |
995 fprintf(fp_hpp, " uint resourcesUsed() const {\n"); | |
996 fprintf(fp_hpp, " return _resource_use.resourcesUsed();\n }\n\n"); | |
997 fprintf(fp_hpp, " uint resourcesUsedExclusively() const {\n"); | |
998 fprintf(fp_hpp, " return _resource_use.resourcesUsedExclusively();\n }\n\n"); | |
999 fprintf(fp_hpp, " bool hasFixedLatency() const {\n"); | |
1000 fprintf(fp_hpp, " return (_has_fixed_latency);\n }\n\n"); | |
1001 fprintf(fp_hpp, " uint fixedLatency() const {\n"); | |
1002 fprintf(fp_hpp, " return (_fixed_latency);\n }\n\n"); | |
1003 fprintf(fp_hpp, " uint functional_unit_latency(uint start, const Pipeline *pred) const;\n\n"); | |
1004 fprintf(fp_hpp, " uint operand_latency(uint opnd, const Pipeline *pred) const;\n\n"); | |
1005 fprintf(fp_hpp, " const Pipeline_Use& resourceUse() const {\n"); | |
1006 fprintf(fp_hpp, " return (_resource_use); }\n\n"); | |
1007 fprintf(fp_hpp, " const Pipeline_Use_Element * resourceUseElement(uint i) const {\n"); | |
1008 fprintf(fp_hpp, " return (&_resource_use._elements[i]); }\n\n"); | |
1009 fprintf(fp_hpp, " uint resourceUseCount() const {\n"); | |
1010 fprintf(fp_hpp, " return (_resource_use._count); }\n\n"); | |
1011 fprintf(fp_hpp, " uint instructionCount() const {\n"); | |
1012 fprintf(fp_hpp, " return (_instruction_count); }\n\n"); | |
1013 fprintf(fp_hpp, " bool hasBranchDelay() const {\n"); | |
1014 fprintf(fp_hpp, " return (_has_branch_delay); }\n\n"); | |
1015 fprintf(fp_hpp, " bool hasMultipleBundles() const {\n"); | |
1016 fprintf(fp_hpp, " return (_has_multiple_bundles); }\n\n"); | |
1017 fprintf(fp_hpp, " bool forceSerialization() const {\n"); | |
1018 fprintf(fp_hpp, " return (_force_serialization); }\n\n"); | |
1019 fprintf(fp_hpp, " bool mayHaveNoCode() const {\n"); | |
1020 fprintf(fp_hpp, " return (_may_have_no_code); }\n\n"); | |
1021 fprintf(fp_hpp, "//const Pipeline_Use_Cycle_Mask& resourceUseMask(int resource) const {\n"); | |
1022 fprintf(fp_hpp, "// return (_resource_use_masks[resource]); }\n\n"); | |
1023 fprintf(fp_hpp, "\n#ifndef PRODUCT\n"); | |
1024 fprintf(fp_hpp, " static const char * stageName(uint i);\n"); | |
1025 fprintf(fp_hpp, "#endif\n"); | |
1026 fprintf(fp_hpp, "};\n\n"); | |
1027 | |
1028 fprintf(fp_hpp, "// Bundle class\n"); | |
1029 fprintf(fp_hpp, "class Bundle {\n"); | |
1030 | |
1031 uint mshift = 0; | |
1032 for (uint msize = _pipeline->_maxInstrsPerBundle * _pipeline->_maxBundlesPerCycle; msize != 0; msize >>= 1) | |
1033 mshift++; | |
1034 | |
1035 uint rshift = rescount; | |
1036 | |
1037 fprintf(fp_hpp, "protected:\n"); | |
1038 fprintf(fp_hpp, " enum {\n"); | |
1039 fprintf(fp_hpp, " _unused_delay = 0x%x,\n", 0); | |
1040 fprintf(fp_hpp, " _use_nop_delay = 0x%x,\n", 1); | |
1041 fprintf(fp_hpp, " _use_unconditional_delay = 0x%x,\n", 2); | |
1042 fprintf(fp_hpp, " _use_conditional_delay = 0x%x,\n", 3); | |
1043 fprintf(fp_hpp, " _used_in_conditional_delay = 0x%x,\n", 4); | |
1044 fprintf(fp_hpp, " _used_in_unconditional_delay = 0x%x,\n", 5); | |
1045 fprintf(fp_hpp, " _used_in_all_conditional_delays = 0x%x,\n", 6); | |
1046 fprintf(fp_hpp, "\n"); | |
1047 fprintf(fp_hpp, " _use_delay = 0x%x,\n", 3); | |
1048 fprintf(fp_hpp, " _used_in_delay = 0x%x\n", 4); | |
1049 fprintf(fp_hpp, " };\n\n"); | |
1050 fprintf(fp_hpp, " uint _flags : 3,\n"); | |
1051 fprintf(fp_hpp, " _starts_bundle : 1,\n"); | |
1052 fprintf(fp_hpp, " _instr_count : %d,\n", mshift); | |
1053 fprintf(fp_hpp, " _resources_used : %d;\n", rshift); | |
1054 fprintf(fp_hpp, "public:\n"); | |
1055 fprintf(fp_hpp, " Bundle() : _flags(_unused_delay), _starts_bundle(0), _instr_count(0), _resources_used(0) {}\n\n"); | |
1056 fprintf(fp_hpp, " void set_instr_count(uint i) { _instr_count = i; }\n"); | |
1057 fprintf(fp_hpp, " void set_resources_used(uint i) { _resources_used = i; }\n"); | |
1058 fprintf(fp_hpp, " void clear_usage() { _flags = _unused_delay; }\n"); | |
1059 fprintf(fp_hpp, " void set_starts_bundle() { _starts_bundle = true; }\n"); | |
1060 | |
1061 fprintf(fp_hpp, " uint flags() const { return (_flags); }\n"); | |
1062 fprintf(fp_hpp, " uint instr_count() const { return (_instr_count); }\n"); | |
1063 fprintf(fp_hpp, " uint resources_used() const { return (_resources_used); }\n"); | |
1064 fprintf(fp_hpp, " bool starts_bundle() const { return (_starts_bundle != 0); }\n"); | |
1065 | |
1066 fprintf(fp_hpp, " void set_use_nop_delay() { _flags = _use_nop_delay; }\n"); | |
1067 fprintf(fp_hpp, " void set_use_unconditional_delay() { _flags = _use_unconditional_delay; }\n"); | |
1068 fprintf(fp_hpp, " void set_use_conditional_delay() { _flags = _use_conditional_delay; }\n"); | |
1069 fprintf(fp_hpp, " void set_used_in_unconditional_delay() { _flags = _used_in_unconditional_delay; }\n"); | |
1070 fprintf(fp_hpp, " void set_used_in_conditional_delay() { _flags = _used_in_conditional_delay; }\n"); | |
1071 fprintf(fp_hpp, " void set_used_in_all_conditional_delays() { _flags = _used_in_all_conditional_delays; }\n"); | |
1072 | |
1073 fprintf(fp_hpp, " bool use_nop_delay() { return (_flags == _use_nop_delay); }\n"); | |
1074 fprintf(fp_hpp, " bool use_unconditional_delay() { return (_flags == _use_unconditional_delay); }\n"); | |
1075 fprintf(fp_hpp, " bool use_conditional_delay() { return (_flags == _use_conditional_delay); }\n"); | |
1076 fprintf(fp_hpp, " bool used_in_unconditional_delay() { return (_flags == _used_in_unconditional_delay); }\n"); | |
1077 fprintf(fp_hpp, " bool used_in_conditional_delay() { return (_flags == _used_in_conditional_delay); }\n"); | |
1078 fprintf(fp_hpp, " bool used_in_all_conditional_delays() { return (_flags == _used_in_all_conditional_delays); }\n"); | |
1079 fprintf(fp_hpp, " bool use_delay() { return ((_flags & _use_delay) != 0); }\n"); | |
1080 fprintf(fp_hpp, " bool used_in_delay() { return ((_flags & _used_in_delay) != 0); }\n\n"); | |
1081 | |
1082 fprintf(fp_hpp, " enum {\n"); | |
1083 fprintf(fp_hpp, " _nop_count = %d\n", | |
1084 _pipeline->_nopcnt); | |
1085 fprintf(fp_hpp, " };\n\n"); | |
1086 fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n", | |
1087 _pipeline->_nopcnt); | |
1088 fprintf(fp_hpp, "#ifndef PRODUCT\n"); | |
1089 fprintf(fp_hpp, " void dump() const;\n"); | |
1090 fprintf(fp_hpp, "#endif\n"); | |
1091 fprintf(fp_hpp, "};\n\n"); | |
1092 | |
1093 // const char *classname; | |
1094 // for (_pipeline->_classlist.reset(); (classname = _pipeline->_classlist.iter()) != NULL; ) { | |
1095 // PipeClassForm *pipeclass = _pipeline->_classdict[classname]->is_pipeclass(); | |
1096 // fprintf(fp_hpp, "// Pipeline Class Instance for \"%s\"\n", classname); | |
1097 // } | |
1098 } | |
1099 | |
1100 //------------------------------declareClasses--------------------------------- | |
1101 // Construct the class hierarchy of MachNode classes from the instruction & | |
1102 // operand lists | |
1103 void ArchDesc::declareClasses(FILE *fp) { | |
1104 | |
1105 // Declare an array containing the machine register names, strings. | |
1106 declareRegNames(fp, _register); | |
1107 | |
1108 // Declare an array containing the machine register encoding values | |
1109 declareRegEncodes(fp, _register); | |
1110 | |
1111 // Generate declarations for the total number of operands | |
1112 fprintf(fp,"\n"); | |
1113 fprintf(fp,"// Total number of operands defined in architecture definition\n"); | |
1114 int num_operands = 0; | |
1115 OperandForm *op; | |
1116 for (_operands.reset(); (op = (OperandForm*)_operands.iter()) != NULL; ) { | |
1117 // Ensure this is a machine-world instruction | |
1118 if (op->ideal_only()) continue; | |
1119 | |
1120 ++num_operands; | |
1121 } | |
1122 int first_operand_class = num_operands; | |
1123 OpClassForm *opc; | |
1124 for (_opclass.reset(); (opc = (OpClassForm*)_opclass.iter()) != NULL; ) { | |
1125 // Ensure this is a machine-world instruction | |
1126 if (opc->ideal_only()) continue; | |
1127 | |
1128 ++num_operands; | |
1129 } | |
1130 fprintf(fp,"#define FIRST_OPERAND_CLASS %d\n", first_operand_class); | |
1131 fprintf(fp,"#define NUM_OPERANDS %d\n", num_operands); | |
1132 fprintf(fp,"\n"); | |
1133 // Generate declarations for the total number of instructions | |
1134 fprintf(fp,"// Total number of instructions defined in architecture definition\n"); | |
1135 fprintf(fp,"#define NUM_INSTRUCTIONS %d\n",instructFormCount()); | |
1136 | |
1137 | |
1138 // Generate Machine Classes for each operand defined in AD file | |
1139 fprintf(fp,"\n"); | |
1140 fprintf(fp,"//----------------------------Declare classes derived from MachOper----------\n"); | |
1141 // Iterate through all operands | |
1142 _operands.reset(); | |
1143 OperandForm *oper; | |
1144 for( ; (oper = (OperandForm*)_operands.iter()) != NULL;) { | |
1145 // Ensure this is a machine-world instruction | |
1146 if (oper->ideal_only() ) continue; | |
1147 // The declaration of labelOper is in machine-independent file: machnode | |
1148 if ( strcmp(oper->_ident,"label") == 0 ) continue; | |
1149 // The declaration of methodOper is in machine-independent file: machnode | |
1150 if ( strcmp(oper->_ident,"method") == 0 ) continue; | |
1151 | |
1152 // Build class definition for this operand | |
1153 fprintf(fp,"\n"); | |
1154 fprintf(fp,"class %sOper : public MachOper { \n",oper->_ident); | |
1155 fprintf(fp,"private:\n"); | |
1156 // Operand definitions that depend upon number of input edges | |
1157 { | |
1158 uint num_edges = oper->num_edges(_globalNames); | |
1159 if( num_edges != 1 ) { // Use MachOper::num_edges() {return 1;} | |
1160 fprintf(fp," virtual uint num_edges() const { return %d; }\n", | |
1161 num_edges ); | |
1162 } | |
1163 if( num_edges > 0 ) { | |
1164 in_RegMask(fp); | |
1165 } | |
1166 } | |
1167 | |
1168 // Support storing constants inside the MachOper | |
1169 declareConstStorage(fp,_globalNames,oper); | |
1170 | |
1171 // Support storage of the condition codes | |
1172 if( oper->is_ideal_bool() ) { | |
1173 fprintf(fp," virtual int ccode() const { \n"); | |
1174 fprintf(fp," switch (_c0) {\n"); | |
1175 fprintf(fp," case BoolTest::eq : return equal();\n"); | |
1176 fprintf(fp," case BoolTest::gt : return greater();\n"); | |
1177 fprintf(fp," case BoolTest::lt : return less();\n"); | |
1178 fprintf(fp," case BoolTest::ne : return not_equal();\n"); | |
1179 fprintf(fp," case BoolTest::le : return less_equal();\n"); | |
1180 fprintf(fp," case BoolTest::ge : return greater_equal();\n"); | |
1181 fprintf(fp," default : ShouldNotReachHere(); return 0;\n"); | |
1182 fprintf(fp," }\n"); | |
1183 fprintf(fp," };\n"); | |
1184 } | |
1185 | |
1186 // Support storage of the condition codes | |
1187 if( oper->is_ideal_bool() ) { | |
1188 fprintf(fp," virtual void negate() { \n"); | |
1189 fprintf(fp," _c0 = (BoolTest::mask)((int)_c0^0x4); \n"); | |
1190 fprintf(fp," };\n"); | |
1191 } | |
1192 | |
1193 // Declare constructor. | |
1194 // Parameters start with condition code, then all other constants | |
1195 // | |
1196 // (1) MachXOper(int32 ccode, int32 c0, int32 c1, ..., int32 cn) | |
1197 // (2) : _ccode(ccode), _c0(c0), _c1(c1), ..., _cn(cn) { } | |
1198 // | |
1199 Form::DataType constant_type = oper->simple_type(_globalNames); | |
1200 defineConstructor(fp, oper->_ident, oper->num_consts(_globalNames), | |
1201 oper->_components, oper->is_ideal_bool(), | |
1202 constant_type, _globalNames); | |
1203 | |
1204 // Clone function | |
1205 fprintf(fp," virtual MachOper *clone(Compile* C) const;\n"); | |
1206 | |
1207 // Support setting a spill offset into a constant operand. | |
1208 // We only support setting an 'int' offset, while in the | |
1209 // LP64 build spill offsets are added with an AddP which | |
1210 // requires a long constant. Thus we don't support spilling | |
1211 // in frames larger than 4Gig. | |
1212 if( oper->has_conI(_globalNames) || | |
1213 oper->has_conL(_globalNames) ) | |
1214 fprintf(fp, " virtual void set_con( jint c0 ) { _c0 = c0; }\n"); | |
1215 | |
1216 // virtual functions for encoding and format | |
1217 // fprintf(fp," virtual void encode() const {\n %s }\n", | |
1218 // (oper->_encrule)?(oper->_encrule->_encrule):""); | |
1219 // Check the interface type, and generate the correct query functions | |
1220 // encoding queries based upon MEMORY_INTER, REG_INTER, CONST_INTER. | |
1221 | |
1222 fprintf(fp," virtual uint opcode() const { return %s; }\n", | |
1223 machOperEnum(oper->_ident)); | |
1224 | |
1225 // virtual function to look up ideal return type of machine instruction | |
1226 // | |
1227 // (1) virtual const Type *type() const { return .....; } | |
1228 // | |
1229 if ((oper->_matrule) && (oper->_matrule->_lChild == NULL) && | |
1230 (oper->_matrule->_rChild == NULL)) { | |
1231 unsigned int position = 0; | |
1232 const char *opret, *opname, *optype; | |
1233 oper->_matrule->base_operand(position,_globalNames,opret,opname,optype); | |
1234 fprintf(fp," virtual const Type *type() const {"); | |
1235 const char *type = getIdealType(optype); | |
1236 if( type != NULL ) { | |
1237 Form::DataType data_type = oper->is_base_constant(_globalNames); | |
1238 // Check if we are an ideal pointer type | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1239 if( data_type == Form::idealP || data_type == Form::idealN ) { |
0 | 1240 // Return the ideal type we already have: <TypePtr *> |
1241 fprintf(fp," return _c0;"); | |
1242 } else { | |
1243 // Return the appropriate bottom type | |
1244 fprintf(fp," return %s;", getIdealType(optype)); | |
1245 } | |
1246 } else { | |
1247 fprintf(fp," ShouldNotCallThis(); return Type::BOTTOM;"); | |
1248 } | |
1249 fprintf(fp," }\n"); | |
1250 } else { | |
1251 // Check for user-defined stack slots, based upon sRegX | |
1252 Form::DataType data_type = oper->is_user_name_for_sReg(); | |
1253 if( data_type != Form::none ){ | |
1254 const char *type = NULL; | |
1255 switch( data_type ) { | |
1256 case Form::idealI: type = "TypeInt::INT"; break; | |
1257 case Form::idealP: type = "TypePtr::BOTTOM";break; | |
1258 case Form::idealF: type = "Type::FLOAT"; break; | |
1259 case Form::idealD: type = "Type::DOUBLE"; break; | |
1260 case Form::idealL: type = "TypeLong::LONG"; break; | |
1261 case Form::none: // fall through | |
1262 default: | |
1263 assert( false, "No support for this type of stackSlot"); | |
1264 } | |
1265 fprintf(fp," virtual const Type *type() const { return %s; } // stackSlotX\n", type); | |
1266 } | |
1267 } | |
1268 | |
1269 | |
1270 // | |
1271 // virtual functions for defining the encoding interface. | |
1272 // | |
1273 // Access the linearized ideal register mask, | |
1274 // map to physical register encoding | |
1275 if ( oper->_matrule && oper->_matrule->is_base_register(_globalNames) ) { | |
1276 // Just use the default virtual 'reg' call | |
1277 } else if ( oper->ideal_to_sReg_type(oper->_ident) != Form::none ) { | |
1278 // Special handling for operand 'sReg', a Stack Slot Register. | |
1279 // Map linearized ideal register mask to stack slot number | |
1280 fprintf(fp," virtual int reg(PhaseRegAlloc *ra_, const Node *node) const {\n"); | |
1281 fprintf(fp," return (int)OptoReg::reg2stack(ra_->get_reg_first(node));/* sReg */\n"); | |
1282 fprintf(fp," }\n"); | |
1283 fprintf(fp," virtual int reg(PhaseRegAlloc *ra_, const Node *node, int idx) const {\n"); | |
1284 fprintf(fp," return (int)OptoReg::reg2stack(ra_->get_reg_first(node->in(idx)));/* sReg */\n"); | |
1285 fprintf(fp," }\n"); | |
1286 } | |
1287 | |
1288 // Output the operand specific access functions used by an enc_class | |
1289 // These are only defined when we want to override the default virtual func | |
1290 if (oper->_interface != NULL) { | |
1291 fprintf(fp,"\n"); | |
1292 // Check if it is a Memory Interface | |
1293 if ( oper->_interface->is_MemInterface() != NULL ) { | |
1294 MemInterface *mem_interface = oper->_interface->is_MemInterface(); | |
1295 const char *base = mem_interface->_base; | |
1296 if( base != NULL ) { | |
1297 define_oper_interface(fp, *oper, _globalNames, "base", base); | |
1298 } | |
1299 char *index = mem_interface->_index; | |
1300 if( index != NULL ) { | |
1301 define_oper_interface(fp, *oper, _globalNames, "index", index); | |
1302 } | |
1303 const char *scale = mem_interface->_scale; | |
1304 if( scale != NULL ) { | |
1305 define_oper_interface(fp, *oper, _globalNames, "scale", scale); | |
1306 } | |
1307 const char *disp = mem_interface->_disp; | |
1308 if( disp != NULL ) { | |
1309 define_oper_interface(fp, *oper, _globalNames, "disp", disp); | |
1310 oper->disp_is_oop(fp, _globalNames); | |
1311 } | |
1312 if( oper->stack_slots_only(_globalNames) ) { | |
1313 // should not call this: | |
1314 fprintf(fp," virtual int constant_disp() const { return Type::OffsetBot; }"); | |
1315 } else if ( disp != NULL ) { | |
1316 define_oper_interface(fp, *oper, _globalNames, "constant_disp", disp); | |
1317 } | |
1318 } // end Memory Interface | |
1319 // Check if it is a Conditional Interface | |
1320 else if (oper->_interface->is_CondInterface() != NULL) { | |
1321 CondInterface *cInterface = oper->_interface->is_CondInterface(); | |
1322 const char *equal = cInterface->_equal; | |
1323 if( equal != NULL ) { | |
1324 define_oper_interface(fp, *oper, _globalNames, "equal", equal); | |
1325 } | |
1326 const char *not_equal = cInterface->_not_equal; | |
1327 if( not_equal != NULL ) { | |
1328 define_oper_interface(fp, *oper, _globalNames, "not_equal", not_equal); | |
1329 } | |
1330 const char *less = cInterface->_less; | |
1331 if( less != NULL ) { | |
1332 define_oper_interface(fp, *oper, _globalNames, "less", less); | |
1333 } | |
1334 const char *greater_equal = cInterface->_greater_equal; | |
1335 if( greater_equal != NULL ) { | |
1336 define_oper_interface(fp, *oper, _globalNames, "greater_equal", greater_equal); | |
1337 } | |
1338 const char *less_equal = cInterface->_less_equal; | |
1339 if( less_equal != NULL ) { | |
1340 define_oper_interface(fp, *oper, _globalNames, "less_equal", less_equal); | |
1341 } | |
1342 const char *greater = cInterface->_greater; | |
1343 if( greater != NULL ) { | |
1344 define_oper_interface(fp, *oper, _globalNames, "greater", greater); | |
1345 } | |
1346 } // end Conditional Interface | |
1347 // Check if it is a Constant Interface | |
1348 else if (oper->_interface->is_ConstInterface() != NULL ) { | |
1349 assert( oper->num_consts(_globalNames) == 1, | |
1350 "Must have one constant when using CONST_INTER encoding"); | |
1351 if (!strcmp(oper->ideal_type(_globalNames), "ConI")) { | |
1352 // Access the locally stored constant | |
1353 fprintf(fp," virtual intptr_t constant() const {"); | |
1354 fprintf(fp, " return (intptr_t)_c0;"); | |
1355 fprintf(fp," }\n"); | |
1356 } | |
1357 else if (!strcmp(oper->ideal_type(_globalNames), "ConP")) { | |
1358 // Access the locally stored constant | |
1359 fprintf(fp," virtual intptr_t constant() const {"); | |
1360 fprintf(fp, " return _c0->get_con();"); | |
1361 fprintf(fp, " }\n"); | |
1362 // Generate query to determine if this pointer is an oop | |
1363 fprintf(fp," virtual bool constant_is_oop() const {"); | |
1364 fprintf(fp, " return _c0->isa_oop_ptr();"); | |
1365 fprintf(fp, " }\n"); | |
1366 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1367 else if (!strcmp(oper->ideal_type(_globalNames), "ConN")) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1368 // Access the locally stored constant |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1369 fprintf(fp," virtual intptr_t constant() const {"); |
827
bf3489cc0aa0
6856025: assert(_base >= OopPtr && _base <= KlassPtr,"Not a Java pointer")
never
parents:
605
diff
changeset
|
1370 fprintf(fp, " return _c0->get_ptrtype()->get_con();"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1371 fprintf(fp, " }\n"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1372 // Generate query to determine if this pointer is an oop |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1373 fprintf(fp," virtual bool constant_is_oop() const {"); |
827
bf3489cc0aa0
6856025: assert(_base >= OopPtr && _base <= KlassPtr,"Not a Java pointer")
never
parents:
605
diff
changeset
|
1374 fprintf(fp, " return _c0->get_ptrtype()->isa_oop_ptr();"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1375 fprintf(fp, " }\n"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1376 } |
0 | 1377 else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) { |
1378 fprintf(fp," virtual intptr_t constant() const {"); | |
1379 // We don't support addressing modes with > 4Gig offsets. | |
1380 // Truncate to int. | |
1381 fprintf(fp, " return (intptr_t)_c0;"); | |
1382 fprintf(fp, " }\n"); | |
1383 fprintf(fp," virtual jlong constantL() const {"); | |
1384 fprintf(fp, " return _c0;"); | |
1385 fprintf(fp, " }\n"); | |
1386 } | |
1387 else if (!strcmp(oper->ideal_type(_globalNames), "ConF")) { | |
1388 fprintf(fp," virtual intptr_t constant() const {"); | |
1389 fprintf(fp, " ShouldNotReachHere(); return 0; "); | |
1390 fprintf(fp, " }\n"); | |
1391 fprintf(fp," virtual jfloat constantF() const {"); | |
1392 fprintf(fp, " return (jfloat)_c0;"); | |
1393 fprintf(fp, " }\n"); | |
1394 } | |
1395 else if (!strcmp(oper->ideal_type(_globalNames), "ConD")) { | |
1396 fprintf(fp," virtual intptr_t constant() const {"); | |
1397 fprintf(fp, " ShouldNotReachHere(); return 0; "); | |
1398 fprintf(fp, " }\n"); | |
1399 fprintf(fp," virtual jdouble constantD() const {"); | |
1400 fprintf(fp, " return _c0;"); | |
1401 fprintf(fp, " }\n"); | |
1402 } | |
1403 } | |
1404 else if (oper->_interface->is_RegInterface() != NULL) { | |
1405 // make sure that a fixed format string isn't used for an | |
1406 // operand which might be assiged to multiple registers. | |
1407 // Otherwise the opto assembly output could be misleading. | |
1408 if (oper->_format->_strings.count() != 0 && !oper->is_bound_register()) { | |
1409 syntax_err(oper->_linenum, | |
1410 "Only bound registers can have fixed formats: %s\n", | |
1411 oper->_ident); | |
1412 } | |
1413 } | |
1414 else { | |
1415 assert( false, "ShouldNotReachHere();"); | |
1416 } | |
1417 } | |
1418 | |
1419 fprintf(fp,"\n"); | |
1420 // // Currently all XXXOper::hash() methods are identical (990820) | |
1421 // declare_hash(fp); | |
1422 // // Currently all XXXOper::Cmp() methods are identical (990820) | |
1423 // declare_cmp(fp); | |
1424 | |
1425 // Do not place dump_spec() and Name() into PRODUCT code | |
1426 // int_format and ext_format are not needed in PRODUCT code either | |
1427 fprintf(fp, "#ifndef PRODUCT\n"); | |
1428 | |
1429 // Declare int_format() and ext_format() | |
1430 gen_oper_format(fp, _globalNames, *oper); | |
1431 | |
1432 // Machine independent print functionality for debugging | |
1433 // IF we have constants, create a dump_spec function for the derived class | |
1434 // | |
1435 // (1) virtual void dump_spec() const { | |
1436 // (2) st->print("#%d", _c#); // Constant != ConP | |
1437 // OR _c#->dump_on(st); // Type ConP | |
1438 // ... | |
1439 // (3) } | |
1440 uint num_consts = oper->num_consts(_globalNames); | |
1441 if( num_consts > 0 ) { | |
1442 // line (1) | |
1443 fprintf(fp, " virtual void dump_spec(outputStream *st) const {\n"); | |
1444 // generate format string for st->print | |
1445 // Iterate over the component list & spit out the right thing | |
1446 uint i = 0; | |
1447 const char *type = oper->ideal_type(_globalNames); | |
1448 Component *comp; | |
1449 oper->_components.reset(); | |
1450 if ((comp = oper->_components.iter()) == NULL) { | |
1451 assert(num_consts == 1, "Bad component list detected.\n"); | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
1452 i = dump_spec_constant( fp, type, i, oper ); |
0 | 1453 // Check that type actually matched |
1454 assert( i != 0, "Non-constant operand lacks component list."); | |
1455 } // end if NULL | |
1456 else { | |
1457 // line (2) | |
1458 // dump all components | |
1459 oper->_components.reset(); | |
1460 while((comp = oper->_components.iter()) != NULL) { | |
1461 type = comp->base_type(_globalNames); | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
293
diff
changeset
|
1462 i = dump_spec_constant( fp, type, i, NULL ); |
0 | 1463 } |
1464 } | |
1465 // finish line (3) | |
1466 fprintf(fp," }\n"); | |
1467 } | |
1468 | |
1469 fprintf(fp," virtual const char *Name() const { return \"%s\";}\n", | |
1470 oper->_ident); | |
1471 | |
1472 fprintf(fp,"#endif\n"); | |
1473 | |
1474 // Close definition of this XxxMachOper | |
1475 fprintf(fp,"};\n"); | |
1476 } | |
1477 | |
1478 | |
1479 // Generate Machine Classes for each instruction defined in AD file | |
1480 fprintf(fp,"\n"); | |
1481 fprintf(fp,"//----------------------------Declare classes for Pipelines-----------------\n"); | |
1482 declare_pipe_classes(fp); | |
1483 | |
1484 // Generate Machine Classes for each instruction defined in AD file | |
1485 fprintf(fp,"\n"); | |
1486 fprintf(fp,"//----------------------------Declare classes derived from MachNode----------\n"); | |
1487 _instructions.reset(); | |
1488 InstructForm *instr; | |
1489 for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { | |
1490 // Ensure this is a machine-world instruction | |
1491 if ( instr->ideal_only() ) continue; | |
1492 | |
1493 // Build class definition for this instruction | |
1494 fprintf(fp,"\n"); | |
1495 fprintf(fp,"class %sNode : public %s { \n", | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1203
diff
changeset
|
1496 instr->_ident, instr->mach_base_class(_globalNames) ); |
0 | 1497 fprintf(fp,"private:\n"); |
1498 fprintf(fp," MachOper *_opnd_array[%d];\n", instr->num_opnds() ); | |
1499 if ( instr->is_ideal_jump() ) { | |
1500 fprintf(fp, " GrowableArray<Label*> _index2label;\n"); | |
1501 } | |
1502 fprintf(fp,"public:\n"); | |
1503 fprintf(fp," MachOper *opnd_array(uint operand_index) const { assert(operand_index < _num_opnds, \"invalid _opnd_array index\"); return _opnd_array[operand_index]; }\n"); | |
1504 fprintf(fp," void set_opnd_array(uint operand_index, MachOper *operand) { assert(operand_index < _num_opnds, \"invalid _opnd_array index\"); _opnd_array[operand_index] = operand; }\n"); | |
1505 fprintf(fp,"private:\n"); | |
1506 if ( instr->is_ideal_jump() ) { | |
1507 fprintf(fp," virtual void add_case_label(int index_num, Label* blockLabel) {\n"); | |
1508 fprintf(fp," _index2label.at_put_grow(index_num, blockLabel);}\n"); | |
1509 } | |
1510 if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) { | |
1511 fprintf(fp," const RegMask *_cisc_RegMask;\n"); | |
1512 } | |
1513 | |
1514 out_RegMask(fp); // output register mask | |
1515 fprintf(fp," virtual uint rule() const { return %s_rule; }\n", | |
1516 instr->_ident); | |
1517 | |
1518 // If this instruction contains a labelOper | |
1519 // Declare Node::methods that set operand Label's contents | |
1520 int label_position = instr->label_position(); | |
1521 if( label_position != -1 ) { | |
1522 // Set the label, stored in labelOper::_branch_label | |
1523 fprintf(fp," virtual void label_set( Label& label, uint block_num );\n"); | |
1524 } | |
1525 | |
1526 // If this instruction contains a methodOper | |
1527 // Declare Node::methods that set operand method's contents | |
1528 int method_position = instr->method_position(); | |
1529 if( method_position != -1 ) { | |
1530 // Set the address method, stored in methodOper::_method | |
1531 fprintf(fp," virtual void method_set( intptr_t method );\n"); | |
1532 } | |
1533 | |
1534 // virtual functions for attributes | |
1535 // | |
1536 // Each instruction attribute results in a virtual call of same name. | |
1537 // The ins_cost is not handled here. | |
1538 Attribute *attr = instr->_attribs; | |
1539 bool is_pc_relative = false; | |
1540 while (attr != NULL) { | |
1541 if (strcmp(attr->_ident,"ins_cost") && | |
1542 strcmp(attr->_ident,"ins_pc_relative")) { | |
1543 fprintf(fp," int %s() const { return %s; }\n", | |
1544 attr->_ident, attr->_val); | |
1545 } | |
1546 // Check value for ins_pc_relative, and if it is true (1), set the flag | |
1547 if (!strcmp(attr->_ident,"ins_pc_relative") && attr->int_val(*this) != 0) | |
1548 is_pc_relative = true; | |
1549 attr = (Attribute *)attr->_next; | |
1550 } | |
1551 | |
1552 // virtual functions for encode and format | |
1553 // | |
1554 // Output the opcode function and the encode function here using the | |
1555 // encoding class information in the _insencode slot. | |
1556 if ( instr->_insencode ) { | |
1557 fprintf(fp," virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;\n"); | |
1558 } | |
1559 | |
1560 // virtual function for getting the size of an instruction | |
1561 if ( instr->_size ) { | |
1562 fprintf(fp," virtual uint size(PhaseRegAlloc *ra_) const;\n"); | |
1563 } | |
1564 | |
1565 // Return the top-level ideal opcode. | |
1566 // Use MachNode::ideal_Opcode() for nodes based on MachNode class | |
1567 // if the ideal_Opcode == Op_Node. | |
1568 if ( strcmp("Node", instr->ideal_Opcode(_globalNames)) != 0 || | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1203
diff
changeset
|
1569 strcmp("MachNode", instr->mach_base_class(_globalNames)) != 0 ) { |
0 | 1570 fprintf(fp," virtual int ideal_Opcode() const { return Op_%s; }\n", |
1571 instr->ideal_Opcode(_globalNames) ); | |
1572 } | |
1573 | |
1574 // Allow machine-independent optimization, invert the sense of the IF test | |
1575 if( instr->is_ideal_if() ) { | |
1576 fprintf(fp," virtual void negate() { \n"); | |
1577 // Identify which operand contains the negate(able) ideal condition code | |
1578 int idx = 0; | |
1579 instr->_components.reset(); | |
1580 for( Component *comp; (comp = instr->_components.iter()) != NULL; ) { | |
1581 // Check that component is an operand | |
1582 Form *form = (Form*)_globalNames[comp->_type]; | |
1583 OperandForm *opForm = form ? form->is_operand() : NULL; | |
1584 if( opForm == NULL ) continue; | |
1585 | |
1586 // Lookup the position of the operand in the instruction. | |
1587 if( opForm->is_ideal_bool() ) { | |
1588 idx = instr->operand_position(comp->_name, comp->_usedef); | |
1589 assert( idx != NameList::Not_in_list, "Did not find component in list that contained it."); | |
1590 break; | |
1591 } | |
1592 } | |
1593 fprintf(fp," opnd_array(%d)->negate();\n", idx); | |
1594 fprintf(fp," _prob = 1.0f - _prob;\n"); | |
1595 fprintf(fp," };\n"); | |
1596 } | |
1597 | |
1598 | |
1599 // Identify which input register matches the input register. | |
1600 uint matching_input = instr->two_address(_globalNames); | |
1601 | |
1602 // Generate the method if it returns != 0 otherwise use MachNode::two_adr() | |
1603 if( matching_input != 0 ) { | |
1604 fprintf(fp," virtual uint two_adr() const "); | |
1605 fprintf(fp,"{ return oper_input_base()"); | |
1606 for( uint i = 2; i <= matching_input; i++ ) | |
1607 fprintf(fp," + opnd_array(%d)->num_edges()",i-1); | |
1608 fprintf(fp,"; }\n"); | |
1609 } | |
1610 | |
1611 // Declare cisc_version, if applicable | |
1612 // MachNode *cisc_version( int offset /* ,... */ ); | |
1613 instr->declare_cisc_version(*this, fp); | |
1614 | |
1615 // If there is an explicit peephole rule, build it | |
1616 if ( instr->peepholes() != NULL ) { | |
1617 fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n"); | |
1618 } | |
1619 | |
1620 // Output the declaration for number of relocation entries | |
1621 if ( instr->reloc(_globalNames) != 0 ) { | |
1622 fprintf(fp," virtual int reloc() const;\n"); | |
1623 } | |
1624 | |
1625 if (instr->alignment() != 1) { | |
1626 fprintf(fp," virtual int alignment_required() const { return %d; }\n", instr->alignment()); | |
1627 fprintf(fp," virtual int compute_padding(int current_offset) const;\n"); | |
1628 } | |
1629 | |
1630 // Starting point for inputs matcher wants. | |
1631 // Use MachNode::oper_input_base() for nodes based on MachNode class | |
1632 // if the base == 1. | |
1633 if ( instr->oper_input_base(_globalNames) != 1 || | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1203
diff
changeset
|
1634 strcmp("MachNode", instr->mach_base_class(_globalNames)) != 0 ) { |
0 | 1635 fprintf(fp," virtual uint oper_input_base() const { return %d; }\n", |
1636 instr->oper_input_base(_globalNames)); | |
1637 } | |
1638 | |
1639 // Make the constructor and following methods 'public:' | |
1640 fprintf(fp,"public:\n"); | |
1641 | |
1642 // Constructor | |
1643 if ( instr->is_ideal_jump() ) { | |
1644 fprintf(fp," %sNode() : _index2label(MinJumpTableSize*2) { ", instr->_ident); | |
1645 } else { | |
1646 fprintf(fp," %sNode() { ", instr->_ident); | |
1647 if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) { | |
1648 fprintf(fp,"_cisc_RegMask = NULL; "); | |
1649 } | |
1650 } | |
1651 | |
1652 fprintf(fp," _num_opnds = %d; _opnds = _opnd_array; ", instr->num_opnds()); | |
1653 | |
1654 bool node_flags_set = false; | |
1655 // flag: if this instruction matches an ideal 'Goto' node | |
1656 if ( instr->is_ideal_goto() ) { | |
1657 fprintf(fp,"init_flags(Flag_is_Goto"); | |
1658 node_flags_set = true; | |
1659 } | |
1660 | |
1661 // flag: if this instruction matches an ideal 'Copy*' node | |
1662 if ( instr->is_ideal_copy() != 0 ) { | |
1663 if ( node_flags_set ) { | |
1664 fprintf(fp," | Flag_is_Copy"); | |
1665 } else { | |
1666 fprintf(fp,"init_flags(Flag_is_Copy"); | |
1667 node_flags_set = true; | |
1668 } | |
1669 } | |
1670 | |
1671 // Is an instruction is a constant? If so, get its type | |
1672 Form::DataType data_type; | |
1673 const char *opType = NULL; | |
1674 const char *result = NULL; | |
1675 data_type = instr->is_chain_of_constant(_globalNames, opType, result); | |
1676 // Check if this instruction is a constant | |
1677 if ( data_type != Form::none ) { | |
1678 if ( node_flags_set ) { | |
1679 fprintf(fp," | Flag_is_Con"); | |
1680 } else { | |
1681 fprintf(fp,"init_flags(Flag_is_Con"); | |
1682 node_flags_set = true; | |
1683 } | |
1684 } | |
1685 | |
1686 // flag: if instruction matches 'If' | 'Goto' | 'CountedLoopEnd | 'Jump' | |
1687 if ( instr->is_ideal_branch() ) { | |
1688 if ( node_flags_set ) { | |
1689 fprintf(fp," | Flag_is_Branch"); | |
1690 } else { | |
1691 fprintf(fp,"init_flags(Flag_is_Branch"); | |
1692 node_flags_set = true; | |
1693 } | |
1694 } | |
1695 | |
1696 // flag: if this instruction is cisc alternate | |
1697 if ( can_cisc_spill() && instr->is_cisc_alternate() ) { | |
1698 if ( node_flags_set ) { | |
1699 fprintf(fp," | Flag_is_cisc_alternate"); | |
1700 } else { | |
1701 fprintf(fp,"init_flags(Flag_is_cisc_alternate"); | |
1702 node_flags_set = true; | |
1703 } | |
1704 } | |
1705 | |
1706 // flag: if this instruction is pc relative | |
1707 if ( is_pc_relative ) { | |
1708 if ( node_flags_set ) { | |
1709 fprintf(fp," | Flag_is_pc_relative"); | |
1710 } else { | |
1711 fprintf(fp,"init_flags(Flag_is_pc_relative"); | |
1712 node_flags_set = true; | |
1713 } | |
1714 } | |
1715 | |
1716 // flag: if this instruction has short branch form | |
1717 if ( instr->has_short_branch_form() ) { | |
1718 if ( node_flags_set ) { | |
1719 fprintf(fp," | Flag_may_be_short_branch"); | |
1720 } else { | |
1721 fprintf(fp,"init_flags(Flag_may_be_short_branch"); | |
1722 node_flags_set = true; | |
1723 } | |
1724 } | |
1725 | |
1726 // Check if machine instructions that USE memory, but do not DEF memory, | |
1727 // depend upon a node that defines memory in machine-independent graph. | |
1728 if ( instr->needs_anti_dependence_check(_globalNames) ) { | |
1729 if ( node_flags_set ) { | |
1730 fprintf(fp," | Flag_needs_anti_dependence_check"); | |
1731 } else { | |
1732 fprintf(fp,"init_flags(Flag_needs_anti_dependence_check"); | |
1733 node_flags_set = true; | |
1734 } | |
1735 } | |
1736 | |
1737 if ( node_flags_set ) { | |
1738 fprintf(fp,"); "); | |
1739 } | |
1740 | |
1741 if (instr->is_ideal_unlock() || instr->is_ideal_call_leaf()) { | |
1742 fprintf(fp,"clear_flag(Flag_is_safepoint_node); "); | |
1743 } | |
1744 | |
1745 fprintf(fp,"}\n"); | |
1746 | |
1747 // size_of, used by base class's clone to obtain the correct size. | |
1748 fprintf(fp," virtual uint size_of() const {"); | |
1749 fprintf(fp, " return sizeof(%sNode);", instr->_ident); | |
1750 fprintf(fp, " }\n"); | |
1751 | |
1752 // Virtual methods which are only generated to override base class | |
1753 if( instr->expands() || instr->needs_projections() || | |
1754 instr->has_temps() || | |
1755 instr->_matrule != NULL && | |
1756 instr->num_opnds() != instr->num_unique_opnds() ) { | |
1203 | 1757 fprintf(fp," virtual MachNode *Expand(State *state, Node_List &proj_list, Node* mem);\n"); |
0 | 1758 } |
1759 | |
1760 if (instr->is_pinned(_globalNames)) { | |
1761 fprintf(fp," virtual bool pinned() const { return "); | |
1762 if (instr->is_parm(_globalNames)) { | |
1763 fprintf(fp,"_in[0]->pinned();"); | |
1764 } else { | |
1765 fprintf(fp,"true;"); | |
1766 } | |
1767 fprintf(fp," }\n"); | |
1768 } | |
1769 if (instr->is_projection(_globalNames)) { | |
1770 fprintf(fp," virtual const Node *is_block_proj() const { return this; }\n"); | |
1771 } | |
1772 if ( instr->num_post_match_opnds() != 0 | |
1773 || instr->is_chain_of_constant(_globalNames) ) { | |
1774 fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode, Compile* C);\n"); | |
1775 } | |
1776 if ( instr->rematerialize(_globalNames, get_registers()) ) { | |
1777 fprintf(fp," // Rematerialize %s\n", instr->_ident); | |
1778 } | |
1779 | |
1780 // Declare short branch methods, if applicable | |
1781 instr->declare_short_branch_methods(fp); | |
1782 | |
1783 // Instructions containing a constant that will be entered into the | |
1784 // float/double table redefine the base virtual function | |
1785 #ifdef SPARC | |
1786 // Sparc doubles entries in the constant table require more space for | |
1787 // alignment. (expires 9/98) | |
1788 int table_entries = (3 * instr->num_consts( _globalNames, Form::idealD )) | |
1789 + instr->num_consts( _globalNames, Form::idealF ); | |
1790 #else | |
1791 int table_entries = instr->num_consts( _globalNames, Form::idealD ) | |
1792 + instr->num_consts( _globalNames, Form::idealF ); | |
1793 #endif | |
1794 if( table_entries != 0 ) { | |
1795 fprintf(fp," virtual int const_size() const {"); | |
1796 fprintf(fp, " return %d;", table_entries); | |
1797 fprintf(fp, " }\n"); | |
1798 } | |
1799 | |
1800 | |
1801 // See if there is an "ins_pipe" declaration for this instruction | |
1802 if (instr->_ins_pipe) { | |
1803 fprintf(fp," static const Pipeline *pipeline_class();\n"); | |
1804 fprintf(fp," virtual const Pipeline *pipeline() const;\n"); | |
1805 } | |
1806 | |
1807 // Generate virtual function for MachNodeX::bottom_type when necessary | |
1808 // | |
1809 // Note on accuracy: Pointer-types of machine nodes need to be accurate, | |
1810 // or else alias analysis on the matched graph may produce bad code. | |
1811 // Moreover, the aliasing decisions made on machine-node graph must be | |
1812 // no less accurate than those made on the ideal graph, or else the graph | |
1813 // may fail to schedule. (Reason: Memory ops which are reordered in | |
1814 // the ideal graph might look interdependent in the machine graph, | |
1815 // thereby removing degrees of scheduling freedom that the optimizer | |
1816 // assumed would be available.) | |
1817 // | |
1818 // %%% We should handle many of these cases with an explicit ADL clause: | |
1819 // instruct foo() %{ ... bottom_type(TypeRawPtr::BOTTOM); ... %} | |
1820 if( data_type != Form::none ) { | |
1821 // A constant's bottom_type returns a Type containing its constant value | |
1822 | |
1823 // !!!!! | |
1824 // Convert all ints, floats, ... to machine-independent TypeXs | |
1825 // as is done for pointers | |
1826 // | |
1827 // Construct appropriate constant type containing the constant value. | |
1828 fprintf(fp," virtual const class Type *bottom_type() const{\n"); | |
1829 switch( data_type ) { | |
1830 case Form::idealI: | |
1831 fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n"); | |
1832 break; | |
1833 case Form::idealP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1834 case Form::idealN: |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
417
diff
changeset
|
1835 fprintf(fp," return opnd_array(1)->type();\n"); |
0 | 1836 break; |
1837 case Form::idealD: | |
1838 fprintf(fp," return TypeD::make(opnd_array(1)->constantD());\n"); | |
1839 break; | |
1840 case Form::idealF: | |
1841 fprintf(fp," return TypeF::make(opnd_array(1)->constantF());\n"); | |
1842 break; | |
1843 case Form::idealL: | |
1844 fprintf(fp," return TypeLong::make(opnd_array(1)->constantL());\n"); | |
1845 break; | |
1846 default: | |
1847 assert( false, "Unimplemented()" ); | |
1848 break; | |
1849 } | |
1850 fprintf(fp," };\n"); | |
1851 } | |
1852 /* else if ( instr->_matrule && instr->_matrule->_rChild && | |
1853 ( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0 | |
1854 || strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) { | |
1855 // !!!!! !!!!! | |
1856 // Provide explicit bottom type for conversions to int | |
1857 // On Intel the result operand is a stackSlot, untyped. | |
1858 fprintf(fp," virtual const class Type *bottom_type() const{"); | |
1859 fprintf(fp, " return TypeInt::INT;"); | |
1860 fprintf(fp, " };\n"); | |
1861 }*/ | |
1862 else if( instr->is_ideal_copy() && | |
1863 !strcmp(instr->_matrule->_lChild->_opType,"stackSlotP") ) { | |
1864 // !!!!! | |
1865 // Special hack for ideal Copy of pointer. Bottom type is oop or not depending on input. | |
1866 fprintf(fp," const Type *bottom_type() const { return in(1)->bottom_type(); } // Copy?\n"); | |
1867 } | |
1868 else if( instr->is_ideal_loadPC() ) { | |
1869 // LoadPCNode provides the return address of a call to native code. | |
1870 // Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM | |
1871 // since it is a pointer to an internal VM location and must have a zero offset. | |
1872 // Allocation detects derived pointers, in part, by their non-zero offsets. | |
1873 fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // LoadPC?\n"); | |
1874 } | |
1875 else if( instr->is_ideal_box() ) { | |
1876 // BoxNode provides the address of a stack slot. | |
1877 // Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM | |
1878 // This prevent s insert_anti_dependencies from complaining. It will | |
1879 // complain if it see that the pointer base is TypePtr::BOTTOM since | |
1880 // it doesn't understand what that might alias. | |
1881 fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n"); | |
1882 } | |
1883 else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveP") ) { | |
1884 int offset = 1; | |
1885 // Special special hack to see if the Cmp? has been incorporated in the conditional move | |
1886 MatchNode *rl = instr->_matrule->_rChild->_lChild; | |
1887 if( rl && !strcmp(rl->_opType, "Binary") ) { | |
1888 MatchNode *rlr = rl->_rChild; | |
1889 if (rlr && strncmp(rlr->_opType, "Cmp", 3) == 0) | |
1890 offset = 2; | |
1891 } | |
1892 // Special hack for ideal CMoveP; ideal type depends on inputs | |
1893 fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveP\n", | |
1894 offset, offset+1, offset+1); | |
1895 } | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1896 else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveN") ) { |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1897 int offset = 1; |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1898 // Special special hack to see if the Cmp? has been incorporated in the conditional move |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1899 MatchNode *rl = instr->_matrule->_rChild->_lChild; |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1900 if( rl && !strcmp(rl->_opType, "Binary") ) { |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1901 MatchNode *rlr = rl->_rChild; |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1902 if (rlr && strncmp(rlr->_opType, "Cmp", 3) == 0) |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1903 offset = 2; |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1904 } |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1905 // Special hack for ideal CMoveN; ideal type depends on inputs |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1906 fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveN\n", |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1907 offset, offset+1, offset+1); |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
196
diff
changeset
|
1908 } |
0 | 1909 else if (instr->is_tls_instruction()) { |
1910 // Special hack for tlsLoadP | |
1911 fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // tlsLoadP\n"); | |
1912 } | |
1913 else if ( instr->is_ideal_if() ) { | |
1914 fprintf(fp," const Type *bottom_type() const { return TypeTuple::IFBOTH; } // matched IfNode\n"); | |
1915 } | |
1916 else if ( instr->is_ideal_membar() ) { | |
1917 fprintf(fp," const Type *bottom_type() const { return TypeTuple::MEMBAR; } // matched MemBar\n"); | |
1918 } | |
1919 | |
1920 // Check where 'ideal_type' must be customized | |
1921 /* | |
1922 if ( instr->_matrule && instr->_matrule->_rChild && | |
1923 ( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0 | |
1924 || strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) { | |
1925 fprintf(fp," virtual uint ideal_reg() const { return Compile::current()->matcher()->base2reg[Type::Int]; }\n"); | |
1926 }*/ | |
1927 | |
1928 // Analyze machine instructions that either USE or DEF memory. | |
1929 int memory_operand = instr->memory_operand(_globalNames); | |
1930 // Some guys kill all of memory | |
1931 if ( instr->is_wide_memory_kill(_globalNames) ) { | |
1932 memory_operand = InstructForm::MANY_MEMORY_OPERANDS; | |
1933 } | |
1934 if ( memory_operand != InstructForm::NO_MEMORY_OPERAND ) { | |
1935 if( memory_operand == InstructForm::MANY_MEMORY_OPERANDS ) { | |
1936 fprintf(fp," virtual const TypePtr *adr_type() const;\n"); | |
1937 } | |
1938 fprintf(fp," virtual const MachOper *memory_operand() const;\n"); | |
1939 } | |
1940 | |
1941 fprintf(fp, "#ifndef PRODUCT\n"); | |
1942 | |
1943 // virtual function for generating the user's assembler output | |
1944 gen_inst_format(fp, _globalNames,*instr); | |
1945 | |
1946 // Machine independent print functionality for debugging | |
1947 fprintf(fp," virtual const char *Name() const { return \"%s\";}\n", | |
1948 instr->_ident); | |
1949 | |
1950 fprintf(fp, "#endif\n"); | |
1951 | |
1952 // Close definition of this XxxMachNode | |
1953 fprintf(fp,"};\n"); | |
1954 }; | |
1955 | |
1956 } | |
1957 | |
1958 void ArchDesc::defineStateClass(FILE *fp) { | |
1959 static const char *state__valid = "_valid[((uint)index) >> 5] & (0x1 << (((uint)index) & 0x0001F))"; | |
1960 static const char *state__set_valid= "_valid[((uint)index) >> 5] |= (0x1 << (((uint)index) & 0x0001F))"; | |
1961 | |
1962 fprintf(fp,"\n"); | |
1963 fprintf(fp,"// MACROS to inline and constant fold State::valid(index)...\n"); | |
1964 fprintf(fp,"// when given a constant 'index' in dfa_<arch>.cpp\n"); | |
1965 fprintf(fp,"// uint word = index >> 5; // Shift out bit position\n"); | |
1966 fprintf(fp,"// uint bitpos = index & 0x0001F; // Mask off word bits\n"); | |
1967 fprintf(fp,"#define STATE__VALID(index) "); | |
1968 fprintf(fp," (%s)\n", state__valid); | |
1969 fprintf(fp,"\n"); | |
1970 fprintf(fp,"#define STATE__NOT_YET_VALID(index) "); | |
1971 fprintf(fp," ( (%s) == 0 )\n", state__valid); | |
1972 fprintf(fp,"\n"); | |
1973 fprintf(fp,"#define STATE__VALID_CHILD(state,index) "); | |
1974 fprintf(fp," ( state && (state->%s) )\n", state__valid); | |
1975 fprintf(fp,"\n"); | |
1976 fprintf(fp,"#define STATE__SET_VALID(index) "); | |
1977 fprintf(fp," (%s)\n", state__set_valid); | |
1978 fprintf(fp,"\n"); | |
1979 fprintf(fp, | |
1980 "//---------------------------State-------------------------------------------\n"); | |
1981 fprintf(fp,"// State contains an integral cost vector, indexed by machine operand opcodes,\n"); | |
1982 fprintf(fp,"// a rule vector consisting of machine operand/instruction opcodes, and also\n"); | |
1983 fprintf(fp,"// indexed by machine operand opcodes, pointers to the children in the label\n"); | |
1984 fprintf(fp,"// tree generated by the Label routines in ideal nodes (currently limited to\n"); | |
1985 fprintf(fp,"// two for convenience, but this could change).\n"); | |
1986 fprintf(fp,"class State : public ResourceObj {\n"); | |
1987 fprintf(fp,"public:\n"); | |
1988 fprintf(fp," int _id; // State identifier\n"); | |
1989 fprintf(fp," Node *_leaf; // Ideal (non-machine-node) leaf of match tree\n"); | |
1990 fprintf(fp," State *_kids[2]; // Children of state node in label tree\n"); | |
1991 fprintf(fp," unsigned int _cost[_LAST_MACH_OPER]; // Cost vector, indexed by operand opcodes\n"); | |
1992 fprintf(fp," unsigned int _rule[_LAST_MACH_OPER]; // Rule vector, indexed by operand opcodes\n"); | |
1993 fprintf(fp," unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entries\n"); | |
1994 fprintf(fp,"\n"); | |
1995 fprintf(fp," State(void); // Constructor\n"); | |
1996 fprintf(fp," DEBUG_ONLY( ~State(void); ) // Destructor\n"); | |
1997 fprintf(fp,"\n"); | |
1998 fprintf(fp," // Methods created by ADLC and invoked by Reduce\n"); | |
1999 fprintf(fp," MachOper *MachOperGenerator( int opcode, Compile* C );\n"); | |
2000 fprintf(fp," MachNode *MachNodeGenerator( int opcode, Compile* C );\n"); | |
2001 fprintf(fp,"\n"); | |
2002 fprintf(fp," // Assign a state to a node, definition of method produced by ADLC\n"); | |
2003 fprintf(fp," bool DFA( int opcode, const Node *ideal );\n"); | |
2004 fprintf(fp,"\n"); | |
2005 fprintf(fp," // Access function for _valid bit vector\n"); | |
2006 fprintf(fp," bool valid(uint index) {\n"); | |
2007 fprintf(fp," return( STATE__VALID(index) != 0 );\n"); | |
2008 fprintf(fp," }\n"); | |
2009 fprintf(fp,"\n"); | |
2010 fprintf(fp," // Set function for _valid bit vector\n"); | |
2011 fprintf(fp," void set_valid(uint index) {\n"); | |
2012 fprintf(fp," STATE__SET_VALID(index);\n"); | |
2013 fprintf(fp," }\n"); | |
2014 fprintf(fp,"\n"); | |
2015 fprintf(fp,"#ifndef PRODUCT\n"); | |
2016 fprintf(fp," void dump(); // Debugging prints\n"); | |
2017 fprintf(fp," void dump(int depth);\n"); | |
2018 fprintf(fp,"#endif\n"); | |
2019 if (_dfa_small) { | |
2020 // Generate the routine name we'll need | |
2021 for (int i = 1; i < _last_opcode; i++) { | |
2022 if (_mlistab[i] == NULL) continue; | |
2023 fprintf(fp, " void _sub_Op_%s(const Node *n);\n", NodeClassNames[i]); | |
2024 } | |
2025 } | |
2026 fprintf(fp,"};\n"); | |
2027 fprintf(fp,"\n"); | |
2028 fprintf(fp,"\n"); | |
2029 | |
2030 } | |
2031 | |
2032 | |
2033 //---------------------------buildMachOperEnum--------------------------------- | |
2034 // Build enumeration for densely packed operands. | |
2035 // This enumeration is used to index into the arrays in the State objects | |
2036 // that indicate cost and a successfull rule match. | |
2037 | |
2038 // Information needed to generate the ReduceOp mapping for the DFA | |
2039 class OutputMachOperands : public OutputMap { | |
2040 public: | |
2041 OutputMachOperands(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) | |
2042 : OutputMap(hpp, cpp, globals, AD) {}; | |
2043 | |
2044 void declaration() { } | |
2045 void definition() { fprintf(_cpp, "enum MachOperands {\n"); } | |
2046 void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n"); | |
2047 OutputMap::closing(); | |
2048 } | |
2049 void map(OpClassForm &opc) { fprintf(_cpp, " %s", _AD.machOperEnum(opc._ident) ); } | |
2050 void map(OperandForm &oper) { fprintf(_cpp, " %s", _AD.machOperEnum(oper._ident) ); } | |
2051 void map(char *name) { fprintf(_cpp, " %s", _AD.machOperEnum(name)); } | |
2052 | |
2053 bool do_instructions() { return false; } | |
2054 void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); } | |
2055 }; | |
2056 | |
2057 | |
2058 void ArchDesc::buildMachOperEnum(FILE *fp_hpp) { | |
2059 // Construct the table for MachOpcodes | |
2060 OutputMachOperands output_mach_operands(fp_hpp, fp_hpp, _globalNames, *this); | |
2061 build_map(output_mach_operands); | |
2062 } | |
2063 | |
2064 | |
2065 //---------------------------buildMachEnum---------------------------------- | |
2066 // Build enumeration for all MachOpers and all MachNodes | |
2067 | |
2068 // Information needed to generate the ReduceOp mapping for the DFA | |
2069 class OutputMachOpcodes : public OutputMap { | |
2070 int begin_inst_chain_rule; | |
2071 int end_inst_chain_rule; | |
2072 int begin_rematerialize; | |
2073 int end_rematerialize; | |
2074 int end_instructions; | |
2075 public: | |
2076 OutputMachOpcodes(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) | |
2077 : OutputMap(hpp, cpp, globals, AD), | |
2078 begin_inst_chain_rule(-1), end_inst_chain_rule(-1), end_instructions(-1) | |
2079 {}; | |
2080 | |
2081 void declaration() { } | |
2082 void definition() { fprintf(_cpp, "enum MachOpcodes {\n"); } | |
2083 void closing() { | |
2084 if( begin_inst_chain_rule != -1 ) | |
2085 fprintf(_cpp, " _BEGIN_INST_CHAIN_RULE = %d,\n", begin_inst_chain_rule); | |
2086 if( end_inst_chain_rule != -1 ) | |
2087 fprintf(_cpp, " _END_INST_CHAIN_RULE = %d,\n", end_inst_chain_rule); | |
2088 if( begin_rematerialize != -1 ) | |
2089 fprintf(_cpp, " _BEGIN_REMATERIALIZE = %d,\n", begin_rematerialize); | |
2090 if( end_rematerialize != -1 ) | |
2091 fprintf(_cpp, " _END_REMATERIALIZE = %d,\n", end_rematerialize); | |
2092 // always execute since do_instructions() is true, and avoids trailing comma | |
2093 fprintf(_cpp, " _last_Mach_Node = %d \n", end_instructions); | |
2094 OutputMap::closing(); | |
2095 } | |
2096 void map(OpClassForm &opc) { fprintf(_cpp, " %s_rule", opc._ident ); } | |
2097 void map(OperandForm &oper) { fprintf(_cpp, " %s_rule", oper._ident ); } | |
2098 void map(char *name) { if (name) fprintf(_cpp, " %s_rule", name); | |
2099 else fprintf(_cpp, " 0"); } | |
2100 void map(InstructForm &inst) {fprintf(_cpp, " %s_rule", inst._ident ); } | |
2101 | |
2102 void record_position(OutputMap::position place, int idx ) { | |
2103 switch(place) { | |
2104 case OutputMap::BEGIN_INST_CHAIN_RULES : | |
2105 begin_inst_chain_rule = idx; | |
2106 break; | |
2107 case OutputMap::END_INST_CHAIN_RULES : | |
2108 end_inst_chain_rule = idx; | |
2109 break; | |
2110 case OutputMap::BEGIN_REMATERIALIZE : | |
2111 begin_rematerialize = idx; | |
2112 break; | |
2113 case OutputMap::END_REMATERIALIZE : | |
2114 end_rematerialize = idx; | |
2115 break; | |
2116 case OutputMap::END_INSTRUCTIONS : | |
2117 end_instructions = idx; | |
2118 break; | |
2119 default: | |
2120 break; | |
2121 } | |
2122 } | |
2123 }; | |
2124 | |
2125 | |
2126 void ArchDesc::buildMachOpcodesEnum(FILE *fp_hpp) { | |
2127 // Construct the table for MachOpcodes | |
2128 OutputMachOpcodes output_mach_opcodes(fp_hpp, fp_hpp, _globalNames, *this); | |
2129 build_map(output_mach_opcodes); | |
2130 } | |
2131 | |
2132 | |
2133 // Generate an enumeration of the pipeline states, and both | |
2134 // the functional units (resources) and the masks for | |
2135 // specifying resources | |
2136 void ArchDesc::build_pipeline_enums(FILE *fp_hpp) { | |
2137 int stagelen = (int)strlen("undefined"); | |
2138 int stagenum = 0; | |
2139 | |
2140 if (_pipeline) { // Find max enum string length | |
2141 const char *stage; | |
2142 for ( _pipeline->_stages.reset(); (stage = _pipeline->_stages.iter()) != NULL; ) { | |
2143 int len = (int)strlen(stage); | |
2144 if (stagelen < len) stagelen = len; | |
2145 } | |
2146 } | |
2147 | |
2148 // Generate a list of stages | |
2149 fprintf(fp_hpp, "\n"); | |
2150 fprintf(fp_hpp, "// Pipeline Stages\n"); | |
2151 fprintf(fp_hpp, "enum machPipelineStages {\n"); | |
2152 fprintf(fp_hpp, " stage_%-*s = 0,\n", stagelen, "undefined"); | |
2153 | |
2154 if( _pipeline ) { | |
2155 const char *stage; | |
2156 for ( _pipeline->_stages.reset(); (stage = _pipeline->_stages.iter()) != NULL; ) | |
2157 fprintf(fp_hpp, " stage_%-*s = %d,\n", stagelen, stage, ++stagenum); | |
2158 } | |
2159 | |
2160 fprintf(fp_hpp, " stage_%-*s = %d\n", stagelen, "count", stagenum); | |
2161 fprintf(fp_hpp, "};\n"); | |
2162 | |
2163 fprintf(fp_hpp, "\n"); | |
2164 fprintf(fp_hpp, "// Pipeline Resources\n"); | |
2165 fprintf(fp_hpp, "enum machPipelineResources {\n"); | |
2166 int rescount = 0; | |
2167 | |
2168 if( _pipeline ) { | |
2169 const char *resource; | |
2170 int reslen = 0; | |
2171 | |
2172 // Generate a list of resources, and masks | |
2173 for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) { | |
2174 int len = (int)strlen(resource); | |
2175 if (reslen < len) | |
2176 reslen = len; | |
2177 } | |
2178 | |
2179 for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) { | |
2180 const ResourceForm *resform = _pipeline->_resdict[resource]->is_resource(); | |
2181 int mask = resform->mask(); | |
2182 if ((mask & (mask-1)) == 0) | |
2183 fprintf(fp_hpp, " resource_%-*s = %d,\n", reslen, resource, rescount++); | |
2184 } | |
2185 fprintf(fp_hpp, "\n"); | |
2186 for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) { | |
2187 const ResourceForm *resform = _pipeline->_resdict[resource]->is_resource(); | |
2188 fprintf(fp_hpp, " res_mask_%-*s = 0x%08x,\n", reslen, resource, resform->mask()); | |
2189 } | |
2190 fprintf(fp_hpp, "\n"); | |
2191 } | |
2192 fprintf(fp_hpp, " resource_count = %d\n", rescount); | |
2193 fprintf(fp_hpp, "};\n"); | |
2194 } |