File: | jdk/src/hotspot/share/adlc/archDesc.cpp |
Warning: | line 612, column 11 Although the value stored to 'cur' is used in the enclosing expression, the value is never actually read from 'cur' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // |
2 | // Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | // |
5 | // This code is free software; you can redistribute it and/or modify it |
6 | // under the terms of the GNU General Public License version 2 only, as |
7 | // published by the Free Software Foundation. |
8 | // |
9 | // This code is distributed in the hope that it will be useful, but WITHOUT |
10 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | // version 2 for more details (a copy is included in the LICENSE file that |
13 | // accompanied this code). |
14 | // |
15 | // You should have received a copy of the GNU General Public License version |
16 | // 2 along with this work; if not, write to the Free Software Foundation, |
17 | // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | // |
19 | // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | // or visit www.oracle.com if you need additional information or have any |
21 | // questions. |
22 | // |
23 | // |
24 | |
25 | |
26 | // archDesc.cpp - Internal format for architecture definition |
27 | #include "adlc.hpp" |
28 | |
29 | static FILE *errfile = stderrstderr; |
30 | |
31 | //--------------------------- utility functions ----------------------------- |
32 | inline char toUpper(char lower) { |
33 | return (('a' <= lower && lower <= 'z') ? ((char) (lower + ('A'-'a'))) : lower); |
34 | } |
35 | char *toUpper(const char *str) { |
36 | char *upper = new char[strlen(str)+1]; |
37 | char *result = upper; |
38 | const char *end = str + strlen(str); |
39 | for (; str < end; ++str, ++upper) { |
40 | *upper = toUpper(*str); |
41 | } |
42 | *upper = '\0'; |
43 | return result; |
44 | } |
45 | |
46 | //---------------------------ChainList Methods------------------------------- |
47 | ChainList::ChainList() { |
48 | } |
49 | |
50 | void ChainList::insert(const char *name, const char *cost, const char *rule) { |
51 | _name.addName(name); |
52 | _cost.addName(cost); |
53 | _rule.addName(rule); |
54 | } |
55 | |
56 | bool ChainList::search(const char *name) { |
57 | return _name.search(name); |
58 | } |
59 | |
60 | void ChainList::reset() { |
61 | _name.reset(); |
62 | _cost.reset(); |
63 | _rule.reset(); |
64 | } |
65 | |
66 | bool ChainList::iter(const char * &name, const char * &cost, const char * &rule) { |
67 | bool notDone = false; |
68 | const char *n = _name.iter(); |
69 | const char *c = _cost.iter(); |
70 | const char *r = _rule.iter(); |
71 | |
72 | if (n && c && r) { |
73 | notDone = true; |
74 | name = n; |
75 | cost = c; |
76 | rule = r; |
77 | } |
78 | |
79 | return notDone; |
80 | } |
81 | |
82 | void ChainList::dump() { |
83 | output(stderrstderr); |
84 | } |
85 | |
86 | void ChainList::output(FILE *fp) { |
87 | fprintf(fp, "\nChain Rules: output resets iterator\n"); |
88 | const char *cost = NULL__null; |
89 | const char *name = NULL__null; |
90 | const char *rule = NULL__null; |
91 | bool chains_exist = false; |
92 | for(reset(); (iter(name,cost,rule)) == true; ) { |
93 | fprintf(fp, "Chain to <%s> at cost #%s using %s_rule\n",name, cost ? cost : "0", rule); |
94 | // // Check for transitive chain rules |
95 | // Form *form = (Form *)_globalNames[rule]; |
96 | // if (form->is_instruction()) { |
97 | // // chain_rule(fp, indent, name, cost, rule); |
98 | // chain_rule(fp, indent, name, cost, rule); |
99 | // } |
100 | } |
101 | reset(); |
102 | if( ! chains_exist ) { |
103 | fprintf(fp, "No entries in this ChainList\n"); |
104 | } |
105 | } |
106 | |
107 | |
108 | //---------------------------MatchList Methods------------------------------- |
109 | bool MatchList::search(const char *opc, const char *res, const char *lch, |
110 | const char *rch, Predicate *pr) { |
111 | bool tmp = false; |
112 | if ((res == _resultStr) || (res && _resultStr && !strcmp(res, _resultStr))) { |
113 | if ((lch == _lchild) || (lch && _lchild && !strcmp(lch, _lchild))) { |
114 | if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) { |
115 | char * predStr = get_pred(); |
116 | char * prStr = pr?pr->_pred:NULL__null; |
117 | if (ADLParser::equivalent_expressions(prStr, predStr)) { |
118 | return true; |
119 | } |
120 | } |
121 | } |
122 | } |
123 | if (_next) { |
124 | tmp = _next->search(opc, res, lch, rch, pr); |
125 | } |
126 | return tmp; |
127 | } |
128 | |
129 | |
130 | void MatchList::dump() { |
131 | output(stderrstderr); |
132 | } |
133 | |
134 | void MatchList::output(FILE *fp) { |
135 | fprintf(fp, "\nMatchList output is Unimplemented();\n"); |
136 | } |
137 | |
138 | |
139 | //---------------------------ArchDesc Constructor and Destructor------------- |
140 | |
141 | ArchDesc::ArchDesc() |
142 | : _globalNames(cmpstr,hashstr, Form::arena), |
143 | _globalDefs(cmpstr,hashstr, Form::arena), |
144 | _preproc_table(cmpstr,hashstr, Form::arena), |
145 | _idealIndex(cmpstr,hashstr, Form::arena), |
146 | _internalOps(cmpstr,hashstr, Form::arena), |
147 | _internalMatch(cmpstr,hashstr, Form::arena), |
148 | _chainRules(cmpstr,hashstr, Form::arena), |
149 | _cisc_spill_operand(NULL__null), |
150 | _needs_deep_clone_jvms(false) { |
151 | |
152 | // Initialize the opcode to MatchList table with NULLs |
153 | for( int i=0; i<_last_opcode; ++i ) { |
154 | _mlistab[i] = NULL__null; |
155 | } |
156 | |
157 | // Set-up the global tables |
158 | initKeywords(_globalNames); // Initialize the Name Table with keywords |
159 | |
160 | // Prime user-defined types with predefined types: Set, RegI, RegF, ... |
161 | initBaseOpTypes(); |
162 | |
163 | // Initialize flags & counters |
164 | _TotalLines = 0; |
165 | _no_output = 0; |
166 | _quiet_mode = 0; |
167 | _disable_warnings = 0; |
168 | _dfa_debug = 0; |
169 | _dfa_small = 0; |
170 | _adl_debug = 0; |
171 | _adlocation_debug = 0; |
172 | _internalOpCounter = 0; |
173 | _cisc_spill_debug = false; |
174 | _short_branch_debug = false; |
175 | |
176 | // Initialize match rule flags |
177 | for (int i = 0; i < _last_opcode; i++) { |
178 | _has_match_rule[i] = false; |
179 | } |
180 | |
181 | // Error/Warning Counts |
182 | _syntax_errs = 0; |
183 | _semantic_errs = 0; |
184 | _warnings = 0; |
185 | _internal_errs = 0; |
186 | |
187 | // Initialize I/O Files |
188 | _ADL_file._name = NULL__null; _ADL_file._fp = NULL__null; |
189 | // Machine dependent output files |
190 | _DFA_file._name = NULL__null; _DFA_file._fp = NULL__null; |
191 | _HPP_file._name = NULL__null; _HPP_file._fp = NULL__null; |
192 | _CPP_file._name = NULL__null; _CPP_file._fp = NULL__null; |
193 | _bug_file._name = "bugs.out"; _bug_file._fp = NULL__null; |
194 | |
195 | // Initialize Register & Pipeline Form Pointers |
196 | _register = NULL__null; |
197 | _encode = NULL__null; |
198 | _pipeline = NULL__null; |
199 | _frame = NULL__null; |
200 | } |
201 | |
202 | ArchDesc::~ArchDesc() { |
203 | // Clean-up and quit |
204 | |
205 | } |
206 | |
207 | //---------------------------ArchDesc methods: Public ---------------------- |
208 | // Store forms according to type |
209 | void ArchDesc::addForm(PreHeaderForm *ptr) { _pre_header.addForm(ptr); }; |
210 | void ArchDesc::addForm(HeaderForm *ptr) { _header.addForm(ptr); }; |
211 | void ArchDesc::addForm(SourceForm *ptr) { _source.addForm(ptr); }; |
212 | void ArchDesc::addForm(EncodeForm *ptr) { _encode = ptr; }; |
213 | void ArchDesc::addForm(InstructForm *ptr) { _instructions.addForm(ptr); }; |
214 | void ArchDesc::addForm(MachNodeForm *ptr) { _machnodes.addForm(ptr); }; |
215 | void ArchDesc::addForm(OperandForm *ptr) { _operands.addForm(ptr); }; |
216 | void ArchDesc::addForm(OpClassForm *ptr) { _opclass.addForm(ptr); }; |
217 | void ArchDesc::addForm(AttributeForm *ptr) { _attributes.addForm(ptr); }; |
218 | void ArchDesc::addForm(RegisterForm *ptr) { _register = ptr; }; |
219 | void ArchDesc::addForm(FrameForm *ptr) { _frame = ptr; }; |
220 | void ArchDesc::addForm(PipelineForm *ptr) { _pipeline = ptr; }; |
221 | |
222 | // Build MatchList array and construct MatchLists |
223 | void ArchDesc::generateMatchLists() { |
224 | // Call inspection routines to populate array |
225 | inspectOperands(); |
226 | inspectInstructions(); |
227 | } |
228 | |
229 | // Build MatchList structures for operands |
230 | void ArchDesc::inspectOperands() { |
231 | |
232 | // Iterate through all operands |
233 | _operands.reset(); |
234 | OperandForm *op; |
235 | for( ; (op = (OperandForm*)_operands.iter()) != NULL__null;) { |
236 | // Construct list of top-level operands (components) |
237 | op->build_components(); |
238 | |
239 | // Ensure that match field is defined. |
240 | if ( op->_matrule == NULL__null ) continue; |
241 | |
242 | // Type check match rules |
243 | check_optype(op->_matrule); |
244 | |
245 | // Construct chain rules |
246 | build_chain_rule(op); |
247 | |
248 | MatchRule *mrule = op->_matrule; |
249 | Predicate *pred = op->_predicate; |
250 | |
251 | // Grab the machine type of the operand |
252 | const char *rootOp = op->_ident; |
253 | mrule->_machType = rootOp; |
254 | |
255 | // Check for special cases |
256 | if (strcmp(rootOp,"Universe")==0) continue; |
257 | if (strcmp(rootOp,"label")==0) continue; |
258 | // !!!!! !!!!! |
259 | assert( strcmp(rootOp,"sReg") != 0, "Disable untyped 'sReg'"){ if (!(strcmp(rootOp,"sReg") != 0)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 259, "Disable untyped 'sReg'"); abort(); }}; |
260 | if (strcmp(rootOp,"sRegI")==0) continue; |
261 | if (strcmp(rootOp,"sRegP")==0) continue; |
262 | if (strcmp(rootOp,"sRegF")==0) continue; |
263 | if (strcmp(rootOp,"sRegD")==0) continue; |
264 | if (strcmp(rootOp,"sRegL")==0) continue; |
265 | |
266 | // Cost for this match |
267 | const char *costStr = op->cost(); |
268 | const char *defaultCost = |
269 | ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef; |
270 | const char *cost = costStr? costStr : defaultCost; |
271 | |
272 | // Find result type for match. |
273 | const char *result = op->reduce_result(); |
274 | |
275 | // Construct a MatchList for this entry. |
276 | // Iterate over the list to enumerate all match cases for operands with multiple match rules. |
277 | for (; mrule != NULL__null; mrule = mrule->_next) { |
278 | mrule->_machType = rootOp; |
279 | buildMatchList(mrule, result, rootOp, pred, cost); |
280 | } |
281 | } |
282 | } |
283 | |
284 | // Build MatchList structures for instructions |
285 | void ArchDesc::inspectInstructions() { |
286 | |
287 | // Iterate through all instructions |
288 | _instructions.reset(); |
289 | InstructForm *instr; |
290 | for( ; (instr = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
291 | // Construct list of top-level operands (components) |
292 | instr->build_components(); |
293 | |
294 | // Ensure that match field is defined. |
295 | if ( instr->_matrule == NULL__null ) continue; |
296 | |
297 | MatchRule &mrule = *instr->_matrule; |
298 | Predicate *pred = instr->build_predicate(); |
299 | |
300 | // Grab the machine type of the operand |
301 | const char *rootOp = instr->_ident; |
302 | mrule._machType = rootOp; |
303 | |
304 | // Cost for this match |
305 | const char *costStr = instr->cost(); |
306 | const char *defaultCost = |
307 | ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; |
308 | const char *cost = costStr? costStr : defaultCost; |
309 | |
310 | // Find result type for match |
311 | const char *result = instr->reduce_result(); |
312 | |
313 | if (( instr->is_ideal_branch() && instr->label_position() == -1) || |
314 | (!instr->is_ideal_branch() && instr->label_position() != -1)) { |
315 | syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp); |
316 | } |
317 | |
318 | Attribute *attr = instr->_attribs; |
319 | while (attr != NULL__null) { |
320 | if (strcmp(attr->_ident,"ins_short_branch") == 0 && |
321 | attr->int_val(*this) != 0) { |
322 | if (!instr->is_ideal_branch() || instr->label_position() == -1) { |
323 | syntax_err(instr->_linenum, "%s: Only short branch to a label is supported\n", rootOp); |
324 | } |
325 | instr->set_short_branch(true); |
326 | } else if (strcmp(attr->_ident,"ins_alignment") == 0 && |
327 | attr->int_val(*this) != 0) { |
328 | instr->set_alignment(attr->int_val(*this)); |
329 | } |
330 | attr = (Attribute *)attr->_next; |
331 | } |
332 | |
333 | if (!instr->is_short_branch()) { |
334 | buildMatchList(instr->_matrule, result, mrule._machType, pred, cost); |
335 | } |
336 | } |
337 | } |
338 | |
339 | static int setsResult(MatchRule &mrule) { |
340 | if (strcmp(mrule._name,"Set") == 0) return 1; |
341 | return 0; |
342 | } |
343 | |
344 | const char *ArchDesc::getMatchListIndex(MatchRule &mrule) { |
345 | if (setsResult(mrule)) { |
346 | // right child |
347 | return mrule._rChild->_opType; |
348 | } else { |
349 | // first entry |
350 | return mrule._opType; |
351 | } |
352 | } |
353 | |
354 | |
355 | //------------------------------result of reduction---------------------------- |
356 | |
357 | |
358 | //------------------------------left reduction--------------------------------- |
359 | // Return the left reduction associated with an internal name |
360 | const char *ArchDesc::reduceLeft(char *internalName) { |
361 | const char *left = NULL__null; |
362 | MatchNode *mnode = (MatchNode*)_internalMatch[internalName]; |
363 | if (mnode->_lChild) { |
364 | mnode = mnode->_lChild; |
365 | left = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
366 | } |
367 | return left; |
368 | } |
369 | |
370 | |
371 | //------------------------------right reduction-------------------------------- |
372 | const char *ArchDesc::reduceRight(char *internalName) { |
373 | const char *right = NULL__null; |
374 | MatchNode *mnode = (MatchNode*)_internalMatch[internalName]; |
375 | if (mnode->_rChild) { |
376 | mnode = mnode->_rChild; |
377 | right = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
378 | } |
379 | return right; |
380 | } |
381 | |
382 | |
383 | //------------------------------check_optype----------------------------------- |
384 | void ArchDesc::check_optype(MatchRule *mrule) { |
385 | MatchRule *rule = mrule; |
386 | |
387 | // !!!!! |
388 | // // Cycle through the list of match rules |
389 | // while(mrule) { |
390 | // // Check for a filled in type field |
391 | // if (mrule->_opType == NULL) { |
392 | // const Form *form = operands[_result]; |
393 | // OpClassForm *opcForm = form ? form->is_opclass() : NULL; |
394 | // assert(opcForm != NULL, "Match Rule contains invalid operand name."); |
395 | // } |
396 | // char *opType = opcForm->_ident; |
397 | // } |
398 | } |
399 | |
400 | //------------------------------add_chain_rule_entry-------------------------- |
401 | void ArchDesc::add_chain_rule_entry(const char *src, const char *cost, |
402 | const char *result) { |
403 | // Look-up the operation in chain rule table |
404 | ChainList *lst = (ChainList *)_chainRules[src]; |
405 | if (lst == NULL__null) { |
406 | lst = new ChainList(); |
407 | _chainRules.Insert(src, lst); |
408 | } |
409 | if (!lst->search(result)) { |
410 | if (cost == NULL__null) { |
411 | cost = ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef; |
412 | } |
413 | lst->insert(result, cost, result); |
414 | } |
415 | } |
416 | |
417 | //------------------------------build_chain_rule------------------------------- |
418 | void ArchDesc::build_chain_rule(OperandForm *oper) { |
419 | MatchRule *rule; |
420 | |
421 | // Check for chain rules here |
422 | // If this is only a chain rule |
423 | if ((oper->_matrule) && (oper->_matrule->_lChild == NULL__null) && |
424 | (oper->_matrule->_rChild == NULL__null)) { |
425 | |
426 | { |
427 | const Form *form = _globalNames[oper->_matrule->_opType]; |
428 | if ((form) && form->is_operand() && |
429 | (form->ideal_only() == false)) { |
430 | add_chain_rule_entry(oper->_matrule->_opType, oper->cost(), oper->_ident); |
431 | } |
432 | } |
433 | // Check for additional chain rules |
434 | if (oper->_matrule->_next) { |
435 | rule = oper->_matrule; |
436 | do { |
437 | rule = rule->_next; |
438 | // Any extra match rules after the first must be chain rules |
439 | const Form *form = _globalNames[rule->_opType]; |
440 | if ((form) && form->is_operand() && |
441 | (form->ideal_only() == false)) { |
442 | add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident); |
443 | } |
444 | } while(rule->_next != NULL__null); |
445 | } |
446 | } |
447 | else if ((oper->_matrule) && (oper->_matrule->_next)) { |
448 | // Regardles of whether the first matchrule is a chain rule, check the list |
449 | rule = oper->_matrule; |
450 | do { |
451 | rule = rule->_next; |
452 | // Any extra match rules after the first must be chain rules |
453 | const Form *form = _globalNames[rule->_opType]; |
454 | if ((form) && form->is_operand() && |
455 | (form->ideal_only() == false)) { |
456 | assert( oper->cost(), "This case expects NULL cost, not default cost"){ if (!(oper->cost())) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 456, "This case expects NULL cost, not default cost"); abort (); }}; |
457 | add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident); |
458 | } |
459 | } while(rule->_next != NULL__null); |
460 | } |
461 | |
462 | } |
463 | |
464 | //------------------------------buildMatchList--------------------------------- |
465 | // operands and instructions provide the result |
466 | void ArchDesc::buildMatchList(MatchRule *mrule, const char *resultStr, |
467 | const char *rootOp, Predicate *pred, |
468 | const char *cost) { |
469 | const char *leftstr, *rightstr; |
470 | MatchNode *mnode; |
471 | |
472 | leftstr = rightstr = NULL__null; |
473 | // Check for chain rule, and do not generate a match list for it |
474 | if ( mrule->is_chain_rule(_globalNames) ) { |
475 | return; |
476 | } |
477 | |
478 | // Identify index position among ideal operands |
479 | intptr_t index = _last_opcode; |
480 | const char *indexStr = getMatchListIndex(*mrule); |
481 | index = (intptr_t)_idealIndex[indexStr]; |
482 | if (index == 0) { |
483 | fprintf(stderrstderr, "Ideal node missing: %s\n", indexStr); |
484 | assert(index != 0, "Failed lookup of ideal node\n"){ if (!(index != 0)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 484, "Failed lookup of ideal node\n"); abort(); }}; |
485 | } |
486 | |
487 | // Check that this will be placed appropriately in the DFA |
488 | if (index >= _last_opcode) { |
489 | fprintf(stderrstderr, "Invalid match rule %s <-- ( %s )\n", |
490 | resultStr ? resultStr : " ", |
491 | rootOp ? rootOp : " "); |
492 | assert(index < _last_opcode, "Matching item not in ideal graph\n"){ if (!(index < _last_opcode)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 492, "Matching item not in ideal graph\n"); abort(); }}; |
493 | return; |
494 | } |
495 | |
496 | |
497 | // Walk the MatchRule, generating MatchList entries for each level |
498 | // of the rule (each nesting of parentheses) |
499 | // Check for "Set" |
500 | if (!strcmp(mrule->_opType, "Set")) { |
501 | mnode = mrule->_rChild; |
502 | buildMList(mnode, rootOp, resultStr, pred, cost); |
503 | return; |
504 | } |
505 | // Build MatchLists for children |
506 | // Check each child for an internal operand name, and use that name |
507 | // for the parent's matchlist entry if it exists |
508 | mnode = mrule->_lChild; |
509 | if (mnode) { |
510 | buildMList(mnode, NULL__null, NULL__null, NULL__null, NULL__null); |
511 | leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
512 | } |
513 | mnode = mrule->_rChild; |
514 | if (mnode) { |
515 | buildMList(mnode, NULL__null, NULL__null, NULL__null, NULL__null); |
516 | rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
517 | } |
518 | // Search for an identical matchlist entry already on the list |
519 | if ((_mlistab[index] == NULL__null) || |
520 | (_mlistab[index] && |
521 | !_mlistab[index]->search(rootOp, resultStr, leftstr, rightstr, pred))) { |
522 | // Place this match rule at front of list |
523 | MatchList *mList = |
524 | new MatchList(_mlistab[index], pred, cost, |
525 | rootOp, resultStr, leftstr, rightstr); |
526 | _mlistab[index] = mList; |
527 | } |
528 | } |
529 | |
530 | // Recursive call for construction of match lists |
531 | void ArchDesc::buildMList(MatchNode *node, const char *rootOp, |
532 | const char *resultOp, Predicate *pred, |
533 | const char *cost) { |
534 | const char *leftstr, *rightstr; |
535 | const char *resultop; |
536 | const char *opcode; |
537 | MatchNode *mnode; |
538 | Form *form; |
539 | |
540 | leftstr = rightstr = NULL__null; |
541 | // Do not process leaves of the Match Tree if they are not ideal |
542 | if ((node) && (node->_lChild == NULL__null) && (node->_rChild == NULL__null) && |
543 | ((form = (Form *)_globalNames[node->_opType]) != NULL__null) && |
544 | (!form->ideal_only())) { |
545 | return; |
546 | } |
547 | |
548 | // Identify index position among ideal operands |
549 | intptr_t index = _last_opcode; |
550 | const char *indexStr = node ? node->_opType : (char *) " "; |
551 | index = (intptr_t)_idealIndex[indexStr]; |
552 | if (index == 0) { |
553 | fprintf(stderrstderr, "error: operand \"%s\" not found\n", indexStr); |
554 | assert(0, "fatal error"){ if (!(0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 554, "fatal error"); abort(); }}; |
555 | } |
556 | |
557 | if (node == NULL__null) { |
558 | fprintf(stderrstderr, "error: node is NULL\n"); |
559 | assert(0, "fatal error"){ if (!(0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 559, "fatal error"); abort(); }}; |
560 | } |
561 | // Build MatchLists for children |
562 | // Check each child for an internal operand name, and use that name |
563 | // for the parent's matchlist entry if it exists |
564 | mnode = node->_lChild; |
565 | if (mnode) { |
566 | buildMList(mnode, NULL__null, NULL__null, NULL__null, NULL__null); |
567 | leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
568 | } |
569 | mnode = node->_rChild; |
570 | if (mnode) { |
571 | buildMList(mnode, NULL__null, NULL__null, NULL__null, NULL__null); |
572 | rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType; |
573 | } |
574 | // Grab the string for the opcode of this list entry |
575 | if (rootOp == NULL__null) { |
576 | opcode = (node->_internalop) ? node->_internalop : node->_opType; |
577 | } else { |
578 | opcode = rootOp; |
579 | } |
580 | // Grab the string for the result of this list entry |
581 | if (resultOp == NULL__null) { |
582 | resultop = (node->_internalop) ? node->_internalop : node->_opType; |
583 | } |
584 | else resultop = resultOp; |
585 | // Search for an identical matchlist entry already on the list |
586 | if ((_mlistab[index] == NULL__null) || (_mlistab[index] && |
587 | !_mlistab[index]->search(opcode, resultop, leftstr, rightstr, pred))) { |
588 | // Place this match rule at front of list |
589 | MatchList *mList = |
590 | new MatchList(_mlistab[index],pred,cost, |
591 | opcode, resultop, leftstr, rightstr); |
592 | _mlistab[index] = mList; |
593 | } |
594 | } |
595 | |
596 | // Count number of OperandForms defined |
597 | int ArchDesc::operandFormCount() { |
598 | // Only interested in ones with non-NULL match rule |
599 | int count = 0; _operands.reset(); |
600 | OperandForm *cur; |
601 | for( ; (cur = (OperandForm*)_operands.iter()) != NULL__null; ) { |
602 | if (cur->_matrule != NULL__null) ++count; |
603 | }; |
604 | return count; |
605 | } |
606 | |
607 | // Count number of OpClassForms defined |
608 | int ArchDesc::opclassFormCount() { |
609 | // Only interested in ones with non-NULL match rule |
610 | int count = 0; _operands.reset(); |
611 | OpClassForm *cur; |
612 | for( ; (cur = (OpClassForm*)_opclass.iter()) != NULL__null; ) { |
Although the value stored to 'cur' is used in the enclosing expression, the value is never actually read from 'cur' | |
613 | ++count; |
614 | }; |
615 | return count; |
616 | } |
617 | |
618 | // Count number of InstructForms defined |
619 | int ArchDesc::instructFormCount() { |
620 | // Only interested in ones with non-NULL match rule |
621 | int count = 0; _instructions.reset(); |
622 | InstructForm *cur; |
623 | for( ; (cur = (InstructForm*)_instructions.iter()) != NULL__null; ) { |
624 | if (cur->_matrule != NULL__null) ++count; |
625 | }; |
626 | return count; |
627 | } |
628 | |
629 | |
630 | //------------------------------get_preproc_def-------------------------------- |
631 | // Return the textual binding for a given CPP flag name. |
632 | // Return NULL if there is no binding, or it has been #undef-ed. |
633 | char* ArchDesc::get_preproc_def(const char* flag) { |
634 | // In case of syntax errors, flag may take the value NULL. |
635 | SourceForm* deff = NULL__null; |
636 | if (flag != NULL__null) |
637 | deff = (SourceForm*) _preproc_table[flag]; |
638 | return (deff == NULL__null) ? NULL__null : deff->_code; |
639 | } |
640 | |
641 | |
642 | //------------------------------set_preproc_def-------------------------------- |
643 | // Change or create a textual binding for a given CPP flag name. |
644 | // Giving NULL means the flag name is to be #undef-ed. |
645 | // In any case, _preproc_list collects all names either #defined or #undef-ed. |
646 | void ArchDesc::set_preproc_def(const char* flag, const char* def) { |
647 | SourceForm* deff = (SourceForm*) _preproc_table[flag]; |
648 | if (deff == NULL__null) { |
649 | deff = new SourceForm(NULL__null); |
650 | _preproc_table.Insert(flag, deff); |
651 | _preproc_list.addName(flag); // this supports iteration |
652 | } |
653 | deff->_code = (char*) def; |
654 | } |
655 | |
656 | |
657 | bool ArchDesc::verify() { |
658 | |
659 | if (_register) |
660 | assert( _register->verify(), "Register declarations failed verification"){ if (!(_register->verify())) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 660, "Register declarations failed verification"); abort(); }}; |
661 | if (!_quiet_mode) |
662 | fprintf(stderrstderr,"\n"); |
663 | // fprintf(stderr,"---------------------------- Verify Operands ---------------\n"); |
664 | // _operands.verify(); |
665 | // fprintf(stderr,"\n"); |
666 | // fprintf(stderr,"---------------------------- Verify Operand Classes --------\n"); |
667 | // _opclass.verify(); |
668 | // fprintf(stderr,"\n"); |
669 | // fprintf(stderr,"---------------------------- Verify Attributes ------------\n"); |
670 | // _attributes.verify(); |
671 | // fprintf(stderr,"\n"); |
672 | if (!_quiet_mode) |
673 | fprintf(stderrstderr,"---------------------------- Verify Instructions ----------------------------\n"); |
674 | _instructions.verify(); |
675 | if (!_quiet_mode) |
676 | fprintf(stderrstderr,"\n"); |
677 | // if ( _encode ) { |
678 | // fprintf(stderr,"---------------------------- Verify Encodings --------------\n"); |
679 | // _encode->verify(); |
680 | // } |
681 | |
682 | //if (_pipeline) _pipeline->verify(); |
683 | |
684 | return true; |
685 | } |
686 | |
687 | |
688 | void ArchDesc::dump() { |
689 | _pre_header.dump(); |
690 | _header.dump(); |
691 | _source.dump(); |
692 | if (_register) _register->dump(); |
693 | fprintf(stderrstderr,"\n"); |
694 | fprintf(stderrstderr,"------------------ Dump Operands ---------------------\n"); |
695 | _operands.dump(); |
696 | fprintf(stderrstderr,"\n"); |
697 | fprintf(stderrstderr,"------------------ Dump Operand Classes --------------\n"); |
698 | _opclass.dump(); |
699 | fprintf(stderrstderr,"\n"); |
700 | fprintf(stderrstderr,"------------------ Dump Attributes ------------------\n"); |
701 | _attributes.dump(); |
702 | fprintf(stderrstderr,"\n"); |
703 | fprintf(stderrstderr,"------------------ Dump Instructions -----------------\n"); |
704 | _instructions.dump(); |
705 | if ( _encode ) { |
706 | fprintf(stderrstderr,"------------------ Dump Encodings --------------------\n"); |
707 | _encode->dump(); |
708 | } |
709 | if (_pipeline) _pipeline->dump(); |
710 | } |
711 | |
712 | |
713 | //------------------------------init_keywords---------------------------------- |
714 | // Load the kewords into the global name table |
715 | void ArchDesc::initKeywords(FormDict& names) { |
716 | // Insert keyword strings into Global Name Table. Keywords have a NULL value |
717 | // field for quick easy identification when checking identifiers. |
718 | names.Insert("instruct", NULL__null); |
719 | names.Insert("operand", NULL__null); |
720 | names.Insert("attribute", NULL__null); |
721 | names.Insert("source", NULL__null); |
722 | names.Insert("register", NULL__null); |
723 | names.Insert("pipeline", NULL__null); |
724 | names.Insert("constraint", NULL__null); |
725 | names.Insert("predicate", NULL__null); |
726 | names.Insert("encode", NULL__null); |
727 | names.Insert("enc_class", NULL__null); |
728 | names.Insert("interface", NULL__null); |
729 | names.Insert("opcode", NULL__null); |
730 | names.Insert("ins_encode", NULL__null); |
731 | names.Insert("match", NULL__null); |
732 | names.Insert("effect", NULL__null); |
733 | names.Insert("expand", NULL__null); |
734 | names.Insert("rewrite", NULL__null); |
735 | names.Insert("reg_def", NULL__null); |
736 | names.Insert("reg_class", NULL__null); |
737 | names.Insert("alloc_class", NULL__null); |
738 | names.Insert("resource", NULL__null); |
739 | names.Insert("pipe_class", NULL__null); |
740 | names.Insert("pipe_desc", NULL__null); |
741 | } |
742 | |
743 | |
744 | //------------------------------internal_err---------------------------------- |
745 | // Issue a parser error message, and skip to the end of the current line |
746 | void ArchDesc::internal_err(const char *fmt, ...) { |
747 | va_list args; |
748 | |
749 | va_start(args, fmt)__builtin_va_start(args, fmt); |
750 | _internal_errs += emit_msg(0, INTERNAL_ERR3, 0, fmt, args); |
751 | va_end(args)__builtin_va_end(args); |
752 | |
753 | _no_output = 1; |
754 | } |
755 | |
756 | //------------------------------syntax_err---------------------------------- |
757 | // Issue a parser error message, and skip to the end of the current line |
758 | void ArchDesc::syntax_err(int lineno, const char *fmt, ...) { |
759 | va_list args; |
760 | |
761 | va_start(args, fmt)__builtin_va_start(args, fmt); |
762 | _internal_errs += emit_msg(0, SYNERR1, lineno, fmt, args); |
763 | va_end(args)__builtin_va_end(args); |
764 | |
765 | _no_output = 1; |
766 | } |
767 | |
768 | //------------------------------emit_msg--------------------------------------- |
769 | // Emit a user message, typically a warning or error |
770 | int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt, |
771 | va_list args) { |
772 | static int last_lineno = -1; |
773 | int i; |
774 | const char *pref; |
775 | |
776 | switch(flag) { |
777 | case 0: pref = "Warning: "; break; |
778 | case 1: pref = "Syntax Error: "; break; |
779 | case 2: pref = "Semantic Error: "; break; |
780 | case 3: pref = "Internal Error: "; break; |
781 | default: assert(0, ""){ if (!(0)) { fprintf(stderr, "assert fails %s %d: %s\n", "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 781, ""); abort(); }}; break; |
782 | } |
783 | |
784 | if (line == last_lineno) return 0; |
785 | last_lineno = line; |
786 | |
787 | if (!quiet) { /* no output if in quiet mode */ |
788 | i = fprintf(errfile, "%s(%d) ", _ADL_file._name, line); |
789 | while (i++ <= 15) fputc(' ', errfile); |
790 | fprintf(errfile, "%-8s:", pref); |
791 | vfprintf(errfile, fmt, args); |
792 | fprintf(errfile, "\n"); |
793 | fflush(errfile); |
794 | } |
795 | return 1; |
796 | } |
797 | |
798 | |
799 | // --------------------------------------------------------------------------- |
800 | //--------Utilities to build mappings for machine registers ------------------ |
801 | // --------------------------------------------------------------------------- |
802 | |
803 | // Construct the name of the register mask. |
804 | static const char *getRegMask(const char *reg_class_name) { |
805 | if( reg_class_name == NULL__null ) return "RegMask::Empty"; |
806 | |
807 | if (strcmp(reg_class_name,"Universe")==0) { |
808 | return "RegMask::Empty"; |
809 | } else if (strcmp(reg_class_name,"stack_slots")==0) { |
810 | return "(Compile::current()->FIRST_STACK_mask())"; |
811 | } else if (strcmp(reg_class_name, "dynamic")==0) { |
812 | return "*_opnds[0]->in_RegMask(0)"; |
813 | } else { |
814 | char *rc_name = toUpper(reg_class_name); |
815 | const char *mask = "_mask"; |
816 | int length = (int)strlen(rc_name) + (int)strlen(mask) + 5; |
817 | char *regMask = new char[length]; |
818 | sprintf(regMask,"%s%s()", rc_name, mask); |
819 | delete[] rc_name; |
820 | return regMask; |
821 | } |
822 | } |
823 | |
824 | // Convert a register class name to its register mask. |
825 | const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) { |
826 | const char *reg_mask = "RegMask::Empty"; |
827 | |
828 | if( _register ) { |
829 | RegClass *reg_class = _register->getRegClass(rc_name); |
830 | if (reg_class == NULL__null) { |
831 | syntax_err(0, "Use of an undefined register class %s", rc_name); |
832 | return reg_mask; |
833 | } |
834 | |
835 | // Construct the name of the register mask. |
836 | reg_mask = getRegMask(rc_name); |
837 | } |
838 | |
839 | return reg_mask; |
840 | } |
841 | |
842 | |
843 | // Obtain the name of the RegMask for an OperandForm |
844 | const char *ArchDesc::reg_mask(OperandForm &opForm) { |
845 | const char *regMask = "RegMask::Empty"; |
846 | |
847 | // Check constraints on result's register class |
848 | const char *result_class = opForm.constrained_reg_class(); |
849 | if (result_class == NULL__null) { |
850 | opForm.dump(); |
851 | syntax_err(opForm._linenum, |
852 | "Use of an undefined result class for operand: %s", |
853 | opForm._ident); |
854 | abort(); |
855 | } |
856 | |
857 | regMask = reg_class_to_reg_mask( result_class ); |
858 | |
859 | return regMask; |
860 | } |
861 | |
862 | // Obtain the name of the RegMask for an InstructForm |
863 | const char *ArchDesc::reg_mask(InstructForm &inForm) { |
864 | const char *result = inForm.reduce_result(); |
865 | |
866 | if (result == NULL__null) { |
867 | syntax_err(inForm._linenum, |
868 | "Did not find result operand or RegMask" |
869 | " for this instruction: %s", |
870 | inForm._ident); |
871 | abort(); |
872 | } |
873 | |
874 | // Instructions producing 'Universe' use RegMask::Empty |
875 | if (strcmp(result,"Universe") == 0) { |
876 | return "RegMask::Empty"; |
877 | } |
878 | |
879 | // Lookup this result operand and get its register class |
880 | Form *form = (Form*)_globalNames[result]; |
881 | if (form == NULL__null) { |
882 | syntax_err(inForm._linenum, |
883 | "Did not find result operand for result: %s", result); |
884 | abort(); |
885 | } |
886 | OperandForm *oper = form->is_operand(); |
887 | if (oper == NULL__null) { |
888 | syntax_err(inForm._linenum, "Form is not an OperandForm:"); |
889 | form->dump(); |
890 | abort(); |
891 | } |
892 | return reg_mask( *oper ); |
893 | } |
894 | |
895 | |
896 | // Obtain the STACK_OR_reg_mask name for an OperandForm |
897 | char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) { |
898 | // name of cisc_spillable version |
899 | const char *reg_mask_name = reg_mask(opForm); |
900 | |
901 | if (reg_mask_name == NULL__null) { |
902 | syntax_err(opForm._linenum, |
903 | "Did not find reg_mask for opForm: %s", |
904 | opForm._ident); |
905 | abort(); |
906 | } |
907 | |
908 | const char *stack_or = "STACK_OR_"; |
909 | int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1; |
910 | char *result = new char[length]; |
911 | sprintf(result,"%s%s", stack_or, reg_mask_name); |
912 | |
913 | return result; |
914 | } |
915 | |
916 | // Record that the register class must generate a stack_or_reg_mask |
917 | void ArchDesc::set_stack_or_reg(const char *reg_class_name) { |
918 | if( _register ) { |
919 | RegClass *reg_class = _register->getRegClass(reg_class_name); |
920 | reg_class->set_stack_version(true); |
921 | } |
922 | } |
923 | |
924 | |
925 | // Return the type signature for the ideal operation |
926 | const char *ArchDesc::getIdealType(const char *idealOp) { |
927 | // Find last character in idealOp, it specifies the type |
928 | char last_char = 0; |
929 | const char *ptr = idealOp; |
930 | for (; *ptr != '\0'; ++ptr) { |
931 | last_char = *ptr; |
932 | } |
933 | |
934 | // Match Vector types. |
935 | if (strncmp(idealOp, "Vec",3)==0) { |
936 | switch(last_char) { |
937 | case 'A': return "TypeVect::VECTA"; |
938 | case 'S': return "TypeVect::VECTS"; |
939 | case 'D': return "TypeVect::VECTD"; |
940 | case 'X': return "TypeVect::VECTX"; |
941 | case 'Y': return "TypeVect::VECTY"; |
942 | case 'Z': return "TypeVect::VECTZ"; |
943 | default: |
944 | internal_err("Vector type %s with unrecognized type\n",idealOp); |
945 | } |
946 | } |
947 | |
948 | if (strncmp(idealOp, "RegVectMask", 8) == 0) { |
949 | return "TypeVect::VECTMASK"; |
950 | } |
951 | |
952 | // !!!!! |
953 | switch(last_char) { |
954 | case 'I': return "TypeInt::INT"; |
955 | case 'P': return "TypePtr::BOTTOM"; |
956 | case 'N': return "TypeNarrowOop::BOTTOM"; |
957 | case 'F': return "Type::FLOAT"; |
958 | case 'D': return "Type::DOUBLE"; |
959 | case 'L': return "TypeLong::LONG"; |
960 | case 's': return "TypeInt::CC /*flags*/"; |
961 | default: |
962 | return NULL__null; |
963 | // !!!!! |
964 | // internal_err("Ideal type %s with unrecognized type\n",idealOp); |
965 | break; |
966 | } |
967 | |
968 | return NULL__null; |
969 | } |
970 | |
971 | |
972 | |
973 | OperandForm *ArchDesc::constructOperand(const char *ident, |
974 | bool ideal_only) { |
975 | OperandForm *opForm = new OperandForm(ident, ideal_only); |
976 | _globalNames.Insert(ident, opForm); |
977 | addForm(opForm); |
978 | |
979 | return opForm; |
980 | } |
981 | |
982 | |
983 | // Import predefined base types: Set = 1, RegI, RegP, ... |
984 | void ArchDesc::initBaseOpTypes() { |
985 | // Create OperandForm and assign type for each opcode. |
986 | for (int i = 1; i < _last_machine_leaf; ++i) { |
987 | char *ident = (char *)NodeClassNames[i]; |
988 | constructOperand(ident, true); |
989 | } |
990 | // Create InstructForm and assign type for each ideal instruction. |
991 | for (int j = _last_machine_leaf+1; j < _last_opcode; ++j) { |
992 | char *ident = (char *)NodeClassNames[j]; |
993 | if (!strcmp(ident, "ConI") || !strcmp(ident, "ConP") || |
994 | !strcmp(ident, "ConN") || !strcmp(ident, "ConNKlass") || |
995 | !strcmp(ident, "ConF") || !strcmp(ident, "ConD") || |
996 | !strcmp(ident, "ConL") || !strcmp(ident, "Con" ) || |
997 | !strcmp(ident, "Bool")) { |
998 | constructOperand(ident, true); |
999 | } else { |
1000 | InstructForm *insForm = new InstructForm(ident, true); |
1001 | // insForm->_opcode = nextUserOpType(ident); |
1002 | _globalNames.Insert(ident, insForm); |
1003 | addForm(insForm); |
1004 | } |
1005 | } |
1006 | |
1007 | { OperandForm *opForm; |
1008 | // Create operand type "Universe" for return instructions. |
1009 | const char *ident = "Universe"; |
1010 | opForm = constructOperand(ident, false); |
1011 | |
1012 | // Create operand type "label" for branch targets |
1013 | ident = "label"; |
1014 | opForm = constructOperand(ident, false); |
1015 | |
1016 | // !!!!! Update - when adding a new sReg/stackSlot type |
1017 | // Create operand types "sReg[IPFDL]" for stack slot registers |
1018 | opForm = constructOperand("sRegI", false); |
1019 | opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots"); |
1020 | opForm = constructOperand("sRegP", false); |
1021 | opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots"); |
1022 | opForm = constructOperand("sRegF", false); |
1023 | opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots"); |
1024 | opForm = constructOperand("sRegD", false); |
1025 | opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots"); |
1026 | opForm = constructOperand("sRegL", false); |
1027 | opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots"); |
1028 | |
1029 | // Create operand type "method" for call targets |
1030 | ident = "method"; |
1031 | opForm = constructOperand(ident, false); |
1032 | } |
1033 | |
1034 | // Create Effect Forms for each of the legal effects |
1035 | // USE, DEF, USE_DEF, KILL, USE_KILL |
1036 | { |
1037 | const char *ident = "USE"; |
1038 | Effect *eForm = new Effect(ident); |
1039 | _globalNames.Insert(ident, eForm); |
1040 | ident = "DEF"; |
1041 | eForm = new Effect(ident); |
1042 | _globalNames.Insert(ident, eForm); |
1043 | ident = "USE_DEF"; |
1044 | eForm = new Effect(ident); |
1045 | _globalNames.Insert(ident, eForm); |
1046 | ident = "KILL"; |
1047 | eForm = new Effect(ident); |
1048 | _globalNames.Insert(ident, eForm); |
1049 | ident = "USE_KILL"; |
1050 | eForm = new Effect(ident); |
1051 | _globalNames.Insert(ident, eForm); |
1052 | ident = "TEMP"; |
1053 | eForm = new Effect(ident); |
1054 | _globalNames.Insert(ident, eForm); |
1055 | ident = "TEMP_DEF"; |
1056 | eForm = new Effect(ident); |
1057 | _globalNames.Insert(ident, eForm); |
1058 | ident = "CALL"; |
1059 | eForm = new Effect(ident); |
1060 | _globalNames.Insert(ident, eForm); |
1061 | } |
1062 | |
1063 | // |
1064 | // Build mapping from ideal names to ideal indices |
1065 | int idealIndex = 0; |
1066 | for (idealIndex = 1; idealIndex < _last_machine_leaf; ++idealIndex) { |
1067 | const char *idealName = NodeClassNames[idealIndex]; |
1068 | _idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex); |
1069 | } |
1070 | for (idealIndex = _last_machine_leaf+1; |
1071 | idealIndex < _last_opcode; ++idealIndex) { |
1072 | const char *idealName = NodeClassNames[idealIndex]; |
1073 | _idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex); |
1074 | } |
1075 | |
1076 | } |
1077 | |
1078 | |
1079 | //---------------------------addSUNcopyright------------------------------- |
1080 | // output SUN copyright info |
1081 | void ArchDesc::addSunCopyright(char* legal, int size, FILE *fp) { |
1082 | size_t count = fwrite(legal, 1, size, fp); |
1083 | assert(count == (size_t) size, "copyright info truncated"){ if (!(count == (size_t) size)) { fprintf(stderr, "assert fails %s %d: %s\n" , "/home/daniel/Projects/java/jdk/src/hotspot/share/adlc/archDesc.cpp" , 1083, "copyright info truncated"); abort(); }}; |
1084 | fprintf(fp,"\n"); |
1085 | fprintf(fp,"// Machine Generated File. Do Not Edit!\n"); |
1086 | fprintf(fp,"\n"); |
1087 | } |
1088 | |
1089 | |
1090 | //---------------------------addIncludeGuardStart-------------------------- |
1091 | // output the start of an include guard. |
1092 | void ArchDesc::addIncludeGuardStart(ADLFILE &adlfile, const char* guardString) { |
1093 | // Build #include lines |
1094 | fprintf(adlfile._fp, "\n"); |
1095 | fprintf(adlfile._fp, "#ifndef %s\n", guardString); |
1096 | fprintf(adlfile._fp, "#define %s\n", guardString); |
1097 | fprintf(adlfile._fp, "\n"); |
1098 | |
1099 | } |
1100 | |
1101 | //---------------------------addIncludeGuardEnd-------------------------- |
1102 | // output the end of an include guard. |
1103 | void ArchDesc::addIncludeGuardEnd(ADLFILE &adlfile, const char* guardString) { |
1104 | // Build #include lines |
1105 | fprintf(adlfile._fp, "\n"); |
1106 | fprintf(adlfile._fp, "#endif // %s\n", guardString); |
1107 | |
1108 | } |
1109 | |
1110 | //---------------------------addInclude-------------------------- |
1111 | // output the #include line for this file. |
1112 | void ArchDesc::addInclude(ADLFILE &adlfile, const char* fileName) { |
1113 | fprintf(adlfile._fp, "#include \"%s\"\n", fileName); |
1114 | |
1115 | } |
1116 | |
1117 | void ArchDesc::addInclude(ADLFILE &adlfile, const char* includeDir, const char* fileName) { |
1118 | fprintf(adlfile._fp, "#include \"%s/%s\"\n", includeDir, fileName); |
1119 | |
1120 | } |
1121 | |
1122 | //---------------------------addPreprocessorChecks----------------------------- |
1123 | // Output C preprocessor code to verify the backend compilation environment. |
1124 | // The idea is to force code produced by "adlc -DHS64" to be compiled by a |
1125 | // command of the form "CC ... -DHS64 ...", so that any #ifdefs in the source |
1126 | // blocks select C code that is consistent with adlc's selections of AD code. |
1127 | void ArchDesc::addPreprocessorChecks(FILE *fp) { |
1128 | const char* flag; |
1129 | _preproc_list.reset(); |
1130 | if (_preproc_list.count() > 0 && !_preproc_list.current_is_signal()) { |
1131 | fprintf(fp, "// Check consistency of C++ compilation with ADLC options:\n"); |
1132 | } |
1133 | for (_preproc_list.reset(); (flag = _preproc_list.iter()) != NULL__null; ) { |
1134 | if (_preproc_list.current_is_signal()) break; |
1135 | char* def = get_preproc_def(flag); |
1136 | fprintf(fp, "// Check adlc "); |
1137 | if (def) |
1138 | fprintf(fp, "-D%s=%s\n", flag, def); |
1139 | else fprintf(fp, "-U%s\n", flag); |
1140 | fprintf(fp, "#%s %s\n", |
1141 | def ? "ifndef" : "ifdef", flag); |
1142 | fprintf(fp, "# error \"%s %s be defined\"\n", |
1143 | flag, def ? "must" : "must not"); |
1144 | fprintf(fp, "#endif // %s\n", flag); |
1145 | } |
1146 | } |
1147 | |
1148 | |
1149 | // Convert operand name into enum name |
1150 | const char *ArchDesc::machOperEnum(const char *opName) { |
1151 | return ArchDesc::getMachOperEnum(opName); |
1152 | } |
1153 | |
1154 | // Convert operand name into enum name |
1155 | const char *ArchDesc::getMachOperEnum(const char *opName) { |
1156 | return (opName ? toUpper(opName) : opName); |
1157 | } |
1158 | |
1159 | //---------------------------buildMustCloneMap----------------------------- |
1160 | // Flag cases when machine needs cloned values or instructions |
1161 | void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) { |
1162 | // Build external declarations for mappings |
1163 | fprintf(fp_hpp, "// Mapping from machine-independent opcode to boolean\n"); |
1164 | fprintf(fp_hpp, "// Flag cases where machine needs cloned values or instructions\n"); |
1165 | fprintf(fp_hpp, "extern const char must_clone[];\n"); |
1166 | fprintf(fp_hpp, "\n"); |
1167 | |
1168 | // Build mapping from ideal names to ideal indices |
1169 | fprintf(fp_cpp, "\n"); |
1170 | fprintf(fp_cpp, "// Mapping from machine-independent opcode to boolean\n"); |
1171 | fprintf(fp_cpp, "const char must_clone[] = {\n"); |
1172 | for (int idealIndex = 0; idealIndex < _last_opcode; ++idealIndex) { |
1173 | int must_clone = 0; |
1174 | const char *idealName = NodeClassNames[idealIndex]; |
1175 | // Previously selected constants for cloning |
1176 | // !!!!! |
1177 | // These are the current machine-dependent clones |
1178 | if ( strcmp(idealName,"CmpI") == 0 |
1179 | || strcmp(idealName,"CmpU") == 0 |
1180 | || strcmp(idealName,"CmpP") == 0 |
1181 | || strcmp(idealName,"CmpN") == 0 |
1182 | || strcmp(idealName,"CmpL") == 0 |
1183 | || strcmp(idealName,"CmpUL") == 0 |
1184 | || strcmp(idealName,"CmpD") == 0 |
1185 | || strcmp(idealName,"CmpF") == 0 |
1186 | || strcmp(idealName,"FastLock") == 0 |
1187 | || strcmp(idealName,"FastUnlock") == 0 |
1188 | || strcmp(idealName,"OverflowAddI") == 0 |
1189 | || strcmp(idealName,"OverflowAddL") == 0 |
1190 | || strcmp(idealName,"OverflowSubI") == 0 |
1191 | || strcmp(idealName,"OverflowSubL") == 0 |
1192 | || strcmp(idealName,"OverflowMulI") == 0 |
1193 | || strcmp(idealName,"OverflowMulL") == 0 |
1194 | || strcmp(idealName,"Bool") == 0 |
1195 | || strcmp(idealName,"Binary") == 0 ) { |
1196 | // Removed ConI from the must_clone list. CPUs that cannot use |
1197 | // large constants as immediates manifest the constant as an |
1198 | // instruction. The must_clone flag prevents the constant from |
1199 | // floating up out of loops. |
1200 | must_clone = 1; |
1201 | } |
1202 | fprintf(fp_cpp, " %d%s // %s: %d\n", must_clone, |
1203 | (idealIndex != (_last_opcode - 1)) ? "," : " // no trailing comma", |
1204 | idealName, idealIndex); |
1205 | } |
1206 | // Finish defining table |
1207 | fprintf(fp_cpp, "};\n"); |
1208 | } |