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