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