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