1 #ifdef USE_PRAGMA_IDENT_SRC 2 #pragma ident "@(#)adlparse.cpp 1.205 07/05/05 17:05:00 JVM" 3 #endif 4 /* 5 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 23 * CA 95054 USA or visit www.sun.com if you need additional information or 24 * have any questions. 25 * 26 */ 27 28 // ADLPARSE.CPP - Architecture Description Language Parser 29 // Authors: Chris Vick and Mike Paleczny 30 #include "adlc.hpp" 31 32 //----------------------------ADLParser---------------------------------------- 33 // Create a new ADL parser 34 ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc) 35 : _buf(buffer), _AD(archDesc), 36 _globalNames(archDesc.globalNames()) { 37 _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file 38 _AD._warnings = 0; // No warnings either 39 _linenum = 0; // Will increment to first line 40 _curline = _ptr = NULL; // No pointers into buffer yet 41 42 _preproc_depth = 0; 43 _preproc_not_taken = 0; 44 45 // Delimit command-line definitions from in-file definitions: 46 _AD._preproc_list.add_signal(); 47 } 48 49 //------------------------------~ADLParser------------------------------------- 50 // Delete an ADL parser. 51 ADLParser::~ADLParser() { 52 if (!_AD._quiet_mode) 53 fprintf(stderr,"---------------------------- Errors and Warnings ----------------------------\n"); 54 #ifndef ASSERT 55 fprintf(stderr, "**************************************************************\n"); 56 fprintf(stderr, "***** WARNING: ASSERT is undefined, assertions disabled. *****\n"); 57 fprintf(stderr, "**************************************************************\n"); 58 #endif 59 if( _AD._syntax_errs + _AD._semantic_errs + _AD._warnings == 0 ) { 60 if (!_AD._quiet_mode) 61 fprintf(stderr,"No errors or warnings to report from phase-1 parse.\n" ); 62 } 63 else { 64 if( _AD._syntax_errs ) { // Any syntax errors? 65 fprintf(stderr,"%s: Found %d syntax error", _buf._fp->_name, _AD._syntax_errs); 66 if( _AD._syntax_errs > 1 ) fprintf(stderr,"s.\n\n"); 67 else fprintf(stderr,".\n\n"); 68 } 69 if( _AD._semantic_errs ) { // Any semantic errors? 70 fprintf(stderr,"%s: Found %d semantic error", _buf._fp->_name, _AD._semantic_errs); 71 if( _AD._semantic_errs > 1 ) fprintf(stderr,"s.\n\n"); 72 else fprintf(stderr,".\n\n"); 73 } 74 if( _AD._warnings ) { // Any warnings? 75 fprintf(stderr,"%s: Found %d warning", _buf._fp->_name, _AD._warnings); 76 if( _AD._warnings > 1 ) fprintf(stderr,"s.\n\n"); 77 else fprintf(stderr,".\n\n"); 78 } 79 } 80 if (!_AD._quiet_mode) 81 fprintf(stderr,"-----------------------------------------------------------------------------\n"); 82 _AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine 83 84 // Write out information we have stored 85 // // UNIXism == fsync(stderr); 86 } 87 88 //------------------------------parse------------------------------------------ 89 // Each top-level keyword should appear as the first non-whitespace on a line. 90 // 91 void ADLParser::parse() { 92 char *ident; 93 94 // Iterate over the lines in the file buffer parsing Level 1 objects 95 for( next_line(); _curline != NULL; next_line()) { 96 _ptr = _curline; // Reset ptr to start of new line 97 skipws(); // Skip any leading whitespace 98 ident = get_ident(); // Get first token 99 if (ident == NULL) { // Empty line 100 continue; // Get the next line 101 } 102 if (!strcmp(ident, "instruct")) instr_parse(); 103 else if (!strcmp(ident, "operand")) oper_parse(); 104 else if (!strcmp(ident, "opclass")) opclass_parse(); 105 else if (!strcmp(ident, "ins_attrib")) ins_attr_parse(); 106 else if (!strcmp(ident, "op_attrib")) op_attr_parse(); 107 else if (!strcmp(ident, "source")) source_parse(); 108 else if (!strcmp(ident, "source_hpp")) source_hpp_parse(); 109 else if (!strcmp(ident, "register")) reg_parse(); 110 else if (!strcmp(ident, "frame")) frame_parse(); 111 else if (!strcmp(ident, "encode")) encode_parse(); 112 else if (!strcmp(ident, "pipeline")) pipe_parse(); 113 else if (!strcmp(ident, "definitions")) definitions_parse(); 114 else if (!strcmp(ident, "peephole")) peep_parse(); 115 else if (!strcmp(ident, "#define")) preproc_define(); 116 else if (!strcmp(ident, "#undef")) preproc_undef(); 117 else { 118 parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n Found %s",ident); 119 } 120 } 121 122 // Done with parsing, check consistency. 123 124 if (_preproc_depth != 0) { 125 parse_err(SYNERR, "End of file inside #ifdef"); 126 } 127 128 // AttributeForms ins_cost and op_cost must be defined for default behaviour 129 if (_globalNames[AttributeForm::_ins_cost] == NULL) { 130 parse_err(SEMERR, "Did not declare 'ins_cost' attribute"); 131 } 132 if (_globalNames[AttributeForm::_ins_pc_relative] == NULL) { 133 parse_err(SEMERR, "Did not declare 'ins_pc_relative' attribute"); 134 } 135 if (_globalNames[AttributeForm::_op_cost] == NULL) { 136 parse_err(SEMERR, "Did not declare 'op_cost' attribute"); 137 } 138 } 139 140 // ******************** Private Level 1 Parse Functions ******************** 141 //------------------------------instr_parse------------------------------------ 142 // Parse the contents of an instruction definition, build the InstructForm to 143 // represent that instruction, and add it to the InstructForm list. 144 void ADLParser::instr_parse(void) { 145 char *ident; 146 InstructForm *instr; 147 MatchRule *rule; 148 int match_rules_cnt = 0; 149 150 // First get the name of the instruction 151 if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL ) 152 return; 153 instr = new InstructForm(ident); // Create new instruction form 154 instr->_linenum = _linenum; 155 _globalNames.Insert(ident, instr); // Add name to the name table 156 // Debugging Stuff 157 if (_AD._adl_debug > 1) 158 fprintf(stderr,"Parsing Instruction Form %s\n", ident); 159 160 // Then get the operands 161 skipws(); 162 if (_curchar != '(') { 163 parse_err(SYNERR, "missing '(' in instruct definition\n"); 164 } 165 // Parse the operand list 166 else get_oplist(instr->_parameters, instr->_localNames); 167 skipws(); // Skip leading whitespace 168 // Check for block delimiter 169 if ( (_curchar != '%') 170 || ( next_char(), (_curchar != '{')) ) { 171 parse_err(SYNERR, "missing '%{' in instruction definition\n"); 172 return; 173 } 174 next_char(); // Maintain the invariant 175 do { 176 ident = get_ident(); // Grab next identifier 177 if (ident == NULL) { 178 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 179 continue; 180 } 181 if (!strcmp(ident, "predicate")) instr->_predicate = pred_parse(); 182 else if (!strcmp(ident, "match")) { 183 // Allow one instruction have several match rules. 184 rule = instr->_matrule; 185 if (rule == NULL) { 186 // This is first match rule encountered 187 rule = match_parse(instr->_localNames); 188 if (rule) { 189 instr->_matrule = rule; 190 // Special case the treatment of Control instructions. 191 if( instr->is_ideal_control() ) { 192 // Control instructions return a special result, 'Universe' 193 rule->_result = "Universe"; 194 } 195 // Check for commutative operations with tree operands. 196 matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); 197 } 198 } else { 199 // Find the end of the match rule list 200 while (rule->_next != NULL) 201 rule = rule->_next; 202 // Add the new match rule to the list 203 rule->_next = match_parse(instr->_localNames); 204 if (rule->_next) { 205 rule = rule->_next; 206 if( instr->is_ideal_control() ) { 207 parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name); 208 return; 209 } 210 assert(match_rules_cnt < 100," too many match rule clones"); 211 char* buf = (char*) malloc(strlen(instr->_ident) + 4); 212 sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); 213 rule->_result = buf; 214 // Check for commutative operations with tree operands. 215 matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); 216 } 217 } 218 } 219 else if (!strcmp(ident, "encode")) { 220 parse_err(SYNERR, "Instructions specify ins_encode, not encode\n"); 221 } 222 else if (!strcmp(ident, "ins_encode")) 223 instr->_insencode = ins_encode_parse(*instr); 224 else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); 225 else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); 226 else if (!strcmp(ident, "effect")) effect_parse(instr); 227 else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); 228 else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); 229 else if (!strcmp(ident, "constraint")) { 230 parse_err(SYNERR, "Instructions do not specify a constraint\n"); 231 } 232 else if (!strcmp(ident, "construct")) { 233 parse_err(SYNERR, "Instructions do not specify a construct\n"); 234 } 235 else if (!strcmp(ident, "format")) instr->_format = format_parse(); 236 else if (!strcmp(ident, "interface")) { 237 parse_err(SYNERR, "Instructions do not specify an interface\n"); 238 } 239 else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr); 240 else { // Done with staticly defined parts of instruction definition 241 // Check identifier to see if it is the name of an attribute 242 const Form *form = _globalNames[ident]; 243 AttributeForm *attr = form ? form->is_attribute() : NULL; 244 if( attr && (attr->_atype == INS_ATTR) ) { 245 // Insert the new attribute into the linked list. 246 Attribute *temp = attr_parse(ident); 247 temp->_next = instr->_attribs; 248 instr->_attribs = temp; 249 } else { 250 parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident); 251 } 252 } 253 skipws(); 254 } while(_curchar != '%'); 255 next_char(); 256 if (_curchar != '}') { 257 parse_err(SYNERR, "missing '%}' in instruction definition\n"); 258 return; 259 } 260 // Check for "Set" form of chain rule 261 adjust_set_rule(instr); 262 if (_AD._pipeline ) { 263 if( instr->expands() ) { 264 if( instr->_ins_pipe ) 265 parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\"; ins_pipe will be unused\n", instr->_ident); 266 } else { 267 if( !instr->_ins_pipe ) 268 parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident); 269 } 270 } 271 // Add instruction to tail of instruction list 272 _AD.addForm(instr); 273 274 // Create instruction form for each additional match rule 275 rule = instr->_matrule; 276 if (rule != NULL) { 277 rule = rule->_next; 278 while (rule != NULL) { 279 ident = (char*)rule->_result; 280 InstructForm *clone = new InstructForm(ident, instr, rule); // Create new instruction form 281 _globalNames.Insert(ident, clone); // Add name to the name table 282 // Debugging Stuff 283 if (_AD._adl_debug > 1) 284 fprintf(stderr,"Parsing Instruction Form %s\n", ident); 285 // Check for "Set" form of chain rule 286 adjust_set_rule(clone); 287 // Add instruction to tail of instruction list 288 _AD.addForm(clone); 289 rule = rule->_next; 290 clone->_matrule->_next = NULL; // One match rule per clone 291 } 292 } 293 } 294 295 //------------------------------matchrule_clone_and_swap----------------------- 296 // Check for commutative operations with subtree operands, 297 // create clones and swap operands. 298 void ADLParser::matchrule_clone_and_swap(MatchRule* rule, const char* instr_ident, int& match_rules_cnt) { 299 // Check for commutative operations with tree operands. 300 int count = 0; 301 rule->count_commutative_op(count); 302 if (count > 0) { 303 // Clone match rule and swap commutative operation's operands. 304 rule->swap_commutative_op(instr_ident, count, match_rules_cnt); 305 } 306 } 307 308 //------------------------------adjust_set_rule-------------------------------- 309 // Check for "Set" form of chain rule 310 void ADLParser::adjust_set_rule(InstructForm *instr) { 311 if (instr->_matrule == NULL || instr->_matrule->_rChild == NULL) return; 312 const char *rch = instr->_matrule->_rChild->_opType; 313 const Form *frm = _globalNames[rch]; 314 if( (! strcmp(instr->_matrule->_opType,"Set")) && 315 frm && frm->is_operand() && (! frm->ideal_only()) ) { 316 // Previous implementation, which missed leaP*, but worked for loadCon* 317 unsigned position = 0; 318 const char *result = NULL; 319 const char *name = NULL; 320 const char *optype = NULL; 321 MatchNode *right = instr->_matrule->_rChild; 322 if (right->base_operand(position, _globalNames, result, name, optype)) { 323 position = 1; 324 const char *result2 = NULL; 325 const char *name2 = NULL; 326 const char *optype2 = NULL; 327 // Can not have additional base operands in right side of match! 328 if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) { 329 assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates"); 330 // Chain from input _ideal_operand_type_, 331 // Needed for shared roots of match-trees 332 ChainList *lst = (ChainList *)_AD._chainRules[optype]; 333 if (lst == NULL) { 334 lst = new ChainList(); 335 _AD._chainRules.Insert(optype, lst); 336 } 337 if (!lst->search(instr->_matrule->_lChild->_opType)) { 338 const char *cost = instr->cost(); 339 if (cost == NULL) { 340 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 341 } 342 // The ADLC does not support chaining from the ideal operand type 343 // of a predicated user-defined operand 344 if( frm->is_operand() == NULL || frm->is_operand()->_predicate == NULL ) { 345 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 346 } 347 } 348 // Chain from input _user_defined_operand_type_, 349 lst = (ChainList *)_AD._chainRules[result]; 350 if (lst == NULL) { 351 lst = new ChainList(); 352 _AD._chainRules.Insert(result, lst); 353 } 354 if (!lst->search(instr->_matrule->_lChild->_opType)) { 355 const char *cost = instr->cost(); 356 if (cost == NULL) { 357 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 358 } 359 // It is safe to chain from the top-level user-defined operand even 360 // if it has a predicate, since the predicate is checked before 361 // the user-defined type is available. 362 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 363 } 364 } else { 365 // May have instruction chain rule if root of right-tree is an ideal 366 OperandForm *rightOp = _globalNames[right->_opType]->is_operand(); 367 if( rightOp ) { 368 const Form *rightRoot = _globalNames[rightOp->_matrule->_opType]; 369 if( rightRoot && rightRoot->ideal_only() ) { 370 const char *chain_op = NULL; 371 if( rightRoot->is_instruction() ) 372 chain_op = rightOp->_ident; 373 if( chain_op ) { 374 // Look-up the operation in chain rule table 375 ChainList *lst = (ChainList *)_AD._chainRules[chain_op]; 376 if (lst == NULL) { 377 lst = new ChainList(); 378 _AD._chainRules.Insert(chain_op, lst); 379 } 380 // if (!lst->search(instr->_matrule->_lChild->_opType)) { 381 const char *cost = instr->cost(); 382 if (cost == NULL) { 383 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; 384 } 385 // This chains from a top-level operand whose predicate, if any, 386 // has been checked. 387 lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident); 388 // } 389 } 390 } 391 } 392 } // end chain rule from right-tree's ideal root 393 } 394 } 395 } 396 397 398 //------------------------------oper_parse------------------------------------- 399 void ADLParser::oper_parse(void) { 400 char *ident; 401 OperandForm *oper; 402 AttributeForm *attr; 403 MatchRule *rule; 404 405 // First get the name of the operand 406 skipws(); 407 if( (ident = get_unique_ident(_globalNames,"operand")) == NULL ) 408 return; 409 oper = new OperandForm(ident); // Create new operand form 410 oper->_linenum = _linenum; 411 _globalNames.Insert(ident, oper); // Add name to the name table 412 413 // Debugging Stuff 414 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Operand Form %s\n", ident); 415 416 // Get the component operands 417 skipws(); 418 if (_curchar != '(') { 419 parse_err(SYNERR, "missing '(' in operand definition\n"); 420 return; 421 } 422 else get_oplist(oper->_parameters, oper->_localNames); // Parse the component operand list 423 skipws(); 424 // Check for block delimiter 425 if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block 426 parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); 427 return; 428 } 429 next_char(); next_char(); // Skip over "%{" symbol 430 do { 431 ident = get_ident(); // Grab next identifier 432 if (ident == NULL) { 433 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 434 continue; 435 } 436 if (!strcmp(ident, "predicate")) oper->_predicate = pred_parse(); 437 else if (!strcmp(ident, "match")) { 438 // Find the end of the match rule list 439 rule = oper->_matrule; 440 if (rule) { 441 while (rule->_next) rule = rule->_next; 442 // Add the new match rule to the list 443 rule->_next = match_parse(oper->_localNames); 444 if (rule->_next) { 445 rule->_next->_result = oper->_ident; 446 } 447 } 448 else { 449 // This is first match rule encountered 450 oper->_matrule = match_parse(oper->_localNames); 451 if (oper->_matrule) { 452 oper->_matrule->_result = oper->_ident; 453 } 454 } 455 } 456 else if (!strcmp(ident, "encode")) oper->_interface = interface_parse(); 457 else if (!strcmp(ident, "ins_encode")) { 458 parse_err(SYNERR, "Operands specify 'encode', not 'ins_encode'\n"); 459 } 460 else if (!strcmp(ident, "opcode")) { 461 parse_err(SYNERR, "Operands do not specify an opcode\n"); 462 } 463 else if (!strcmp(ident, "effect")) { 464 parse_err(SYNERR, "Operands do not specify an effect\n"); 465 } 466 else if (!strcmp(ident, "expand")) { 467 parse_err(SYNERR, "Operands do not specify an expand\n"); 468 } 469 else if (!strcmp(ident, "rewrite")) { 470 parse_err(SYNERR, "Operands do not specify a rewrite\n"); 471 } 472 else if (!strcmp(ident, "constraint"))oper->_constraint= constraint_parse(); 473 else if (!strcmp(ident, "construct")) oper->_construct = construct_parse(); 474 else if (!strcmp(ident, "format")) oper->_format = format_parse(); 475 else if (!strcmp(ident, "interface")) oper->_interface = interface_parse(); 476 // Check identifier to see if it is the name of an attribute 477 else if (((attr = _globalNames[ident]->is_attribute()) != NULL) && 478 (attr->_atype == OP_ATTR)) oper->_attribs = attr_parse(ident); 479 else { 480 parse_err(SYNERR, "expected one of - constraint, predicate, match, encode, format, construct, or the name of a defined operand attribute at %s\n", ident); 481 } 482 skipws(); 483 } while(_curchar != '%'); 484 next_char(); 485 if (_curchar != '}') { 486 parse_err(SYNERR, "missing '%}' in operand definition\n"); 487 return; 488 } 489 // Add operand to tail of operand list 490 _AD.addForm(oper); 491 } 492 493 //------------------------------opclass_parse---------------------------------- 494 // Operand Classes are a block with a comma delimited list of operand names 495 void ADLParser::opclass_parse(void) { 496 char *ident; 497 OpClassForm *opc; 498 OperandForm *opForm; 499 500 // First get the name of the operand class 501 skipws(); 502 if( (ident = get_unique_ident(_globalNames,"opclass")) == NULL ) 503 return; 504 opc = new OpClassForm(ident); // Create new operand class form 505 _globalNames.Insert(ident, opc); // Add name to the name table 506 507 // Debugging Stuff 508 if (_AD._adl_debug > 1) 509 fprintf(stderr,"Parsing Operand Class Form %s\n", ident); 510 511 // Get the list of operands 512 skipws(); 513 if (_curchar != '(') { 514 parse_err(SYNERR, "missing '(' in operand definition\n"); 515 return; 516 } 517 do { 518 next_char(); // Skip past open paren or comma 519 ident = get_ident(); // Grab next identifier 520 if (ident == NULL) { 521 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 522 continue; 523 } 524 // Check identifier to see if it is the name of an operand 525 const Form *form = _globalNames[ident]; 526 opForm = form ? form->is_operand() : NULL; 527 if ( opForm ) { 528 opc->_oplst.addName(ident); // Add operand to opclass list 529 opForm->_classes.addName(opc->_ident);// Add opclass to operand list 530 } 531 else { 532 parse_err(SYNERR, "expected name of a defined operand at %s\n", ident); 533 } 534 skipws(); // skip trailing whitespace 535 } while (_curchar == ','); // Check for the comma 536 // Check for closing ')' 537 if (_curchar != ')') { 538 parse_err(SYNERR, "missing ')' or ',' in opclass definition\n"); 539 return; 540 } 541 next_char(); // Consume the ')' 542 skipws(); 543 // Check for closing ';' 544 if (_curchar != ';') { 545 parse_err(SYNERR, "missing ';' in opclass definition\n"); 546 return; 547 } 548 next_char(); // Consume the ';' 549 // Add operand to tail of operand list 550 _AD.addForm(opc); 551 } 552 553 //------------------------------ins_attr_parse--------------------------------- 554 void ADLParser::ins_attr_parse(void) { 555 char *ident; 556 char *aexpr; 557 AttributeForm *attrib; 558 559 // get name for the instruction attribute 560 skipws(); // Skip leading whitespace 561 if( (ident = get_unique_ident(_globalNames,"inst_attrib")) == NULL ) 562 return; 563 // Debugging Stuff 564 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Ins_Attribute Form %s\n", ident); 565 566 // Get default value of the instruction attribute 567 skipws(); // Skip whitespace 568 if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) { 569 parse_err(SYNERR, "missing '(' in ins_attrib definition\n"); 570 return; 571 } 572 // Debug Stuff 573 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr); 574 575 // Check for terminator 576 if (_curchar != ';') { 577 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 578 return; 579 } 580 next_char(); // Advance past the ';' 581 582 // Construct the attribute, record global name, and store in ArchDesc 583 attrib = new AttributeForm(ident, INS_ATTR, aexpr); 584 _globalNames.Insert(ident, attrib); // Add name to the name table 585 _AD.addForm(attrib); 586 } 587 588 //------------------------------op_attr_parse---------------------------------- 589 void ADLParser::op_attr_parse(void) { 590 char *ident; 591 char *aexpr; 592 AttributeForm *attrib; 593 594 // get name for the operand attribute 595 skipws(); // Skip leading whitespace 596 if( (ident = get_unique_ident(_globalNames,"op_attrib")) == NULL ) 597 return; 598 // Debugging Stuff 599 if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Op_Attribute Form %s\n", ident); 600 601 // Get default value of the instruction attribute 602 skipws(); // Skip whitespace 603 if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) { 604 parse_err(SYNERR, "missing '(' in op_attrib definition\n"); 605 return; 606 } 607 // Debug Stuff 608 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr); 609 610 // Check for terminator 611 if (_curchar != ';') { 612 parse_err(SYNERR, "missing ';' in op_attrib definition\n"); 613 return; 614 } 615 next_char(); // Advance past the ';' 616 617 // Construct the attribute, record global name, and store in ArchDesc 618 attrib = new AttributeForm(ident, OP_ATTR, aexpr); 619 _globalNames.Insert(ident, attrib); 620 _AD.addForm(attrib); 621 } 622 623 //------------------------------definitions_parse----------------------------------- 624 void ADLParser::definitions_parse(void) { 625 skipws(); // Skip leading whitespace 626 if (_curchar == '%' && *(_ptr+1) == '{') { 627 next_char(); next_char(); // Skip "%{" 628 skipws(); 629 while (_curchar != '%' && *(_ptr+1) != '}') { 630 // Process each definition until finding closing string "%}" 631 char *token = get_ident(); 632 if (token == NULL) { 633 parse_err(SYNERR, "missing identifier inside definitions block.\n"); 634 return; 635 } 636 if (strcmp(token,"int_def")==0) { int_def_parse(); } 637 // if (strcmp(token,"str_def")==0) { str_def_parse(); } 638 skipws(); 639 } 640 } 641 else { 642 parse_err(SYNERR, "Missing %%{ ... %%} block after definitions keyword.\n"); 643 return; 644 } 645 } 646 647 //------------------------------int_def_parse---------------------------------- 648 // Parse Example: 649 // int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2); 650 // <keyword> <name> ( <int_value>, <description> ); 651 // 652 void ADLParser::int_def_parse(void) { 653 char *name = NULL; // Name of definition 654 char *value = NULL; // its value, 655 int int_value = -1; // positive values only 656 char *description = NULL; // textual description 657 658 // Get definition name 659 skipws(); // Skip whitespace 660 name = get_ident(); 661 if (name == NULL) { 662 parse_err(SYNERR, "missing definition name after int_def\n"); 663 return; 664 } 665 666 // Check for value of int_def dname( integer_value [, string_expression ] ) 667 skipws(); 668 if (_curchar == '(') { 669 670 // Parse the integer value. 671 next_char(); 672 value = get_ident(); 673 if (value == NULL) { 674 parse_err(SYNERR, "missing value in int_def\n"); 675 return; 676 } 677 if( !is_int_token(value, int_value) ) { 678 parse_err(SYNERR, "value in int_def is not recognized as integer\n"); 679 return; 680 } 681 skipws(); 682 683 // Check for description 684 if (_curchar == ',') { 685 next_char(); // skip ',' 686 687 description = get_expr("int_def description", ")"); 688 if (description == NULL) { 689 parse_err(SYNERR, "invalid or missing description in int_def\n"); 690 return; 691 } 692 trim(description); 693 } 694 695 if (_curchar != ')') { 696 parse_err(SYNERR, "missing ')' in register definition statement\n"); 697 return; 698 } 699 next_char(); 700 } 701 702 // Check for closing ';' 703 skipws(); 704 if (_curchar != ';') { 705 parse_err(SYNERR, "missing ';' after int_def\n"); 706 return; 707 } 708 next_char(); // move past ';' 709 710 // Debug Stuff 711 if (_AD._adl_debug > 1) { 712 fprintf(stderr,"int_def: %s ( %s, %s )\n", name, 713 (value), (description ? description : "")); 714 } 715 716 // Record new definition. 717 Expr *expr = new Expr(name, description, int_value, int_value); 718 const Expr *old_expr = _AD.globalDefs().define(name, expr); 719 if (old_expr != NULL) { 720 parse_err(SYNERR, "Duplicate definition\n"); 721 return; 722 } 723 724 return; 725 } 726 727 728 //------------------------------source_parse----------------------------------- 729 void ADLParser::source_parse(void) { 730 SourceForm *source; // Encode class for instruction/operand 731 char *rule = NULL; // String representation of encode rule 732 733 skipws(); // Skip leading whitespace 734 if ( (rule = find_cpp_block("source block")) == NULL ) { 735 parse_err(SYNERR, "incorrect or missing block for 'source'.\n"); 736 return; 737 } 738 // Debug Stuff 739 if (_AD._adl_debug > 1) fprintf(stderr,"Source Form: %s\n", rule); 740 741 source = new SourceForm(rule); // Build new Source object 742 _AD.addForm(source); 743 // skipws(); 744 } 745 746 //------------------------------source_hpp_parse------------------------------- 747 // Parse a source_hpp %{ ... %} block. 748 // The code gets stuck into the ad_<arch>.hpp file. 749 // If the source_hpp block appears before the register block in the AD 750 // file, it goes up at the very top of the ad_<arch>.hpp file, so that 751 // it can be used by register encodings, etc. Otherwise, it goes towards 752 // the bottom, where it's useful as a global definition to *.cpp files. 753 void ADLParser::source_hpp_parse(void) { 754 char *rule = NULL; // String representation of encode rule 755 756 skipws(); // Skip leading whitespace 757 if ( (rule = find_cpp_block("source_hpp block")) == NULL ) { 758 parse_err(SYNERR, "incorrect or missing block for 'source_hpp'.\n"); 759 return; 760 } 761 // Debug Stuff 762 if (_AD._adl_debug > 1) fprintf(stderr,"Header Form: %s\n", rule); 763 764 if (_AD.get_registers() == NULL) { 765 // Very early in the file, before reg_defs, we collect pre-headers. 766 PreHeaderForm* pre_header = new PreHeaderForm(rule); 767 _AD.addForm(pre_header); 768 } else { 769 // Normally, we collect header info, placed at the bottom of the hpp file. 770 HeaderForm* header = new HeaderForm(rule); 771 _AD.addForm(header); 772 } 773 } 774 775 //------------------------------reg_parse-------------------------------------- 776 void ADLParser::reg_parse(void) { 777 778 // Create the RegisterForm for the architecture description. 779 RegisterForm *regBlock = new RegisterForm(); // Build new Source object 780 regBlock->_linenum = _linenum; 781 _AD.addForm(regBlock); 782 783 skipws(); // Skip leading whitespace 784 if (_curchar == '%' && *(_ptr+1) == '{') { 785 next_char(); next_char(); // Skip "%{" 786 skipws(); 787 while (_curchar != '%' && *(_ptr+1) != '}') { 788 char *token = get_ident(); 789 if (token == NULL) { 790 parse_err(SYNERR, "missing identifier inside register block.\n"); 791 return; 792 } 793 if (strcmp(token,"reg_def")==0) { reg_def_parse(); } 794 if (strcmp(token,"reg_class")==0) { reg_class_parse(); } 795 if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); } 796 skipws(); 797 } 798 } 799 else { 800 parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%'); 801 return; 802 } 803 804 // Add reg_class spill_regs 805 regBlock->addSpillRegClass(); 806 } 807 808 //------------------------------encode_parse----------------------------------- 809 void ADLParser::encode_parse(void) { 810 EncodeForm *encBlock; // Information about instruction/operand encoding 811 char *desc = NULL; // String representation of encode rule 812 813 _AD.getForm(&encBlock); 814 if ( encBlock == NULL) { 815 // Create the EncodeForm for the architecture description. 816 encBlock = new EncodeForm(); // Build new Source object 817 _AD.addForm(encBlock); 818 } 819 820 skipws(); // Skip leading whitespace 821 if (_curchar == '%' && *(_ptr+1) == '{') { 822 next_char(); next_char(); // Skip "%{" 823 skipws(); 824 while (_curchar != '%' && *(_ptr+1) != '}') { 825 char *token = get_ident(); 826 if (token == NULL) { 827 parse_err(SYNERR, "missing identifier inside encoding block.\n"); 828 return; 829 } 830 if (strcmp(token,"enc_class")==0) { enc_class_parse(); } 831 skipws(); 832 } 833 } 834 else { 835 parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%'); 836 return; 837 } 838 } 839 840 //------------------------------enc_class_parse-------------------------------- 841 void ADLParser::enc_class_parse(void) { 842 char *ec_name; // Name of encoding class being defined 843 844 // Get encoding class name 845 skipws(); // Skip whitespace 846 ec_name = get_ident(); 847 if (ec_name == NULL) { 848 parse_err(SYNERR, "missing encoding class name after encode.\n"); 849 return; 850 } 851 852 EncClass *encoding = _AD._encode->add_EncClass(ec_name); 853 encoding->_linenum = _linenum; 854 855 skipws(); // Skip leading whitespace 856 // Check for optional parameter list 857 if (_curchar == '(') { 858 do { 859 char *pType = NULL; // parameter type 860 char *pName = NULL; // parameter name 861 862 next_char(); // skip open paren & comma characters 863 skipws(); 864 if (_curchar == ')') break; 865 866 // Get parameter type 867 pType = get_ident(); 868 if (pType == NULL) { 869 parse_err(SYNERR, "parameter type expected at %c\n", _curchar); 870 return; 871 } 872 873 skipws(); 874 // Get parameter name 875 pName = get_ident(); 876 if (pName == NULL) { 877 parse_err(SYNERR, "parameter name expected at %c\n", _curchar); 878 return; 879 } 880 881 // Record parameter type and name 882 encoding->add_parameter( pType, pName ); 883 884 skipws(); 885 } while(_curchar == ','); 886 887 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 888 else { 889 next_char(); // Skip ')' 890 } 891 } // Done with parameter list 892 893 skipws(); 894 // Check for block starting delimiters 895 if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block 896 parse_err(SYNERR, "missing '%c{' in enc_class definition\n", '%'); 897 return; 898 } 899 next_char(); // Skip '%' 900 next_char(); // Skip '{' 901 902 enc_class_parse_block(encoding, ec_name); 903 } 904 905 906 void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) { 907 skipws_no_preproc(); // Skip leading whitespace 908 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block 909 if (_AD._adlocation_debug) { 910 const char* file = _AD._ADL_file._name; 911 int line = _linenum; 912 char* location = (char *)malloc(strlen(file) + 100); 913 sprintf(location, "#line %d \"%s\"\n", line, file); 914 encoding->add_code(location); 915 } 916 917 // Collect the parts of the encode description 918 // (1) strings that are passed through to output 919 // (2) replacement/substitution variable, preceeded by a '$' 920 while ( (_curchar != '%') && (*(_ptr+1) != '}') ) { 921 922 // (1) 923 // Check if there is a string to pass through to output 924 char *start = _ptr; // Record start of the next string 925 while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) { 926 // If at the start of a comment, skip past it 927 if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) { 928 skipws_no_preproc(); 929 } else { 930 // ELSE advance to the next character, or start of the next line 931 next_char_or_line(); 932 } 933 } 934 // If a string was found, terminate it and record in EncClass 935 if ( start != _ptr ) { 936 *_ptr = '\0'; // Terminate the string 937 encoding->add_code(start); 938 } 939 940 // (2) 941 // If we are at a replacement variable, 942 // copy it and record in EncClass 943 if ( _curchar == '$' ) { 944 // Found replacement Variable 945 char *rep_var = get_rep_var_ident_dup(); 946 // Add flag to _strings list indicating we should check _rep_vars 947 encoding->add_rep_var(rep_var); 948 } 949 } // end while part of format description 950 next_char(); // Skip '%' 951 next_char(); // Skip '}' 952 953 skipws(); 954 955 // Debug Stuff 956 if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name); 957 } 958 959 //------------------------------frame_parse----------------------------------- 960 void ADLParser::frame_parse(void) { 961 FrameForm *frame; // Information about stack-frame layout 962 char *desc = NULL; // String representation of frame 963 964 skipws(); // Skip leading whitespace 965 966 frame = new FrameForm(); // Build new Frame object 967 // Check for open block sequence 968 skipws(); // Skip leading whitespace 969 if (_curchar == '%' && *(_ptr+1) == '{') { 970 next_char(); next_char(); // Skip "%{" 971 skipws(); 972 while (_curchar != '%' && *(_ptr+1) != '}') { 973 char *token = get_ident(); 974 if (token == NULL) { 975 parse_err(SYNERR, "missing identifier inside frame block.\n"); 976 return; 977 } 978 if (strcmp(token,"stack_direction")==0) { 979 stack_dir_parse(frame); 980 } 981 if (strcmp(token,"sync_stack_slots")==0) { 982 sync_stack_slots_parse(frame); 983 } 984 if (strcmp(token,"frame_pointer")==0) { 985 frame_pointer_parse(frame, false); 986 } 987 if (strcmp(token,"interpreter_frame_pointer")==0) { 988 interpreter_frame_pointer_parse(frame, false); 989 // Add reg_class interpreter_frame_pointer_reg 990 if( _AD._register != NULL ) { 991 RegClass *reg_class = _AD._register->addRegClass("interpreter_frame_pointer_reg"); 992 char *interpreter_frame_pointer_reg = frame->_interpreter_frame_pointer_reg; 993 if( interpreter_frame_pointer_reg != NULL ) { 994 RegDef *regDef = _AD._register->getRegDef(interpreter_frame_pointer_reg); 995 reg_class->addReg(regDef); // add regDef to regClass 996 } 997 } 998 } 999 if (strcmp(token,"inline_cache_reg")==0) { 1000 inline_cache_parse(frame, false); 1001 // Add reg_class inline_cache_reg 1002 if( _AD._register != NULL ) { 1003 RegClass *reg_class = _AD._register->addRegClass("inline_cache_reg"); 1004 char *inline_cache_reg = frame->_inline_cache_reg; 1005 if( inline_cache_reg != NULL ) { 1006 RegDef *regDef = _AD._register->getRegDef(inline_cache_reg); 1007 reg_class->addReg(regDef); // add regDef to regClass 1008 } 1009 } 1010 } 1011 if (strcmp(token,"compiler_method_oop_reg")==0) { 1012 parse_err(WARN, "Using obsolete Token, compiler_method_oop_reg"); 1013 skipws(); 1014 } 1015 if (strcmp(token,"interpreter_method_oop_reg")==0) { 1016 interpreter_method_oop_parse(frame, false); 1017 // Add reg_class interpreter_method_oop_reg 1018 if( _AD._register != NULL ) { 1019 RegClass *reg_class = _AD._register->addRegClass("interpreter_method_oop_reg"); 1020 char *method_oop_reg = frame->_interpreter_method_oop_reg; 1021 if( method_oop_reg != NULL ) { 1022 RegDef *regDef = _AD._register->getRegDef(method_oop_reg); 1023 reg_class->addReg(regDef); // add regDef to regClass 1024 } 1025 } 1026 } 1027 if (strcmp(token,"cisc_spilling_operand_name")==0) { 1028 cisc_spilling_operand_name_parse(frame, false); 1029 } 1030 if (strcmp(token,"stack_alignment")==0) { 1031 stack_alignment_parse(frame); 1032 } 1033 if (strcmp(token,"return_addr")==0) { 1034 return_addr_parse(frame, false); 1035 } 1036 if (strcmp(token,"in_preserve_stack_slots")==0) { 1037 preserve_stack_parse(frame); 1038 } 1039 if (strcmp(token,"out_preserve_stack_slots")==0) { 1040 parse_err(WARN, "Using obsolete token, out_preserve_stack_slots"); 1041 skipws(); 1042 } 1043 if (strcmp(token,"varargs_C_out_slots_killed")==0) { 1044 frame->_varargs_C_out_slots_killed = parse_one_arg("varargs C out slots killed"); 1045 } 1046 if (strcmp(token,"calling_convention")==0) { 1047 frame->_calling_convention = calling_convention_parse(); 1048 } 1049 if (strcmp(token,"return_value")==0) { 1050 frame->_return_value = return_value_parse(); 1051 } 1052 if (strcmp(token,"c_frame_pointer")==0) { 1053 frame_pointer_parse(frame, true); 1054 } 1055 if (strcmp(token,"c_return_addr")==0) { 1056 return_addr_parse(frame, true); 1057 } 1058 if (strcmp(token,"c_calling_convention")==0) { 1059 frame->_c_calling_convention = calling_convention_parse(); 1060 } 1061 if (strcmp(token,"c_return_value")==0) { 1062 frame->_c_return_value = return_value_parse(); 1063 } 1064 1065 skipws(); 1066 } 1067 } 1068 else { 1069 parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%'); 1070 return; 1071 } 1072 // All Java versions are required, native versions are optional 1073 if(frame->_frame_pointer == NULL) { 1074 parse_err(SYNERR, "missing frame pointer definition in frame section.\n"); 1075 return; 1076 } 1077 // !!!!! !!!!! 1078 // if(frame->_interpreter_frame_ptr_reg == NULL) { 1079 // parse_err(SYNERR, "missing interpreter frame pointer definition in frame section.\n"); 1080 // return; 1081 // } 1082 if(frame->_alignment == NULL) { 1083 parse_err(SYNERR, "missing alignment definition in frame section.\n"); 1084 return; 1085 } 1086 if(frame->_return_addr == NULL) { 1087 parse_err(SYNERR, "missing return address location in frame section.\n"); 1088 return; 1089 } 1090 if(frame->_in_preserve_slots == NULL) { 1091 parse_err(SYNERR, "missing stack slot preservation definition in frame section.\n"); 1092 return; 1093 } 1094 if(frame->_varargs_C_out_slots_killed == NULL) { 1095 parse_err(SYNERR, "missing varargs C out slots killed definition in frame section.\n"); 1096 return; 1097 } 1098 if(frame->_calling_convention == NULL) { 1099 parse_err(SYNERR, "missing calling convention definition in frame section.\n"); 1100 return; 1101 } 1102 if(frame->_return_value == NULL) { 1103 parse_err(SYNERR, "missing return value definition in frame section.\n"); 1104 return; 1105 } 1106 // Fill natives in identically with the Java versions if not present. 1107 if(frame->_c_frame_pointer == NULL) { 1108 frame->_c_frame_pointer = frame->_frame_pointer; 1109 } 1110 if(frame->_c_return_addr == NULL) { 1111 frame->_c_return_addr = frame->_return_addr; 1112 frame->_c_return_addr_loc = frame->_return_addr_loc; 1113 } 1114 if(frame->_c_calling_convention == NULL) { 1115 frame->_c_calling_convention = frame->_calling_convention; 1116 } 1117 if(frame->_c_return_value == NULL) { 1118 frame->_c_return_value = frame->_return_value; 1119 } 1120 1121 // Debug Stuff 1122 if (_AD._adl_debug > 1) fprintf(stderr,"Frame Form: %s\n", desc); 1123 1124 // Create the EncodeForm for the architecture description. 1125 _AD.addForm(frame); 1126 // skipws(); 1127 } 1128 1129 //------------------------------stack_dir_parse-------------------------------- 1130 void ADLParser::stack_dir_parse(FrameForm *frame) { 1131 char *direction = parse_one_arg("stack direction entry"); 1132 if (strcmp(direction, "TOWARDS_LOW") == 0) { 1133 frame->_direction = false; 1134 } 1135 else if (strcmp(direction, "TOWARDS_HIGH") == 0) { 1136 frame->_direction = true; 1137 } 1138 else { 1139 parse_err(SYNERR, "invalid value inside stack direction entry.\n"); 1140 return; 1141 } 1142 } 1143 1144 //------------------------------sync_stack_slots_parse------------------------- 1145 void ADLParser::sync_stack_slots_parse(FrameForm *frame) { 1146 // Assign value into frame form 1147 frame->_sync_stack_slots = parse_one_arg("sync stack slots entry"); 1148 } 1149 1150 //------------------------------frame_pointer_parse---------------------------- 1151 void ADLParser::frame_pointer_parse(FrameForm *frame, bool native) { 1152 char *frame_pointer = parse_one_arg("frame pointer entry"); 1153 // Assign value into frame form 1154 if (native) { frame->_c_frame_pointer = frame_pointer; } 1155 else { frame->_frame_pointer = frame_pointer; } 1156 } 1157 1158 //------------------------------interpreter_frame_pointer_parse---------------------------- 1159 void ADLParser::interpreter_frame_pointer_parse(FrameForm *frame, bool native) { 1160 frame->_interpreter_frame_pointer_reg = parse_one_arg("interpreter frame pointer entry"); 1161 } 1162 1163 //------------------------------inline_cache_parse----------------------------- 1164 void ADLParser::inline_cache_parse(FrameForm *frame, bool native) { 1165 frame->_inline_cache_reg = parse_one_arg("inline cache reg entry"); 1166 } 1167 1168 //------------------------------interpreter_method_oop_parse------------------ 1169 void ADLParser::interpreter_method_oop_parse(FrameForm *frame, bool native) { 1170 frame->_interpreter_method_oop_reg = parse_one_arg("method oop reg entry"); 1171 } 1172 1173 //------------------------------cisc_spilling_operand_parse--------------------- 1174 void ADLParser::cisc_spilling_operand_name_parse(FrameForm *frame, bool native) { 1175 frame->_cisc_spilling_operand_name = parse_one_arg("cisc spilling operand name"); 1176 } 1177 1178 //------------------------------stack_alignment_parse-------------------------- 1179 void ADLParser::stack_alignment_parse(FrameForm *frame) { 1180 char *alignment = parse_one_arg("stack alignment entry"); 1181 // Assign value into frame 1182 frame->_alignment = alignment; 1183 } 1184 1185 //------------------------------parse_one_arg------------------------------- 1186 char *ADLParser::parse_one_arg(const char *description) { 1187 char *token = NULL; 1188 if(_curchar == '(') { 1189 next_char(); 1190 skipws(); 1191 token = get_expr(description, ")"); 1192 if (token == NULL) { 1193 parse_err(SYNERR, "missing value inside %s.\n", description); 1194 return NULL; 1195 } 1196 next_char(); // skip the close paren 1197 if(_curchar != ';') { // check for semi-colon 1198 parse_err(SYNERR, "missing %c in.\n", ';', description); 1199 return NULL; 1200 } 1201 next_char(); // skip the semi-colon 1202 } 1203 else { 1204 parse_err(SYNERR, "Missing %c in.\n", '(', description); 1205 return NULL; 1206 } 1207 1208 trim(token); 1209 return token; 1210 } 1211 1212 //------------------------------return_addr_parse------------------------------ 1213 void ADLParser::return_addr_parse(FrameForm *frame, bool native) { 1214 bool in_register = true; 1215 if(_curchar == '(') { 1216 next_char(); 1217 skipws(); 1218 char *token = get_ident(); 1219 if (token == NULL) { 1220 parse_err(SYNERR, "missing value inside return address entry.\n"); 1221 return; 1222 } 1223 // check for valid values for stack/register 1224 if (strcmp(token, "REG") == 0) { 1225 in_register = true; 1226 } 1227 else if (strcmp(token, "STACK") == 0) { 1228 in_register = false; 1229 } 1230 else { 1231 parse_err(SYNERR, "invalid value inside return_address entry.\n"); 1232 return; 1233 } 1234 if (native) { frame->_c_return_addr_loc = in_register; } 1235 else { frame->_return_addr_loc = in_register; } 1236 1237 // Parse expression that specifies register or stack position 1238 skipws(); 1239 char *token2 = get_expr("return address entry", ")"); 1240 if (token2 == NULL) { 1241 parse_err(SYNERR, "missing value inside return address entry.\n"); 1242 return; 1243 } 1244 next_char(); // skip the close paren 1245 if (native) { frame->_c_return_addr = token2; } 1246 else { frame->_return_addr = token2; } 1247 1248 if(_curchar != ';') { // check for semi-colon 1249 parse_err(SYNERR, "missing %c in return address entry.\n", ';'); 1250 return; 1251 } 1252 next_char(); // skip the semi-colon 1253 } 1254 else { 1255 parse_err(SYNERR, "Missing %c in return_address entry.\n", '('); 1256 } 1257 } 1258 1259 //------------------------------preserve_stack_parse--------------------------- 1260 void ADLParser::preserve_stack_parse(FrameForm *frame) { 1261 if(_curchar == '(') { 1262 char *token = get_paren_expr("preserve_stack_slots"); 1263 frame->_in_preserve_slots = token; 1264 1265 if(_curchar != ';') { // check for semi-colon 1266 parse_err(SYNERR, "missing %c in preserve stack slot entry.\n", ';'); 1267 return; 1268 } 1269 next_char(); // skip the semi-colon 1270 } 1271 else { 1272 parse_err(SYNERR, "Missing %c in preserve stack slot entry.\n", '('); 1273 } 1274 } 1275 1276 //------------------------------calling_convention_parse----------------------- 1277 char *ADLParser::calling_convention_parse() { 1278 char *desc = NULL; // String representation of calling_convention 1279 1280 skipws(); // Skip leading whitespace 1281 if ( (desc = find_cpp_block("calling convention block")) == NULL ) { 1282 parse_err(SYNERR, "incorrect or missing block for 'calling_convention'.\n"); 1283 } 1284 return desc; 1285 } 1286 1287 //------------------------------return_value_parse----------------------------- 1288 char *ADLParser::return_value_parse() { 1289 char *desc = NULL; // String representation of calling_convention 1290 1291 skipws(); // Skip leading whitespace 1292 if ( (desc = find_cpp_block("return value block")) == NULL ) { 1293 parse_err(SYNERR, "incorrect or missing block for 'return_value'.\n"); 1294 } 1295 return desc; 1296 } 1297 1298 //------------------------------ins_pipe_parse--------------------------------- 1299 void ADLParser::ins_pipe_parse(InstructForm &instr) { 1300 char * ident; 1301 1302 skipws(); 1303 if ( _curchar != '(' ) { // Check for delimiter 1304 parse_err(SYNERR, "missing \"(\" in ins_pipe definition\n"); 1305 return; 1306 } 1307 1308 next_char(); 1309 ident = get_ident(); // Grab next identifier 1310 1311 if (ident == NULL) { 1312 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 1313 return; 1314 } 1315 1316 skipws(); 1317 if ( _curchar != ')' ) { // Check for delimiter 1318 parse_err(SYNERR, "missing \")\" in ins_pipe definition\n"); 1319 return; 1320 } 1321 1322 next_char(); // skip the close paren 1323 if(_curchar != ';') { // check for semi-colon 1324 parse_err(SYNERR, "missing %c in return value entry.\n", ';'); 1325 return; 1326 } 1327 next_char(); // skip the semi-colon 1328 1329 // Check ident for validity 1330 if (_AD._pipeline && !_AD._pipeline->_classlist.search(ident)) { 1331 parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", ident); 1332 return; 1333 } 1334 1335 // Add this instruction to the list in the pipeline class 1336 _AD._pipeline->_classdict[ident]->is_pipeclass()->_instructs.addName(instr._ident); 1337 1338 // Set the name of the pipeline class in the instruction 1339 instr._ins_pipe = ident; 1340 return; 1341 } 1342 1343 //------------------------------pipe_parse------------------------------------- 1344 void ADLParser::pipe_parse(void) { 1345 PipelineForm *pipeline; // Encode class for instruction/operand 1346 char * ident; 1347 1348 pipeline = new PipelineForm(); // Build new Source object 1349 _AD.addForm(pipeline); 1350 1351 skipws(); // Skip leading whitespace 1352 // Check for block delimiter 1353 if ( (_curchar != '%') 1354 || ( next_char(), (_curchar != '{')) ) { 1355 parse_err(SYNERR, "missing '%{' in pipeline definition\n"); 1356 return; 1357 } 1358 next_char(); // Maintain the invariant 1359 do { 1360 ident = get_ident(); // Grab next identifier 1361 if (ident == NULL) { 1362 parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar); 1363 continue; 1364 } 1365 if (!strcmp(ident, "resources" )) resource_parse(*pipeline); 1366 else if (!strcmp(ident, "pipe_desc" )) pipe_desc_parse(*pipeline); 1367 else if (!strcmp(ident, "pipe_class")) pipe_class_parse(*pipeline); 1368 else if (!strcmp(ident, "define")) { 1369 skipws(); 1370 if ( (_curchar != '%') 1371 || ( next_char(), (_curchar != '{')) ) { 1372 parse_err(SYNERR, "expected '%{'\n"); 1373 return; 1374 } 1375 next_char(); skipws(); 1376 1377 char *node_class = get_ident(); 1378 if (node_class == NULL) { 1379 parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar); 1380 return; 1381 } 1382 1383 skipws(); 1384 if (_curchar != ',' && _curchar != '=') { 1385 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1386 break; 1387 } 1388 next_char(); skipws(); 1389 1390 char *pipe_class = get_ident(); 1391 if (pipe_class == NULL) { 1392 parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar); 1393 return; 1394 } 1395 if (_curchar != ';' ) { 1396 parse_err(SYNERR, "expected `;`, found '%c'\n", _curchar); 1397 break; 1398 } 1399 next_char(); // Skip over semi-colon 1400 1401 skipws(); 1402 if ( (_curchar != '%') 1403 || ( next_char(), (_curchar != '}')) ) { 1404 parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); 1405 } 1406 next_char(); 1407 1408 // Check ident for validity 1409 if (_AD._pipeline && !_AD._pipeline->_classlist.search(pipe_class)) { 1410 parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", pipe_class); 1411 return; 1412 } 1413 1414 // Add this machine node to the list in the pipeline class 1415 _AD._pipeline->_classdict[pipe_class]->is_pipeclass()->_instructs.addName(node_class); 1416 1417 MachNodeForm *machnode = new MachNodeForm(node_class); // Create new machnode form 1418 machnode->_machnode_pipe = pipe_class; 1419 1420 _AD.addForm(machnode); 1421 } 1422 else if (!strcmp(ident, "attributes")) { 1423 bool vsi_seen = false, bhds_seen = false; 1424 1425 skipws(); 1426 if ( (_curchar != '%') 1427 || ( next_char(), (_curchar != '{')) ) { 1428 parse_err(SYNERR, "expected '%{'\n"); 1429 return; 1430 } 1431 next_char(); skipws(); 1432 1433 while (_curchar != '%') { 1434 ident = get_ident(); 1435 if (ident == NULL) 1436 break; 1437 1438 if (!strcmp(ident, "variable_size_instructions")) { 1439 skipws(); 1440 if (_curchar == ';') { 1441 next_char(); skipws(); 1442 } 1443 1444 pipeline->_variableSizeInstrs = true; 1445 vsi_seen = true; 1446 continue; 1447 } 1448 1449 if (!strcmp(ident, "fixed_size_instructions")) { 1450 skipws(); 1451 if (_curchar == ';') { 1452 next_char(); skipws(); 1453 } 1454 1455 pipeline->_variableSizeInstrs = false; 1456 vsi_seen = true; 1457 continue; 1458 } 1459 1460 if (!strcmp(ident, "branch_has_delay_slot")) { 1461 skipws(); 1462 if (_curchar == ';') { 1463 next_char(); skipws(); 1464 } 1465 1466 pipeline->_branchHasDelaySlot = true; 1467 bhds_seen = true; 1468 continue; 1469 } 1470 1471 if (!strcmp(ident, "max_instructions_per_bundle")) { 1472 skipws(); 1473 if (_curchar != '=') { 1474 parse_err(SYNERR, "expected `=`\n"); 1475 break; 1476 } 1477 1478 next_char(); skipws(); 1479 pipeline->_maxInstrsPerBundle = get_int(); 1480 skipws(); 1481 1482 if (_curchar == ';') { 1483 next_char(); skipws(); 1484 } 1485 1486 continue; 1487 } 1488 1489 if (!strcmp(ident, "max_bundles_per_cycle")) { 1490 skipws(); 1491 if (_curchar != '=') { 1492 parse_err(SYNERR, "expected `=`\n"); 1493 break; 1494 } 1495 1496 next_char(); skipws(); 1497 pipeline->_maxBundlesPerCycle = get_int(); 1498 skipws(); 1499 1500 if (_curchar == ';') { 1501 next_char(); skipws(); 1502 } 1503 1504 continue; 1505 } 1506 1507 if (!strcmp(ident, "instruction_unit_size")) { 1508 skipws(); 1509 if (_curchar != '=') { 1510 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1511 break; 1512 } 1513 1514 next_char(); skipws(); 1515 pipeline->_instrUnitSize = get_int(); 1516 skipws(); 1517 1518 if (_curchar == ';') { 1519 next_char(); skipws(); 1520 } 1521 1522 continue; 1523 } 1524 1525 if (!strcmp(ident, "bundle_unit_size")) { 1526 skipws(); 1527 if (_curchar != '=') { 1528 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1529 break; 1530 } 1531 1532 next_char(); skipws(); 1533 pipeline->_bundleUnitSize = get_int(); 1534 skipws(); 1535 1536 if (_curchar == ';') { 1537 next_char(); skipws(); 1538 } 1539 1540 continue; 1541 } 1542 1543 if (!strcmp(ident, "instruction_fetch_unit_size")) { 1544 skipws(); 1545 if (_curchar != '=') { 1546 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1547 break; 1548 } 1549 1550 next_char(); skipws(); 1551 pipeline->_instrFetchUnitSize = get_int(); 1552 skipws(); 1553 1554 if (_curchar == ';') { 1555 next_char(); skipws(); 1556 } 1557 1558 continue; 1559 } 1560 1561 if (!strcmp(ident, "instruction_fetch_units")) { 1562 skipws(); 1563 if (_curchar != '=') { 1564 parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar); 1565 break; 1566 } 1567 1568 next_char(); skipws(); 1569 pipeline->_instrFetchUnits = get_int(); 1570 skipws(); 1571 1572 if (_curchar == ';') { 1573 next_char(); skipws(); 1574 } 1575 1576 continue; 1577 } 1578 1579 if (!strcmp(ident, "nops")) { 1580 skipws(); 1581 if (_curchar != '(') { 1582 parse_err(SYNERR, "expected `(`, found '%c'\n", _curchar); 1583 break; 1584 } 1585 1586 next_char(); skipws(); 1587 1588 while (_curchar != ')') { 1589 ident = get_ident(); 1590 if (ident == NULL) { 1591 parse_err(SYNERR, "expected identifier for nop instruction, found '%c'\n", _curchar); 1592 break; 1593 } 1594 1595 pipeline->_noplist.addName(ident); 1596 pipeline->_nopcnt++; 1597 skipws(); 1598 1599 if (_curchar == ',') { 1600 next_char(); skipws(); 1601 } 1602 } 1603 1604 next_char(); skipws(); 1605 1606 if (_curchar == ';') { 1607 next_char(); skipws(); 1608 } 1609 1610 continue; 1611 } 1612 1613 parse_err(SYNERR, "unknown specifier \"%s\"\n", ident); 1614 } 1615 1616 if ( (_curchar != '%') 1617 || ( next_char(), (_curchar != '}')) ) { 1618 parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); 1619 } 1620 next_char(); skipws(); 1621 1622 if (pipeline->_maxInstrsPerBundle == 0) 1623 parse_err(SYNERR, "\"max_instructions_per_bundle\" unspecified\n"); 1624 if (pipeline->_instrUnitSize == 0 && pipeline->_bundleUnitSize == 0) 1625 parse_err(SYNERR, "\"instruction_unit_size\" and \"bundle_unit_size\" unspecified\n"); 1626 if (pipeline->_instrFetchUnitSize == 0) 1627 parse_err(SYNERR, "\"instruction_fetch_unit_size\" unspecified\n"); 1628 if (pipeline->_instrFetchUnits == 0) 1629 parse_err(SYNERR, "\"instruction_fetch_units\" unspecified\n"); 1630 if (!vsi_seen) 1631 parse_err(SYNERR, "\"variable_size_instruction\" or \"fixed_size_instruction\" unspecified\n"); 1632 } 1633 else { // Done with staticly defined parts of instruction definition 1634 parse_err(SYNERR, "expected one of \"resources\", \"pipe_desc\", \"pipe_class\", found \"%s\"\n", ident); 1635 return; 1636 } 1637 skipws(); 1638 if (_curchar == ';') 1639 skipws(); 1640 } while(_curchar != '%'); 1641 1642 next_char(); 1643 if (_curchar != '}') { 1644 parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); 1645 return; 1646 } 1647 1648 next_char(); 1649 } 1650 1651 //------------------------------resource_parse---------------------------- 1652 void ADLParser::resource_parse(PipelineForm &pipeline) { 1653 ResourceForm *resource; 1654 char * ident; 1655 char * expr; 1656 unsigned mask; 1657 pipeline._rescount = 0; 1658 1659 skipws(); // Skip leading whitespace 1660 1661 if (_curchar != '(') { 1662 parse_err(SYNERR, "missing \"(\" in resource definition\n"); 1663 return; 1664 } 1665 1666 do { 1667 next_char(); // Skip "(" or "," 1668 ident = get_ident(); // Grab next identifier 1669 1670 if (ident == NULL) { 1671 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1672 return; 1673 } 1674 skipws(); 1675 1676 if (_curchar != '=') { 1677 mask = (1 << pipeline._rescount++); 1678 } 1679 else { 1680 next_char(); skipws(); 1681 expr = get_ident(); // Grab next identifier 1682 if (expr == NULL) { 1683 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1684 return; 1685 } 1686 resource = (ResourceForm *) pipeline._resdict[expr]; 1687 if (resource == NULL) { 1688 parse_err(SYNERR, "resource \"%s\" is not defined\n", expr); 1689 return; 1690 } 1691 mask = resource->mask(); 1692 1693 skipws(); 1694 while (_curchar == '|') { 1695 next_char(); skipws(); 1696 1697 expr = get_ident(); // Grab next identifier 1698 if (expr == NULL) { 1699 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1700 return; 1701 } 1702 1703 resource = (ResourceForm *) pipeline._resdict[expr]; // Look up the value 1704 if (resource == NULL) { 1705 parse_err(SYNERR, "resource \"%s\" is not defined\n", expr); 1706 return; 1707 } 1708 1709 mask |= resource->mask(); 1710 skipws(); 1711 } 1712 } 1713 1714 resource = new ResourceForm(mask); 1715 1716 pipeline._resdict.Insert(ident, resource); 1717 pipeline._reslist.addName(ident); 1718 } while (_curchar == ','); 1719 1720 if (_curchar != ')') { 1721 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1722 return; 1723 } 1724 1725 next_char(); // Skip ")" 1726 if (_curchar == ';') 1727 next_char(); // Skip ";" 1728 } 1729 1730 //------------------------------resource_parse---------------------------- 1731 void ADLParser::pipe_desc_parse(PipelineForm &pipeline) { 1732 char * ident; 1733 1734 skipws(); // Skip leading whitespace 1735 1736 if (_curchar != '(') { 1737 parse_err(SYNERR, "missing \"(\" in pipe_desc definition\n"); 1738 return; 1739 } 1740 1741 do { 1742 next_char(); // Skip "(" or "," 1743 ident = get_ident(); // Grab next identifier 1744 if (ident == NULL) { 1745 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1746 return; 1747 } 1748 1749 // Add the name to the list 1750 pipeline._stages.addName(ident); 1751 pipeline._stagecnt++; 1752 1753 skipws(); 1754 } while (_curchar == ','); 1755 1756 if (_curchar != ')') { 1757 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1758 return; 1759 } 1760 1761 next_char(); // Skip ")" 1762 if (_curchar == ';') 1763 next_char(); // Skip ";" 1764 } 1765 1766 //------------------------------pipe_class_parse-------------------------- 1767 void ADLParser::pipe_class_parse(PipelineForm &pipeline) { 1768 PipeClassForm *pipe_class; 1769 char * ident; 1770 char * stage; 1771 char * read_or_write; 1772 int is_write; 1773 int is_read; 1774 OperandForm *oper; 1775 1776 skipws(); // Skip leading whitespace 1777 1778 ident = get_ident(); // Grab next identifier 1779 1780 if (ident == NULL) { 1781 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1782 return; 1783 } 1784 1785 // Create a record for the pipe_class 1786 pipe_class = new PipeClassForm(ident, ++pipeline._classcnt); 1787 pipeline._classdict.Insert(ident, pipe_class); 1788 pipeline._classlist.addName(ident); 1789 1790 // Then get the operands 1791 skipws(); 1792 if (_curchar != '(') { 1793 parse_err(SYNERR, "missing \"(\" in pipe_class definition\n"); 1794 } 1795 // Parse the operand list 1796 else get_oplist(pipe_class->_parameters, pipe_class->_localNames); 1797 skipws(); // Skip leading whitespace 1798 // Check for block delimiter 1799 if ( (_curchar != '%') 1800 || ( next_char(), (_curchar != '{')) ) { 1801 parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); 1802 return; 1803 } 1804 next_char(); 1805 1806 do { 1807 ident = get_ident(); // Grab next identifier 1808 if (ident == NULL) { 1809 parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); 1810 continue; 1811 } 1812 skipws(); 1813 1814 if (!strcmp(ident, "fixed_latency")) { 1815 skipws(); 1816 if (_curchar != '(') { 1817 parse_err(SYNERR, "missing \"(\" in latency definition\n"); 1818 return; 1819 } 1820 next_char(); skipws(); 1821 if( !isdigit(_curchar) ) { 1822 parse_err(SYNERR, "number expected for \"%c\" in latency definition\n", _curchar); 1823 return; 1824 } 1825 int fixed_latency = get_int(); 1826 skipws(); 1827 if (_curchar != ')') { 1828 parse_err(SYNERR, "missing \")\" in latency definition\n"); 1829 return; 1830 } 1831 next_char(); skipws(); 1832 if (_curchar != ';') { 1833 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1834 return; 1835 } 1836 1837 pipe_class->setFixedLatency(fixed_latency); 1838 next_char(); skipws(); 1839 continue; 1840 } 1841 1842 if (!strcmp(ident, "zero_instructions") || 1843 !strcmp(ident, "no_instructions")) { 1844 skipws(); 1845 if (_curchar != ';') { 1846 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1847 return; 1848 } 1849 1850 pipe_class->setInstructionCount(0); 1851 next_char(); skipws(); 1852 continue; 1853 } 1854 1855 if (!strcmp(ident, "one_instruction_with_delay_slot") || 1856 !strcmp(ident, "single_instruction_with_delay_slot")) { 1857 skipws(); 1858 if (_curchar != ';') { 1859 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1860 return; 1861 } 1862 1863 pipe_class->setInstructionCount(1); 1864 pipe_class->setBranchDelay(true); 1865 next_char(); skipws(); 1866 continue; 1867 } 1868 1869 if (!strcmp(ident, "one_instruction") || 1870 !strcmp(ident, "single_instruction")) { 1871 skipws(); 1872 if (_curchar != ';') { 1873 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1874 return; 1875 } 1876 1877 pipe_class->setInstructionCount(1); 1878 next_char(); skipws(); 1879 continue; 1880 } 1881 1882 if (!strcmp(ident, "instructions_in_first_bundle") || 1883 !strcmp(ident, "instruction_count")) { 1884 skipws(); 1885 1886 int number_of_instructions = 1; 1887 1888 if (_curchar != '(') { 1889 parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar); 1890 continue; 1891 } 1892 1893 next_char(); skipws(); 1894 number_of_instructions = get_int(); 1895 1896 skipws(); 1897 if (_curchar != ')') { 1898 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 1899 continue; 1900 } 1901 1902 next_char(); skipws(); 1903 if (_curchar != ';') { 1904 parse_err(SYNERR, "missing \";\" in latency definition\n"); 1905 return; 1906 } 1907 1908 pipe_class->setInstructionCount(number_of_instructions); 1909 next_char(); skipws(); 1910 continue; 1911 } 1912 1913 if (!strcmp(ident, "multiple_bundles")) { 1914 skipws(); 1915 if (_curchar != ';') { 1916 parse_err(SYNERR, "missing \";\" after multiple bundles\n"); 1917 return; 1918 } 1919 1920 pipe_class->setMultipleBundles(true); 1921 next_char(); skipws(); 1922 continue; 1923 } 1924 1925 if (!strcmp(ident, "has_delay_slot")) { 1926 skipws(); 1927 if (_curchar != ';') { 1928 parse_err(SYNERR, "missing \";\" after \"has_delay_slot\"\n"); 1929 return; 1930 } 1931 1932 pipe_class->setBranchDelay(true); 1933 next_char(); skipws(); 1934 continue; 1935 } 1936 1937 if (!strcmp(ident, "force_serialization")) { 1938 skipws(); 1939 if (_curchar != ';') { 1940 parse_err(SYNERR, "missing \";\" after \"force_serialization\"\n"); 1941 return; 1942 } 1943 1944 pipe_class->setForceSerialization(true); 1945 next_char(); skipws(); 1946 continue; 1947 } 1948 1949 if (!strcmp(ident, "may_have_no_code")) { 1950 skipws(); 1951 if (_curchar != ';') { 1952 parse_err(SYNERR, "missing \";\" after \"may_have_no_code\"\n"); 1953 return; 1954 } 1955 1956 pipe_class->setMayHaveNoCode(true); 1957 next_char(); skipws(); 1958 continue; 1959 } 1960 1961 const Form *parm = pipe_class->_localNames[ident]; 1962 if (parm != NULL) { 1963 oper = parm->is_operand(); 1964 if (oper == NULL && !parm->is_opclass()) { 1965 parse_err(SYNERR, "operand name expected at %s\n", ident); 1966 continue; 1967 } 1968 1969 if (_curchar != ':') { 1970 parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar); 1971 continue; 1972 } 1973 next_char(); skipws(); 1974 stage = get_ident(); 1975 if (stage == NULL) { 1976 parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar); 1977 continue; 1978 } 1979 1980 skipws(); 1981 if (_curchar != '(') { 1982 parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar); 1983 continue; 1984 } 1985 1986 next_char(); 1987 read_or_write = get_ident(); 1988 if (read_or_write == NULL) { 1989 parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar); 1990 continue; 1991 } 1992 1993 is_read = strcmp(read_or_write, "read") == 0; 1994 is_write = strcmp(read_or_write, "write") == 0; 1995 if (!is_read && !is_write) { 1996 parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar); 1997 continue; 1998 } 1999 2000 skipws(); 2001 if (_curchar != ')') { 2002 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 2003 continue; 2004 } 2005 2006 next_char(); skipws(); 2007 int more_instrs = 0; 2008 if (_curchar == '+') { 2009 next_char(); skipws(); 2010 if (_curchar < '0' || _curchar > '9') { 2011 parse_err(SYNERR, "<number> expected at \"%c\"\n", _curchar); 2012 continue; 2013 } 2014 while (_curchar >= '0' && _curchar <= '9') { 2015 more_instrs *= 10; 2016 more_instrs += _curchar - '0'; 2017 next_char(); 2018 } 2019 skipws(); 2020 } 2021 2022 PipeClassOperandForm *pipe_operand = new PipeClassOperandForm(stage, is_write, more_instrs); 2023 pipe_class->_localUsage.Insert(ident, pipe_operand); 2024 2025 if (_curchar == '%') 2026 continue; 2027 2028 if (_curchar != ';') { 2029 parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar); 2030 continue; 2031 } 2032 next_char(); skipws(); 2033 continue; 2034 } 2035 2036 // Scan for Resource Specifier 2037 const Form *res = pipeline._resdict[ident]; 2038 if (res != NULL) { 2039 int cyclecnt = 1; 2040 if (_curchar != ':') { 2041 parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar); 2042 continue; 2043 } 2044 next_char(); skipws(); 2045 stage = get_ident(); 2046 if (stage == NULL) { 2047 parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar); 2048 continue; 2049 } 2050 2051 skipws(); 2052 if (_curchar == '(') { 2053 next_char(); 2054 cyclecnt = get_int(); 2055 2056 skipws(); 2057 if (_curchar != ')') { 2058 parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar); 2059 continue; 2060 } 2061 2062 next_char(); skipws(); 2063 } 2064 2065 PipeClassResourceForm *resource = new PipeClassResourceForm(ident, stage, cyclecnt); 2066 int stagenum = pipeline._stages.index(stage); 2067 if (pipeline._maxcycleused < (stagenum+cyclecnt)) 2068 pipeline._maxcycleused = (stagenum+cyclecnt); 2069 pipe_class->_resUsage.addForm(resource); 2070 2071 if (_curchar == '%') 2072 continue; 2073 2074 if (_curchar != ';') { 2075 parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar); 2076 continue; 2077 } 2078 next_char(); skipws(); 2079 continue; 2080 } 2081 2082 parse_err(SYNERR, "resource expected at \"%s\"\n", ident); 2083 return; 2084 } while(_curchar != '%'); 2085 2086 next_char(); 2087 if (_curchar != '}') { 2088 parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); 2089 return; 2090 } 2091 2092 next_char(); 2093 } 2094 2095 //------------------------------peep_parse------------------------------------- 2096 void ADLParser::peep_parse(void) { 2097 Peephole *peep; // Pointer to current peephole rule form 2098 char *desc = NULL; // String representation of rule 2099 2100 skipws(); // Skip leading whitespace 2101 2102 peep = new Peephole(); // Build new Peephole object 2103 // Check for open block sequence 2104 skipws(); // Skip leading whitespace 2105 if (_curchar == '%' && *(_ptr+1) == '{') { 2106 next_char(); next_char(); // Skip "%{" 2107 skipws(); 2108 while (_curchar != '%' && *(_ptr+1) != '}') { 2109 char *token = get_ident(); 2110 if (token == NULL) { 2111 parse_err(SYNERR, "missing identifier inside peephole rule.\n"); 2112 return; 2113 } 2114 // check for legal subsections of peephole rule 2115 if (strcmp(token,"peepmatch")==0) { 2116 peep_match_parse(*peep); } 2117 else if (strcmp(token,"peepconstraint")==0) { 2118 peep_constraint_parse(*peep); } 2119 else if (strcmp(token,"peepreplace")==0) { 2120 peep_replace_parse(*peep); } 2121 else { 2122 parse_err(SYNERR, "expected peepmatch, peepconstraint, or peepreplace for identifier %s.\n", token); 2123 } 2124 skipws(); 2125 } 2126 } 2127 else { 2128 parse_err(SYNERR, "Missing %%{ ... %%} block after peephole keyword.\n"); 2129 return; 2130 } 2131 next_char(); // Skip past '%' 2132 next_char(); // Skip past '}' 2133 } 2134 2135 // ******************** Private Level 2 Parse Functions ******************** 2136 //------------------------------constraint_parse------------------------------ 2137 Constraint *ADLParser::constraint_parse(void) { 2138 char *func; 2139 char *arg; 2140 2141 // Check for constraint expression 2142 skipws(); 2143 if (_curchar != '(') { 2144 parse_err(SYNERR, "missing constraint expression, (...)\n"); 2145 return NULL; 2146 } 2147 next_char(); // Skip past '(' 2148 2149 // Get constraint function 2150 skipws(); 2151 func = get_ident(); 2152 if (func == NULL) { 2153 parse_err(SYNERR, "missing function in constraint expression.\n"); 2154 return NULL; 2155 } 2156 if (strcmp(func,"ALLOC_IN_RC")==0 2157 || strcmp(func,"IS_R_CLASS")==0) { 2158 // Check for '(' before argument 2159 skipws(); 2160 if (_curchar != '(') { 2161 parse_err(SYNERR, "missing '(' for constraint function's argument.\n"); 2162 return NULL; 2163 } 2164 next_char(); 2165 2166 // Get it's argument 2167 skipws(); 2168 arg = get_ident(); 2169 if (arg == NULL) { 2170 parse_err(SYNERR, "missing argument for constraint function %s\n",func); 2171 return NULL; 2172 } 2173 // Check for ')' after argument 2174 skipws(); 2175 if (_curchar != ')') { 2176 parse_err(SYNERR, "missing ')' after constraint function argument %s\n",arg); 2177 return NULL; 2178 } 2179 next_char(); 2180 } else { 2181 parse_err(SYNERR, "Invalid constraint function %s\n",func); 2182 return NULL; 2183 } 2184 2185 // Check for closing paren and ';' 2186 skipws(); 2187 if (_curchar != ')') { 2188 parse_err(SYNERR, "Missing ')' for constraint function %s\n",func); 2189 return NULL; 2190 } 2191 next_char(); 2192 skipws(); 2193 if (_curchar != ';') { 2194 parse_err(SYNERR, "Missing ';' after constraint.\n"); 2195 return NULL; 2196 } 2197 next_char(); 2198 2199 // Create new "Constraint" 2200 Constraint *constraint = new Constraint(func,arg); 2201 return constraint; 2202 } 2203 2204 //------------------------------constr_parse----------------------------------- 2205 ConstructRule *ADLParser::construct_parse(void) { 2206 return NULL; 2207 } 2208 2209 2210 //------------------------------reg_def_parse---------------------------------- 2211 void ADLParser::reg_def_parse(void) { 2212 char *rname; // Name of register being defined 2213 2214 // Get register name 2215 skipws(); // Skip whitespace 2216 rname = get_ident(); 2217 if (rname == NULL) { 2218 parse_err(SYNERR, "missing register name after reg_def\n"); 2219 return; 2220 } 2221 2222 // Check for definition of register calling convention (save on call, ...), 2223 // register save type, and register encoding value. 2224 skipws(); 2225 char *callconv = NULL; 2226 char *c_conv = NULL; 2227 char *idealtype = NULL; 2228 char *encoding = NULL; 2229 char *concrete = NULL; 2230 if (_curchar == '(') { 2231 next_char(); 2232 callconv = get_ident(); 2233 // Parse the internal calling convention, must be NS, SOC, SOE, or AS. 2234 if (callconv == NULL) { 2235 parse_err(SYNERR, "missing register calling convention value\n"); 2236 return; 2237 } 2238 if(strcmp(callconv, "SOC") && strcmp(callconv,"SOE") && 2239 strcmp(callconv, "NS") && strcmp(callconv, "AS")) { 2240 parse_err(SYNERR, "invalid value for register calling convention\n"); 2241 } 2242 skipws(); 2243 if (_curchar != ',') { 2244 parse_err(SYNERR, "missing comma in register definition statement\n"); 2245 return; 2246 } 2247 next_char(); 2248 2249 // Parse the native calling convention, must be NS, SOC, SOE, AS 2250 c_conv = get_ident(); 2251 if (c_conv == NULL) { 2252 parse_err(SYNERR, "missing register native calling convention value\n"); 2253 return; 2254 } 2255 if(strcmp(c_conv, "SOC") && strcmp(c_conv,"SOE") && 2256 strcmp(c_conv, "NS") && strcmp(c_conv, "AS")) { 2257 parse_err(SYNERR, "invalid value for register calling convention\n"); 2258 } 2259 skipws(); 2260 if (_curchar != ',') { 2261 parse_err(SYNERR, "missing comma in register definition statement\n"); 2262 return; 2263 } 2264 next_char(); 2265 skipws(); 2266 2267 // Parse the ideal save type 2268 idealtype = get_ident(); 2269 if (idealtype == NULL) { 2270 parse_err(SYNERR, "missing register save type value\n"); 2271 return; 2272 } 2273 skipws(); 2274 if (_curchar != ',') { 2275 parse_err(SYNERR, "missing comma in register definition statement\n"); 2276 return; 2277 } 2278 next_char(); 2279 skipws(); 2280 2281 // Parse the encoding value 2282 encoding = get_expr("encoding", ","); 2283 if (encoding == NULL) { 2284 parse_err(SYNERR, "missing register encoding value\n"); 2285 return; 2286 } 2287 trim(encoding); 2288 if (_curchar != ',') { 2289 parse_err(SYNERR, "missing comma in register definition statement\n"); 2290 return; 2291 } 2292 next_char(); 2293 skipws(); 2294 // Parse the concrete name type 2295 // concrete = get_ident(); 2296 concrete = get_expr("concrete", ")"); 2297 if (concrete == NULL) { 2298 parse_err(SYNERR, "missing vm register name value\n"); 2299 return; 2300 } 2301 2302 if (_curchar != ')') { 2303 parse_err(SYNERR, "missing ')' in register definition statement\n"); 2304 return; 2305 } 2306 next_char(); 2307 } 2308 2309 // Check for closing ';' 2310 skipws(); 2311 if (_curchar != ';') { 2312 parse_err(SYNERR, "missing ';' after reg_def\n"); 2313 return; 2314 } 2315 next_char(); // move past ';' 2316 2317 // Debug Stuff 2318 if (_AD._adl_debug > 1) { 2319 fprintf(stderr,"Register Definition: %s ( %s, %s %s )\n", rname, 2320 (callconv ? callconv : ""), (c_conv ? c_conv : ""), concrete); 2321 } 2322 2323 // Record new register definition. 2324 _AD._register->addRegDef(rname, callconv, c_conv, idealtype, encoding, concrete); 2325 return; 2326 } 2327 2328 //------------------------------reg_class_parse-------------------------------- 2329 void ADLParser::reg_class_parse(void) { 2330 char *cname; // Name of register class being defined 2331 2332 // Get register class name 2333 skipws(); // Skip leading whitespace 2334 cname = get_ident(); 2335 if (cname == NULL) { 2336 parse_err(SYNERR, "missing register class name after 'reg_class'\n"); 2337 return; 2338 } 2339 // Debug Stuff 2340 if (_AD._adl_debug >1) fprintf(stderr,"Register Class: %s\n", cname); 2341 2342 RegClass *reg_class = _AD._register->addRegClass(cname); 2343 2344 // Collect registers in class 2345 skipws(); 2346 if (_curchar == '(') { 2347 next_char(); // Skip '(' 2348 skipws(); 2349 while (_curchar != ')') { 2350 char *rname = get_ident(); 2351 if (rname==NULL) { 2352 parse_err(SYNERR, "missing identifier inside reg_class list.\n"); 2353 return; 2354 } 2355 RegDef *regDef = _AD._register->getRegDef(rname); 2356 reg_class->addReg(regDef); // add regDef to regClass 2357 2358 // Check for ',' and position to next token. 2359 skipws(); 2360 if (_curchar == ',') { 2361 next_char(); // Skip trailing ',' 2362 skipws(); 2363 } 2364 } 2365 next_char(); // Skip closing ')' 2366 } 2367 2368 // Check for terminating ';' 2369 skipws(); 2370 if (_curchar != ';') { 2371 parse_err(SYNERR, "missing ';' at end of reg_class definition.\n"); 2372 return; 2373 } 2374 next_char(); // Skip trailing ';' 2375 2376 // Check RegClass size, must be <= 32 registers in class. 2377 2378 return; 2379 } 2380 2381 //------------------------------alloc_class_parse------------------------------ 2382 void ADLParser::alloc_class_parse(void) { 2383 char *name; // Name of allocation class being defined 2384 2385 // Get allocation class name 2386 skipws(); // Skip leading whitespace 2387 name = get_ident(); 2388 if (name == NULL) { 2389 parse_err(SYNERR, "missing allocation class name after 'reg_class'\n"); 2390 return; 2391 } 2392 // Debug Stuff 2393 if (_AD._adl_debug >1) fprintf(stderr,"Allocation Class: %s\n", name); 2394 2395 AllocClass *alloc_class = _AD._register->addAllocClass(name); 2396 2397 // Collect registers in class 2398 skipws(); 2399 if (_curchar == '(') { 2400 next_char(); // Skip '(' 2401 skipws(); 2402 while (_curchar != ')') { 2403 char *rname = get_ident(); 2404 if (rname==NULL) { 2405 parse_err(SYNERR, "missing identifier inside reg_class list.\n"); 2406 return; 2407 } 2408 // Check if name is a RegDef 2409 RegDef *regDef = _AD._register->getRegDef(rname); 2410 if (regDef) { 2411 alloc_class->addReg(regDef); // add regDef to allocClass 2412 } else { 2413 2414 // name must be a RegDef or a RegClass 2415 parse_err(SYNERR, "name %s should be a previously defined reg_def.\n", rname); 2416 return; 2417 } 2418 2419 // Check for ',' and position to next token. 2420 skipws(); 2421 if (_curchar == ',') { 2422 next_char(); // Skip trailing ',' 2423 skipws(); 2424 } 2425 } 2426 next_char(); // Skip closing ')' 2427 } 2428 2429 // Check for terminating ';' 2430 skipws(); 2431 if (_curchar != ';') { 2432 parse_err(SYNERR, "missing ';' at end of reg_class definition.\n"); 2433 return; 2434 } 2435 next_char(); // Skip trailing ';' 2436 2437 return; 2438 } 2439 2440 //------------------------------peep_match_child_parse------------------------- 2441 InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, int &position, int input){ 2442 char *token = NULL; 2443 int lparen = 0; // keep track of parenthesis nesting depth 2444 int rparen = 0; // position of instruction at this depth 2445 InstructForm *inst_seen = NULL; 2446 InstructForm *child_seen = NULL; 2447 2448 // Walk the match tree, 2449 // Record <parent, position, instruction name, input position> 2450 while ( lparen >= rparen ) { 2451 skipws(); 2452 // Left paren signals start of an input, collect with recursive call 2453 if (_curchar == '(') { 2454 ++lparen; 2455 next_char(); 2456 child_seen = peep_match_child_parse(match, parent, position, rparen); 2457 } 2458 // Right paren signals end of an input, may be more 2459 else if (_curchar == ')') { 2460 ++rparen; 2461 if( rparen == lparen ) { // IF rparen matches an lparen I've seen 2462 next_char(); // move past ')' 2463 } else { // ELSE leave ')' for parent 2464 assert( rparen == lparen + 1, "Should only see one extra ')'"); 2465 // if an instruction was not specified for this paren-pair 2466 if( ! inst_seen ) { // record signal entry 2467 match.add_instruction( parent, position, NameList::_signal, input ); 2468 ++position; 2469 } 2470 // ++input; // TEMPORARY 2471 return inst_seen; 2472 } 2473 } 2474 // if no parens, then check for instruction name 2475 // This instruction is the parent of a sub-tree 2476 else if ((token = get_ident_dup()) != NULL) { 2477 const Form *form = _AD._globalNames[token]; 2478 if (form) { 2479 InstructForm *inst = form->is_instruction(); 2480 // Record the first instruction at this level 2481 if( inst_seen == NULL ) { 2482 inst_seen = inst; 2483 } 2484 if (inst) { 2485 match.add_instruction( parent, position, token, input ); 2486 parent = position; 2487 ++position; 2488 } else { 2489 parse_err(SYNERR, "instruction name expected at identifier %s.\n", 2490 token); 2491 return inst_seen; 2492 } 2493 } 2494 else { 2495 parse_err(SYNERR, "missing identifier in peepmatch rule.\n"); 2496 return NULL; 2497 } 2498 } 2499 else { 2500 parse_err(SYNERR, "missing identifier in peepmatch rule.\n"); 2501 return NULL; 2502 } 2503 2504 } // end while 2505 2506 assert( false, "ShouldNotReachHere();"); 2507 return NULL; 2508 } 2509 2510 //------------------------------peep_match_parse------------------------------- 2511 // Syntax for a peepmatch rule 2512 // 2513 // peepmatch ( root_instr_name [(instruction subtree)] [,(instruction subtree)]* ); 2514 // 2515 void ADLParser::peep_match_parse(Peephole &peep) { 2516 2517 skipws(); 2518 // Check the structure of the rule 2519 // Check for open paren 2520 if (_curchar != '(') { 2521 parse_err(SYNERR, "missing '(' at start of peepmatch rule.\n"); 2522 return; 2523 } 2524 next_char(); // skip '(' 2525 2526 // Construct PeepMatch and parse the peepmatch rule. 2527 PeepMatch *match = new PeepMatch(_ptr); 2528 int parent = -1; // parent of root 2529 int position = 0; // zero-based positions 2530 int input = 0; // input position in parent's operands 2531 InstructForm *root= peep_match_child_parse( *match, parent, position, input); 2532 if( root == NULL ) { 2533 parse_err(SYNERR, "missing instruction-name at start of peepmatch.\n"); 2534 return; 2535 } 2536 2537 if( _curchar != ')' ) { 2538 parse_err(SYNERR, "missing ')' at end of peepmatch.\n"); 2539 return; 2540 } 2541 next_char(); // skip ')' 2542 2543 // Check for closing semicolon 2544 skipws(); 2545 if( _curchar != ';' ) { 2546 parse_err(SYNERR, "missing ';' at end of peepmatch.\n"); 2547 return; 2548 } 2549 next_char(); // skip ';' 2550 2551 // Store match into peep, and store peep into instruction 2552 peep.add_match(match); 2553 root->append_peephole(&peep); 2554 } 2555 2556 //------------------------------peep_constraint_parse-------------------------- 2557 // Syntax for a peepconstraint rule 2558 // A parenthesized list of relations between operands in peepmatch subtree 2559 // 2560 // peepconstraint %{ 2561 // (instruction_number.operand_name 2562 // relational_op 2563 // instruction_number.operand_name OR register_name 2564 // [, ...] ); 2565 // 2566 // // instruction numbers are zero-based using topological order in peepmatch 2567 // 2568 void ADLParser::peep_constraint_parse(Peephole &peep) { 2569 2570 skipws(); 2571 // Check the structure of the rule 2572 // Check for open paren 2573 if (_curchar != '(') { 2574 parse_err(SYNERR, "missing '(' at start of peepconstraint rule.\n"); 2575 return; 2576 } 2577 else { 2578 next_char(); // Skip '(' 2579 } 2580 2581 // Check for a constraint 2582 skipws(); 2583 while( _curchar != ')' ) { 2584 // Get information on the left instruction and its operand 2585 // left-instructions's number 2586 intptr_t left_inst = get_int(); 2587 // Left-instruction's operand 2588 skipws(); 2589 if( _curchar != '.' ) { 2590 parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n"); 2591 return; 2592 } 2593 next_char(); // Skip '.' 2594 char *left_op = get_ident_dup(); 2595 2596 skipws(); 2597 // Collect relational operator 2598 char *relation = get_relation_dup(); 2599 2600 skipws(); 2601 // Get information on the right instruction and its operand 2602 intptr_t right_inst; // Right-instructions's number 2603 if( isdigit(_curchar) ) { 2604 right_inst = get_int(); 2605 // Right-instruction's operand 2606 skipws(); 2607 if( _curchar != '.' ) { 2608 parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n"); 2609 return; 2610 } 2611 next_char(); // Skip '.' 2612 } else { 2613 right_inst = -1; // Flag as being a register constraint 2614 } 2615 2616 char *right_op = get_ident_dup(); 2617 2618 // Construct the next PeepConstraint 2619 PeepConstraint *constraint = new PeepConstraint( left_inst, left_op, 2620 relation, 2621 right_inst, right_op ); 2622 // And append it to the list for this peephole rule 2623 peep.append_constraint( constraint ); 2624 2625 // Check for another constraint, or end of rule 2626 skipws(); 2627 if( _curchar == ',' ) { 2628 next_char(); // Skip ',' 2629 skipws(); 2630 } 2631 else if( _curchar != ')' ) { 2632 parse_err(SYNERR, "expected ',' or ')' after peephole constraint.\n"); 2633 return; 2634 } 2635 } // end while( processing constraints ) 2636 next_char(); // Skip ')' 2637 2638 // Check for terminating ';' 2639 skipws(); 2640 if (_curchar != ';') { 2641 parse_err(SYNERR, "missing ';' at end of peepconstraint.\n"); 2642 return; 2643 } 2644 next_char(); // Skip trailing ';' 2645 } 2646 2647 2648 //------------------------------peep_replace_parse----------------------------- 2649 // Syntax for a peepreplace rule 2650 // root instruction name followed by a 2651 // parenthesized list of whitespace separated instruction.operand specifiers 2652 // 2653 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 2654 // 2655 // 2656 void ADLParser::peep_replace_parse(Peephole &peep) { 2657 int lparen = 0; // keep track of parenthesis nesting depth 2658 int rparen = 0; // keep track of parenthesis nesting depth 2659 int icount = 0; // count of instructions in rule for naming 2660 char *str = NULL; 2661 char *token = NULL; 2662 2663 skipws(); 2664 // Check for open paren 2665 if (_curchar != '(') { 2666 parse_err(SYNERR, "missing '(' at start of peepreplace rule.\n"); 2667 return; 2668 } 2669 else { 2670 lparen++; 2671 next_char(); 2672 } 2673 2674 // Check for root instruction 2675 char *inst = get_ident_dup(); 2676 const Form *form = _AD._globalNames[inst]; 2677 if( form == NULL || form->is_instruction() == NULL ) { 2678 parse_err(SYNERR, "Instruction name expected at start of peepreplace.\n"); 2679 return; 2680 } 2681 2682 // Store string representation of rule into replace 2683 PeepReplace *replace = new PeepReplace(str); 2684 replace->add_instruction( inst ); 2685 2686 skipws(); 2687 // Start of root's operand-list 2688 if (_curchar != '(') { 2689 parse_err(SYNERR, "missing '(' at peepreplace root's operand-list.\n"); 2690 return; 2691 } 2692 else { 2693 lparen++; 2694 next_char(); 2695 } 2696 2697 skipws(); 2698 // Get the list of operands 2699 while( _curchar != ')' ) { 2700 // Get information on an instruction and its operand 2701 // instructions's number 2702 int inst_num = get_int(); 2703 // Left-instruction's operand 2704 skipws(); 2705 if( _curchar != '.' ) { 2706 parse_err(SYNERR, "missing '.' in peepreplace after instruction number.\n"); 2707 return; 2708 } 2709 next_char(); // Skip '.' 2710 char *inst_op = get_ident_dup(); 2711 if( inst_op == NULL ) { 2712 parse_err(SYNERR, "missing operand identifier in peepreplace.\n"); 2713 return; 2714 } 2715 2716 // Record this operand's position in peepmatch 2717 replace->add_operand( inst_num, inst_op ); 2718 skipws(); 2719 } 2720 2721 // Check for the end of operands list 2722 skipws(); 2723 assert( _curchar == ')', "While loop should have advanced to ')'."); 2724 next_char(); // Skip ')' 2725 2726 skipws(); 2727 // Check for end of peepreplace 2728 if( _curchar != ')' ) { 2729 parse_err(SYNERR, "missing ')' at end of peepmatch.\n"); 2730 parse_err(SYNERR, "Support one replacement instruction.\n"); 2731 return; 2732 } 2733 next_char(); // Skip ')' 2734 2735 // Check for closing semicolon 2736 skipws(); 2737 if( _curchar != ';' ) { 2738 parse_err(SYNERR, "missing ';' at end of peepreplace.\n"); 2739 return; 2740 } 2741 next_char(); // skip ';' 2742 2743 // Store replace into peep 2744 peep.add_replace( replace ); 2745 } 2746 2747 //------------------------------pred_parse------------------------------------- 2748 Predicate *ADLParser::pred_parse(void) { 2749 Predicate *predicate; // Predicate class for operand 2750 char *rule = NULL; // String representation of predicate 2751 2752 skipws(); // Skip leading whitespace 2753 if ( (rule = get_paren_expr("pred expression")) == NULL ) { 2754 parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n"); 2755 return NULL; 2756 } 2757 // Debug Stuff 2758 if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule); 2759 if (_curchar != ';') { 2760 parse_err(SYNERR, "missing ';' in predicate definition\n"); 2761 return NULL; 2762 } 2763 next_char(); // Point after the terminator 2764 2765 predicate = new Predicate(rule); // Build new predicate object 2766 skipws(); 2767 return predicate; 2768 } 2769 2770 2771 //------------------------------ins_encode_parse_block------------------------- 2772 // Parse the block form of ins_encode. See ins_encode_parse for more details 2773 InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) { 2774 // Create a new encoding name based on the name of the instruction 2775 // definition, which should be unique. 2776 const char * prefix = "__enc_"; 2777 char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1); 2778 sprintf(ec_name, "%s%s", prefix, inst._ident); 2779 2780 assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); 2781 EncClass *encoding = _AD._encode->add_EncClass(ec_name); 2782 encoding->_linenum = _linenum; 2783 2784 // synthesize the arguments list for the enc_class from the 2785 // arguments to the instruct definition. 2786 const char * param = NULL; 2787 inst._parameters.reset(); 2788 while ((param = inst._parameters.iter()) != NULL) { 2789 OperandForm *opForm = (OperandForm*)inst._localNames[param]; 2790 encoding->add_parameter(opForm->_ident, param); 2791 } 2792 2793 // Add the prologue to create the MacroAssembler 2794 encoding->add_code("\n" 2795 " // Define a MacroAssembler instance for use by the encoding. The\n" 2796 " // name is chosen to match the __ idiom used for assembly in other\n" 2797 " // parts of hotspot and assumes the existence of the standard\n" 2798 " // #define __ _masm.\n" 2799 " MacroAssembler _masm(&cbuf);\n"); 2800 2801 // Parse the following %{ }% block 2802 enc_class_parse_block(encoding, ec_name); 2803 2804 // Build an encoding rule which invokes the encoding rule we just 2805 // created, passing all arguments that we received. 2806 InsEncode *encrule = new InsEncode(); // Encode class for instruction 2807 NameAndList *params = encrule->add_encode(ec_name); 2808 inst._parameters.reset(); 2809 while ((param = inst._parameters.iter()) != NULL) { 2810 params->add_entry(param); 2811 } 2812 2813 return encrule; 2814 } 2815 2816 2817 //------------------------------ins_encode_parse------------------------------- 2818 // Encode rules have the form 2819 // ins_encode( encode_class_name(parameter_list), ... ); 2820 // 2821 // The "encode_class_name" must be defined in the encode section 2822 // The parameter list contains $names that are locals. 2823 // 2824 // Alternatively it can be written like this: 2825 // 2826 // ins_encode %{ 2827 // ... // body 2828 // %} 2829 // 2830 // which synthesizes a new encoding class taking the same arguments as 2831 // the InstructForm, and automatically prefixes the definition with: 2832 // 2833 // MacroAssembler masm(&cbuf);\n"); 2834 // 2835 // making it more compact to take advantage of the MacroAssembler and 2836 // placing the assembly closer to it's use by instructions. 2837 InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) { 2838 2839 // Parse encode class name 2840 skipws(); // Skip whitespace 2841 if (_curchar != '(') { 2842 // Check for ins_encode %{ form 2843 if ((_curchar == '%') && (*(_ptr+1) == '{')) { 2844 next_char(); // Skip '%' 2845 next_char(); // Skip '{' 2846 2847 // Parse the block form of ins_encode 2848 return ins_encode_parse_block(inst); 2849 } 2850 2851 parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n"); 2852 return NULL; 2853 } 2854 next_char(); // move past '(' 2855 skipws(); 2856 2857 InsEncode *encrule = new InsEncode(); // Encode class for instruction 2858 encrule->_linenum = _linenum; 2859 char *ec_name = NULL; // String representation of encode rule 2860 // identifier is optional. 2861 while (_curchar != ')') { 2862 ec_name = get_ident(); 2863 if (ec_name == NULL) { 2864 parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n"); 2865 return NULL; 2866 } 2867 // Check that encoding is defined in the encode section 2868 EncClass *encode_class = _AD._encode->encClass(ec_name); 2869 if (encode_class == NULL) { 2870 // Like to defer checking these till later... 2871 // parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name); 2872 } 2873 2874 // Get list for encode method's parameters 2875 NameAndList *params = encrule->add_encode(ec_name); 2876 2877 // Parse the parameters to this encode method. 2878 skipws(); 2879 if ( _curchar == '(' ) { 2880 next_char(); // move past '(' for parameters 2881 2882 // Parse the encode method's parameters 2883 while (_curchar != ')') { 2884 char *param = get_ident_or_literal_constant("encoding operand"); 2885 if ( param != NULL ) { 2886 // Found a parameter: 2887 // Check it is a local name, add it to the list, then check for more 2888 // New: allow hex constants as parameters to an encode method. 2889 // New: allow parenthesized expressions as parameters. 2890 // New: allow "primary", "secondary", "tertiary" as parameters. 2891 // New: allow user-defined register name as parameter 2892 if ( (inst._localNames[param] == NULL) && 2893 !ADLParser::is_literal_constant(param) && 2894 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && 2895 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) { 2896 parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); 2897 return NULL; 2898 } 2899 params->add_entry(param); 2900 2901 skipws(); 2902 if (_curchar == ',' ) { 2903 // More parameters to come 2904 next_char(); // move past ',' between parameters 2905 skipws(); // Skip to next parameter 2906 } 2907 else if (_curchar == ')') { 2908 // Done with parameter list 2909 } 2910 else { 2911 // Only ',' or ')' are valid after a parameter name 2912 parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", 2913 ec_name); 2914 return NULL; 2915 } 2916 2917 } else { 2918 skipws(); 2919 // Did not find a parameter 2920 if (_curchar == ',') { 2921 parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name); 2922 return NULL; 2923 } 2924 if (_curchar != ')') { 2925 parse_err(SYNERR, "Expected ')' after encode parameters.\n"); 2926 return NULL; 2927 } 2928 } 2929 } // WHILE loop collecting parameters 2930 next_char(); // move past ')' at end of parameters 2931 } // done with parameter list for encoding 2932 2933 // Check for ',' or ')' after encoding 2934 skipws(); // move to character after parameters 2935 if ( _curchar == ',' ) { 2936 // Found a ',' 2937 next_char(); // move past ',' between encode methods 2938 skipws(); 2939 } 2940 else if ( _curchar != ')' ) { 2941 // If not a ',' then only a ')' is allowed 2942 parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name); 2943 return NULL; 2944 } 2945 2946 // Check for ',' separating parameters 2947 // if ( _curchar != ',' && _curchar != ')' ) { 2948 // parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n"); 2949 // return NULL; 2950 // } 2951 2952 } // done parsing ins_encode methods and their parameters 2953 if (_curchar != ')') { 2954 parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n"); 2955 return NULL; 2956 } 2957 next_char(); // move past ')' 2958 skipws(); // Skip leading whitespace 2959 2960 if ( _curchar != ';' ) { 2961 parse_err(SYNERR, "Missing ';' at end of ins_encode.\n"); 2962 return NULL; 2963 } 2964 next_char(); // move past ';' 2965 skipws(); // be friendly to oper_parse() 2966 2967 // Debug Stuff 2968 if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name); 2969 2970 return encrule; 2971 } 2972 2973 2974 //------------------------------size_parse----------------------------------- 2975 char* ADLParser::size_parse(InstructForm *instr) { 2976 char* sizeOfInstr = NULL; 2977 2978 // Get value of the instruction's size 2979 skipws(); 2980 2981 // Parse size 2982 sizeOfInstr = get_paren_expr("size expression"); 2983 if (sizeOfInstr == NULL) { 2984 parse_err(SYNERR, "size of opcode expected at %c\n", _curchar); 2985 return NULL; 2986 } 2987 2988 skipws(); 2989 2990 // Check for terminator 2991 if (_curchar != ';') { 2992 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 2993 return NULL; 2994 } 2995 next_char(); // Advance past the ';' 2996 skipws(); // necessary for instr_parse() 2997 2998 // Debug Stuff 2999 if (_AD._adl_debug > 1) { 3000 if (sizeOfInstr != NULL) { 3001 fprintf(stderr,"size of opcode: %s\n", sizeOfInstr); 3002 } 3003 } 3004 3005 return sizeOfInstr; 3006 } 3007 3008 3009 //------------------------------opcode_parse----------------------------------- 3010 Opcode * ADLParser::opcode_parse(InstructForm *instr) { 3011 char *primary = NULL; 3012 char *secondary = NULL; 3013 char *tertiary = NULL; 3014 3015 char *val = NULL; 3016 Opcode *opcode = NULL; 3017 3018 // Get value of the instruction's opcode 3019 skipws(); 3020 if (_curchar != '(') { // Check for parenthesized operand list 3021 parse_err(SYNERR, "missing '(' in expand instruction declaration\n"); 3022 return NULL; 3023 } 3024 next_char(); // skip open paren 3025 skipws(); 3026 if (_curchar != ')') { 3027 // Parse primary, secondary, and tertiary opcodes, if provided. 3028 if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) { 3029 parse_err(SYNERR, "primary hex opcode expected at %c\n", _curchar); 3030 return NULL; 3031 } 3032 skipws(); 3033 if (_curchar == ',') { 3034 next_char(); 3035 skipws(); 3036 // Parse secondary opcode 3037 if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) { 3038 parse_err(SYNERR, "secondary hex opcode expected at %c\n", _curchar); 3039 return NULL; 3040 } 3041 skipws(); 3042 if (_curchar == ',') { 3043 next_char(); 3044 skipws(); 3045 // Parse tertiary opcode 3046 if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) { 3047 parse_err(SYNERR,"tertiary hex opcode expected at %c\n", _curchar); 3048 return NULL; 3049 } 3050 skipws(); 3051 } 3052 } 3053 skipws(); 3054 if (_curchar != ')') { 3055 parse_err(SYNERR, "Missing ')' in opcode description\n"); 3056 return NULL; 3057 } 3058 } 3059 next_char(); // Skip ')' 3060 skipws(); 3061 // Check for terminator 3062 if (_curchar != ';') { 3063 parse_err(SYNERR, "missing ';' in ins_attrib definition\n"); 3064 return NULL; 3065 } 3066 next_char(); // Advance past the ';' 3067 skipws(); // necessary for instr_parse() 3068 3069 // Debug Stuff 3070 if (_AD._adl_debug > 1) { 3071 if (primary != NULL) fprintf(stderr,"primary opcode: %s\n", primary); 3072 if (secondary != NULL) fprintf(stderr,"secondary opcode: %s\n", secondary); 3073 if (tertiary != NULL) fprintf(stderr,"tertiary opcode: %s\n", tertiary); 3074 } 3075 3076 // Generate new object and return 3077 opcode = new Opcode(primary, secondary, tertiary); 3078 return opcode; 3079 } 3080 3081 3082 //------------------------------interface_parse-------------------------------- 3083 Interface *ADLParser::interface_parse(void) { 3084 char *iface_name = NULL; // Name of interface class being used 3085 char *iface_code = NULL; // Describe components of this class 3086 3087 // Get interface class name 3088 skipws(); // Skip whitespace 3089 if (_curchar != '(') { 3090 parse_err(SYNERR, "Missing '(' at start of interface description.\n"); 3091 return NULL; 3092 } 3093 next_char(); // move past '(' 3094 skipws(); 3095 iface_name = get_ident(); 3096 if (iface_name == NULL) { 3097 parse_err(SYNERR, "missing interface name after 'interface'.\n"); 3098 return NULL; 3099 } 3100 skipws(); 3101 if (_curchar != ')') { 3102 parse_err(SYNERR, "Missing ')' after name of interface.\n"); 3103 return NULL; 3104 } 3105 next_char(); // move past ')' 3106 3107 // Get details of the interface, 3108 // for the type of interface indicated by iface_name. 3109 Interface *inter = NULL; 3110 skipws(); 3111 if ( _curchar != ';' ) { 3112 if ( strcmp(iface_name,"MEMORY_INTER") == 0 ) { 3113 inter = mem_interface_parse(); 3114 } 3115 else if ( strcmp(iface_name,"COND_INTER") == 0 ) { 3116 inter = cond_interface_parse(); 3117 } 3118 // The parse routines consume the "%}" 3119 3120 // Check for probable extra ';' after defining block. 3121 if ( _curchar == ';' ) { 3122 parse_err(SYNERR, "Extra ';' after defining interface block.\n"); 3123 next_char(); // Skip ';' 3124 return NULL; 3125 } 3126 } else { 3127 next_char(); // move past ';' 3128 3129 // Create appropriate interface object 3130 if ( strcmp(iface_name,"REG_INTER") == 0 ) { 3131 inter = new RegInterface(); 3132 } 3133 else if ( strcmp(iface_name,"CONST_INTER") == 0 ) { 3134 inter = new ConstInterface(); 3135 } 3136 } 3137 skipws(); // be friendly to oper_parse() 3138 // Debug Stuff 3139 if (_AD._adl_debug > 1) fprintf(stderr,"Interface Form: %s\n", iface_name); 3140 3141 // Create appropriate interface object and return. 3142 return inter; 3143 } 3144 3145 3146 //------------------------------mem_interface_parse---------------------------- 3147 Interface *ADLParser::mem_interface_parse(void) { 3148 // Fields for MemInterface 3149 char *base = NULL; 3150 char *index = NULL; 3151 char *scale = NULL; 3152 char *disp = NULL; 3153 3154 if (_curchar != '%') { 3155 parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); 3156 return NULL; 3157 } 3158 next_char(); // Skip '%' 3159 if (_curchar != '{') { 3160 parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); 3161 return NULL; 3162 } 3163 next_char(); // Skip '{' 3164 skipws(); 3165 do { 3166 char *field = get_ident(); 3167 if (field == NULL) { 3168 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3169 return NULL; 3170 } 3171 if ( strcmp(field,"base") == 0 ) { 3172 base = interface_field_parse(); 3173 } 3174 else if ( strcmp(field,"index") == 0 ) { 3175 index = interface_field_parse(); 3176 } 3177 else if ( strcmp(field,"scale") == 0 ) { 3178 scale = interface_field_parse(); 3179 } 3180 else if ( strcmp(field,"disp") == 0 ) { 3181 disp = interface_field_parse(); 3182 } 3183 else { 3184 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3185 return NULL; 3186 } 3187 } while( _curchar != '%' ); 3188 next_char(); // Skip '%' 3189 if ( _curchar != '}' ) { 3190 parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); 3191 return NULL; 3192 } 3193 next_char(); // Skip '}' 3194 3195 // Construct desired object and return 3196 Interface *inter = new MemInterface(base, index, scale, disp); 3197 return inter; 3198 } 3199 3200 3201 //------------------------------cond_interface_parse--------------------------- 3202 Interface *ADLParser::cond_interface_parse(void) { 3203 char *equal; 3204 char *not_equal; 3205 char *less; 3206 char *greater_equal; 3207 char *less_equal; 3208 char *greater; 3209 3210 if (_curchar != '%') { 3211 parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); 3212 return NULL; 3213 } 3214 next_char(); // Skip '%' 3215 if (_curchar != '{') { 3216 parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); 3217 return NULL; 3218 } 3219 next_char(); // Skip '{' 3220 skipws(); 3221 do { 3222 char *field = get_ident(); 3223 if (field == NULL) { 3224 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3225 return NULL; 3226 } 3227 if ( strcmp(field,"equal") == 0 ) { 3228 equal = interface_field_parse(); 3229 } 3230 else if ( strcmp(field,"not_equal") == 0 ) { 3231 not_equal = interface_field_parse(); 3232 } 3233 else if ( strcmp(field,"less") == 0 ) { 3234 less = interface_field_parse(); 3235 } 3236 else if ( strcmp(field,"greater_equal") == 0 ) { 3237 greater_equal = interface_field_parse(); 3238 } 3239 else if ( strcmp(field,"less_equal") == 0 ) { 3240 less_equal = interface_field_parse(); 3241 } 3242 else if ( strcmp(field,"greater") == 0 ) { 3243 greater = interface_field_parse(); 3244 } 3245 else { 3246 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 3247 return NULL; 3248 } 3249 } while( _curchar != '%' ); 3250 next_char(); // Skip '%' 3251 if ( _curchar != '}' ) { 3252 parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); 3253 return NULL; 3254 } 3255 next_char(); // Skip '}' 3256 3257 // Construct desired object and return 3258 Interface *inter = new CondInterface(equal, not_equal, less, greater_equal, 3259 less_equal, greater); 3260 return inter; 3261 } 3262 3263 3264 //------------------------------interface_field_parse-------------------------- 3265 char *ADLParser::interface_field_parse(void) { 3266 char *iface_field = NULL; 3267 3268 // Get interface field 3269 skipws(); // Skip whitespace 3270 if (_curchar != '(') { 3271 parse_err(SYNERR, "Missing '(' at start of interface field.\n"); 3272 return NULL; 3273 } 3274 next_char(); // move past '(' 3275 skipws(); 3276 if ( _curchar != '0' && _curchar != '$' ) { 3277 parse_err(SYNERR, "missing or invalid interface field contents.\n"); 3278 return NULL; 3279 } 3280 iface_field = get_rep_var_ident(); 3281 if (iface_field == NULL) { 3282 parse_err(SYNERR, "missing or invalid interface field contents.\n"); 3283 return NULL; 3284 } 3285 skipws(); 3286 if (_curchar != ')') { 3287 parse_err(SYNERR, "Missing ')' after interface field.\n"); 3288 return NULL; 3289 } 3290 next_char(); // move past ')' 3291 skipws(); 3292 if ( _curchar != ';' ) { 3293 parse_err(SYNERR, "Missing ';' at end of interface field.\n"); 3294 return NULL; 3295 } 3296 next_char(); // move past ';' 3297 skipws(); // be friendly to interface_parse() 3298 3299 return iface_field; 3300 } 3301 3302 3303 //------------------------------match_parse------------------------------------ 3304 MatchRule *ADLParser::match_parse(FormDict &operands) { 3305 MatchRule *match; // Match Rule class for instruction/operand 3306 char *cnstr = NULL; // Code for constructor 3307 int depth = 0; // Counter for matching parentheses 3308 int numleaves = 0; // Counter for number of leaves in rule 3309 3310 // Parse the match rule tree 3311 MatchNode *mnode = matchNode_parse(operands, depth, numleaves, true); 3312 3313 // Either there is a block with a constructor, or a ';' here 3314 skipws(); // Skip whitespace 3315 if ( _curchar == ';' ) { // Semicolon is valid terminator 3316 cnstr = NULL; // no constructor for this form 3317 next_char(); // Move past the ';', replaced with '\0' 3318 } 3319 else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { 3320 parse_err(SYNERR, "invalid construction of match rule\n" 3321 "Missing ';' or invalid '%{' and '%}' constructor\n"); 3322 return NULL; // No MatchRule to return 3323 } 3324 if (_AD._adl_debug > 1) 3325 if (cnstr) fprintf(stderr,"Match Constructor: %s\n", cnstr); 3326 // Build new MatchRule object 3327 match = new MatchRule(_AD, mnode, depth, cnstr, numleaves); 3328 skipws(); // Skip any trailing whitespace 3329 return match; // Return MatchRule object 3330 } 3331 3332 //------------------------------format_parse----------------------------------- 3333 FormatRule* ADLParser::format_parse(void) { 3334 char *desc = NULL; 3335 FormatRule *format = (new FormatRule(desc)); 3336 3337 // Without expression form, MUST have a code block; 3338 skipws(); // Skip whitespace 3339 if ( _curchar == ';' ) { // Semicolon is valid terminator 3340 desc = NULL; // no constructor for this form 3341 next_char(); // Move past the ';', replaced with '\0' 3342 } 3343 else if ( _curchar == '%' && *(_ptr+1) == '{') { 3344 next_char(); // Move past the '%' 3345 next_char(); // Move past the '{' 3346 3347 skipws(); 3348 // Check for the opening '"' inside the format description 3349 if ( _curchar == '"' ) { 3350 next_char(); // Move past the initial '"' 3351 if( _curchar == '"' ) { // Handle empty format string case 3352 *_ptr = '\0'; // Terminate empty string 3353 format->_strings.addName(_ptr); 3354 } 3355 3356 // Collect the parts of the format description 3357 // (1) strings that are passed through to tty->print 3358 // (2) replacement/substitution variable, preceeded by a '$' 3359 // (3) multi-token ANSIY C style strings 3360 while ( true ) { 3361 if ( _curchar == '%' || _curchar == '\n' ) { 3362 if ( _curchar != '"' ) { 3363 parse_err(SYNERR, "missing '\"' at end of format block"); 3364 return NULL; 3365 } 3366 } 3367 3368 // (1) 3369 // Check if there is a string to pass through to output 3370 char *start = _ptr; // Record start of the next string 3371 while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { 3372 if (_curchar == '\\') next_char(); // superquote 3373 if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! 3374 next_char(); 3375 } 3376 // If a string was found, terminate it and record in FormatRule 3377 if ( start != _ptr ) { 3378 *_ptr = '\0'; // Terminate the string 3379 format->_strings.addName(start); 3380 } 3381 3382 // (2) 3383 // If we are at a replacement variable, 3384 // copy it and record in FormatRule 3385 if ( _curchar == '$' ) { 3386 next_char(); // Move past the '$' 3387 char* rep_var = get_ident(); // Nil terminate the variable name 3388 rep_var = strdup(rep_var);// Copy the string 3389 *_ptr = _curchar; // and replace Nil with original character 3390 format->_rep_vars.addName(rep_var); 3391 // Add flag to _strings list indicating we should check _rep_vars 3392 format->_strings.addName(NameList::_signal); 3393 } 3394 3395 // (3) 3396 // Allow very long strings to be broken up, 3397 // using the ANSI C syntax "foo\n" <newline> "bar" 3398 if ( _curchar == '"') { 3399 next_char(); // Move past the '"' 3400 skipws(); // Skip white space before next string token 3401 if ( _curchar != '"') { 3402 break; 3403 } else { 3404 // Found one. Skip both " and the whitespace in between. 3405 next_char(); 3406 } 3407 } 3408 } // end while part of format description 3409 3410 // Check for closing '"' and '%}' in format description 3411 skipws(); // Move to closing '%}' 3412 if ( _curchar != '%' ) { 3413 parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); 3414 return NULL; 3415 } 3416 } // Done with format description inside 3417 3418 skipws(); 3419 // Past format description, at '%' 3420 if ( _curchar != '%' || *(_ptr+1) != '}' ) { 3421 parse_err(SYNERR, "missing '%}' at end of format block"); 3422 return NULL; 3423 } 3424 next_char(); // Move past the '%' 3425 next_char(); // Move past the '}' 3426 } 3427 else { // parameter list alone must terminate with a ';' 3428 parse_err(SYNERR, "missing ';' after Format expression"); 3429 return NULL; 3430 } 3431 // Debug Stuff 3432 if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc); 3433 3434 skipws(); 3435 return format; 3436 } 3437 3438 3439 //------------------------------effect_parse----------------------------------- 3440 void ADLParser::effect_parse(InstructForm *instr) { 3441 char* desc = NULL; 3442 3443 skipws(); // Skip whitespace 3444 if (_curchar != '(') { 3445 parse_err(SYNERR, "missing '(' in effect definition\n"); 3446 return; 3447 } 3448 // Get list of effect-operand pairs and insert into dictionary 3449 else get_effectlist(instr->_effects, instr->_localNames); 3450 3451 // Debug Stuff 3452 if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc); 3453 if (_curchar != ';') { 3454 parse_err(SYNERR, "missing ';' in Effect definition\n"); 3455 } 3456 next_char(); // Skip ';' 3457 3458 } 3459 3460 //------------------------------expand_parse----------------------------------- 3461 ExpandRule* ADLParser::expand_parse(InstructForm *instr) { 3462 char *ident, *ident2; 3463 OperandForm *oper; 3464 InstructForm *ins; 3465 NameAndList *instr_and_operands = NULL; 3466 ExpandRule *exp = new ExpandRule(); 3467 3468 // Expand is a block containing an ordered list of instructions, each of 3469 // which has an ordered list of operands. 3470 // Check for block delimiter 3471 skipws(); // Skip leading whitespace 3472 if ((_curchar != '%') 3473 || (next_char(), (_curchar != '{')) ) { // If not open block 3474 parse_err(SYNERR, "missing '%{' in expand definition\n"); 3475 return(NULL); 3476 } 3477 next_char(); // Maintain the invariant 3478 do { 3479 ident = get_ident(); // Grab next identifier 3480 if (ident == NULL) { 3481 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3482 continue; 3483 } // Check that you have a valid instruction 3484 const Form *form = _globalNames[ident]; 3485 ins = form ? form->is_instruction() : NULL; 3486 if (ins == NULL) { 3487 // This is a new operand 3488 oper = form ? form->is_operand() : NULL; 3489 if (oper == NULL) { 3490 parse_err(SYNERR, "instruction/operand name expected at %s\n", ident); 3491 continue; 3492 } 3493 // Throw the operand on the _newopers list 3494 skipws(); 3495 ident = get_unique_ident(instr->_localNames,"Operand"); 3496 if (ident == NULL) { 3497 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3498 continue; 3499 } 3500 exp->_newopers.addName(ident); 3501 // Add new operand to LocalNames 3502 instr->_localNames.Insert(ident, oper); 3503 // Grab any constructor code and save as a string 3504 char *c = NULL; 3505 skipws(); 3506 if (_curchar == '%') { // Need a constructor for the operand 3507 c = find_cpp_block("Operand Constructor"); 3508 if (c == NULL) { 3509 parse_err(SYNERR, "Invalid code block for operand constructor\n", _curchar); 3510 continue; 3511 } 3512 // Add constructor to _newopconst Dict 3513 exp->_newopconst.Insert(ident, c); 3514 } 3515 else if (_curchar != ';') { // If no constructor, need a ; 3516 parse_err(SYNERR, "Missing ; in expand rule operand declaration\n"); 3517 continue; 3518 } 3519 else next_char(); // Skip the ; 3520 skipws(); 3521 } 3522 else { 3523 // Add instruction to list 3524 instr_and_operands = new NameAndList(ident); 3525 // Grab operands, build nameList of them, and then put into dictionary 3526 skipws(); 3527 if (_curchar != '(') { // Check for parenthesized operand list 3528 parse_err(SYNERR, "missing '(' in expand instruction declaration\n"); 3529 continue; 3530 } 3531 do { 3532 next_char(); // skip open paren & comma characters 3533 skipws(); 3534 if (_curchar == ')') break; 3535 ident2 = get_ident(); 3536 skipws(); 3537 if (ident2 == NULL) { 3538 parse_err(SYNERR, "identifier expected at %c\n", _curchar); 3539 continue; 3540 } // Check that you have a valid operand 3541 const Form *form = instr->_localNames[ident2]; 3542 if (!form) { 3543 parse_err(SYNERR, "operand name expected at %s\n", ident2); 3544 continue; 3545 } 3546 oper = form->is_operand(); 3547 if (oper == NULL && !form->is_opclass()) { 3548 parse_err(SYNERR, "operand name expected at %s\n", ident2); 3549 continue; 3550 } // Add operand to list 3551 instr_and_operands->add_entry(ident2); 3552 } while(_curchar == ','); 3553 if (_curchar != ')') { 3554 parse_err(SYNERR, "missing ')'in expand instruction declaration\n"); 3555 continue; 3556 } 3557 next_char(); 3558 if (_curchar != ';') { 3559 parse_err(SYNERR, "missing ';'in expand instruction declaration\n"); 3560 continue; 3561 } 3562 next_char(); 3563 3564 // Record both instruction name and its operand list 3565 exp->add_instruction(instr_and_operands); 3566 3567 skipws(); 3568 } 3569 3570 } while(_curchar != '%'); 3571 next_char(); 3572 if (_curchar != '}') { 3573 parse_err(SYNERR, "missing '%}' in expand rule definition\n"); 3574 return(NULL); 3575 } 3576 next_char(); 3577 3578 // Debug Stuff 3579 if (_AD._adl_debug > 1) fprintf(stderr,"Expand Rule:\n"); 3580 3581 skipws(); 3582 return (exp); 3583 } 3584 3585 //------------------------------rewrite_parse---------------------------------- 3586 RewriteRule* ADLParser::rewrite_parse(void) { 3587 char* params = NULL; 3588 char* desc = NULL; 3589 3590 3591 // This feature targeted for second generation description language. 3592 3593 skipws(); // Skip whitespace 3594 // Get parameters for rewrite 3595 if ((params = get_paren_expr("rewrite parameters")) == NULL) { 3596 parse_err(SYNERR, "missing '(' in rewrite rule\n"); 3597 return NULL; 3598 } 3599 // Debug Stuff 3600 if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite parameters: %s\n", params); 3601 3602 // For now, grab entire block; 3603 skipws(); 3604 if ( (desc = find_cpp_block("rewrite block")) == NULL ) { 3605 parse_err(SYNERR, "incorrect or missing block for 'rewrite'.\n"); 3606 return NULL; 3607 } 3608 // Debug Stuff 3609 if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite Rule: %s\n", desc); 3610 3611 skipws(); 3612 return (new RewriteRule(params,desc)); 3613 } 3614 3615 //------------------------------attr_parse------------------------------------- 3616 Attribute *ADLParser::attr_parse(char* ident) { 3617 Attribute *attrib; // Attribute class 3618 char *cost = NULL; // String representation of cost attribute 3619 3620 skipws(); // Skip leading whitespace 3621 if ( (cost = get_paren_expr("attribute")) == NULL ) { 3622 parse_err(SYNERR, "incorrect or missing expression for 'attribute'\n"); 3623 return NULL; 3624 } 3625 // Debug Stuff 3626 if (_AD._adl_debug > 1) fprintf(stderr,"Attribute: %s\n", cost); 3627 if (_curchar != ';') { 3628 parse_err(SYNERR, "missing ';' in attribute definition\n"); 3629 return NULL; 3630 } 3631 next_char(); // Point after the terminator 3632 3633 skipws(); 3634 attrib = new Attribute(ident,cost,INS_ATTR); // Build new predicate object 3635 return attrib; 3636 } 3637 3638 3639 //------------------------------matchNode_parse-------------------------------- 3640 MatchNode *ADLParser::matchNode_parse(FormDict &operands, int &depth, int &numleaves, bool atroot) { 3641 // Count depth of parenthesis nesting for both left and right children 3642 int lParens = depth; 3643 int rParens = depth; 3644 3645 // MatchNode objects for left, right, and root of subtree. 3646 MatchNode *lChild = NULL; 3647 MatchNode *rChild = NULL; 3648 char *token; // Identifier which may be opcode or operand 3649 3650 // Match expression starts with a '(' 3651 if (cur_char() != '(') 3652 return NULL; 3653 3654 next_char(); // advance past '(' 3655 3656 // Parse the opcode 3657 token = get_ident(); // Get identifier, opcode 3658 if (token == NULL) { 3659 parse_err(SYNERR, "missing opcode in match expression\n"); 3660 return NULL; 3661 } 3662 3663 // Take note if we see one of a few special operations - those that are 3664 // treated differently on different architectures in the sense that on 3665 // one architecture there is a match rule and on another there isn't (so 3666 // a call will eventually be generated). 3667 3668 for (int i = _last_machine_leaf + 1; i < _last_opcode; i++) { 3669 if (strcmp(token, NodeClassNames[i]) == 0) { 3670 _AD.has_match_rule(i, true); 3671 } 3672 } 3673 3674 // Lookup the root value in the operands dict to perform substitution 3675 const char *result = NULL; // Result type will be filled in later 3676 const char *name = token; // local name associated with this node 3677 const char *operation = token; // remember valid operation for later 3678 const Form *form = operands[token]; 3679 OpClassForm *opcForm = form ? form->is_opclass() : NULL; 3680 if (opcForm != NULL) { 3681 // If this token is an entry in the local names table, record its type 3682 if (!opcForm->ideal_only()) { 3683 operation = opcForm->_ident; 3684 result = operation; // Operands result in their own type 3685 } 3686 // Otherwise it is an ideal type, and so, has no local name 3687 else name = NULL; 3688 } 3689 3690 // Parse the operands 3691 skipws(); 3692 if (cur_char() != ')') { 3693 3694 // Parse the left child 3695 if (strcmp(operation,"Set")) 3696 lChild = matchChild_parse(operands, lParens, numleaves, false); 3697 else 3698 lChild = matchChild_parse(operands, lParens, numleaves, true); 3699 3700 skipws(); 3701 if (cur_char() != ')' ) { 3702 if(strcmp(operation, "Set")) 3703 rChild = matchChild_parse(operands,rParens,numleaves,false); 3704 else 3705 rChild = matchChild_parse(operands,rParens,numleaves,true); 3706 } 3707 } 3708 3709 // Check for required ')' 3710 skipws(); 3711 if (cur_char() != ')') { 3712 parse_err(SYNERR, "missing ')' in match expression\n"); 3713 return NULL; 3714 } 3715 next_char(); // skip the ')' 3716 3717 MatchNode* mroot = new MatchNode(_AD,result,name,operation,lChild,rChild); 3718 3719 // If not the root, reduce this subtree to an internal operand 3720 if (!atroot) { 3721 mroot->build_internalop(); 3722 } 3723 // depth is greater of left and right paths. 3724 depth = (lParens > rParens) ? lParens : rParens; 3725 3726 return mroot; 3727 } 3728 3729 3730 //------------------------------matchChild_parse------------------------------- 3731 MatchNode *ADLParser::matchChild_parse(FormDict &operands, int &parens, int &numleaves, bool atroot) { 3732 MatchNode *child = NULL; 3733 const char *result = NULL; 3734 const char *token = NULL; 3735 const char *opType = NULL; 3736 3737 if (cur_char() == '(') { // child is an operation 3738 ++parens; 3739 child = matchNode_parse(operands, parens, numleaves, atroot); 3740 } 3741 else { // child is an operand 3742 token = get_ident(); 3743 const Form *form = operands[token]; 3744 OpClassForm *opcForm = form ? form->is_opclass() : NULL; 3745 if (opcForm != NULL) { 3746 opType = opcForm->_ident; 3747 result = opcForm->_ident; // an operand's result matches its type 3748 } else { 3749 parse_err(SYNERR, "undefined operand %s in match rule\n", token); 3750 return NULL; 3751 } 3752 3753 if (opType == NULL) { 3754 parse_err(SYNERR, "missing type for argument '%s'\n", token); 3755 } 3756 3757 child = new MatchNode(_AD, result, token, opType); 3758 ++numleaves; 3759 } 3760 3761 return child; 3762 } 3763 3764 3765 3766 // ******************** Private Utility Functions ************************* 3767 3768 3769 char* ADLParser::find_cpp_block(const char* description) { 3770 char *next; // Pointer for finding block delimiters 3771 char* cppBlock = NULL; // Beginning of C++ code block 3772 3773 if (_curchar == '%') { // Encoding is a C++ expression 3774 next_char(); 3775 if (_curchar != '{') { 3776 parse_err(SYNERR, "missing '{' in %s \n", description); 3777 return NULL; 3778 } 3779 next_char(); // Skip block delimiter 3780 skipws_no_preproc(); // Skip leading whitespace 3781 cppBlock = _ptr; // Point to start of expression 3782 const char* file = _AD._ADL_file._name; 3783 int line = _linenum; 3784 next = _ptr + 1; 3785 while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { 3786 next_char_or_line(); 3787 next = _ptr+1; // Maintain the next pointer 3788 } // Grab string 3789 if (_curchar == '\0') { 3790 parse_err(SYNERR, "invalid termination of %s \n", description); 3791 return NULL; 3792 } 3793 *_ptr = '\0'; // Terminate string 3794 _ptr += 2; // Skip block delimiter 3795 _curchar = *_ptr; // Maintain invariant 3796 3797 // Prepend location descriptor, for debugging. 3798 char* location = (char *)malloc(strlen(file) + 100); 3799 *location = '\0'; 3800 if (_AD._adlocation_debug) 3801 sprintf(location, "#line %d \"%s\"\n", line, file); 3802 char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1); 3803 strcpy(result, location); 3804 strcat(result, cppBlock); 3805 cppBlock = result; 3806 free(location); 3807 } 3808 3809 return cppBlock; 3810 } 3811 3812 // Move to the closing token of the expression we are currently at, 3813 // as defined by stop_chars. Match parens and quotes. 3814 char* ADLParser::get_expr(const char *desc, const char *stop_chars) { 3815 char* expr = NULL; 3816 int paren = 0; 3817 3818 expr = _ptr; 3819 while (paren > 0 || !strchr(stop_chars, _curchar)) { 3820 if (_curchar == '(') { // Down level of nesting 3821 paren++; // Bump the parenthesis counter 3822 next_char(); // maintain the invariant 3823 } 3824 else if (_curchar == ')') { // Up one level of nesting 3825 if (paren == 0) { 3826 // Paren underflow: We didn't encounter the required stop-char. 3827 parse_err(SYNERR, "too many )'s, did not find %s after %s\n", 3828 stop_chars, desc); 3829 return NULL; 3830 } 3831 paren--; // Drop the parenthesis counter 3832 next_char(); // Maintain the invariant 3833 } 3834 else if (_curchar == '"' || _curchar == '\'') { 3835 int qchar = _curchar; 3836 while (true) { 3837 next_char(); 3838 if (_curchar == qchar) { next_char(); break; } 3839 if (_curchar == '\\') next_char(); // superquote 3840 if (_curchar == '\n' || _curchar == '\0') { 3841 parse_err(SYNERR, "newline in string in %s\n", desc); 3842 return NULL; 3843 } 3844 } 3845 } 3846 else if (_curchar == '%' && (_ptr[1] == '{' || _ptr[1] == '}')) { 3847 // Make sure we do not stray into the next ADLC-level form. 3848 parse_err(SYNERR, "unexpected %%%c in %s\n", _ptr[1], desc); 3849 return NULL; 3850 } 3851 else if (_curchar == '\0') { 3852 parse_err(SYNERR, "unexpected EOF in %s\n", desc); 3853 return NULL; 3854 } 3855 else { 3856 // Always walk over whitespace, comments, preprocessor directives, etc. 3857 char* pre_skip_ptr = _ptr; 3858 skipws(); 3859 // If the parser declined to make progress on whitespace, 3860 // skip the next character, which is therefore NOT whitespace. 3861 if (pre_skip_ptr == _ptr) { 3862 next_char(); 3863 } else if (pre_skip_ptr+strlen(pre_skip_ptr) != _ptr+strlen(_ptr)) { 3864 parse_err(SYNERR, "unimplemented: preprocessor must not elide subexpression in %s", desc); 3865 } 3866 } 3867 } 3868 3869 assert(strchr(stop_chars, _curchar), "non-null return must be at stop-char"); 3870 *_ptr = '\0'; // Replace ')' or other stop-char with '\0' 3871 return expr; 3872 } 3873 3874 // Helper function around get_expr 3875 // Sets _curchar to '(' so that get_paren_expr will search for a matching ')' 3876 char *ADLParser::get_paren_expr(const char *description) { 3877 if (_curchar != '(') // Escape if not valid starting position 3878 return NULL; 3879 next_char(); // Skip the required initial paren. 3880 char *token2 = get_expr(description, ")"); 3881 if (_curchar == ')') 3882 next_char(); // Skip required final paren. 3883 return token2; 3884 } 3885 3886 //------------------------------get_ident_common------------------------------- 3887 // Looks for an identifier in the buffer, and turns it into a null terminated 3888 // string(still inside the file buffer). Returns a pointer to the string or 3889 // NULL if some other token is found instead. 3890 char *ADLParser::get_ident_common(bool do_preproc) { 3891 register char c; 3892 char *start; // Pointer to start of token 3893 char *end; // Pointer to end of token 3894 3895 if( _curline == NULL ) // Return NULL at EOF. 3896 return NULL; 3897 3898 skipws_common(do_preproc); // Skip whitespace before identifier 3899 start = end = _ptr; // Start points at first character 3900 end--; // unwind end by one to prepare for loop 3901 do { 3902 end++; // Increment end pointer 3903 c = *end; // Grab character to test 3904 } while ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) 3905 || ((c >= '0') && (c <= '9')) 3906 || ((c == '_')) || ((c == ':')) || ((c == '#')) ); 3907 if (start == end) { // We popped out on the first try 3908 parse_err(SYNERR, "identifier expected at %c\n", c); 3909 start = NULL; 3910 } 3911 else { 3912 _curchar = c; // Save the first character of next token 3913 *end = '\0'; // NULL terminate the string in place 3914 } 3915 _ptr = end; // Reset _ptr to point to next char after token 3916 3917 // Make sure we do not try to use #defined identifiers. If start is 3918 // NULL an error was already reported. 3919 if (do_preproc && start != NULL) { 3920 const char* def = _AD.get_preproc_def(start); 3921 if (def != NULL && strcmp(def, start)) { 3922 const char* def2 = _AD.get_preproc_def(def); 3923 if (def2 != NULL && strcmp(def2, def)) { 3924 parse_err(SYNERR, "unimplemented: using %s defined as %s => %s", 3925 start, def, def2); 3926 } 3927 start = strdup(def); 3928 } 3929 } 3930 3931 return start; // Pointer to token in filebuf 3932 } 3933 3934 //------------------------------get_ident_dup---------------------------------- 3935 // Looks for an identifier in the buffer, and returns a duplicate 3936 // or NULL if some other token is found instead. 3937 char *ADLParser::get_ident_dup(void) { 3938 char *ident = get_ident(); 3939 3940 // Duplicate an identifier before returning and restore string. 3941 if( ident != NULL ) { 3942 ident = strdup(ident); // Copy the string 3943 *_ptr = _curchar; // and replace Nil with original character 3944 } 3945 3946 return ident; 3947 } 3948 3949 //----------------------get_ident_or_literal_constant-------------------------- 3950 // Looks for an identifier in the buffer, or a parenthesized expression. 3951 char *ADLParser::get_ident_or_literal_constant(const char* description) { 3952 char* param = NULL; 3953 skipws(); 3954 if (_curchar == '(') { 3955 // Grab a constant expression. 3956 param = get_paren_expr(description); 3957 if (param[0] != '(') { 3958 char* buf = (char*) malloc(strlen(param) + 3); 3959 sprintf(buf, "(%s)", param); 3960 param = buf; 3961 } 3962 assert(is_literal_constant(param), 3963 "expr must be recognizable as a constant"); 3964 } else { 3965 param = get_ident(); 3966 } 3967 return param; 3968 } 3969 3970 //------------------------------get_rep_var_ident----------------------------- 3971 // Do NOT duplicate, 3972 // Leave nil terminator in buffer 3973 // Preserve initial '$'(s) in string 3974 char *ADLParser::get_rep_var_ident(void) { 3975 // Remember starting point 3976 char *rep_var = _ptr; 3977 3978 // Check for replacement variable indicator '$' and pass if present 3979 if ( _curchar == '$' ) { 3980 next_char(); 3981 } 3982 // Check for a subfield indicator, a second '$', and pass if present 3983 if ( _curchar == '$' ) { 3984 next_char(); 3985 } 3986 3987 // Check for a control indicator, a third '$': 3988 if ( _curchar == '$' ) { 3989 next_char(); 3990 } 3991 3992 // Check for more than three '$'s in sequence, SYNERR 3993 if( _curchar == '$' ) { 3994 parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'"); 3995 next_char(); 3996 return NULL; 3997 } 3998 3999 // Nil terminate the variable name following the '$' 4000 char *rep_var_name = get_ident(); 4001 assert( rep_var_name != NULL, 4002 "Missing identifier after replacement variable indicator '$'"); 4003 4004 return rep_var; 4005 } 4006 4007 4008 4009 //------------------------------get_rep_var_ident_dup------------------------- 4010 // Return the next replacement variable identifier, skipping first '$' 4011 // given a pointer into a line of the buffer. 4012 // Null terminates string, still inside the file buffer, 4013 // Returns a pointer to a copy of the string, or NULL on failure 4014 char *ADLParser::get_rep_var_ident_dup(void) { 4015 if( _curchar != '$' ) return NULL; 4016 4017 next_char(); // Move past the '$' 4018 char *rep_var = _ptr; // Remember starting point 4019 4020 // Check for a subfield indicator, a second '$': 4021 if ( _curchar == '$' ) { 4022 next_char(); 4023 } 4024 4025 // Check for a control indicator, a third '$': 4026 if ( _curchar == '$' ) { 4027 next_char(); 4028 } 4029 4030 // Check for more than three '$'s in sequence, SYNERR 4031 if( _curchar == '$' ) { 4032 parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'"); 4033 next_char(); 4034 return NULL; 4035 } 4036 4037 // Nil terminate the variable name following the '$' 4038 char *rep_var_name = get_ident(); 4039 assert( rep_var_name != NULL, 4040 "Missing identifier after replacement variable indicator '$'"); 4041 rep_var = strdup(rep_var); // Copy the string 4042 *_ptr = _curchar; // and replace Nil with original character 4043 4044 return rep_var; 4045 } 4046 4047 4048 //------------------------------get_unique_ident------------------------------ 4049 // Looks for an identifier in the buffer, terminates it with a NULL, 4050 // and checks that it is unique 4051 char *ADLParser::get_unique_ident(FormDict& dict, const char* nameDescription){ 4052 char* ident = get_ident(); 4053 4054 if (ident == NULL) { 4055 parse_err(SYNERR, "missing %s identifier at %c\n", nameDescription, _curchar); 4056 } 4057 else { 4058 if (dict[ident] != NULL) { 4059 parse_err(SYNERR, "duplicate name %s for %s\n", ident, nameDescription); 4060 ident = NULL; 4061 } 4062 } 4063 4064 return ident; 4065 } 4066 4067 4068 //------------------------------get_int---------------------------------------- 4069 // Looks for a character string integer in the buffer, and turns it into an int 4070 // invokes a parse_err if the next token is not an integer. 4071 // This routine does not leave the integer null-terminated. 4072 int ADLParser::get_int(void) { 4073 register char c; 4074 char *start; // Pointer to start of token 4075 char *end; // Pointer to end of token 4076 int result; // Storage for integer result 4077 4078 if( _curline == NULL ) // Return NULL at EOF. 4079 return NULL; 4080 4081 skipws(); // Skip whitespace before identifier 4082 start = end = _ptr; // Start points at first character 4083 c = *end; // Grab character to test 4084 while ((c >= '0') && (c <= '9') 4085 || ((c == '-') && (end == start))) { 4086 end++; // Increment end pointer 4087 c = *end; // Grab character to test 4088 } 4089 if (start == end) { // We popped out on the first try 4090 parse_err(SYNERR, "integer expected at %c\n", c); 4091 result = 0; 4092 } 4093 else { 4094 _curchar = c; // Save the first character of next token 4095 *end = '\0'; // NULL terminate the string in place 4096 result = atoi(start); // Convert the string to an integer 4097 *end = _curchar; // Restore buffer to original condition 4098 } 4099 4100 // Reset _ptr to next char after token 4101 _ptr = end; 4102 4103 return result; // integer 4104 } 4105 4106 4107 //------------------------------get_relation_dup------------------------------ 4108 // Looks for a relational operator in the buffer 4109 // invokes a parse_err if the next token is not a relation 4110 // This routine creates a duplicate of the string in the buffer. 4111 char *ADLParser::get_relation_dup(void) { 4112 char *result = NULL; // relational operator being returned 4113 4114 if( _curline == NULL ) // Return NULL at EOF. 4115 return NULL; 4116 4117 skipws(); // Skip whitespace before relation 4118 char *start = _ptr; // Store start of relational operator 4119 char first = *_ptr; // the first character 4120 if( (first == '=') || (first == '!') || (first == '<') || (first == '>') ) { 4121 next_char(); 4122 char second = *_ptr; // the second character 4123 if( (second == '=') ) { 4124 next_char(); 4125 char tmp = *_ptr; 4126 *_ptr = '\0'; // NULL terminate 4127 result = strdup(start); // Duplicate the string 4128 *_ptr = tmp; // restore buffer 4129 } else { 4130 parse_err(SYNERR, "relational operator expected at %s\n", _ptr); 4131 } 4132 } else { 4133 parse_err(SYNERR, "relational operator expected at %s\n", _ptr); 4134 } 4135 4136 return result; 4137 } 4138 4139 4140 4141 //------------------------------get_oplist------------------------------------- 4142 // Looks for identifier pairs where first must be the name of an operand, and 4143 // second must be a name unique in the scope of this instruction. Stores the 4144 // names with a pointer to the OpClassForm of their type in a local name table. 4145 void ADLParser::get_oplist(NameList ¶meters, FormDict &operands) { 4146 OpClassForm *opclass = NULL; 4147 char *ident = NULL; 4148 4149 do { 4150 next_char(); // skip open paren & comma characters 4151 skipws(); 4152 if (_curchar == ')') break; 4153 4154 // Get operand type, and check it against global name table 4155 ident = get_ident(); 4156 if (ident == NULL) { 4157 parse_err(SYNERR, "optype identifier expected at %c\n", _curchar); 4158 return; 4159 } 4160 else { 4161 const Form *form = _globalNames[ident]; 4162 if( form == NULL ) { 4163 parse_err(SYNERR, "undefined operand type %s\n", ident); 4164 return; 4165 } 4166 4167 // Check for valid operand type 4168 OpClassForm *opc = form->is_opclass(); 4169 OperandForm *oper = form->is_operand(); 4170 if((oper == NULL) && (opc == NULL)) { 4171 parse_err(SYNERR, "identifier %s not operand type\n", ident); 4172 return; 4173 } 4174 opclass = opc; 4175 } 4176 // Debugging Stuff 4177 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Type: %s\t", ident); 4178 4179 // Get name of operand and add it to local name table 4180 if( (ident = get_unique_ident(operands, "operand")) == NULL) { 4181 return; 4182 } 4183 // Parameter names must not be global names. 4184 if( _globalNames[ident] != NULL ) { 4185 parse_err(SYNERR, "Reuse of global name %s as operand.\n",ident); 4186 return; 4187 } 4188 operands.Insert(ident, opclass); 4189 parameters.addName(ident); 4190 4191 // Debugging Stuff 4192 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 4193 skipws(); 4194 } while(_curchar == ','); 4195 4196 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 4197 else { 4198 next_char(); // set current character position past the close paren 4199 } 4200 } 4201 4202 4203 //------------------------------get_effectlist--------------------------------- 4204 // Looks for identifier pairs where first must be the name of a pre-defined, 4205 // effect, and the second must be the name of an operand defined in the 4206 // operand list of this instruction. Stores the names with a pointer to the 4207 // effect form in a local effects table. 4208 void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) { 4209 OperandForm *opForm; 4210 Effect *eForm; 4211 char *ident; 4212 4213 do { 4214 next_char(); // skip open paren & comma characters 4215 skipws(); 4216 if (_curchar == ')') break; 4217 4218 // Get effect type, and check it against global name table 4219 ident = get_ident(); 4220 if (ident == NULL) { 4221 parse_err(SYNERR, "effect type identifier expected at %c\n", _curchar); 4222 return; 4223 } 4224 else { 4225 // Check for valid effect type 4226 const Form *form = _globalNames[ident]; 4227 if( form == NULL ) { 4228 parse_err(SYNERR, "undefined effect type %s\n", ident); 4229 return; 4230 } 4231 else { 4232 if( (eForm = form->is_effect()) == NULL) { 4233 parse_err(SYNERR, "identifier %s not effect type\n", ident); 4234 return; 4235 } 4236 } 4237 } 4238 // Debugging Stuff 4239 if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident); 4240 skipws(); 4241 // Get name of operand and check that it is in the local name table 4242 if( (ident = get_unique_ident(effects, "effect")) == NULL) { 4243 parse_err(SYNERR, "missing operand identifier in effect list\n"); 4244 return; 4245 } 4246 const Form *form = operands[ident]; 4247 opForm = form ? form->is_operand() : NULL; 4248 if( opForm == NULL ) { 4249 if( form && form->is_opclass() ) { 4250 const char* cname = form->is_opclass()->_ident; 4251 parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident); 4252 } else { 4253 parse_err(SYNERR, "undefined operand %s in effect list\n", ident); 4254 } 4255 return; 4256 } 4257 // Add the pair to the effects table 4258 effects.Insert(ident, eForm); 4259 // Debugging Stuff 4260 if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 4261 skipws(); 4262 } while(_curchar == ','); 4263 4264 if (_curchar != ')') parse_err(SYNERR, "missing ')'\n"); 4265 else { 4266 next_char(); // set current character position past the close paren 4267 } 4268 } 4269 4270 4271 //------------------------------preproc_define--------------------------------- 4272 // A "#define" keyword has been seen, so parse the rest of the line. 4273 void ADLParser::preproc_define(void) { 4274 char* flag = get_ident_no_preproc(); 4275 skipws_no_preproc(); 4276 // only #define x y is supported for now 4277 char* def = get_ident_no_preproc(); 4278 _AD.set_preproc_def(flag, def); 4279 skipws_no_preproc(); 4280 if (_curchar != '\n') { 4281 parse_err(SYNERR, "non-identifier in preprocessor definition\n"); 4282 } 4283 } 4284 4285 //------------------------------preproc_undef---------------------------------- 4286 // An "#undef" keyword has been seen, so parse the rest of the line. 4287 void ADLParser::preproc_undef(void) { 4288 char* flag = get_ident_no_preproc(); 4289 skipws_no_preproc(); 4290 ensure_end_of_line(); 4291 _AD.set_preproc_def(flag, NULL); 4292 } 4293 4294 4295 4296 //------------------------------parse_err-------------------------------------- 4297 // Issue a parser error message, and skip to the end of the current line 4298 void ADLParser::parse_err(int flag, const char *fmt, ...) { 4299 va_list args; 4300 4301 va_start(args, fmt); 4302 if (flag == 1) 4303 _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); 4304 else if (flag == 2) 4305 _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); 4306 else 4307 _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args); 4308 4309 int error_char = _curchar; 4310 char* error_ptr = _ptr+1; 4311 for(;*_ptr != '\n'; _ptr++) ; // Skip to the end of the current line 4312 _curchar = '\n'; 4313 va_end(args); 4314 _AD._no_output = 1; 4315 4316 if (flag == 1) { 4317 char* error_tail = strchr(error_ptr, '\n'); 4318 char tem = *error_ptr; 4319 error_ptr[-1] = '\0'; 4320 char* error_head = error_ptr-1; 4321 while (error_head > _curline && *error_head) --error_head; 4322 if (error_tail) *error_tail = '\0'; 4323 fprintf(stderr, "Error Context: %s>>>%c<<<%s\n", 4324 error_head, error_char, error_ptr); 4325 if (error_tail) *error_tail = '\n'; 4326 error_ptr[-1] = tem; 4327 } 4328 } 4329 4330 //---------------------------ensure_start_of_line------------------------------ 4331 // A preprocessor directive has been encountered. Be sure it has fallen at 4332 // the begining of a line, or else report an error. 4333 void ADLParser::ensure_start_of_line(void) { 4334 assert( _ptr >= _curline && _ptr < _curline+strlen(_curline), 4335 "Must be able to find which line we are in" ); 4336 4337 for (char *s = _curline; s < _ptr; s++) { 4338 if (*s > ' ') { 4339 parse_err(SYNERR, "'%c' must be at beginning of line\n", _curchar); 4340 break; 4341 } 4342 } 4343 } 4344 4345 //---------------------------ensure_end_of_line-------------------------------- 4346 // A preprocessor directive has been parsed. Be sure there is no trailing 4347 // garbage at the end of this line. Set the scan point to the beginning of 4348 // the next line. 4349 void ADLParser::ensure_end_of_line(void) { 4350 skipws_no_preproc(); 4351 if (_curchar != '\n' && _curchar != '\0') { 4352 parse_err(SYNERR, "garbage char '%c' at end of line\n", _curchar); 4353 } else { 4354 next_char_or_line(); 4355 } 4356 } 4357 4358 //---------------------------handle_preproc------------------------------------ 4359 // The '#' character introducing a preprocessor directive has been found. 4360 // Parse the whole directive name (e.g., #define, #endif) and take appropriate 4361 // action. If we are in an "untaken" span of text, simply keep track of 4362 // #ifdef nesting structure, so we can find out when to start taking text 4363 // again. (In this state, we "sort of support" C's #if directives, enough 4364 // to disregard their associated #else and #endif lines.) If we are in a 4365 // "taken" span of text, there are two cases: "#define" and "#undef" 4366 // directives are preserved and passed up to the caller, which eventually 4367 // passes control to the top-level parser loop, which handles #define and 4368 // #undef directly. (This prevents these directives from occurring in 4369 // arbitrary positions in the AD file--we require better structure than C.) 4370 // In the other case, and #ifdef, #ifndef, #else, or #endif is silently 4371 // processed as whitespace, with the "taken" state of the text correctly 4372 // updated. This routine returns "false" exactly in the case of a "taken" 4373 // #define or #undef, which tells the caller that a preprocessor token 4374 // has appeared which must be handled explicitly by the parse loop. 4375 bool ADLParser::handle_preproc_token() { 4376 assert(*_ptr == '#', "must be at start of preproc"); 4377 ensure_start_of_line(); 4378 next_char(); 4379 skipws_no_preproc(); 4380 char* start_ident = _ptr; 4381 char* ident = (_curchar == '\n') ? NULL : get_ident_no_preproc(); 4382 if (ident == NULL) { 4383 parse_err(SYNERR, "expected preprocessor command, got end of line\n"); 4384 } else if (!strcmp(ident, "ifdef") || 4385 !strcmp(ident, "ifndef")) { 4386 char* flag = get_ident_no_preproc(); 4387 ensure_end_of_line(); 4388 // Test the identifier only if we are already in taken code: 4389 bool flag_def = preproc_taken() && (_AD.get_preproc_def(flag) != NULL); 4390 bool now_taken = !strcmp(ident, "ifdef") ? flag_def : !flag_def; 4391 begin_if_def(now_taken); 4392 } else if (!strcmp(ident, "if")) { 4393 if (preproc_taken()) 4394 parse_err(SYNERR, "unimplemented: #%s %s", ident, _ptr+1); 4395 next_line(); 4396 // Intelligently skip this nested C preprocessor directive: 4397 begin_if_def(true); 4398 } else if (!strcmp(ident, "else")) { 4399 ensure_end_of_line(); 4400 invert_if_def(); 4401 } else if (!strcmp(ident, "endif")) { 4402 ensure_end_of_line(); 4403 end_if_def(); 4404 } else if (preproc_taken()) { 4405 // pass this token up to the main parser as "#define" or "#undef" 4406 _ptr = start_ident; 4407 _curchar = *--_ptr; 4408 if( _curchar != '#' ) { 4409 parse_err(SYNERR, "no space allowed after # in #define or #undef"); 4410 assert(_curchar == '#', "no space allowed after # in #define or #undef"); 4411 } 4412 return false; 4413 } 4414 return true; 4415 } 4416 4417 //---------------------------skipws_common------------------------------------- 4418 // Skip whitespace, including comments and newlines, while keeping an accurate 4419 // line count. 4420 // Maybe handle certain preprocessor constructs: #ifdef, #ifndef, #else, #endif 4421 void ADLParser::skipws_common(bool do_preproc) { 4422 char *start = _ptr; 4423 char *next = _ptr + 1; 4424 4425 if (*_ptr == '\0') { 4426 // Check for string terminator 4427 if (_curchar > ' ') return; 4428 if (_curchar == '\n') { 4429 if (!do_preproc) return; // let caller handle the newline 4430 next_line(); 4431 _ptr = _curline; next = _ptr + 1; 4432 } 4433 else if (_curchar == '#' || 4434 (_curchar == '/' && (*next == '/' || *next == '*'))) { 4435 parse_err(SYNERR, "unimplemented: comment token in a funny place"); 4436 } 4437 } 4438 while(_curline != NULL) { // Check for end of file 4439 if (*_ptr == '\n') { // keep proper track of new lines 4440 if (!do_preproc) break; // let caller handle the newline 4441 next_line(); 4442 _ptr = _curline; next = _ptr + 1; 4443 } 4444 else if ((*_ptr == '/') && (*next == '/')) // C++ comment 4445 do { _ptr++; next++; } while(*_ptr != '\n'); // So go to end of line 4446 else if ((*_ptr == '/') && (*next == '*')) { // C comment 4447 _ptr++; next++; 4448 do { 4449 _ptr++; next++; 4450 if (*_ptr == '\n') { // keep proper track of new lines 4451 next_line(); // skip newlines within comments 4452 if (_curline == NULL) { // check for end of file 4453 parse_err(SYNERR, "end-of-file detected inside comment\n"); 4454 break; 4455 } 4456 _ptr = _curline; next = _ptr + 1; 4457 } 4458 } while(!((*_ptr == '*') && (*next == '/'))); // Go to end of comment 4459 _ptr = ++next; next++; // increment _ptr past comment end 4460 } 4461 else if (do_preproc && *_ptr == '#') { 4462 // Note that this calls skipws_common(false) recursively! 4463 bool preproc_handled = handle_preproc_token(); 4464 if (!preproc_handled) { 4465 if (preproc_taken()) { 4466 return; // short circuit 4467 } 4468 ++_ptr; // skip the preprocessor character 4469 } 4470 next = _ptr+1; 4471 } else if(*_ptr > ' ' && !(do_preproc && !preproc_taken())) { 4472 break; 4473 } 4474 else if (*_ptr == '"' || *_ptr == '\'') { 4475 assert(do_preproc, "only skip strings if doing preproc"); 4476 // skip untaken quoted string 4477 int qchar = *_ptr; 4478 while (true) { 4479 ++_ptr; 4480 if (*_ptr == qchar) { ++_ptr; break; } 4481 if (*_ptr == '\\') ++_ptr; 4482 if (*_ptr == '\n' || *_ptr == '\0') { 4483 parse_err(SYNERR, "newline in string"); 4484 break; 4485 } 4486 } 4487 next = _ptr + 1; 4488 } 4489 else { ++_ptr; ++next; } 4490 } 4491 if( _curline != NULL ) // at end of file _curchar isn't valid 4492 _curchar = *_ptr; // reset _curchar to maintain invariant 4493 } 4494 4495 //---------------------------cur_char----------------------------------------- 4496 char ADLParser::cur_char() { 4497 return (_curchar); 4498 } 4499 4500 //---------------------------next_char----------------------------------------- 4501 void ADLParser::next_char() { 4502 _curchar = *++_ptr; 4503 // if ( _curchar == '\n' ) { 4504 // next_line(); 4505 // } 4506 } 4507 4508 //---------------------------next_char_or_line--------------------------------- 4509 void ADLParser::next_char_or_line() { 4510 if ( _curchar != '\n' ) { 4511 _curchar = *++_ptr; 4512 } else { 4513 next_line(); 4514 _ptr = _curline; 4515 _curchar = *_ptr; // maintain invariant 4516 } 4517 } 4518 4519 //---------------------------next_line----------------------------------------- 4520 void ADLParser::next_line() { 4521 _curline = _buf.get_line(); _linenum++; 4522 } 4523 4524 //-------------------------is_literal_constant--------------------------------- 4525 bool ADLParser::is_literal_constant(const char *param) { 4526 if (param[0] == 0) return false; // null string 4527 if (param[0] == '(') return true; // parenthesized expression 4528 if (param[0] == '0' && (param[1] == 'x' || param[1] == 'X')) { 4529 // Make sure it's a hex constant. 4530 int i = 2; 4531 do { 4532 if( !ADLParser::is_hex_digit(*(param+i)) ) return false; 4533 ++i; 4534 } while( *(param+i) != 0 ); 4535 return true; 4536 } 4537 return false; 4538 } 4539 4540 //---------------------------is_hex_digit-------------------------------------- 4541 bool ADLParser::is_hex_digit(char digit) { 4542 return ((digit >= '0') && (digit <= '9')) 4543 ||((digit >= 'a') && (digit <= 'f')) 4544 ||((digit >= 'A') && (digit <= 'F')); 4545 } 4546 4547 //---------------------------is_int_token-------------------------------------- 4548 bool ADLParser::is_int_token(const char* token, int& intval) { 4549 const char* cp = token; 4550 while (*cp != '\0' && *cp <= ' ') cp++; 4551 if (*cp == '-') cp++; 4552 int ndigit = 0; 4553 while (*cp >= '0' && *cp <= '9') { cp++; ndigit++; } 4554 while (*cp != '\0' && *cp <= ' ') cp++; 4555 if (ndigit == 0 || *cp != '\0') { 4556 return false; 4557 } 4558 intval = atoi(token); 4559 return true; 4560 } 4561 4562 //-------------------------------trim------------------------------------------ 4563 void ADLParser::trim(char* &token) { 4564 while (*token <= ' ') token++; 4565 char* end = token + strlen(token); 4566 while (end > token && *(end-1) <= ' ') --end; 4567 *end = '\0'; 4568 }