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