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