ssssss01

C:\hotspot-69087d08d473\src\share\vm/adlc/adlc.hpp
#ifndef SHARE_VM_ADLC_ADLC_HPP
#define SHARE_VM_ADLC_ADLC_HPP
#include "stdio.h"
#include "stdlib.h"
#include <iostream>
#include "string.h"
#include "ctype.h"
#include "stdarg.h"
#include <sys/types.h>
#if _MSC_VER >= 1300
using namespace std;
#endif
#if _MSC_VER >= 1400
#define strdup _strdup
#endif
#ifdef _WIN32
#ifndef _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef int intptr_t;
#endif
#define _INTPTR_T_DEFINED
#endif
#ifndef _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned int uintptr_t;
#endif
#define _UINTPTR_T_DEFINED
#endif
#endif // _WIN32
#if defined(LINUX) || defined(_ALLBSD_SOURCE)
  #include <inttypes.h>
#endif // LINUX || _ALLBSD_SOURCE
#define uint32 unsigned int
#define uint   unsigned int
#include "opto/opcodes.hpp"
#undef assert
#define assert(cond, msg) { if (!(cond)) { fprintf(stderr, "assert fails %s %d: %s\n", __FILE__, __LINE__, msg); abort(); }}
#undef max
#define max(a, b)   (((a)>(b)) ? (a) : (b))
#include "arena.hpp"
#include "opto/adlcVMDeps.hpp"
#include "filebuff.hpp"
#include "dict2.hpp"
#include "forms.hpp"
#include "formsopt.hpp"
#include "formssel.hpp"
#include "archDesc.hpp"
#include "adlparse.hpp"
extern ArchDesc* globalAD;
#endif // SHARE_VM_ADLC_ADLC_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/adlparse.cpp
#include "adlc.hpp"
ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
  : _buf(buffer), _AD(archDesc),
    _globalNames(archDesc.globalNames()) {
  _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
  _AD._warnings    = 0;                      // No warnings either
  _curline         = _ptr = NULL;            // No pointers into buffer yet
  _preproc_depth = 0;
  _preproc_not_taken = 0;
  _AD._preproc_list.add_signal();
}
ADLParser::~ADLParser() {
  if (!_AD._quiet_mode)
    fprintf(stderr,"---------------------------- Errors and Warnings ----------------------------\n");
#ifndef ASSERT
  fprintf(stderr, "**************************************************************\n");
  fprintf(stderr, "***** WARNING: ASSERT is undefined, assertions disabled. *****\n");
  fprintf(stderr, "**************************************************************\n");
#endif
  if( _AD._syntax_errs + _AD._semantic_errs + _AD._warnings == 0 ) {
    if (!_AD._quiet_mode)
      fprintf(stderr,"No errors or warnings to report from phase-1 parse.\n" );
  }
  else {
    if( _AD._syntax_errs ) {      // Any syntax errors?
      fprintf(stderr,"%s:  Found %d syntax error", _buf._fp->_name, _AD._syntax_errs);
      if( _AD._syntax_errs > 1 ) fprintf(stderr,"s.\n\n");
      else fprintf(stderr,".\n\n");
    }
    if( _AD._semantic_errs ) {    // Any semantic errors?
      fprintf(stderr,"%s:  Found %d semantic error", _buf._fp->_name, _AD._semantic_errs);
      if( _AD._semantic_errs > 1 ) fprintf(stderr,"s.\n\n");
      else fprintf(stderr,".\n\n");
    }
    if( _AD._warnings ) {         // Any warnings?
      fprintf(stderr,"%s:  Found %d warning", _buf._fp->_name, _AD._warnings);
      if( _AD._warnings > 1 ) fprintf(stderr,"s.\n\n");
      else fprintf(stderr,".\n\n");
    }
  }
  if (!_AD._quiet_mode)
    fprintf(stderr,"-----------------------------------------------------------------------------\n");
  _AD._TotalLines += linenum()-1;     // -1 for overshoot in "nextline" routine
}
void ADLParser::parse() {
  char *ident;
  for( next_line(); _curline != NULL; next_line()) {
    _ptr = _curline;             // Reset ptr to start of new line
    skipws();                    // Skip any leading whitespace
    ident = get_ident();         // Get first token
    if (ident == NULL) {         // Empty line
      continue;                  // Get the next line
    }
         if (!strcmp(ident, "instruct"))   instr_parse();
    else if (!strcmp(ident, "operand"))    oper_parse();
    else if (!strcmp(ident, "opclass"))    opclass_parse();
    else if (!strcmp(ident, "ins_attrib")) ins_attr_parse();
    else if (!strcmp(ident, "op_attrib"))  op_attr_parse();
    else if (!strcmp(ident, "source"))     source_parse();
    else if (!strcmp(ident, "source_hpp")) source_hpp_parse();
    else if (!strcmp(ident, "register"))   reg_parse();
    else if (!strcmp(ident, "frame"))      frame_parse();
    else if (!strcmp(ident, "encode"))     encode_parse();
    else if (!strcmp(ident, "pipeline"))   pipe_parse();
    else if (!strcmp(ident, "definitions")) definitions_parse();
    else if (!strcmp(ident, "peephole"))   peep_parse();
    else if (!strcmp(ident, "#line"))      preproc_line();
    else if (!strcmp(ident, "#define"))    preproc_define();
    else if (!strcmp(ident, "#undef"))     preproc_undef();
    else {
      parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n     Found %s",ident);
    }
  }
  RegisterForm *regBlock = _AD.get_registers();
  if (regBlock == NULL) {
    parse_err(SEMERR, "Did not declare 'register' definitions");
  }
  regBlock->addSpillRegClass();
  if (_preproc_depth != 0) {
    parse_err(SYNERR, "End of file inside #ifdef");
  }
  if (_globalNames[AttributeForm::_ins_cost] == NULL) {
    parse_err(SEMERR, "Did not declare 'ins_cost' attribute");
  }
  if (_globalNames[AttributeForm::_op_cost] == NULL) {
    parse_err(SEMERR, "Did not declare 'op_cost' attribute");
  }
}
void ADLParser::instr_parse(void) {
  char          *ident;
  InstructForm  *instr;
  MatchRule     *rule;
  int            match_rules_cnt = 0;
  if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
    return;
  instr = new InstructForm(ident); // Create new instruction form
  instr->_linenum = linenum();
  _globalNames.Insert(ident, instr); // Add name to the name table
  if (_AD._adl_debug > 1)
    fprintf(stderr,"Parsing Instruction Form %s\n", ident);
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' in instruct definition\n");
  }
  else get_oplist(instr->_parameters, instr->_localNames);
  skipws();                        // Skip leading whitespace
  if ( (_curchar != '%')
       || ( next_char(),  (_curchar != '{')) ) {
    parse_err(SYNERR, "missing '%%{' in instruction definition\n");
    return;
  }
  next_char();                     // Maintain the invariant
  do {
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
      continue;
    }
    if      (!strcmp(ident, "predicate")) instr->_predicate = pred_parse();
    else if      (!strcmp(ident, "match")) {
      rule = instr->_matrule;
      if (rule == NULL) {
        rule = match_parse(instr->_localNames);
        if (rule) {
          instr->_matrule = rule;
          if( instr->is_ideal_control() ) {
            rule->_result = "Universe";
          }
          matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
        }
      } else {
        while (rule->_next != NULL)
          rule = rule->_next;
        rule->_next = match_parse(instr->_localNames);
        if (rule->_next) {
          rule = rule->_next;
          if( instr->is_ideal_control() ) {
            parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name);
            return;
          }
          assert(match_rules_cnt < 100," too many match rule clones");
          char* buf = (char*) malloc(strlen(instr->_ident) + 4);
          sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++);
          rule->_result = buf;
          matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
        }
      }
    }
    else if (!strcmp(ident, "encode"))  {
      parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
    }
    else if (!strcmp(ident, "ins_encode"))       ins_encode_parse(*instr);
    else if (!strcmp(ident, "postalloc_expand")) postalloc_expand_parse(*instr);
    else if (!strcmp(ident, "opcode"))           instr->_opcode    = opcode_parse(instr);
    else if (!strcmp(ident, "size"))             instr->_size      = size_parse(instr);
    else if (!strcmp(ident, "effect"))           effect_parse(instr);
    else if (!strcmp(ident, "expand"))           instr->_exprule   = expand_parse(instr);
    else if (!strcmp(ident, "rewrite"))          instr->_rewrule   = rewrite_parse();
    else if (!strcmp(ident, "constraint")) {
      parse_err(SYNERR, "Instructions do not specify a constraint\n");
    }
    else if (!strcmp(ident, "construct")) {
      parse_err(SYNERR, "Instructions do not specify a construct\n");
    }
    else if (!strcmp(ident, "format"))           instr->_format    = format_parse();
    else if (!strcmp(ident, "interface")) {
      parse_err(SYNERR, "Instructions do not specify an interface\n");
    }
    else if (!strcmp(ident, "ins_pipe"))        ins_pipe_parse(*instr);
    else {  // Done with staticly defined parts of instruction definition
      const Form    *form = _globalNames[ident];
      AttributeForm *attr = form ? form->is_attribute() : NULL;
      if (attr && (attr->_atype == INS_ATTR)) {
        Attribute *temp = attr_parse(ident);
        temp->_next = instr->_attribs;
        instr->_attribs = temp;
      } else {
        parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of"
                  " an instruction attribute at %s\n", ident);
      }
    }
    skipws();
  } while(_curchar != '%');
  next_char();
  if (_curchar != '}') {
    parse_err(SYNERR, "missing '%%}' in instruction definition\n");
    return;
  }
  adjust_set_rule(instr);
  if (_AD._pipeline) {
    if (instr->expands() || instr->postalloc_expands()) {
      if (instr->_ins_pipe) {
        parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\";"
                  " ins_pipe will be unused\n", instr->_ident);
      }
    } else {
      if (!instr->_ins_pipe) {
        parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident);
      }
    }
  }
  _AD.addForm(instr);
  rule = instr->_matrule;
  if (rule != NULL) {
    rule = rule->_next;
    while (rule != NULL) {
      ident = (char*)rule->_result;
      InstructForm *clone = new InstructForm(ident, instr, rule); // Create new instruction form
      _globalNames.Insert(ident, clone); // Add name to the name table
      if (_AD._adl_debug > 1)
        fprintf(stderr,"Parsing Instruction Form %s\n", ident);
      adjust_set_rule(clone);
      _AD.addForm(clone);
      rule = rule->_next;
      clone->_matrule->_next = NULL; // One match rule per clone
    }
  }
}
void ADLParser::matchrule_clone_and_swap(MatchRule* rule, const char* instr_ident, int& match_rules_cnt) {
  int count = 0;
  rule->count_commutative_op(count);
  if (count > 0) {
    rule->matchrule_swap_commutative_op(instr_ident, count, match_rules_cnt);
  }
}
void ADLParser::adjust_set_rule(InstructForm *instr) {
  if (instr->_matrule == NULL || instr->_matrule->_rChild == NULL) return;
  const char *rch = instr->_matrule->_rChild->_opType;
  const Form *frm = _globalNames[rch];
  if( (! strcmp(instr->_matrule->_opType,"Set")) &&
      frm && frm->is_operand() && (! frm->ideal_only()) ) {
    unsigned    position = 0;
    const char *result   = NULL;
    const char *name     = NULL;
    const char *optype   = NULL;
    MatchNode  *right    = instr->_matrule->_rChild;
    if (right->base_operand(position, _globalNames, result, name, optype)) {
      position = 1;
      const char *result2  = NULL;
      const char *name2    = NULL;
      const char *optype2  = NULL;
      if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) {
        if (instr->_predicate != NULL)
          parse_err(SYNERR, "ADLC does not support instruction chain rules with predicates");
        ChainList *lst = (ChainList *)_AD._chainRules[optype];
        if (lst == NULL) {
          lst = new ChainList();
          _AD._chainRules.Insert(optype, lst);
        }
        if (!lst->search(instr->_matrule->_lChild->_opType)) {
          const char *cost = instr->cost();
          if (cost == NULL) {
            cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
          }
          if( frm->is_operand() == NULL || frm->is_operand()->_predicate == NULL ) {
            lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
          }
        }
        lst = (ChainList *)_AD._chainRules[result];
        if (lst == NULL) {
          lst = new ChainList();
          _AD._chainRules.Insert(result, lst);
        }
        if (!lst->search(instr->_matrule->_lChild->_opType)) {
          const char *cost = instr->cost();
          if (cost == NULL) {
            cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
          }
          lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
        }
      } else {
        OperandForm *rightOp = _globalNames[right->_opType]->is_operand();
        if( rightOp ) {
          const Form *rightRoot = _globalNames[rightOp->_matrule->_opType];
          if( rightRoot && rightRoot->ideal_only() ) {
            const char *chain_op = NULL;
            if( rightRoot->is_instruction() )
              chain_op = rightOp->_ident;
            if( chain_op ) {
              ChainList *lst = (ChainList *)_AD._chainRules[chain_op];
              if (lst == NULL) {
                lst = new ChainList();
                _AD._chainRules.Insert(chain_op, lst);
              }
              const char *cost = instr->cost();
              if (cost == NULL) {
                cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
              }
              lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
            }
          }
        }
      } // end chain rule from right-tree's ideal root
    }
  }
}
void ADLParser::oper_parse(void) {
  char          *ident;
  OperandForm   *oper;
  AttributeForm *attr;
  MatchRule     *rule;
  skipws();
  if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
    return;
  oper = new OperandForm(ident);        // Create new operand form
  oper->_linenum = linenum();
  _globalNames.Insert(ident, oper); // Add name to the name table
  if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Operand Form %s\n", ident);
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' in operand definition\n");
    return;
  }
  else get_oplist(oper->_parameters, oper->_localNames); // Parse the component operand list
  skipws();
  if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block
    parse_err(SYNERR, "missing '%%{' in operand definition\n");
    return;
  }
  next_char(); next_char();        // Skip over "%{" symbol
  do {
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
      continue;
    }
    if      (!strcmp(ident, "predicate")) oper->_predicate = pred_parse();
    else if (!strcmp(ident, "match"))     {
      rule = oper->_matrule;
      if (rule) {
        while (rule->_next) rule = rule->_next;
        rule->_next = match_parse(oper->_localNames);
        if (rule->_next) {
          rule->_next->_result = oper->_ident;
        }
      }
      else {
        oper->_matrule = match_parse(oper->_localNames);
        if (oper->_matrule) {
          oper->_matrule->_result = oper->_ident;
        }
      }
    }
    else if (!strcmp(ident, "encode"))    oper->_interface = interface_parse();
    else if (!strcmp(ident, "ins_encode")) {
      parse_err(SYNERR, "Operands specify 'encode', not 'ins_encode'\n");
    }
    else if (!strcmp(ident, "opcode"))    {
      parse_err(SYNERR, "Operands do not specify an opcode\n");
    }
    else if (!strcmp(ident, "effect"))    {
      parse_err(SYNERR, "Operands do not specify an effect\n");
    }
    else if (!strcmp(ident, "expand"))    {
      parse_err(SYNERR, "Operands do not specify an expand\n");
    }
    else if (!strcmp(ident, "rewrite"))   {
      parse_err(SYNERR, "Operands do not specify a rewrite\n");
    }
    else if (!strcmp(ident, "constraint"))oper->_constraint= constraint_parse();
    else if (!strcmp(ident, "construct")) oper->_construct = construct_parse();
    else if (!strcmp(ident, "format"))    oper->_format    = format_parse();
    else if (!strcmp(ident, "interface")) oper->_interface = interface_parse();
    else if (((attr = _globalNames[ident]->is_attribute()) != NULL) &&
             (attr->_atype == OP_ATTR))   oper->_attribs   = attr_parse(ident);
    else {
      parse_err(SYNERR, "expected one of - constraint, predicate, match, encode, format, construct, or the name of a defined operand attribute at %s\n", ident);
    }
    skipws();
  } while(_curchar != '%');
  next_char();
  if (_curchar != '}') {
    parse_err(SYNERR, "missing '%%}' in operand definition\n");
    return;
  }
  _AD.addForm(oper);
}
void ADLParser::opclass_parse(void) {
  char          *ident;
  OpClassForm   *opc;
  OperandForm   *opForm;
  skipws();
  if( (ident = get_unique_ident(_globalNames,"opclass")) == NULL )
    return;
  opc = new OpClassForm(ident);             // Create new operand class form
  _globalNames.Insert(ident, opc);  // Add name to the name table
  if (_AD._adl_debug > 1)
    fprintf(stderr,"Parsing Operand Class Form %s\n", ident);
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' in operand definition\n");
    return;
  }
  do {
    next_char();                            // Skip past open paren or comma
    ident = get_ident();                    // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
      continue;
    }
    const Form *form = _globalNames[ident];
    opForm     = form ? form->is_operand() : NULL;
    if ( opForm ) {
      opc->_oplst.addName(ident);           // Add operand to opclass list
      opForm->_classes.addName(opc->_ident);// Add opclass to operand list
    }
    else {
      parse_err(SYNERR, "expected name of a defined operand at %s\n", ident);
    }
    skipws();                               // skip trailing whitespace
  } while (_curchar == ',');                // Check for the comma
  if (_curchar != ')') {
    parse_err(SYNERR, "missing ')' or ',' in opclass definition\n");
    return;
  }
  next_char();                              // Consume the ')'
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in opclass definition\n");
    return;
  }
  next_char();                             // Consume the ';'
  _AD.addForm(opc);
}
void ADLParser::ins_attr_parse(void) {
  char          *ident;
  char          *aexpr;
  AttributeForm *attrib;
  skipws();                      // Skip leading whitespace
  if( (ident = get_unique_ident(_globalNames,"inst_attrib")) == NULL )
    return;
  if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Ins_Attribute Form %s\n", ident);
  skipws();                      // Skip whitespace
  if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) {
    parse_err(SYNERR, "missing '(' in ins_attrib definition\n");
    return;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr);
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
    return;
  }
  next_char();                    // Advance past the ';'
  attrib = new AttributeForm(ident, INS_ATTR, aexpr);
  _globalNames.Insert(ident, attrib);  // Add name to the name table
  _AD.addForm(attrib);
}
void ADLParser::op_attr_parse(void) {
  char          *ident;
  char          *aexpr;
  AttributeForm *attrib;
  skipws();                      // Skip leading whitespace
  if( (ident = get_unique_ident(_globalNames,"op_attrib")) == NULL )
    return;
  if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Op_Attribute Form %s\n", ident);
  skipws();                      // Skip whitespace
  if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) {
    parse_err(SYNERR, "missing '(' in op_attrib definition\n");
    return;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr);
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in op_attrib definition\n");
    return;
  }
  next_char();                    // Advance past the ';'
  attrib = new AttributeForm(ident, OP_ATTR, aexpr);
  _globalNames.Insert(ident, attrib);
  _AD.addForm(attrib);
}
void ADLParser::definitions_parse(void) {
  skipws();                       // Skip leading whitespace
  if (_curchar == '%' && *(_ptr+1) == '{') {
    next_char(); next_char();     // Skip "%{"
    skipws();
    while (_curchar != '%' && *(_ptr+1) != '}') {
      char *token = get_ident();
      if (token == NULL) {
        parse_err(SYNERR, "missing identifier inside definitions block.\n");
        return;
      }
      if (strcmp(token,"int_def")==0)     { int_def_parse(); }
      skipws();
    }
  }
  else {
    parse_err(SYNERR, "Missing %%{ ... %%} block after definitions keyword.\n");
    return;
  }
}
void ADLParser::int_def_parse(void) {
  char *name        = NULL;         // Name of definition
  char *value       = NULL;         // its value,
  int   int_value   = -1;           // positive values only
  char *description = NULL;         // textual description
  skipws();                      // Skip whitespace
  name = get_ident();
  if (name == NULL) {
    parse_err(SYNERR, "missing definition name after int_def\n");
    return;
  }
  skipws();
  if (_curchar == '(') {
    next_char();
    value = get_ident();
    if (value == NULL) {
      parse_err(SYNERR, "missing value in int_def\n");
      return;
    }
    if( !is_int_token(value, int_value) ) {
      parse_err(SYNERR, "value in int_def is not recognized as integer\n");
      return;
    }
    skipws();
    if (_curchar == ',') {
      next_char();   // skip ','
      description = get_expr("int_def description", ")");
      if (description == NULL) {
        parse_err(SYNERR, "invalid or missing description in int_def\n");
        return;
      }
      trim(description);
    }
    if (_curchar != ')') {
      parse_err(SYNERR, "missing ')' in register definition statement\n");
      return;
    }
    next_char();
  }
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' after int_def\n");
    return;
  }
  next_char();                   // move past ';'
  if (_AD._adl_debug > 1) {
    fprintf(stderr,"int_def: %s ( %s, %s )\n", name,
            (value), (description ? description : ""));
  }
  Expr *expr     = new Expr(name, description, int_value, int_value);
  const Expr *old_expr = _AD.globalDefs().define(name, expr);
  if (old_expr != NULL) {
    parse_err(SYNERR, "Duplicate definition\n");
    return;
  }
  return;
}
void ADLParser::source_parse(void) {
  SourceForm *source;             // Encode class for instruction/operand
  char   *rule = NULL;            // String representation of encode rule
  skipws();                       // Skip leading whitespace
  if ( (rule = find_cpp_block("source block")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing block for 'source'.\n");
    return;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Source Form: %s\n", rule);
  source = new SourceForm(rule);    // Build new Source object
  _AD.addForm(source);
}
void ADLParser::source_hpp_parse(void) {
  char   *rule = NULL;            // String representation of encode rule
  skipws();                       // Skip leading whitespace
  if ( (rule = find_cpp_block("source_hpp block")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing block for 'source_hpp'.\n");
    return;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Header Form: %s\n", rule);
  if (_AD.get_registers() == NULL) {
    PreHeaderForm* pre_header = new PreHeaderForm(rule);
    _AD.addForm(pre_header);
  } else {
    HeaderForm* header = new HeaderForm(rule);
    _AD.addForm(header);
  }
}
void ADLParser::reg_parse(void) {
  RegisterForm *regBlock = _AD.get_registers(); // Information about registers encoding
  if (regBlock == NULL) {
    regBlock = new RegisterForm();    // Build new Source object
    _AD.addForm(regBlock);
  }
  skipws();                       // Skip leading whitespace
  if (_curchar == '%' && *(_ptr+1) == '{') {
    next_char(); next_char();     // Skip "%{"
    skipws();
    while (_curchar != '%' && *(_ptr+1) != '}') {
      char *token = get_ident();
      if (token == NULL) {
        parse_err(SYNERR, "missing identifier inside register block.\n");
        return;
      }
      if (strcmp(token,"reg_def")==0)          { reg_def_parse(); }
      else if (strcmp(token,"reg_class")==0)   { reg_class_parse(); }
      else if (strcmp(token, "reg_class_dynamic") == 0) { reg_class_dynamic_parse(); }
      else if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
      else if (strcmp(token,"#define")==0)     { preproc_define(); }
      else { parse_err(SYNERR, "bad token %s inside register block.\n", token); break; }
      skipws();
    }
  }
  else {
    parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%');
    return;
  }
}
void ADLParser::encode_parse(void) {
  EncodeForm *encBlock;         // Information about instruction/operand encoding
  _AD.getForm(&encBlock);
  if ( encBlock == NULL) {
    encBlock = new EncodeForm();    // Build new Source object
    _AD.addForm(encBlock);
  }
  skipws();                       // Skip leading whitespace
  if (_curchar == '%' && *(_ptr+1) == '{') {
    next_char(); next_char();     // Skip "%{"
    skipws();
    while (_curchar != '%' && *(_ptr+1) != '}') {
      char *token = get_ident();
      if (token == NULL) {
            parse_err(SYNERR, "missing identifier inside encoding block.\n");
            return;
      }
      if (strcmp(token,"enc_class")==0)   { enc_class_parse(); }
      skipws();
    }
  }
  else {
    parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%');
    return;
  }
}
void ADLParser::enc_class_parse(void) {
  char       *ec_name;           // Name of encoding class being defined
  skipws();                      // Skip whitespace
  ec_name = get_ident();
  if (ec_name == NULL) {
    parse_err(SYNERR, "missing encoding class name after encode.\n");
    return;
  }
  EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
  encoding->_linenum = linenum();
  skipws();                      // Skip leading whitespace
  if (_curchar == '(') {
    do {
      char *pType = NULL;        // parameter type
      char *pName = NULL;        // parameter name
      next_char();               // skip open paren & comma characters
      skipws();
      if (_curchar == ')') break;
      pType = get_ident();
      if (pType == NULL) {
        parse_err(SYNERR, "parameter type expected at %c\n", _curchar);
        return;
      }
      skipws();
      pName = get_ident();
      if (pName == NULL) {
        parse_err(SYNERR, "parameter name expected at %c\n", _curchar);
        return;
      }
      encoding->add_parameter( pType, pName );
      skipws();
    } while(_curchar == ',');
    if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
    else {
      next_char();                  // Skip ')'
    }
  } // Done with parameter list
  skipws();
  if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block
    parse_err(SYNERR, "missing '%c{' in enc_class definition\n", '%');
    return;
  }
  next_char();                      // Skip '%'
  next_char();                      // Skip '{'
  enc_class_parse_block(encoding, ec_name);
}
void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
  skipws_no_preproc();              // Skip leading whitespace
  if (_AD._adlocation_debug) {
    encoding->add_code(get_line_string());
  }
  while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
    char *start = _ptr;       // Record start of the next string
    while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
      if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
        skipws_no_preproc();
      } else {
        next_char_or_line();
      }
    }
    if ( start != _ptr ) {
      encoding->add_code(start);
    }
    if (_curchar == '$') {
      char* rep_var = get_rep_var_ident_dup();
      encoding->add_rep_var(rep_var);
    }
  } // end while part of format description
  next_char();                      // Skip '%'
  next_char();                      // Skip '}'
  skipws();
  if (_AD._adlocation_debug) {
    encoding->add_code(end_line_marker());
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
}
void ADLParser::frame_parse(void) {
  FrameForm  *frame;              // Information about stack-frame layout
  char       *desc = NULL;        // String representation of frame
  skipws();                       // Skip leading whitespace
  frame = new FrameForm();        // Build new Frame object
  skipws();                       // Skip leading whitespace
  if (_curchar == '%' && *(_ptr+1) == '{') {
    next_char(); next_char();     // Skip "%{"
    skipws();
    while (_curchar != '%' && *(_ptr+1) != '}') {
      char *token = get_ident();
      if (token == NULL) {
            parse_err(SYNERR, "missing identifier inside frame block.\n");
            return;
      }
      if (strcmp(token,"stack_direction")==0) {
        stack_dir_parse(frame);
      }
      if (strcmp(token,"sync_stack_slots")==0) {
        sync_stack_slots_parse(frame);
      }
      if (strcmp(token,"frame_pointer")==0) {
        frame_pointer_parse(frame, false);
      }
      if (strcmp(token,"interpreter_frame_pointer")==0) {
        interpreter_frame_pointer_parse(frame, false);
      }
      if (strcmp(token,"inline_cache_reg")==0) {
        inline_cache_parse(frame, false);
      }
      if (strcmp(token,"compiler_method_oop_reg")==0) {
        parse_err(WARN, "Using obsolete Token, compiler_method_oop_reg");
        skipws();
      }
      if (strcmp(token,"interpreter_method_oop_reg")==0) {
        interpreter_method_oop_parse(frame, false);
      }
      if (strcmp(token,"cisc_spilling_operand_name")==0) {
        cisc_spilling_operand_name_parse(frame, false);
      }
      if (strcmp(token,"stack_alignment")==0) {
        stack_alignment_parse(frame);
      }
      if (strcmp(token,"return_addr")==0) {
        return_addr_parse(frame, false);
      }
      if (strcmp(token,"in_preserve_stack_slots")==0) {
        preserve_stack_parse(frame);
      }
      if (strcmp(token,"out_preserve_stack_slots")==0) {
        parse_err(WARN, "Using obsolete token, out_preserve_stack_slots");
        skipws();
      }
      if (strcmp(token,"varargs_C_out_slots_killed")==0) {
        frame->_varargs_C_out_slots_killed = parse_one_arg("varargs C out slots killed");
      }
      if (strcmp(token,"calling_convention")==0) {
        frame->_calling_convention = calling_convention_parse();
      }
      if (strcmp(token,"return_value")==0) {
        frame->_return_value = return_value_parse();
      }
      if (strcmp(token,"c_frame_pointer")==0) {
        frame_pointer_parse(frame, true);
      }
      if (strcmp(token,"c_return_addr")==0) {
        return_addr_parse(frame, true);
      }
      if (strcmp(token,"c_calling_convention")==0) {
        frame->_c_calling_convention = calling_convention_parse();
      }
      if (strcmp(token,"c_return_value")==0) {
        frame->_c_return_value = return_value_parse();
      }
      skipws();
    }
  }
  else {
    parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%');
    return;
  }
  if(frame->_frame_pointer == NULL) {
    parse_err(SYNERR, "missing frame pointer definition in frame section.\n");
    return;
  }
  if(frame->_alignment == NULL) {
    parse_err(SYNERR, "missing alignment definition in frame section.\n");
    return;
  }
  if(frame->_return_addr == NULL) {
    parse_err(SYNERR, "missing return address location in frame section.\n");
    return;
  }
  if(frame->_in_preserve_slots == NULL) {
    parse_err(SYNERR, "missing stack slot preservation definition in frame section.\n");
    return;
  }
  if(frame->_varargs_C_out_slots_killed == NULL) {
    parse_err(SYNERR, "missing varargs C out slots killed definition in frame section.\n");
    return;
  }
  if(frame->_calling_convention == NULL) {
    parse_err(SYNERR, "missing calling convention definition in frame section.\n");
    return;
  }
  if(frame->_return_value == NULL) {
    parse_err(SYNERR, "missing return value definition in frame section.\n");
    return;
  }
  if(frame->_c_frame_pointer == NULL) {
    frame->_c_frame_pointer = frame->_frame_pointer;
  }
  if(frame->_c_return_addr == NULL) {
    frame->_c_return_addr = frame->_return_addr;
    frame->_c_return_addr_loc = frame->_return_addr_loc;
  }
  if(frame->_c_calling_convention == NULL) {
    frame->_c_calling_convention = frame->_calling_convention;
  }
  if(frame->_c_return_value == NULL) {
    frame->_c_return_value = frame->_return_value;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Frame Form: %s\n", desc);
  _AD.addForm(frame);
}
void ADLParser::stack_dir_parse(FrameForm *frame) {
  char *direction = parse_one_arg("stack direction entry");
  if (strcmp(direction, "TOWARDS_LOW") == 0) {
    frame->_direction = false;
  }
  else if (strcmp(direction, "TOWARDS_HIGH") == 0) {
    frame->_direction = true;
  }
  else {
    parse_err(SYNERR, "invalid value inside stack direction entry.\n");
    return;
  }
}
void ADLParser::sync_stack_slots_parse(FrameForm *frame) {
    frame->_sync_stack_slots = parse_one_arg("sync stack slots entry");
}
void ADLParser::frame_pointer_parse(FrameForm *frame, bool native) {
  char *frame_pointer = parse_one_arg("frame pointer entry");
  if (native) { frame->_c_frame_pointer = frame_pointer; }
  else        { frame->_frame_pointer   = frame_pointer; }
}
void ADLParser::interpreter_frame_pointer_parse(FrameForm *frame, bool native) {
  frame->_interpreter_frame_pointer_reg = parse_one_arg("interpreter frame pointer entry");
}
void ADLParser::inline_cache_parse(FrameForm *frame, bool native) {
  frame->_inline_cache_reg = parse_one_arg("inline cache reg entry");
}
void ADLParser::interpreter_method_oop_parse(FrameForm *frame, bool native) {
  frame->_interpreter_method_oop_reg = parse_one_arg("method oop reg entry");
}
void ADLParser::cisc_spilling_operand_name_parse(FrameForm *frame, bool native) {
  frame->_cisc_spilling_operand_name = parse_one_arg("cisc spilling operand name");
}
void ADLParser::stack_alignment_parse(FrameForm *frame) {
  char *alignment = parse_one_arg("stack alignment entry");
  frame->_alignment   = alignment;
}
char *ADLParser::parse_one_arg(const char *description) {
  char *token = NULL;
  if(_curchar == '(') {
    next_char();
    skipws();
    token = get_expr(description, ")");
    if (token == NULL) {
      parse_err(SYNERR, "missing value inside %s.\n", description);
      return NULL;
    }
    next_char();           // skip the close paren
    if(_curchar != ';') {  // check for semi-colon
      parse_err(SYNERR, "missing %c in.\n", ';', description);
      return NULL;
    }
    next_char();           // skip the semi-colon
  }
  else {
    parse_err(SYNERR, "Missing %c in.\n", '(', description);
    return NULL;
  }
  trim(token);
  return token;
}
void ADLParser::return_addr_parse(FrameForm *frame, bool native) {
  bool in_register  = true;
  if(_curchar == '(') {
    next_char();
    skipws();
    char *token = get_ident();
    if (token == NULL) {
      parse_err(SYNERR, "missing value inside return address entry.\n");
      return;
    }
    if (strcmp(token, "REG") == 0) {
      in_register = true;
    }
    else if (strcmp(token, "STACK") == 0) {
      in_register = false;
    }
    else {
      parse_err(SYNERR, "invalid value inside return_address entry.\n");
      return;
    }
    if (native) { frame->_c_return_addr_loc = in_register; }
    else        { frame->_return_addr_loc   = in_register; }
    skipws();
    char *token2 = get_expr("return address entry", ")");
    if (token2 == NULL) {
      parse_err(SYNERR, "missing value inside return address entry.\n");
      return;
    }
    next_char();           // skip the close paren
    if (native) { frame->_c_return_addr = token2; }
    else        { frame->_return_addr   = token2; }
    if(_curchar != ';') {  // check for semi-colon
      parse_err(SYNERR, "missing %c in return address entry.\n", ';');
      return;
    }
    next_char();           // skip the semi-colon
  }
  else {
    parse_err(SYNERR, "Missing %c in return_address entry.\n", '(');
  }
}
void ADLParser::preserve_stack_parse(FrameForm *frame) {
  if(_curchar == '(') {
    char *token = get_paren_expr("preserve_stack_slots");
    frame->_in_preserve_slots   = token;
    if(_curchar != ';') {  // check for semi-colon
      parse_err(SYNERR, "missing %c in preserve stack slot entry.\n", ';');
      return;
    }
    next_char();           // skip the semi-colon
  }
  else {
    parse_err(SYNERR, "Missing %c in preserve stack slot entry.\n", '(');
  }
}
char *ADLParser::calling_convention_parse() {
  char   *desc = NULL;          // String representation of calling_convention
  skipws();                     // Skip leading whitespace
  if ( (desc = find_cpp_block("calling convention block")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing block for 'calling_convention'.\n");
  }
  return desc;
}
char *ADLParser::return_value_parse() {
  char   *desc = NULL;          // String representation of calling_convention
  skipws();                     // Skip leading whitespace
  if ( (desc = find_cpp_block("return value block")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing block for 'return_value'.\n");
  }
  return desc;
}
void ADLParser::ins_pipe_parse(InstructForm &instr) {
  char * ident;
  skipws();
  if ( _curchar != '(' ) {       // Check for delimiter
    parse_err(SYNERR, "missing \"(\" in ins_pipe definition\n");
    return;
  }
  next_char();
  ident = get_ident();           // Grab next identifier
  if (ident == NULL) {
    parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
    return;
  }
  skipws();
  if ( _curchar != ')' ) {       // Check for delimiter
    parse_err(SYNERR, "missing \")\" in ins_pipe definition\n");
    return;
  }
  next_char();                   // skip the close paren
  if(_curchar != ';') {          // check for semi-colon
    parse_err(SYNERR, "missing %c in return value entry.\n", ';');
    return;
  }
  next_char();                   // skip the semi-colon
  if (_AD._pipeline && !_AD._pipeline->_classlist.search(ident)) {
    parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", ident);
    return;
  }
  _AD._pipeline->_classdict[ident]->is_pipeclass()->_instructs.addName(instr._ident);
  instr._ins_pipe = ident;
  return;
}
void ADLParser::pipe_parse(void) {
  PipelineForm *pipeline;         // Encode class for instruction/operand
  char * ident;
  pipeline = new PipelineForm();  // Build new Source object
  _AD.addForm(pipeline);
  skipws();                       // Skip leading whitespace
  if ( (_curchar != '%')
       || ( next_char(),  (_curchar != '{')) ) {
    parse_err(SYNERR, "missing '%%{' in pipeline definition\n");
    return;
  }
  next_char();                     // Maintain the invariant
  do {
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
      continue;
    }
    if      (!strcmp(ident, "resources" )) resource_parse(*pipeline);
    else if (!strcmp(ident, "pipe_desc" )) pipe_desc_parse(*pipeline);
    else if (!strcmp(ident, "pipe_class")) pipe_class_parse(*pipeline);
    else if (!strcmp(ident, "define")) {
      skipws();
      if ( (_curchar != '%')
           || ( next_char(),  (_curchar != '{')) ) {
        parse_err(SYNERR, "expected '%%{'\n");
        return;
      }
      next_char(); skipws();
      char *node_class = get_ident();
      if (node_class == NULL) {
        parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar);
        return;
      }
      skipws();
      if (_curchar != ',' && _curchar != '=') {
        parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
        break;
      }
      next_char(); skipws();
      char *pipe_class = get_ident();
      if (pipe_class == NULL) {
        parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar);
        return;
      }
      if (_curchar != ';' ) {
        parse_err(SYNERR, "expected `;`, found '%c'\n", _curchar);
        break;
      }
      next_char();              // Skip over semi-colon
      skipws();
      if ( (_curchar != '%')
           || ( next_char(),  (_curchar != '}')) ) {
        parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar);
      }
      next_char();
      if (_AD._pipeline && !_AD._pipeline->_classlist.search(pipe_class)) {
        parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", pipe_class);
        return;
      }
      _AD._pipeline->_classdict[pipe_class]->is_pipeclass()->_instructs.addName(node_class);
      MachNodeForm *machnode = new MachNodeForm(node_class); // Create new machnode form
      machnode->_machnode_pipe = pipe_class;
      _AD.addForm(machnode);
    }
    else if (!strcmp(ident, "attributes")) {
      bool vsi_seen = false;
      skipws();
      if ( (_curchar != '%')
           || ( next_char(),  (_curchar != '{')) ) {
        parse_err(SYNERR, "expected '%%{'\n");
        return;
      }
      next_char(); skipws();
      while (_curchar != '%') {
        ident = get_ident();
        if (ident == NULL)
          break;
        if (!strcmp(ident, "variable_size_instructions")) {
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          pipeline->_variableSizeInstrs = true;
          vsi_seen = true;
          continue;
        }
        if (!strcmp(ident, "fixed_size_instructions")) {
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          pipeline->_variableSizeInstrs = false;
          vsi_seen = true;
          continue;
        }
        if (!strcmp(ident, "branch_has_delay_slot")) {
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          pipeline->_branchHasDelaySlot = true;
          continue;
        }
        if (!strcmp(ident, "max_instructions_per_bundle")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`\n");
            break;
            }
          next_char(); skipws();
          pipeline->_maxInstrsPerBundle = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "max_bundles_per_cycle")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`\n");
            break;
            }
          next_char(); skipws();
          pipeline->_maxBundlesPerCycle = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "instruction_unit_size")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
            break;
            }
          next_char(); skipws();
          pipeline->_instrUnitSize = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "bundle_unit_size")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
            break;
            }
          next_char(); skipws();
          pipeline->_bundleUnitSize = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "instruction_fetch_unit_size")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
            break;
            }
          next_char(); skipws();
          pipeline->_instrFetchUnitSize = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "instruction_fetch_units")) {
          skipws();
          if (_curchar != '=') {
            parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
            break;
            }
          next_char(); skipws();
          pipeline->_instrFetchUnits = get_int();
          skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        if (!strcmp(ident, "nops")) {
          skipws();
          if (_curchar != '(') {
            parse_err(SYNERR, "expected `(`, found '%c'\n", _curchar);
            break;
            }
          next_char(); skipws();
          while (_curchar != ')') {
            ident = get_ident();
            if (ident == NULL) {
              parse_err(SYNERR, "expected identifier for nop instruction, found '%c'\n", _curchar);
              break;
            }
            pipeline->_noplist.addName(ident);
            pipeline->_nopcnt++;
            skipws();
            if (_curchar == ',') {
              next_char(); skipws();
            }
          }
          next_char(); skipws();
          if (_curchar == ';') {
            next_char(); skipws();
          }
          continue;
        }
        parse_err(SYNERR, "unknown specifier \"%s\"\n", ident);
      }
      if ( (_curchar != '%')
           || ( next_char(),  (_curchar != '}')) ) {
        parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar);
      }
      next_char(); skipws();
      if (pipeline->_maxInstrsPerBundle == 0)
        parse_err(SYNERR, "\"max_instructions_per_bundle\" unspecified\n");
      if (pipeline->_instrUnitSize == 0 && pipeline->_bundleUnitSize == 0)
        parse_err(SYNERR, "\"instruction_unit_size\" and \"bundle_unit_size\" unspecified\n");
      if (pipeline->_instrFetchUnitSize == 0)
        parse_err(SYNERR, "\"instruction_fetch_unit_size\" unspecified\n");
      if (pipeline->_instrFetchUnits == 0)
        parse_err(SYNERR, "\"instruction_fetch_units\" unspecified\n");
      if (!vsi_seen)
        parse_err(SYNERR, "\"variable_size_instruction\" or \"fixed_size_instruction\" unspecified\n");
    }
    else {  // Done with staticly defined parts of instruction definition
      parse_err(SYNERR, "expected one of \"resources\", \"pipe_desc\", \"pipe_class\", found \"%s\"\n", ident);
      return;
    }
    skipws();
    if (_curchar == ';')
      skipws();
  } while(_curchar != '%');
  next_char();
  if (_curchar != '}') {
    parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n");
    return;
  }
  next_char();
}
void ADLParser::resource_parse(PipelineForm &pipeline) {
  ResourceForm *resource;
  char * ident;
  char * expr;
  unsigned mask;
  pipeline._rescount = 0;
  skipws();                       // Skip leading whitespace
  if (_curchar != '(') {
    parse_err(SYNERR, "missing \"(\" in resource definition\n");
    return;
  }
  do {
    next_char();                   // Skip "(" or ","
    ident = get_ident();           // Grab next identifier
    if (_AD._adl_debug > 1) {
      if (ident != NULL) {
        fprintf(stderr, "resource_parse: identifier: %s\n", ident);
      }
    }
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
      return;
    }
    skipws();
    if (_curchar != '=') {
      mask = (1 << pipeline._rescount++);
    }
    else {
      next_char(); skipws();
      expr = get_ident();          // Grab next identifier
      if (expr == NULL) {
        parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
        return;
      }
      resource = (ResourceForm *) pipeline._resdict[expr];
      if (resource == NULL) {
        parse_err(SYNERR, "resource \"%s\" is not defined\n", expr);
        return;
      }
      mask = resource->mask();
      skipws();
      while (_curchar == '|') {
        next_char(); skipws();
        expr = get_ident();          // Grab next identifier
        if (expr == NULL) {
          parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
          return;
        }
        resource = (ResourceForm *) pipeline._resdict[expr];   // Look up the value
        if (resource == NULL) {
          parse_err(SYNERR, "resource \"%s\" is not defined\n", expr);
          return;
        }
        mask |= resource->mask();
        skipws();
      }
    }
    resource = new ResourceForm(mask);
    pipeline._resdict.Insert(ident, resource);
    pipeline._reslist.addName(ident);
  } while (_curchar == ',');
  if (_curchar != ')') {
      parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
      return;
  }
  next_char();                 // Skip ")"
  if (_curchar == ';')
    next_char();               // Skip ";"
}
void ADLParser::pipe_desc_parse(PipelineForm &pipeline) {
  char * ident;
  skipws();                       // Skip leading whitespace
  if (_curchar != '(') {
    parse_err(SYNERR, "missing \"(\" in pipe_desc definition\n");
    return;
  }
  do {
    next_char();                   // Skip "(" or ","
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
      return;
    }
    pipeline._stages.addName(ident);
    pipeline._stagecnt++;
    skipws();
  } while (_curchar == ',');
  if (_curchar != ')') {
      parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
      return;
  }
  next_char();                     // Skip ")"
  if (_curchar == ';')
    next_char();                   // Skip ";"
}
void ADLParser::pipe_class_parse(PipelineForm &pipeline) {
  PipeClassForm *pipe_class;
  char * ident;
  char * stage;
  char * read_or_write;
  int is_write;
  int is_read;
  OperandForm  *oper;
  skipws();                       // Skip leading whitespace
  ident = get_ident();            // Grab next identifier
  if (ident == NULL) {
    parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
    return;
  }
  pipe_class = new PipeClassForm(ident, ++pipeline._classcnt);
  pipeline._classdict.Insert(ident, pipe_class);
  pipeline._classlist.addName(ident);
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing \"(\" in pipe_class definition\n");
  }
  else get_oplist(pipe_class->_parameters, pipe_class->_localNames);
  skipws();                        // Skip leading whitespace
  if ( (_curchar != '%')
       || ( next_char(),  (_curchar != '{')) ) {
    parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n");
    return;
  }
  next_char();
  do {
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
      continue;
    }
    skipws();
    if (!strcmp(ident, "fixed_latency")) {
      skipws();
      if (_curchar != '(') {
        parse_err(SYNERR, "missing \"(\" in latency definition\n");
        return;
      }
      next_char(); skipws();
      if( !isdigit(_curchar) ) {
        parse_err(SYNERR, "number expected for \"%c\" in latency definition\n", _curchar);
        return;
      }
      int fixed_latency = get_int();
      skipws();
      if (_curchar != ')') {
        parse_err(SYNERR, "missing \")\" in latency definition\n");
        return;
      }
      next_char(); skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" in latency definition\n");
        return;
      }
      pipe_class->setFixedLatency(fixed_latency);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "zero_instructions") ||
        !strcmp(ident, "no_instructions")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" in latency definition\n");
        return;
      }
      pipe_class->setInstructionCount(0);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "one_instruction_with_delay_slot") ||
        !strcmp(ident, "single_instruction_with_delay_slot")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" in latency definition\n");
        return;
      }
      pipe_class->setInstructionCount(1);
      pipe_class->setBranchDelay(true);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "one_instruction") ||
        !strcmp(ident, "single_instruction")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" in latency definition\n");
        return;
      }
      pipe_class->setInstructionCount(1);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "instructions_in_first_bundle") ||
        !strcmp(ident, "instruction_count")) {
      skipws();
      int number_of_instructions = 1;
      if (_curchar != '(') {
        parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      number_of_instructions = get_int();
      skipws();
      if (_curchar != ')') {
        parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" in latency definition\n");
        return;
      }
      pipe_class->setInstructionCount(number_of_instructions);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "multiple_bundles")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" after multiple bundles\n");
        return;
      }
      pipe_class->setMultipleBundles(true);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "has_delay_slot")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" after \"has_delay_slot\"\n");
        return;
      }
      pipe_class->setBranchDelay(true);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "force_serialization")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" after \"force_serialization\"\n");
        return;
      }
      pipe_class->setForceSerialization(true);
      next_char(); skipws();
      continue;
    }
    if (!strcmp(ident, "may_have_no_code")) {
      skipws();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing \";\" after \"may_have_no_code\"\n");
        return;
      }
      pipe_class->setMayHaveNoCode(true);
      next_char(); skipws();
      continue;
    }
    const Form *parm = pipe_class->_localNames[ident];
    if (parm != NULL) {
      oper = parm->is_operand();
      if (oper == NULL && !parm->is_opclass()) {
        parse_err(SYNERR, "operand name expected at %s\n", ident);
        continue;
      }
      if (_curchar != ':') {
        parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      stage = get_ident();
      if (stage == NULL) {
        parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar);
        continue;
      }
      skipws();
      if (_curchar != '(') {
        parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char();
      read_or_write = get_ident();
      if (read_or_write == NULL) {
        parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar);
        continue;
      }
      is_read  = strcmp(read_or_write, "read")   == 0;
      is_write = strcmp(read_or_write, "write")  == 0;
      if (!is_read && !is_write) {
        parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar);
        continue;
      }
      skipws();
      if (_curchar != ')') {
        parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      int more_instrs = 0;
      if (_curchar == '+') {
          next_char(); skipws();
          if (_curchar < '0' || _curchar > '9') {
            parse_err(SYNERR, "<number> expected at \"%c\"\n", _curchar);
            continue;
          }
          while (_curchar >= '0' && _curchar <= '9') {
            more_instrs *= 10;
            more_instrs += _curchar - '0';
            next_char();
          }
          skipws();
      }
      PipeClassOperandForm *pipe_operand = new PipeClassOperandForm(stage, is_write, more_instrs);
      pipe_class->_localUsage.Insert(ident, pipe_operand);
      if (_curchar == '%')
          continue;
      if (_curchar != ';') {
        parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      continue;
    }
    const Form *res = pipeline._resdict[ident];
    if (res != NULL) {
      int cyclecnt = 1;
      if (_curchar != ':') {
        parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      stage = get_ident();
      if (stage == NULL) {
        parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar);
        continue;
      }
      skipws();
      if (_curchar == '(') {
        next_char();
        cyclecnt = get_int();
        skipws();
        if (_curchar != ')') {
          parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
          continue;
        }
        next_char(); skipws();
      }
      PipeClassResourceForm *resource = new PipeClassResourceForm(ident, stage, cyclecnt);
      int stagenum = pipeline._stages.index(stage);
      if (pipeline._maxcycleused < (stagenum+cyclecnt))
        pipeline._maxcycleused = (stagenum+cyclecnt);
      pipe_class->_resUsage.addForm(resource);
      if (_curchar == '%')
          continue;
      if (_curchar != ';') {
        parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar);
        continue;
      }
      next_char(); skipws();
      continue;
    }
    parse_err(SYNERR, "resource expected at \"%s\"\n", ident);
    return;
  } while(_curchar != '%');
  next_char();
  if (_curchar != '}') {
    parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n");
    return;
  }
  next_char();
}
void ADLParser::peep_parse(void) {
  Peephole  *peep;                // Pointer to current peephole rule form
  char      *desc = NULL;         // String representation of rule
  skipws();                       // Skip leading whitespace
  peep = new Peephole();          // Build new Peephole object
  skipws();                       // Skip leading whitespace
  if (_curchar == '%' && *(_ptr+1) == '{') {
    next_char(); next_char();     // Skip "%{"
    skipws();
    while (_curchar != '%' && *(_ptr+1) != '}') {
      char *token = get_ident();
      if (token == NULL) {
        parse_err(SYNERR, "missing identifier inside peephole rule.\n");
        return;
      }
      if (strcmp(token,"peepmatch")==0) {
        peep_match_parse(*peep); }
      else if (strcmp(token,"peepconstraint")==0) {
        peep_constraint_parse(*peep); }
      else if (strcmp(token,"peepreplace")==0) {
        peep_replace_parse(*peep); }
      else {
        parse_err(SYNERR, "expected peepmatch, peepconstraint, or peepreplace for identifier %s.\n", token);
      }
      skipws();
    }
  }
  else {
    parse_err(SYNERR, "Missing %%{ ... %%} block after peephole keyword.\n");
    return;
  }
  next_char();                    // Skip past '%'
  next_char();                    // Skip past '}'
}
Constraint *ADLParser::constraint_parse(void) {
  char *func;
  char *arg;
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing constraint expression, (...)\n");
    return NULL;
  }
  next_char();                    // Skip past '('
  skipws();
  func = get_ident();
  if (func == NULL) {
    parse_err(SYNERR, "missing function in constraint expression.\n");
    return NULL;
  }
  if (strcmp(func,"ALLOC_IN_RC")==0
      || strcmp(func,"IS_R_CLASS")==0) {
    skipws();
    if (_curchar != '(') {
      parse_err(SYNERR, "missing '(' for constraint function's argument.\n");
      return NULL;
    }
    next_char();
    skipws();
    arg = get_ident();
    if (arg == NULL) {
      parse_err(SYNERR, "missing argument for constraint function %s\n",func);
      return NULL;
    }
    skipws();
    if (_curchar != ')') {
      parse_err(SYNERR, "missing ')' after constraint function argument %s\n",arg);
      return NULL;
    }
    next_char();
  } else {
    parse_err(SYNERR, "Invalid constraint function %s\n",func);
    return NULL;
  }
  skipws();
  if (_curchar != ')') {
    parse_err(SYNERR, "Missing ')' for constraint function %s\n",func);
    return NULL;
  }
  next_char();
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "Missing ';' after constraint.\n");
    return NULL;
  }
  next_char();
  Constraint *constraint = new Constraint(func,arg);
  return constraint;
}
ConstructRule *ADLParser::construct_parse(void) {
  return NULL;
}
void ADLParser::reg_def_parse(void) {
  char *rname;                   // Name of register being defined
  skipws();                      // Skip whitespace
  rname = get_ident();
  if (rname == NULL) {
    parse_err(SYNERR, "missing register name after reg_def\n");
    return;
  }
  skipws();
  char *callconv  = NULL;
  char *c_conv    = NULL;
  char *idealtype = NULL;
  char *encoding  = NULL;
  char *concrete = NULL;
  if (_curchar == '(') {
    next_char();
    callconv = get_ident();
    if (callconv == NULL) {
      parse_err(SYNERR, "missing register calling convention value\n");
      return;
    }
    if(strcmp(callconv, "SOC") && strcmp(callconv,"SOE") &&
       strcmp(callconv, "NS") && strcmp(callconv, "AS")) {
      parse_err(SYNERR, "invalid value for register calling convention\n");
    }
    skipws();
    if (_curchar != ',') {
      parse_err(SYNERR, "missing comma in register definition statement\n");
      return;
    }
    next_char();
    c_conv = get_ident();
    if (c_conv == NULL) {
      parse_err(SYNERR, "missing register native calling convention value\n");
      return;
    }
    if(strcmp(c_conv, "SOC") && strcmp(c_conv,"SOE") &&
       strcmp(c_conv, "NS") && strcmp(c_conv, "AS")) {
      parse_err(SYNERR, "invalid value for register calling convention\n");
    }
    skipws();
    if (_curchar != ',') {
      parse_err(SYNERR, "missing comma in register definition statement\n");
      return;
    }
    next_char();
    skipws();
    idealtype = get_ident();
    if (idealtype == NULL) {
      parse_err(SYNERR, "missing register save type value\n");
      return;
    }
    skipws();
    if (_curchar != ',') {
      parse_err(SYNERR, "missing comma in register definition statement\n");
      return;
    }
    next_char();
    skipws();
    encoding = get_expr("encoding", ",");
    if (encoding == NULL) {
      parse_err(SYNERR, "missing register encoding value\n");
      return;
    }
    trim(encoding);
    if (_curchar != ',') {
      parse_err(SYNERR, "missing comma in register definition statement\n");
      return;
    }
    next_char();
    skipws();
    concrete = get_expr("concrete", ")");
    if (concrete == NULL) {
      parse_err(SYNERR, "missing vm register name value\n");
      return;
    }
    if (_curchar != ')') {
      parse_err(SYNERR, "missing ')' in register definition statement\n");
      return;
    }
    next_char();
  }
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' after reg_def\n");
    return;
  }
  next_char();                   // move past ';'
  if (_AD._adl_debug > 1) {
    fprintf(stderr,"Register Definition: %s ( %s, %s %s )\n", rname,
            (callconv ? callconv : ""), (c_conv ? c_conv : ""), concrete);
  }
  _AD._register->addRegDef(rname, callconv, c_conv, idealtype, encoding, concrete);
  return;
}
void ADLParser::reg_class_parse(void) {
  char *cname;                    // Name of register class being defined
  skipws();                       // Skip leading whitespace
  cname = get_ident();
  if (cname == NULL) {
    parse_err(SYNERR, "missing register class name after 'reg_class'\n");
    return;
  }
  if (_AD._adl_debug >1) fprintf(stderr,"Register Class: %s\n", cname);
  skipws();
  if (_curchar == '(') {
    RegClass* reg_class = _AD._register->addRegClass<RegClass>(cname);
    next_char();                  // Skip '('
    skipws();
    while (_curchar != ')') {
      char *rname = get_ident();
      if (rname==NULL) {
        parse_err(SYNERR, "missing identifier inside reg_class list.\n");
        return;
      }
      RegDef *regDef = _AD._register->getRegDef(rname);
      if (!regDef) {
        parse_err(SEMERR, "unknown identifier %s inside reg_class list.\n", rname);
      } else {
        reg_class->addReg(regDef); // add regDef to regClass
      }
      skipws();
      if (_curchar == ',') {
        next_char();              // Skip trailing ','
        skipws();
      }
    }
    next_char();                  // Skip closing ')'
  } else if (_curchar == '%') {
    CodeSnippetRegClass* reg_class = _AD._register->addRegClass<CodeSnippetRegClass>(cname);
    char *code = find_cpp_block("reg class");
    if (code == NULL) {
      parse_err(SYNERR, "missing code declaration for reg class.\n");
      return;
    }
    reg_class->set_code_snippet(code);
    return;
  }
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' at end of reg_class definition.\n");
    return;
  }
  next_char();                    // Skip trailing ';'
  return;
}
void ADLParser::reg_class_dynamic_parse(void) {
  char *cname; // Name of dynamic register class being defined
  skipws();
  cname = get_ident();
  if (cname == NULL) {
    parse_err(SYNERR, "missing dynamic register class name after 'reg_class_dynamic'\n");
    return;
  }
  if (_AD._adl_debug > 1) {
    fprintf(stdout, "Dynamic Register Class: %s\n", cname);
  }
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' at the beginning of reg_class_dynamic definition\n");
    return;
  }
  next_char();
  skipws();
  ConditionalRegClass* reg_class = _AD._register->addRegClass<ConditionalRegClass>(cname);
  int i;
  for (i = 0; i < 2; i++) {
    char* name = get_ident();
    if (name == NULL) {
      parse_err(SYNERR, "missing class identifier inside reg_class_dynamic list.\n");
      return;
    }
    RegClass* rc = _AD._register->getRegClass(name);
    if (rc == NULL) {
      parse_err(SEMERR, "unknown identifier %s inside reg_class_dynamic list.\n", name);
    } else {
      reg_class->set_rclass_at_index(i, rc);
    }
    skipws();
    if (_curchar == ',') {
      next_char();
      skipws();
    } else {
      parse_err(SYNERR, "missing separator ',' inside reg_class_dynamic list.\n");
    }
  }
  skipws();
  if (_curchar == '%') {
    char* code = find_cpp_block("reg class dynamic");
    if (code == NULL) {
       parse_err(SYNERR, "missing code declaration for reg_class_dynamic.\n");
       return;
    }
    reg_class->set_condition_code(code);
  } else {
    parse_err(SYNERR, "missing %% at the beginning of code block in reg_class_dynamic definition\n");
    return;
  }
  skipws();
  if (_curchar != ')') {
    parse_err(SYNERR, "missing ')' at the end of reg_class_dynamic definition\n");
    return;
  }
  next_char();
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' at the end of reg_class_dynamic definition.\n");
    return;
  }
  next_char();                    // Skip trailing ';'
  return;
}
void ADLParser::alloc_class_parse(void) {
  char *name;                     // Name of allocation class being defined
  skipws();                       // Skip leading whitespace
  name = get_ident();
  if (name == NULL) {
    parse_err(SYNERR, "missing allocation class name after 'reg_class'\n");
    return;
  }
  if (_AD._adl_debug >1) fprintf(stderr,"Allocation Class: %s\n", name);
  AllocClass *alloc_class = _AD._register->addAllocClass(name);
  skipws();
  if (_curchar == '(') {
    next_char();                  // Skip '('
    skipws();
    while (_curchar != ')') {
      char *rname = get_ident();
      if (rname==NULL) {
        parse_err(SYNERR, "missing identifier inside reg_class list.\n");
        return;
      }
      RegDef *regDef = _AD._register->getRegDef(rname);
      if (regDef) {
        alloc_class->addReg(regDef);   // add regDef to allocClass
      } else {
        parse_err(SYNERR, "name %s should be a previously defined reg_def.\n", rname);
        return;
      }
      skipws();
      if (_curchar == ',') {
        next_char();              // Skip trailing ','
        skipws();
      }
    }
    next_char();                  // Skip closing ')'
  }
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' at end of reg_class definition.\n");
    return;
  }
  next_char();                    // Skip trailing ';'
  return;
}
InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, int &position, int input){
  char      *token  = NULL;
  int        lparen = 0;          // keep track of parenthesis nesting depth
  int        rparen = 0;          // position of instruction at this depth
  InstructForm *inst_seen  = NULL;
  while ( lparen >= rparen ) {
    skipws();
    if (_curchar == '(') {
      ++lparen;
      next_char();
      ( void ) peep_match_child_parse(match, parent, position, rparen);
    }
    else if (_curchar == ')') {
      ++rparen;
      if( rparen == lparen ) { // IF rparen matches an lparen I've seen
        next_char();           //    move past ')'
      } else {                 // ELSE leave ')' for parent
        assert( rparen == lparen + 1, "Should only see one extra ')'");
        if( ! inst_seen ) {   // record signal entry
          match.add_instruction( parent, position, NameList::_signal, input );
          ++position;
        }
        return inst_seen;
      }
    }
    else if ((token = get_ident_dup()) != NULL) {
      const Form *form = _AD._globalNames[token];
      if (form) {
        InstructForm *inst = form->is_instruction();
        if( inst_seen == NULL ) {
          inst_seen = inst;
        }
        if (inst) {
          match.add_instruction( parent, position, token, input );
          parent = position;
          ++position;
        } else {
          parse_err(SYNERR, "instruction name expected at identifier %s.\n",
                    token);
          return inst_seen;
        }
      }
      else {
        parse_err(SYNERR, "missing identifier in peepmatch rule.\n");
        return NULL;
      }
    }
    else {
      parse_err(SYNERR, "missing identifier in peepmatch rule.\n");
      return NULL;
    }
  } // end while
  assert( false, "ShouldNotReachHere();");
  return NULL;
}
void ADLParser::peep_match_parse(Peephole &peep) {
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' at start of peepmatch rule.\n");
    return;
  }
  next_char();   // skip '('
  PeepMatch *match = new PeepMatch(_ptr);
  int  parent   = -1;                   // parent of root
  int  position = 0;                    // zero-based positions
  int  input    = 0;                    // input position in parent's operands
  InstructForm *root= peep_match_child_parse( *match, parent, position, input);
  if( root == NULL ) {
    parse_err(SYNERR, "missing instruction-name at start of peepmatch.\n");
    return;
  }
  if( _curchar != ')' ) {
    parse_err(SYNERR, "missing ')' at end of peepmatch.\n");
    return;
  }
  next_char();   // skip ')'
  skipws();
  if( _curchar != ';' ) {
    parse_err(SYNERR, "missing ';' at end of peepmatch.\n");
    return;
  }
  next_char();   // skip ';'
  peep.add_match(match);
  root->append_peephole(&peep);
}
void ADLParser::peep_constraint_parse(Peephole &peep) {
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' at start of peepconstraint rule.\n");
    return;
  }
  else {
    next_char();                  // Skip '('
  }
  skipws();
  while( _curchar != ')' ) {
    int left_inst = get_int();
    skipws();
    if( _curchar != '.' ) {
      parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n");
      return;
    }
    next_char();                  // Skip '.'
    char *left_op = get_ident_dup();
    skipws();
    char *relation = get_relation_dup();
    skipws();
    int right_inst;        // Right-instructions's number
    if( isdigit(_curchar) ) {
      right_inst = get_int();
      skipws();
      if( _curchar != '.' ) {
        parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n");
        return;
      }
      next_char();              // Skip '.'
    } else {
      right_inst = -1;          // Flag as being a register constraint
    }
    char *right_op = get_ident_dup();
    PeepConstraint *constraint = new PeepConstraint( left_inst, left_op,
                                                     relation,
                                                     right_inst, right_op );
    peep.append_constraint( constraint );
    skipws();
    if( _curchar == ',' ) {
      next_char();                // Skip ','
      skipws();
    }
    else if( _curchar != ')' ) {
      parse_err(SYNERR, "expected ',' or ')' after peephole constraint.\n");
      return;
    }
  } // end while( processing constraints )
  next_char();                    // Skip ')'
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' at end of peepconstraint.\n");
    return;
  }
  next_char();                    // Skip trailing ';'
}
void ADLParser::peep_replace_parse(Peephole &peep) {
  int          lparen = 0;        // keep track of parenthesis nesting depth
  int          rparen = 0;        // keep track of parenthesis nesting depth
  int          icount = 0;        // count of instructions in rule for naming
  char        *str    = NULL;
  char        *token  = NULL;
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' at start of peepreplace rule.\n");
    return;
  }
  else {
    lparen++;
    next_char();
  }
  char       *inst = get_ident_dup();
  const Form *form = _AD._globalNames[inst];
  if( form == NULL || form->is_instruction() == NULL ) {
    parse_err(SYNERR, "Instruction name expected at start of peepreplace.\n");
    return;
  }
  PeepReplace *replace = new PeepReplace(str);
  replace->add_instruction( inst );
  skipws();
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' at peepreplace root's operand-list.\n");
    return;
  }
  else {
    lparen++;
    next_char();
  }
  skipws();
  while( _curchar != ')' ) {
    int   inst_num = get_int();
    skipws();
    if( _curchar != '.' ) {
      parse_err(SYNERR, "missing '.' in peepreplace after instruction number.\n");
      return;
    }
    next_char();                  // Skip '.'
    char *inst_op = get_ident_dup();
    if( inst_op == NULL ) {
      parse_err(SYNERR, "missing operand identifier in peepreplace.\n");
      return;
    }
    replace->add_operand( inst_num, inst_op );
    skipws();
  }
  skipws();
  assert( _curchar == ')', "While loop should have advanced to ')'.");
  next_char();  // Skip ')'
  skipws();
  if( _curchar != ')' ) {
    parse_err(SYNERR, "missing ')' at end of peepmatch.\n");
    parse_err(SYNERR, "Support one replacement instruction.\n");
    return;
  }
  next_char(); // Skip ')'
  skipws();
  if( _curchar != ';' ) {
    parse_err(SYNERR, "missing ';' at end of peepreplace.\n");
    return;
  }
  next_char();   // skip ';'
  peep.add_replace( replace );
}
Predicate *ADLParser::pred_parse(void) {
  Predicate *predicate;           // Predicate class for operand
  char      *rule = NULL;         // String representation of predicate
  skipws();                       // Skip leading whitespace
  int line = linenum();
  if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
    parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
    return NULL;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule);
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in predicate definition\n");
    return NULL;
  }
  next_char();                     // Point after the terminator
  predicate = new Predicate(rule); // Build new predicate object
  skipws();
  return predicate;
}
void ADLParser::ins_encode_parse_block(InstructForm& inst) {
  const char* prefix = "__ins_encode_";
  char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
  sprintf(ec_name, "%s%s", prefix, inst._ident);
  assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
  EncClass* encoding = _AD._encode->add_EncClass(ec_name);
  encoding->_linenum = linenum();
  const char* param = NULL;
  inst._parameters.reset();
  while ((param = inst._parameters.iter()) != NULL) {
    OpClassForm* opForm = inst._localNames[param]->is_opclass();
    assert(opForm != NULL, "sanity");
    encoding->add_parameter(opForm->_ident, param);
  }
  if (!inst._is_postalloc_expand) {
    encoding->add_code("    MacroAssembler _masm(&cbuf);\n");
  }
  ins_encode_parse_block_impl(inst, encoding, ec_name);
  InsEncode*   encrule = new InsEncode(); // Encode class for instruction
  NameAndList* params  = encrule->add_encode(ec_name);
  inst._parameters.reset();
  while ((param = inst._parameters.iter()) != NULL) {
    params->add_entry(param);
  }
  if (inst._insencode != NULL) {
    parse_err(SYNERR, "Multiple ins_encode sections defined\n");
    return;
  }
  inst._insencode = encrule;
}
void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
  skipws_no_preproc();              // Skip leading whitespace
  if (_AD._adlocation_debug) {
    encoding->add_code(get_line_string());
  }
  while ((_curchar != '%') && (*(_ptr+1) != '}')) {
    char *start = _ptr;       // Record start of the next string
    while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
      if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
        skipws_no_preproc();
      } else {
        next_char_or_line();
      }
    }
    if (start != _ptr) {
      encoding->add_code(start);
    }
    if (_curchar == '$') {
      char* rep_var = get_rep_var_ident_dup();
      encoding->add_rep_var(rep_var);
      skipws();
      if (strcmp(rep_var, "constanttablebase") == 0) {
        inst.set_needs_constant_base(true);
        if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
          inst.set_is_mach_constant(true);
        }
        if (_curchar == '(')  {
          parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
                            "(only constantaddress and constantoffset)", ec_name);
          return;
        }
      }
      else if ((strcmp(rep_var, "constantaddress")   == 0) ||
               (strcmp(rep_var, "constantoffset")    == 0)) {
        inst.set_is_mach_constant(true);
        if (_curchar == '(')  constant_parse(inst);
      }
    }
  } // end while part of format description
  next_char();                      // Skip '%'
  next_char();                      // Skip '}'
  skipws();
  if (_AD._adlocation_debug) {
    encoding->add_code(end_line_marker());
  }
  if (_AD._adl_debug > 1)  fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
void ADLParser::ins_encode_parse(InstructForm& inst) {
  skipws();                        // Skip whitespace
  if (_curchar != '(') {
    if ((_curchar == '%') && (*(_ptr+1) == '{')) {
      next_char();                      // Skip '%'
      next_char();                      // Skip '{'
      ins_encode_parse_block(inst);
      return;
    }
    parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
    return;
  }
  next_char();                     // move past '('
  skipws();
  InsEncode *encrule  = new InsEncode(); // Encode class for instruction
  encrule->_linenum = linenum();
  char      *ec_name  = NULL;      // String representation of encode rule
  while (_curchar != ')') {
    ec_name = get_ident();
    if (ec_name == NULL) {
      parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
      return;
    }
    EncClass *encode_class = _AD._encode->encClass(ec_name);
    if (encode_class == NULL) {
    }
    NameAndList *params = encrule->add_encode(ec_name);
    skipws();
    if ( _curchar == '(' ) {
      next_char();                 // move past '(' for parameters
      while (_curchar != ')') {
        char *param = get_ident_or_literal_constant("encoding operand");
        if ( param != NULL ) {
          if (strcmp(param, "constanttablebase") == 0) {
            inst.set_needs_constant_base(true);
            if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
              inst.set_is_mach_constant(true);
            }
            if (_curchar == '(')  {
              parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
                        "(only constantaddress and constantoffset)", ec_name);
              return;
            }
          } else {
            if ( (inst._localNames[param] == NULL) &&
                 !ADLParser::is_literal_constant(param) &&
                 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
                 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
              parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
              return;
            }
          }
          params->add_entry(param);
          skipws();
          if (_curchar == ',' ) {
            next_char();           // move past ',' between parameters
            skipws();              // Skip to next parameter
          }
          else if (_curchar == ')') {
          }
          else {
            parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
                      ec_name);
            return;
          }
        } else {
          skipws();
          if (_curchar == ',') {
            parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
            return;
          }
          if (_curchar != ')') {
            parse_err(SYNERR, "Expected ')' after encode parameters.\n");
            return;
          }
        }
      } // WHILE loop collecting parameters
      next_char();                   // move past ')' at end of parameters
    } // done with parameter list for encoding
    skipws();                      // move to character after parameters
    if ( _curchar == ',' ) {
      next_char();                 // move past ',' between encode methods
      skipws();
    }
    else if ( _curchar != ')' ) {
      parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
      return;
    }
  } // done parsing ins_encode methods and their parameters
  if (_curchar != ')') {
    parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
    return;
  }
  next_char();                     // move past ')'
  skipws();                        // Skip leading whitespace
  if ( _curchar != ';' ) {
    parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
    return;
  }
  next_char();                     // move past ';'
  skipws();                        // be friendly to oper_parse()
  if (inst._insencode != NULL) {
    parse_err(SYNERR, "Multiple ins_encode sections defined\n");
    return;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
  inst._insencode = encrule;
}
void ADLParser::postalloc_expand_parse(InstructForm& inst) {
  inst._is_postalloc_expand = true;
  skipws();                        // Skip whitespace.
  if (_curchar != '(') {
    if ((_curchar == '%') && (*(_ptr+1) == '{')) {
      next_char();                      // Skip '%'
      next_char();                      // Skip '{'
      ins_encode_parse_block(inst);
      return;
    }
    parse_err(SYNERR, "missing '(' in postalloc_expand definition\n");
    return;
  }
  next_char();                     // Move past '('.
  skipws();
  InsEncode *encrule = new InsEncode(); // Encode class for instruction.
  encrule->_linenum = linenum();
  char      *ec_name = NULL;       // String representation of encode rule.
  if (_curchar != ')') {
    ec_name = get_ident();
    if (ec_name == NULL) {
      parse_err(SYNERR, "Invalid postalloc_expand class name after 'postalloc_expand('.\n");
      return;
    }
    EncClass *encode_class = _AD._encode->encClass(ec_name);
    NameAndList *params = encrule->add_encode(ec_name);
    skipws();
    if (_curchar == '(') {
      next_char();                 // Move past '(' for parameters.
      while (_curchar != ')') {
        char *param = get_ident_or_literal_constant("encoding operand");
        if (param != NULL) {
          if (strcmp(param, "constanttablebase") == 0) {
            inst.set_needs_constant_base(true);
            if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
              inst.set_is_mach_constant(true);
            }
            if (_curchar == '(') {
              parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
                        "(only constantaddress and constantoffset)", ec_name);
              return;
            }
          }
          else if ((strcmp(param, "constantaddress") == 0) ||
                   (strcmp(param, "constantoffset")  == 0))  {
            inst.set_is_mach_constant(true);
            if (_curchar == '(') constant_parse(inst);
          }
          else if ((inst._localNames[param] == NULL) &&
                   !ADLParser::is_literal_constant(param) &&
                   (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
                   ((_AD._register == NULL) || (_AD._register->getRegDef(param) == NULL))) {
            parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
            return;
          }
          params->add_entry(param);
          skipws();
          if (_curchar == ',') {
            next_char();           // Move past ',' between parameters.
            skipws();              // Skip to next parameter.
          } else if (_curchar == ')') {
          } else {
            parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", ec_name);
            return;
          }
        } else {
          skipws();
          if (_curchar == ',') {
            parse_err(SYNERR, "Expected encode parameter before ',' in postalloc_expand %s.\n", ec_name);
            return;
          }
          if (_curchar != ')') {
            parse_err(SYNERR, "Expected ')' after postalloc_expand parameters.\n");
            return;
          }
        }
      } // WHILE loop collecting parameters.
      next_char();                 // Move past ')' at end of parameters.
    } // Done with parameter list for encoding.
    skipws();                      // Move to character after parameters.
    if (_curchar != ')') {
      parse_err(SYNERR, "Expected ')' after postalloc_expand %s.\n", ec_name);
      return;
    }
  } // Done parsing postalloc_expand method and their parameters.
  if (_curchar != ')') {
    parse_err(SYNERR, "Missing ')' at end of postalloc_expand description.\n");
    return;
  }
  next_char();                     // Move past ')'.
  skipws();                        // Skip leading whitespace.
  if (_curchar != ';') {
    parse_err(SYNERR, "Missing ';' at end of postalloc_expand.\n");
    return;
  }
  next_char();                     // Move past ';'.
  skipws();                        // Be friendly to oper_parse().
  if (_AD._adl_debug > 1) fprintf(stderr, "Instruction postalloc_expand: %s\n", ec_name);
  inst._insencode = encrule;
}
void ADLParser::constant_parse(InstructForm& inst) {
  const char* prefix = "__constant_";
  char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
  sprintf(ec_name, "%s%s", prefix, inst._ident);
  assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
  EncClass* encoding = _AD._encode->add_EncClass(ec_name);
  encoding->_linenum = linenum();
  const char* param = NULL;
  inst._parameters.reset();
  while ((param = inst._parameters.iter()) != NULL) {
    OpClassForm* opForm = inst._localNames[param]->is_opclass();
    assert(opForm != NULL, "sanity");
    encoding->add_parameter(opForm->_ident, param);
  }
  constant_parse_expression(encoding, ec_name);
  InsEncode*   encrule = new InsEncode(); // Encode class for instruction
  NameAndList* params  = encrule->add_encode(ec_name);
  inst._parameters.reset();
  while ((param = inst._parameters.iter()) != NULL) {
    params->add_entry(param);
  }
  inst._constant = encrule;
}
void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
  skipws();
  if (_AD._adlocation_debug) {
    encoding->add_code(get_line_string());
  }
  encoding->add_code("    _constant = C->constant_table().add");
  encoding->add_code("(this, ");
  next_char();  // Skip '('
  int parens_depth = 1;
  while (parens_depth > 0) {
    if (_curchar == '(') {
      parens_depth++;
      encoding->add_code("(");
      next_char();
    }
    else if (_curchar == ')') {
      parens_depth--;
      if (parens_depth > 0)
        encoding->add_code(")");
      next_char();
    }
    else {
      char *start = _ptr;  // Record start of the next string
      while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) {
        next_char();
      }
      if (start != _ptr) {
        encoding->add_code(start);
      }
      if (_curchar == '$') {
        char* rep_var = get_rep_var_ident_dup();
        encoding->add_rep_var(rep_var);
      }
    }
  }
  encoding->add_code(");");
  if (_AD._adlocation_debug) {
    encoding->add_code(end_line_marker());
  }
  if (_AD._adl_debug > 1)  fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
char* ADLParser::size_parse(InstructForm *instr) {
  char* sizeOfInstr = NULL;
  skipws();
  sizeOfInstr = get_paren_expr("size expression");
  if (sizeOfInstr == NULL) {
     parse_err(SYNERR, "size of opcode expected at %c\n", _curchar);
     return NULL;
  }
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
    return NULL;
  }
  next_char();                     // Advance past the ';'
  skipws();                        // necessary for instr_parse()
  if (_AD._adl_debug > 1) {
    if (sizeOfInstr != NULL) {
      fprintf(stderr,"size of opcode: %s\n", sizeOfInstr);
    }
  }
  return sizeOfInstr;
}
Opcode * ADLParser::opcode_parse(InstructForm *instr) {
  char *primary   = NULL;
  char *secondary = NULL;
  char *tertiary  = NULL;
  char   *val    = NULL;
  Opcode *opcode = NULL;
  skipws();
  if (_curchar != '(') {         // Check for parenthesized operand list
    parse_err(SYNERR, "missing '(' in expand instruction declaration\n");
    return NULL;
  }
  next_char();                   // skip open paren
  skipws();
  if (_curchar != ')') {
    if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
        parse_err(SYNERR, "primary hex opcode expected at %c\n", _curchar);
        return NULL;
    }
    skipws();
    if (_curchar == ',') {
      next_char();
      skipws();
      if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
        parse_err(SYNERR, "secondary hex opcode expected at %c\n", _curchar);
        return NULL;
      }
      skipws();
      if (_curchar == ',') {
        next_char();
        skipws();
        if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
          parse_err(SYNERR,"tertiary hex opcode expected at %c\n", _curchar);
          return NULL;
        }
        skipws();
      }
    }
    skipws();
    if (_curchar != ')') {
      parse_err(SYNERR, "Missing ')' in opcode description\n");
      return NULL;
    }
  }
  next_char();                     // Skip ')'
  skipws();
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
    return NULL;
  }
  next_char();                     // Advance past the ';'
  skipws();                        // necessary for instr_parse()
  if (_AD._adl_debug > 1) {
    if (primary   != NULL) fprintf(stderr,"primary   opcode: %s\n", primary);
    if (secondary != NULL) fprintf(stderr,"secondary opcode: %s\n", secondary);
    if (tertiary  != NULL) fprintf(stderr,"tertiary  opcode: %s\n", tertiary);
  }
  opcode = new Opcode(primary, secondary, tertiary);
  return opcode;
}
Interface *ADLParser::interface_parse(void) {
  char *iface_name  = NULL;      // Name of interface class being used
  char *iface_code  = NULL;      // Describe components of this class
  skipws();                       // Skip whitespace
  if (_curchar != '(') {
    parse_err(SYNERR, "Missing '(' at start of interface description.\n");
    return NULL;
  }
  next_char();                    // move past '('
  skipws();
  iface_name = get_ident();
  if (iface_name == NULL) {
    parse_err(SYNERR, "missing interface name after 'interface'.\n");
    return NULL;
  }
  skipws();
  if (_curchar != ')') {
    parse_err(SYNERR, "Missing ')' after name of interface.\n");
    return NULL;
  }
  next_char();                    // move past ')'
  Interface *inter = NULL;
  skipws();
  if ( _curchar != ';' ) {
    if ( strcmp(iface_name,"MEMORY_INTER") == 0 ) {
      inter = mem_interface_parse();
    }
    else if ( strcmp(iface_name,"COND_INTER") == 0 ) {
      inter = cond_interface_parse();
    }
    if ( _curchar == ';' ) {
      parse_err(SYNERR, "Extra ';' after defining interface block.\n");
      next_char();                // Skip ';'
      return NULL;
    }
  } else {
    next_char();                  // move past ';'
    if ( strcmp(iface_name,"REG_INTER") == 0 ) {
      inter = new RegInterface();
    }
    else if ( strcmp(iface_name,"CONST_INTER") == 0 ) {
      inter = new ConstInterface();
    }
  }
  skipws();                       // be friendly to oper_parse()
  if (_AD._adl_debug > 1) fprintf(stderr,"Interface Form: %s\n", iface_name);
  return inter;
}
Interface *ADLParser::mem_interface_parse(void) {
  char *base        = NULL;
  char *index       = NULL;
  char *scale       = NULL;
  char *disp        = NULL;
  if (_curchar != '%') {
    parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '%'
  if (_curchar != '{') {
    parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '{'
  skipws();
  do {
    char *field = get_ident();
    if (field == NULL) {
      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
      return NULL;
    }
    if ( strcmp(field,"base") == 0 ) {
      base  = interface_field_parse();
    }
    else if ( strcmp(field,"index") == 0 ) {
      index = interface_field_parse();
    }
    else if ( strcmp(field,"scale") == 0 ) {
      scale = interface_field_parse();
    }
    else if ( strcmp(field,"disp") == 0 ) {
      disp  = interface_field_parse();
    }
    else {
      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
      return NULL;
    }
  } while( _curchar != '%' );
  next_char();                  // Skip '%'
  if ( _curchar != '}' ) {
    parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '}'
  Interface *inter = new MemInterface(base, index, scale, disp);
  return inter;
}
Interface *ADLParser::cond_interface_parse(void) {
  char *equal;
  char *not_equal;
  char *less;
  char *greater_equal;
  char *less_equal;
  char *greater;
  char *overflow;
  char *no_overflow;
  const char *equal_format = "eq";
  const char *not_equal_format = "ne";
  const char *less_format = "lt";
  const char *greater_equal_format = "ge";
  const char *less_equal_format = "le";
  const char *greater_format = "gt";
  const char *overflow_format = "o";
  const char *no_overflow_format = "no";
  if (_curchar != '%') {
    parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '%'
  if (_curchar != '{') {
    parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '{'
  skipws();
  do {
    char *field = get_ident();
    if (field == NULL) {
      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
      return NULL;
    }
    if ( strcmp(field,"equal") == 0 ) {
      equal  = interface_field_parse(&equal_format);
    }
    else if ( strcmp(field,"not_equal") == 0 ) {
      not_equal = interface_field_parse(&not_equal_format);
    }
    else if ( strcmp(field,"less") == 0 ) {
      less = interface_field_parse(&less_format);
    }
    else if ( strcmp(field,"greater_equal") == 0 ) {
      greater_equal  = interface_field_parse(&greater_equal_format);
    }
    else if ( strcmp(field,"less_equal") == 0 ) {
      less_equal = interface_field_parse(&less_equal_format);
    }
    else if ( strcmp(field,"greater") == 0 ) {
      greater = interface_field_parse(&greater_format);
    }
    else if ( strcmp(field,"overflow") == 0 ) {
      overflow = interface_field_parse(&overflow_format);
    }
    else if ( strcmp(field,"no_overflow") == 0 ) {
      no_overflow = interface_field_parse(&no_overflow_format);
    }
    else {
      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
      return NULL;
    }
  } while( _curchar != '%' );
  next_char();                  // Skip '%'
  if ( _curchar != '}' ) {
    parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n");
    return NULL;
  }
  next_char();                  // Skip '}'
  Interface *inter = new CondInterface(equal,         equal_format,
                                       not_equal,     not_equal_format,
                                       less,          less_format,
                                       greater_equal, greater_equal_format,
                                       less_equal,    less_equal_format,
                                       greater,       greater_format,
                                       overflow,      overflow_format,
                                       no_overflow,   no_overflow_format);
  return inter;
}
char *ADLParser::interface_field_parse(const char ** format) {
  char *iface_field = NULL;
  skipws();                      // Skip whitespace
  if (_curchar != '(') {
    parse_err(SYNERR, "Missing '(' at start of interface field.\n");
    return NULL;
  }
  next_char();                   // move past '('
  skipws();
  if ( _curchar != '0' && _curchar != '$' ) {
    parse_err(SYNERR, "missing or invalid interface field contents.\n");
    return NULL;
  }
  iface_field = get_rep_var_ident();
  if (iface_field == NULL) {
    parse_err(SYNERR, "missing or invalid interface field contents.\n");
    return NULL;
  }
  skipws();
  if (format != NULL && _curchar == ',') {
    next_char();
    skipws();
    if (_curchar != '"') {
      parse_err(SYNERR, "Missing '\"' in field format .\n");
      return NULL;
    }
    next_char();
    char *start = _ptr;       // Record start of the next string
    while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
      if (_curchar == '\\')  next_char();  // superquote
      if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
      next_char();
    }
    if (_curchar != '"') {
      parse_err(SYNERR, "Missing '\"' at end of field format .\n");
      return NULL;
    }
    if ( start != _ptr ) {
    }
    next_char();
    skipws();
  }
  if (_curchar != ')') {
    parse_err(SYNERR, "Missing ')' after interface field.\n");
    return NULL;
  }
  next_char();                   // move past ')'
  skipws();
  if ( _curchar != ';' ) {
    parse_err(SYNERR, "Missing ';' at end of interface field.\n");
    return NULL;
  }
  next_char();                    // move past ';'
  skipws();                       // be friendly to interface_parse()
  return iface_field;
}
MatchRule *ADLParser::match_parse(FormDict &operands) {
  MatchRule *match;               // Match Rule class for instruction/operand
  char      *cnstr = NULL;        // Code for constructor
  int        depth = 0;           // Counter for matching parentheses
  int        numleaves = 0;       // Counter for number of leaves in rule
  MatchNode *mnode = matchNode_parse(operands, depth, numleaves, true);
  skipws();                       // Skip whitespace
  if ( _curchar == ';' ) {        // Semicolon is valid terminator
    cnstr = NULL;                 // no constructor for this form
    next_char();                  // Move past the ';', replaced with '\0'
  }
  else if ((cnstr = find_cpp_block("match constructor")) == NULL ) {
    parse_err(SYNERR, "invalid construction of match rule\n"
              "Missing ';' or invalid '%%{' and '%%}' constructor\n");
    return NULL;                  // No MatchRule to return
  }
  if (_AD._adl_debug > 1)
    if (cnstr) fprintf(stderr,"Match Constructor: %s\n", cnstr);
  match = new MatchRule(_AD, mnode, depth, cnstr, numleaves);
  skipws();                       // Skip any trailing whitespace
  return match;                   // Return MatchRule object
}
FormatRule* ADLParser::format_parse(void) {
  char       *desc   = NULL;
  FormatRule *format = (new FormatRule(desc));
  skipws();                       // Skip whitespace
  if ( _curchar == ';' ) {        // Semicolon is valid terminator
    desc  = NULL;                 // no constructor for this form
    next_char();                  // Move past the ';', replaced with '\0'
  }
  else if ( _curchar == '%' && *(_ptr+1) == '{') {
    next_char();                  // Move past the '%'
    next_char();                  // Move past the '{'
    skipws();
    if (_curchar == '$') {
      char* ident = get_rep_var_ident();
      if (strcmp(ident, "$$template") == 0) return template_parse();
      parse_err(SYNERR, "Unknown \"%s\" directive in format", ident);
      return NULL;
    }
    if ( _curchar == '"' ) {
      next_char();              // Move past the initial '"'
      if( _curchar == '"' ) {   // Handle empty format string case
        format->_strings.addName(_ptr);
      }
      while ( true ) {
        if ( _curchar == '%' || _curchar == '\n' ) {
          if ( _curchar != '"' ) {
            parse_err(SYNERR, "missing '\"' at end of format block");
            return NULL;
          }
        }
        char *start = _ptr;       // Record start of the next string
        while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
          if (_curchar == '\\') {
            next_char();  // superquote
            if ((_curchar == '$') || (_curchar == '%'))
          }
          if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
          next_char();
        }
        if ( start != _ptr ) {
          format->_strings.addName(start);
        }
        if ( _curchar == '$' ) {
          next_char();          // Move past the '$'
          char* rep_var = get_ident(); // Nil terminate the variable name
          rep_var = strdup(rep_var);// Copy the string
          format->_rep_vars.addName(rep_var);
          format->_strings.addName(NameList::_signal);
        }
        if ( _curchar == '"') {
          next_char();           // Move past the '"'
          skipws();              // Skip white space before next string token
          if ( _curchar != '"') {
            break;
          } else {
            next_char();
          }
        }
      } // end while part of format description
      skipws();                   // Move to closing '%}'
      if ( _curchar != '%' ) {
        parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format");
        return NULL;
      }
    } // Done with format description inside
    skipws();
    if ( _curchar != '%' || *(_ptr+1) != '}' ) {
      parse_err(SYNERR, "missing '%%}' at end of format block");
      return NULL;
    }
    next_char();                  // Move past the '%'
    next_char();                  // Move past the '}'
  }
  else {  // parameter list alone must terminate with a ';'
    parse_err(SYNERR, "missing ';' after Format expression");
    return NULL;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc);
  skipws();
  return format;
}
FormatRule* ADLParser::template_parse(void) {
  char       *desc   = NULL;
  FormatRule *format = (new FormatRule(desc));
  skipws();
  while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
    {
      char *start = _ptr;       // Record start of the next string
      while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
        if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
          skipws_no_preproc();
        } else {
          next_char_or_line();
        }
      }
      if ( start != _ptr ) {
        format->_strings.addName(NameList::_signal2);
        format->_strings.addName(start);
      }
    }
    if ( _curchar == '$' ) {
      char *rep_var = get_rep_var_ident_dup();
      if (strcmp(rep_var, "$emit") == 0) {
        next_char();
        next_char();
        skipws();
        if ( _curchar == '"' ) {
          next_char();              // Move past the initial '"'
          if( _curchar == '"' ) {   // Handle empty format string case
            format->_strings.addName(_ptr);
          }
          while ( true ) {
            if ( _curchar == '%' || _curchar == '\n' ) {
              parse_err(SYNERR, "missing '\"' at end of format block");
              return NULL;
            }
            char *start = _ptr;       // Record start of the next string
            while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
              if (_curchar == '\\')  next_char();  // superquote
              if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
              next_char();
            }
            if ( start != _ptr ) {
              format->_strings.addName(start);
            }
            if ( _curchar == '$' ) {
              next_char();          // Move past the '$'
              char* next_rep_var = get_ident(); // Nil terminate the variable name
              next_rep_var = strdup(next_rep_var);// Copy the string
              format->_rep_vars.addName(next_rep_var);
              format->_strings.addName(NameList::_signal);
            }
            if ( _curchar == '"') {
              next_char();           // Move past the '"'
              skipws();              // Skip white space before next string token
              if ( _curchar != '"') {
                break;
              } else {
                next_char();
              }
            }
          } // end while part of format description
        }
      } else {
        format->_rep_vars.addName(rep_var);
        format->_strings.addName(NameList::_signal3);
      }
    } // end while part of format description
  }
  skipws();
  if ( _curchar != '%' || *(_ptr+1) != '}' ) {
    parse_err(SYNERR, "missing '%%}' at end of format block");
    return NULL;
  }
  next_char();                  // Move past the '%'
  next_char();                  // Move past the '}'
  if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc);
  skipws();
  return format;
}
void ADLParser::effect_parse(InstructForm *instr) {
  char* desc   = NULL;
  skipws();                      // Skip whitespace
  if (_curchar != '(') {
    parse_err(SYNERR, "missing '(' in effect definition\n");
    return;
  }
  else get_effectlist(instr->_effects, instr->_localNames, instr->_has_call);
  if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc);
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in Effect definition\n");
  }
  next_char();                  // Skip ';'
}
ExpandRule* ADLParser::expand_parse(InstructForm *instr) {
  char         *ident, *ident2;
  NameAndList  *instr_and_operands = NULL;
  ExpandRule   *exp = new ExpandRule();
  skipws();                        // Skip leading whitespace
  if ((_curchar != '%')
      || (next_char(), (_curchar != '{')) ) { // If not open block
    parse_err(SYNERR, "missing '%%{' in expand definition\n");
    return(NULL);
  }
  next_char();                     // Maintain the invariant
  do {
    ident = get_ident();           // Grab next identifier
    if (ident == NULL) {
      parse_err(SYNERR, "identifier expected at %c\n", _curchar);
      continue;
    }
    const Form *form = _globalNames[ident];
    bool parse_oper = false;
    bool parse_ins  = false;
    if (form == NULL) {
      skipws();
      if (_curchar == '(') parse_ins = true;
    } else if (form->is_instruction()) {
      parse_ins = true;
    } else if (form->is_operand()) {
      parse_oper = true;
    } else {
      parse_err(SYNERR, "instruction/operand name expected at %s\n", ident);
      continue;
    }
    if (parse_oper) {
      OperandForm *oper = form->is_operand();
      if (oper == NULL) {
        parse_err(SYNERR, "instruction/operand name expected at %s\n", ident);
        continue;
      }
      skipws();
      ident = get_unique_ident(instr->_localNames,"Operand");
      if (ident == NULL) {
        parse_err(SYNERR, "identifier expected at %c\n", _curchar);
        continue;
      }
      exp->_newopers.addName(ident);
      instr->_localNames.Insert(ident, oper);
      char *c = NULL;
      skipws();
      if (_curchar == '%') { // Need a constructor for the operand
        c = find_cpp_block("Operand Constructor");
        if (c == NULL) {
          parse_err(SYNERR, "Invalid code block for operand constructor\n", _curchar);
          continue;
        }
        exp->_newopconst.Insert(ident, c);
      }
      else if (_curchar != ';') { // If no constructor, need a ;
        parse_err(SYNERR, "Missing ; in expand rule operand declaration\n");
        continue;
      }
      else next_char(); // Skip the ;
      skipws();
    }
    else {
      assert(parse_ins, "sanity");
      instr_and_operands = new NameAndList(ident);
      skipws();
      if (_curchar != '(') {         // Check for parenthesized operand list
        parse_err(SYNERR, "missing '(' in expand instruction declaration\n");
        continue;
      }
      do {
        next_char();                 // skip open paren & comma characters
        skipws();
        if (_curchar == ')') break;
        ident2 = get_ident();
        skipws();
        if (ident2 == NULL) {
          parse_err(SYNERR, "identifier expected at %c\n", _curchar);
          continue;
        }                            // Check that you have a valid operand
        const Form *form2 = instr->_localNames[ident2];
        if (!form2) {
          parse_err(SYNERR, "operand name expected at %s\n", ident2);
          continue;
        }
        OperandForm *oper = form2->is_operand();
        if (oper == NULL && !form2->is_opclass()) {
          parse_err(SYNERR, "operand name expected at %s\n", ident2);
          continue;
        }                            // Add operand to list
        instr_and_operands->add_entry(ident2);
      } while(_curchar == ',');
      if (_curchar != ')') {
        parse_err(SYNERR, "missing ')'in expand instruction declaration\n");
        continue;
      }
      next_char();
      if (_curchar != ';') {
        parse_err(SYNERR, "missing ';'in expand instruction declaration\n");
        continue;
      }
      next_char();
      exp->add_instruction(instr_and_operands);
      skipws();
    }
  } while(_curchar != '%');
  next_char();
  if (_curchar != '}') {
    parse_err(SYNERR, "missing '%%}' in expand rule definition\n");
    return(NULL);
  }
  next_char();
  if (_AD._adl_debug > 1) fprintf(stderr,"Expand Rule:\n");
  skipws();
  return (exp);
}
RewriteRule* ADLParser::rewrite_parse(void) {
  char* params = NULL;
  char* desc   = NULL;
  skipws();                      // Skip whitespace
  if ((params = get_paren_expr("rewrite parameters")) == NULL) {
    parse_err(SYNERR, "missing '(' in rewrite rule\n");
    return NULL;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite parameters: %s\n", params);
  skipws();
  if ( (desc = find_cpp_block("rewrite block")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing block for 'rewrite'.\n");
    return NULL;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite Rule: %s\n", desc);
  skipws();
  return (new RewriteRule(params,desc));
}
Attribute *ADLParser::attr_parse(char* ident) {
  Attribute *attrib;              // Attribute class
  char      *cost = NULL;         // String representation of cost attribute
  skipws();                       // Skip leading whitespace
  if ( (cost = get_paren_expr("attribute")) == NULL ) {
    parse_err(SYNERR, "incorrect or missing expression for 'attribute'\n");
    return NULL;
  }
  if (_AD._adl_debug > 1) fprintf(stderr,"Attribute: %s\n", cost);
  if (_curchar != ';') {
    parse_err(SYNERR, "missing ';' in attribute definition\n");
    return NULL;
  }
  next_char();                   // Point after the terminator
  skipws();
  attrib = new Attribute(ident,cost,INS_ATTR); // Build new predicate object
  return attrib;
}
MatchNode *ADLParser::matchNode_parse(FormDict &operands, int &depth, int &numleaves, bool atroot) {
  int   lParens = depth;
  int   rParens = depth;
  MatchNode *lChild = NULL;
  MatchNode *rChild = NULL;
  char      *token;               // Identifier which may be opcode or operand
  if (cur_char() != '(')
    return NULL;
  next_char();                    // advance past '('
  token = get_ident();            // Get identifier, opcode
  if (token == NULL) {
    parse_err(SYNERR, "missing opcode in match expression\n");
    return NULL;
  }
  for (int i = _last_machine_leaf + 1; i < _last_opcode; i++) {
    if (strcmp(token, NodeClassNames[i]) == 0) {
      _AD.has_match_rule(i, true);
    }
  }
  const char  *result    = NULL;  // Result type will be filled in later
  const char  *name      = token; // local name associated with this node
  const char  *operation = token; // remember valid operation for later
  const Form  *form      = operands[token];
  OpClassForm *opcForm = form ? form->is_opclass() : NULL;
  if (opcForm != NULL) {
    if (!opcForm->ideal_only()) {
      operation = opcForm->_ident;
      result = operation;         // Operands result in their own type
    }
    else                        name = NULL;
  }
  skipws();
  if (cur_char() != ')') {
    if (strcmp(operation,"Set"))
      lChild = matchChild_parse(operands, lParens, numleaves, false);
    else
      lChild = matchChild_parse(operands, lParens, numleaves, true);
    skipws();
    if (cur_char() != ')' ) {
      if(strcmp(operation, "Set"))
        rChild = matchChild_parse(operands,rParens,numleaves,false);
      else
        rChild = matchChild_parse(operands,rParens,numleaves,true);
    }
  }
  skipws();
  if (cur_char() != ')') {
    parse_err(SYNERR, "missing ')' in match expression\n");
    return NULL;
  }
  next_char();                    // skip the ')'
  MatchNode* mroot = new MatchNode(_AD,result,name,operation,lChild,rChild);
  if (!atroot) {
    mroot->build_internalop();
  }
  depth = (lParens > rParens) ? lParens : rParens;
  return mroot;
}
MatchNode *ADLParser::matchChild_parse(FormDict &operands, int &parens, int &numleaves, bool atroot) {
  MatchNode  *child  = NULL;
  const char *result = NULL;
  const char *token  = NULL;
  const char *opType = NULL;
  if (cur_char() == '(') {         // child is an operation
    ++parens;
    child = matchNode_parse(operands, parens, numleaves, atroot);
  }
  else {                           // child is an operand
    token = get_ident();
    const Form  *form    = operands[token];
    OpClassForm *opcForm = form ? form->is_opclass() : NULL;
    if (opcForm != NULL) {
      opType = opcForm->_ident;
      result = opcForm->_ident;    // an operand's result matches its type
    } else {
      parse_err(SYNERR, "undefined operand %s in match rule\n", token);
      return NULL;
    }
    if (opType == NULL) {
      parse_err(SYNERR, "missing type for argument '%s'\n", token);
    }
    child = new MatchNode(_AD, result, token, opType);
    ++numleaves;
  }
  return child;
}
char* ADLParser::find_cpp_block(const char* description) {
  char *next;                     // Pointer for finding block delimiters
  char* cppBlock = NULL;          // Beginning of C++ code block
  if (_curchar == '%') {          // Encoding is a C++ expression
    next_char();
    if (_curchar != '{') {
      parse_err(SYNERR, "missing '{' in %s \n", description);
      return NULL;
    }
    next_char();                  // Skip block delimiter
    skipws_no_preproc();          // Skip leading whitespace
    cppBlock = _ptr;              // Point to start of expression
    int line = linenum();
    next = _ptr + 1;
    while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
      next_char_or_line();
      next = _ptr+1;              // Maintain the next pointer
    }                             // Grab string
    if (_curchar == '\0') {
      parse_err(SYNERR, "invalid termination of %s \n", description);
      return NULL;
    }
    _ptr += 2;                    // Skip block delimiter
    _curchar = *_ptr;             // Maintain invariant
    if (_AD._adlocation_debug) {
      char* location = get_line_string(line);
      char* end_loc  = end_line_marker();
      char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1);
      strcpy(result, location);
      strcat(result, cppBlock);
      strcat(result, end_loc);
      cppBlock = result;
      free(location);
    }
  }
  return cppBlock;
}
char* ADLParser::get_expr(const char *desc, const char *stop_chars) {
  char* expr = NULL;
  int   paren = 0;
  expr = _ptr;
  while (paren > 0 || !strchr(stop_chars, _curchar)) {
    if (_curchar == '(') {        // Down level of nesting
      paren++;                    // Bump the parenthesis counter
      next_char();                // maintain the invariant
    }
    else if (_curchar == ')') {   // Up one level of nesting
      if (paren == 0) {
        parse_err(SYNERR, "too many )'s, did not find %s after %s\n",
                  stop_chars, desc);
        return NULL;
      }
      paren--;                    // Drop the parenthesis counter
      next_char();                // Maintain the invariant
    }
    else if (_curchar == '"' || _curchar == '\'') {
      int qchar = _curchar;
      while (true) {
        next_char();
        if (_curchar == qchar) { next_char(); break; }
        if (_curchar == '\\')  next_char();  // superquote
        if (_curchar == '\n' || _curchar == '\0') {
          parse_err(SYNERR, "newline in string in %s\n", desc);
          return NULL;
        }
      }
    }
    else if (_curchar == '%' && (_ptr[1] == '{' || _ptr[1] == '}')) {
      parse_err(SYNERR, "unexpected %%%c in %s\n", _ptr[1], desc);
      return NULL;
    }
    else if (_curchar == '\0') {
      parse_err(SYNERR, "unexpected EOF in %s\n", desc);
      return NULL;
    }
    else {
      char* pre_skip_ptr = _ptr;
      skipws();
      if (pre_skip_ptr == _ptr) {
        next_char();
      } else if (pre_skip_ptr+strlen(pre_skip_ptr) != _ptr+strlen(_ptr)) {
        parse_err(SYNERR, "unimplemented: preprocessor must not elide subexpression in %s", desc);
      }
    }
  }
  assert(strchr(stop_chars, _curchar), "non-null return must be at stop-char");
  return expr;
}
char *ADLParser::get_paren_expr(const char *description, bool include_location) {
  int line = linenum();
  if (_curchar != '(')            // Escape if not valid starting position
    return NULL;
  next_char();                    // Skip the required initial paren.
  char *token2 = get_expr(description, ")");
  if (_curchar == ')')
    next_char();                  // Skip required final paren.
  int junk = 0;
  if (include_location && _AD._adlocation_debug && !is_int_token(token2, junk)) {
    char* location = get_line_string(line);
    char* end_loc  = end_line_marker();
    char* result = (char *)malloc(strlen(location) + strlen(token2) + strlen(end_loc) + 1);
    strcpy(result, location);
    strcat(result, token2);
    strcat(result, end_loc);
    token2 = result;
    free(location);
  }
  return token2;
}
char *ADLParser::get_ident_common(bool do_preproc) {
  register char c;
  char *start;                    // Pointer to start of token
  char *end;                      // Pointer to end of token
  if( _curline == NULL )          // Return NULL at EOF.
    return NULL;
  skipws_common(do_preproc);      // Skip whitespace before identifier
  start = end = _ptr;             // Start points at first character
  end--;                          // unwind end by one to prepare for loop
  do {
    end++;                        // Increment end pointer
    c = *end;                     // Grab character to test
  } while ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))
            || ((c >= '0') && (c <= '9'))
            || ((c == '_')) || ((c == ':')) || ((c == '#')) );
  if (start == end) {             // We popped out on the first try
    if (strlen(start) > 24) {
      char buf[32];
      strncpy(buf, start, 20);
      buf[20] = '\0';
      strcat(buf, "[...]");
      parse_err(SYNERR, "Identifier expected, but found '%s'.", buf);
    } else {
      parse_err(SYNERR, "Identifier expected, but found '%s'.", start);
    }
    start = NULL;
  }
  else {
    _curchar = c;                 // Save the first character of next token
  }
  _ptr = end;                     // Reset _ptr to point to next char after token
  if (do_preproc && start != NULL) {
    const char* def = _AD.get_preproc_def(start);
    if (def != NULL && strcmp(def, start)) {
      const char* def1 = def;
      const char* def2 = _AD.get_preproc_def(def1);
      if (def2 != NULL && strcmp(def2, def1)) {
        def = def2;
        const char* def3 = _AD.get_preproc_def(def2);
        if (def3 != NULL && strcmp(def3, def2) && strcmp(def3, def1)) {
          parse_err(SYNERR, "unimplemented: using %s defined as %s => %s => %s",
                    start, def1, def2, def3);
        }
      }
      start = strdup(def);
    }
  }
  return start;                   // Pointer to token in filebuf
}
char *ADLParser::get_ident_dup(void) {
  char *ident = get_ident();
  if( ident != NULL ) {
    ident = strdup(ident);  // Copy the string
  }
  return ident;
}
char *ADLParser::get_ident_or_literal_constant(const char* description) {
  char* param = NULL;
  skipws();
  if (_curchar == '(') {
    param = get_paren_expr(description);
    if (param[0] != '(') {
      char* buf = (char*) malloc(strlen(param) + 3);
      sprintf(buf, "(%s)", param);
      param = buf;
    }
    assert(is_literal_constant(param),
           "expr must be recognizable as a constant");
  } else {
    param = get_ident();
  }
  return param;
}
char *ADLParser::get_rep_var_ident(void) {
  char *rep_var = _ptr;
  if ( _curchar == '$' ) {
    next_char();
  }
  if ( _curchar == '$' ) {
    next_char();
  }
  if ( _curchar == '$' ) {
    next_char();
  }
  if( _curchar == '$' ) {
    parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'");
    next_char();
    return NULL;
  }
  char *rep_var_name = get_ident();
  assert( rep_var_name != NULL,
          "Missing identifier after replacement variable indicator '$'");
  return rep_var;
}
char *ADLParser::get_rep_var_ident_dup(void) {
  if( _curchar != '$' ) return NULL;
  next_char();                // Move past the '$'
  char *rep_var = _ptr;       // Remember starting point
  if ( _curchar == '$' ) {
    next_char();
  }
  if ( _curchar == '$' ) {
    next_char();
  }
  if( _curchar == '$' ) {
    parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'");
    next_char();
    return NULL;
  }
  char *rep_var_name = get_ident();
  assert( rep_var_name != NULL,
          "Missing identifier after replacement variable indicator '$'");
  rep_var = strdup(rep_var);  // Copy the string
  return rep_var;
}
char *ADLParser::get_unique_ident(FormDict& dict, const char* nameDescription){
  char* ident = get_ident();
  if (ident == NULL) {
    parse_err(SYNERR, "missing %s identifier at %c\n", nameDescription, _curchar);
  }
  else {
    if (dict[ident] != NULL) {
      parse_err(SYNERR, "duplicate name %s for %s\n", ident, nameDescription);
      ident = NULL;
    }
  }
  return ident;
}
int ADLParser::get_int(void) {
  register char c;
  char         *start;            // Pointer to start of token
  char         *end;              // Pointer to end of token
  int           result;           // Storage for integer result
  if( _curline == NULL )          // Return NULL at EOF.
    return 0;
  skipws();                       // Skip whitespace before identifier
  start = end = _ptr;             // Start points at first character
  c = *end;                       // Grab character to test
  while ((c >= '0') && (c <= '9')
         || ((c == '-') && (end == start))) {
    end++;                        // Increment end pointer
    c = *end;                     // Grab character to test
  }
  if (start == end) {             // We popped out on the first try
    parse_err(SYNERR, "integer expected at %c\n", c);
    result = 0;
  }
  else {
    _curchar = c;                 // Save the first character of next token
    result = atoi(start);         // Convert the string to an integer
  }
  _ptr = end;
  return result;                   // integer
}
char *ADLParser::get_relation_dup(void) {
  char         *result = NULL;    // relational operator being returned
  if( _curline == NULL )          // Return NULL at EOF.
    return  NULL;
  skipws();                       // Skip whitespace before relation
  char *start = _ptr;             // Store start of relational operator
  char first  = *_ptr;            // the first character
  if( (first == '=') || (first == '!') || (first == '<') || (first == '>') ) {
    next_char();
    char second = *_ptr;          // the second character
    if( (second == '=') ) {
      next_char();
      char tmp  = *_ptr;
      result = strdup(start);     // Duplicate the string
    } else {
      parse_err(SYNERR, "relational operator expected at %s\n", _ptr);
    }
  } else {
    parse_err(SYNERR, "relational operator expected at %s\n", _ptr);
  }
  return result;
}
void ADLParser::get_oplist(NameList &parameters, FormDict &operands) {
  OpClassForm *opclass = NULL;
  char        *ident   = NULL;
  do {
    next_char();             // skip open paren & comma characters
    skipws();
    if (_curchar == ')') break;
    ident = get_ident();
    if (ident == NULL) {
      parse_err(SYNERR, "optype identifier expected at %c\n", _curchar);
      return;
    }
    else {
      const Form  *form = _globalNames[ident];
      if( form == NULL ) {
        parse_err(SYNERR, "undefined operand type %s\n", ident);
        return;
      }
      OpClassForm *opc  = form->is_opclass();
      OperandForm *oper = form->is_operand();
      if((oper == NULL) && (opc == NULL)) {
        parse_err(SYNERR, "identifier %s not operand type\n", ident);
        return;
      }
      opclass = opc;
    }
    if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Type: %s\t", ident);
    if( (ident = get_unique_ident(operands, "operand")) == NULL) {
      return;
    }
    if( _globalNames[ident] != NULL ) {
         parse_err(SYNERR, "Reuse of global name %s as operand.\n",ident);
         return;
    }
    operands.Insert(ident, opclass);
    parameters.addName(ident);
    if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
    skipws();
  } while(_curchar == ',');
  if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
  else {
    next_char();  // set current character position past the close paren
  }
}
void ADLParser::get_effectlist(FormDict &effects, FormDict &operands, bool& has_call) {
  OperandForm *opForm;
  Effect      *eForm;
  char        *ident;
  do {
    next_char();             // skip open paren & comma characters
    skipws();
    if (_curchar == ')') break;
    ident = get_ident();
    if (ident == NULL) {
      parse_err(SYNERR, "effect type identifier expected at %c\n", _curchar);
      return;
    }
    else {
      const Form *form = _globalNames[ident];
      if( form == NULL ) {
        parse_err(SYNERR, "undefined effect type %s\n", ident);
        return;
      }
      else {
        if( (eForm = form->is_effect()) == NULL) {
          parse_err(SYNERR, "identifier %s not effect type\n", ident);
          return;
        }
      }
    }
    if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident);
    skipws();
    if (eForm->is(Component::CALL)) {
      if (_AD._adl_debug > 1) fprintf(stderr, "\n");
      has_call = true;
    } else {
      if( (ident = get_unique_ident(effects, "effect")) == NULL) {
        parse_err(SYNERR, "missing operand identifier in effect list\n");
        return;
      }
      const Form *form = operands[ident];
      opForm = form ? form->is_operand() : NULL;
      if( opForm == NULL ) {
        if( form && form->is_opclass() ) {
          const char* cname = form->is_opclass()->_ident;
          parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident);
        } else {
          parse_err(SYNERR, "undefined operand %s in effect list\n", ident);
        }
        return;
      }
      effects.Insert(ident, eForm);
      if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
    }
    skipws();
  } while(_curchar == ',');
  if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
  else {
    next_char();  // set current character position past the close paren
  }
}
void ADLParser::preproc_line(void) {
  int line = get_int();
  skipws_no_preproc();
  const char* file = NULL;
  if (_curchar == '"') {
    next_char();              // Move past the initial '"'
    file = _ptr;
    while (true) {
      if (_curchar == '\n') {
        parse_err(SYNERR, "missing '\"' at end of #line directive");
        return;
      }
      if (_curchar == '"') {
        next_char();
        skipws_no_preproc();
        break;
      }
      next_char();
    }
  }
  ensure_end_of_line();
  if (file != NULL)
    _AD._ADL_file._name = file;
  _buf.set_linenum(line);
}
void ADLParser::preproc_define(void) {
  char* flag = get_ident_no_preproc();
  skipws_no_preproc();
  char* def = get_ident_no_preproc();
  _AD.set_preproc_def(flag, def);
  skipws_no_preproc();
  if (_curchar != '\n') {
    parse_err(SYNERR, "non-identifier in preprocessor definition\n");
  }
}
void ADLParser::preproc_undef(void) {
  char* flag = get_ident_no_preproc();
  skipws_no_preproc();
  ensure_end_of_line();
  _AD.set_preproc_def(flag, NULL);
}
void ADLParser::parse_err(int flag, const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  if (flag == 1)
    _AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
  else if (flag == 2)
    _AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
  else
    _AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args);
  int error_char = _curchar;
  char* error_ptr = _ptr+1;
  for(;*_ptr != '\n'; _ptr++) ; // Skip to the end of the current line
  _curchar = '\n';
  va_end(args);
  _AD._no_output = 1;
  if (flag == 1) {
    char* error_tail = strchr(error_ptr, '\n');
    char tem = *error_ptr;
    error_ptr[-1] = '\0';
    char* error_head = error_ptr-1;
    while (error_head > _curline && *error_head)  --error_head;
    if (error_tail)  *error_tail = '\0';
    fprintf(stderr, "Error Context:  %s>>>%c<<<%s\n",
            error_head, error_char, error_ptr);
    if (error_tail)  *error_tail = '\n';
    error_ptr[-1] = tem;
  }
}
void ADLParser::ensure_start_of_line(void) {
  if (_curchar == '\n') { next_line(); return; }
  assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
          "Must be able to find which line we are in" );
  for (char *s = _curline; s < _ptr; s++) {
    if (*s > ' ') {
      parse_err(SYNERR, "'%c' must be at beginning of line\n", _curchar);
      break;
    }
  }
}
void ADLParser::ensure_end_of_line(void) {
  skipws_no_preproc();
  if (_curchar != '\n' && _curchar != '\0') {
    parse_err(SYNERR, "garbage char '%c' at end of line\n", _curchar);
  } else {
    next_char_or_line();
  }
}
bool ADLParser::handle_preproc_token() {
  assert(*_ptr == '#', "must be at start of preproc");
  ensure_start_of_line();
  next_char();
  skipws_no_preproc();
  char* start_ident = _ptr;
  char* ident = (_curchar == '\n') ? NULL : get_ident_no_preproc();
  if (ident == NULL) {
    parse_err(SYNERR, "expected preprocessor command, got end of line\n");
  } else if (!strcmp(ident, "ifdef") ||
             !strcmp(ident, "ifndef")) {
    char* flag = get_ident_no_preproc();
    ensure_end_of_line();
    bool flag_def  = preproc_taken() && (_AD.get_preproc_def(flag) != NULL);
    bool now_taken = !strcmp(ident, "ifdef") ? flag_def : !flag_def;
    begin_if_def(now_taken);
  } else if (!strcmp(ident, "if")) {
    if (preproc_taken())
      parse_err(SYNERR, "unimplemented: #%s %s", ident, _ptr+1);
    next_line();
    begin_if_def(true);
  } else if (!strcmp(ident, "else")) {
    ensure_end_of_line();
    invert_if_def();
  } else if (!strcmp(ident, "endif")) {
    ensure_end_of_line();
    end_if_def();
  } else if (preproc_taken()) {
    _ptr = start_ident;
    _curchar = *--_ptr;
    if( _curchar != '#' ) {
      parse_err(SYNERR, "no space allowed after # in #define or #undef");
      assert(_curchar == '#', "no space allowed after # in #define or #undef");
    }
    return false;
  }
  return true;
}
void ADLParser::skipws_common(bool do_preproc) {
  char *start = _ptr;
  char *next = _ptr + 1;
  if (*_ptr == '\0') {
    if (_curchar > ' ')  return;
    if (_curchar == '\n') {
      if (!do_preproc)  return;            // let caller handle the newline
      next_line();
      _ptr = _curline; next = _ptr + 1;
    }
    else if (_curchar == '#' ||
        (_curchar == '/' && (*next == '/' || *next == '*'))) {
      parse_err(SYNERR, "unimplemented: comment token in a funny place");
    }
  }
  while(_curline != NULL) {                // Check for end of file
    if (*_ptr == '\n') {                   // keep proper track of new lines
      if (!do_preproc)  break;             // let caller handle the newline
      next_line();
      _ptr = _curline; next = _ptr + 1;
    }
    else if ((*_ptr == '/') && (*next == '/'))      // C++ comment
      do { _ptr++; next++; } while(*_ptr != '\n');  // So go to end of line
    else if ((*_ptr == '/') && (*next == '*')) {    // C comment
      _ptr++; next++;
      do {
        _ptr++; next++;
        if (*_ptr == '\n') {               // keep proper track of new lines
          next_line();                     // skip newlines within comments
          if (_curline == NULL) {          // check for end of file
            parse_err(SYNERR, "end-of-file detected inside comment\n");
            break;
          }
          _ptr = _curline; next = _ptr + 1;
        }
      } while(!((*_ptr == '*') && (*next == '/'))); // Go to end of comment
      _ptr = ++next; next++;               // increment _ptr past comment end
    }
    else if (do_preproc && *_ptr == '#') {
      bool preproc_handled = handle_preproc_token();
      if (!preproc_handled) {
        if (preproc_taken()) {
          return;  // short circuit
        }
        ++_ptr;    // skip the preprocessor character
      }
      next = _ptr+1;
    } else if(*_ptr > ' ' && !(do_preproc && !preproc_taken())) {
      break;
    }
    else if (*_ptr == '"' || *_ptr == '\'') {
      assert(do_preproc, "only skip strings if doing preproc");
      int qchar = *_ptr;
      while (true) {
        ++_ptr;
        if (*_ptr == qchar) { ++_ptr; break; }
        if (*_ptr == '\\')  ++_ptr;
        if (*_ptr == '\n' || *_ptr == '\0') {
          parse_err(SYNERR, "newline in string");
          break;
        }
      }
      next = _ptr + 1;
    }
    else { ++_ptr; ++next; }
  }
  if( _curline != NULL )            // at end of file _curchar isn't valid
    _curchar = *_ptr;               // reset _curchar to maintain invariant
}
char ADLParser::cur_char() {
  return (_curchar);
}
void ADLParser::next_char() {
  if (_curchar == '\n')  parse_err(WARN, "must call next_line!");
  _curchar = *++_ptr;
}
void ADLParser::next_char_or_line() {
  if ( _curchar != '\n' ) {
    _curchar = *++_ptr;
  } else {
    next_line();
    _ptr = _curline;
    _curchar = *_ptr;  // maintain invariant
  }
}
void ADLParser::next_line() {
  _curline = _buf.get_line();
  _curchar = ' ';
}
char* ADLParser::get_line_string(int linenum) {
  const char* file = _AD._ADL_file._name;
  int         line = linenum ? linenum : this->linenum();
  char* location = (char *)malloc(strlen(file) + 100);
  sprintf(location, "\n#line %d \"%s\"\n", line, file);
  return location;
}
bool ADLParser::is_literal_constant(const char *param) {
  if (param[0] == 0)     return false;  // null string
  if (param[0] == '(')   return true;   // parenthesized expression
  if (param[0] == '0' && (param[1] == 'x' || param[1] == 'X')) {
    int i = 2;
    do {
      if( !ADLParser::is_hex_digit(*(param+i)) )  return false;
      ++i;
    } while( *(param+i) != 0 );
    return true;
  }
  return false;
}
bool ADLParser::is_hex_digit(char digit) {
  return ((digit >= '0') && (digit <= '9'))
       ||((digit >= 'a') && (digit <= 'f'))
       ||((digit >= 'A') && (digit <= 'F'));
}
bool ADLParser::is_int_token(const char* token, int& intval) {
  const char* cp = token;
  while (*cp != '\0' && *cp <= ' ')  cp++;
  if (*cp == '-')  cp++;
  int ndigit = 0;
  while (*cp >= '0' && *cp <= '9')  { cp++; ndigit++; }
  while (*cp != '\0' && *cp <= ' ')  cp++;
  if (ndigit == 0 || *cp != '\0') {
    return false;
  }
  intval = atoi(token);
  return true;
}
static const char* skip_expr_ws(const char* str) {
  const char * cp = str;
  while (cp[0]) {
    if (cp[0] <= ' ') {
      ++cp;
    } else if (cp[0] == '#') {
      ++cp;
      while (cp[0] == ' ')  ++cp;
      assert(0 == strncmp(cp, "line", 4), "must be a #line directive");
      const char* eol = strchr(cp, '\n');
      assert(eol != NULL, "must find end of line");
      if (eol == NULL)  eol = cp + strlen(cp);
      cp = eol;
    } else {
      break;
    }
  }
  return cp;
}
bool ADLParser::equivalent_expressions(const char* str1, const char* str2) {
  if (str1 == str2)
    return true;
  else if (str1 == NULL || str2 == NULL)
    return false;
  const char* cp1 = str1;
  const char* cp2 = str2;
  char in_quote = '\0';
  while (cp1[0] && cp2[0]) {
    if (!in_quote) {
      const char* cp1a = skip_expr_ws(cp1);
      const char* cp2a = skip_expr_ws(cp2);
      if (cp1a > cp1 && cp2a > cp2) {
        cp1 = cp1a; cp2 = cp2a;
        continue;
      }
      if (cp1a > cp1 || cp2a > cp2)  break; // fail
    }
    if (cp1[0] != cp2[0])  break; // fail
    char ch = cp1[0];
    cp1++; cp2++;
    if (in_quote && ch == '\\') {
      if (cp1[0] != cp2[0])  break; // fail
      if (!cp1[0])  break;
      cp1++; cp2++;
    }
    if (in_quote && ch == in_quote) {
      in_quote = '\0';
    } else if (!in_quote && (ch == '"' || ch == '\'')) {
      in_quote = ch;
    }
  }
  return (!cp1[0] && !cp2[0]);
}
void ADLParser::trim(char* &token) {
  while (*token <= ' ')  token++;
  char* end = token + strlen(token);
  while (end > token && *(end-1) <= ' ')  --end;
}
C:\hotspot-69087d08d473\src\share\vm/adlc/adlparse.hpp
#ifndef SHARE_VM_ADLC_ADLPARSE_HPP
#define SHARE_VM_ADLC_ADLPARSE_HPP
class Form;
class InstructForm;
class OperandForm;
class OpClassForm;
class AttributeForm;
class RegisterForm;
class PipelineForm;
class SourceForm;
class Peephole;
class Component;
class Predicate;
class MatchRule;
class Encode;
class Attribute;
class Effect;
class ExpandRule;
class RewriteRule;
class Constraint;
class ConstructRule;
class RegDef;
class RegClass;
class CodeSnippetRegClass;
class ConditionalRegClass;
class AllocClass;
class ResourceForm;
class PipeDesc;
class PipeClass;
class RegList;
class PeepMatch;
class PeepConstraint;
class PeepReplace;
extern char *toUpper(const char *str);
class ADLParser {
protected:
  char     *_curline;           // Start of current line
  char     *_ptr;               // Pointer into current location in File Buffer
  char      _curchar;           // Current character from buffer
  FormDict &_globalNames;       // Global names
  enum { _preproc_limit = 20 };
  int       _preproc_depth;                 // How deep are we into ifdefs?
  int       _preproc_not_taken;             // How deep in not-taken ifdefs?
  bool      _preproc_taken[_preproc_limit]; // Are we taking this ifdef level?
  bool      _preproc_else[_preproc_limit];  // Did this level have an else yet?
  void instr_parse(void);       // Parse instruction definitions
  void oper_parse(void);        // Parse operand definitions
  void opclass_parse(void);     // Parse operand class definitions
  void ins_attr_parse(void);    // Parse instruction attrubute definitions
  void op_attr_parse(void);     // Parse operand attrubute definitions
  void source_parse(void);      // Parse source section
  void source_hpp_parse(void);  // Parse source_hpp section
  void reg_parse(void);         // Parse register section
  void encode_parse(void);      // Parse encoding section
  void frame_parse(void);       // Parse frame section
  void pipe_parse(void);        // Parse pipeline section
  void definitions_parse(void); // Parse definitions section
  void peep_parse(void);        // Parse peephole rule definitions
  void preproc_line(void);      // Parse a #line statement
  void preproc_define(void);    // Parse a #define statement
  void preproc_undef(void);     // Parse an #undef statement
  void adjust_set_rule(InstructForm *instr);
  void matchrule_clone_and_swap(MatchRule *rule, const char* instr_ident, int& match_rules_cnt);
  void enc_class_parse(void);   // Parse encoding class definition
  void enc_class_parse_block(EncClass* encoding, char* ec_name);
  void stack_dir_parse(FrameForm *frame);   // Parse the stack direction entry
  void sync_stack_slots_parse(FrameForm *frame);
  void frame_pointer_parse(FrameForm *frame, bool native);
  void interpreter_frame_pointer_parse(FrameForm *frame, bool native);
  void inline_cache_parse(FrameForm *frame, bool native);
  void interpreter_arg_ptr_parse(FrameForm *frame, bool native);
  void interpreter_method_oop_parse(FrameForm *frame, bool native);
  void cisc_spilling_operand_name_parse(FrameForm *frame, bool native);
  void stack_alignment_parse(FrameForm *frame);
  void return_addr_parse(FrameForm *frame, bool native);
  void preserve_stack_parse(FrameForm *frame);
  char *calling_convention_parse();
  char *return_value_parse();
  void reg_def_parse(void);              // Parse register definition
  void reg_class_parse(void);            // Parse register class definition
  void reg_class_dynamic_parse(void);    // Parse dynamic register class definition
  void alloc_class_parse(void);          // Parse allocation class definition
  void int_def_parse(void);              // Parse an integer definition
  void resource_parse(PipelineForm &pipe);   // Parse resource definition
  void pipe_desc_parse(PipelineForm &pipe);  // Parse pipeline description definition
  void pipe_class_parse(PipelineForm &pipe); // Parse pipeline class definition
  void peep_match_parse(Peephole &peep);     // Parse the peephole match rule
  void peep_constraint_parse(Peephole &peep);// Parse the peephole constraints
  void peep_replace_parse(Peephole &peep);   // Parse peephole replacement rule
  InstructForm *peep_match_child_parse(PeepMatch &match, int parent, int &position, int input);
  Predicate     *pred_parse(void);       // Parse predicate rule
  MatchRule     *match_parse(FormDict &operands);
  MatchNode     *matchNode_parse(FormDict &operands, int &depth,
                                 int &numleaves, bool atroot);
  MatchNode     *matchChild_parse(FormDict &operands, int &depth,
                                  int &numleaves, bool atroot);
  Attribute     *attr_parse(char *ident);// Parse instr/operand attribute rule
  void           ins_encode_parse(InstructForm &inst);
  void           ins_encode_parse_block(InstructForm &inst);
  void           ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name);
  void           postalloc_expand_parse(InstructForm &inst);
  void           constant_parse(InstructForm& inst);
  void           constant_parse_expression(EncClass* encoding, char* ec_name);
  Opcode        *opcode_parse(InstructForm *insr); // Parse instruction opcode
  char          *size_parse(InstructForm *insr); // Parse instruction size
  Interface     *interface_parse();      // Parse operand interface rule
  Interface     *mem_interface_parse();  // Parse memory interface rule
  Interface     *cond_interface_parse(); // Parse conditional interface rule
  char          *interface_field_parse(const char** format = NULL);// Parse field contents
  FormatRule    *format_parse(void);     // Parse format rule
  FormatRule    *template_parse(void);     // Parse format rule
  void           effect_parse(InstructForm *instr); // Parse effect rule
  ExpandRule    *expand_parse(InstructForm *instr); // Parse expand rule
  RewriteRule   *rewrite_parse(void);    // Parse rewrite rule
  Constraint    *constraint_parse(void); // Parse constraint rule
  ConstructRule *construct_parse(void);  // Parse construct rule
  void           ins_pipe_parse(InstructForm &instr); // Parse ins_pipe rule
  void begin_if_def(bool taken) {
    assert(_preproc_depth < _preproc_limit, "#ifdef nesting limit");
    int ppn = _preproc_depth++;
    _preproc_taken[ppn] = taken;
    if (!_preproc_taken[ppn])  _preproc_not_taken += 1;
    _preproc_else[ppn] = false;
  }
  void invert_if_def() {
    assert(_preproc_depth > 0, "#ifdef matching");
    int ppn = _preproc_depth - 1;
    assert(!_preproc_else[ppn], "multiple #else lines");
    _preproc_else[ppn] = true;
    if (!_preproc_taken[ppn])  _preproc_not_taken -= 1;
    _preproc_taken[ppn] = !_preproc_taken[ppn];
    if (!_preproc_taken[ppn])  _preproc_not_taken += 1;
  }
  void end_if_def() {
    assert(_preproc_depth > 0, "#ifdef matching");
    int ppn = --_preproc_depth;
    if (!_preproc_taken[ppn])  _preproc_not_taken -= 1;
  }
  bool preproc_taken() {
    return _preproc_not_taken == 0;
  }
  bool handle_preproc_token();
  char *parse_one_arg(const char *description);
  char *get_ident()            { return get_ident_common(true); }
  char *get_ident_no_preproc() { return get_ident_common(false); }
  char *get_ident_common(bool do_preproc);      // Grab it from the file buffer
  char *get_ident_dup(void);    // Grab a duplicate of the identifier
  char *get_ident_or_literal_constant(const char* description);
  char *get_unique_ident(FormDict &dict, const char *nameDescription);
  char *get_rep_var_ident(void);
  char *get_rep_var_ident_dup(void);
  int   get_int(void);
  char *get_relation_dup(void);
  void  get_oplist(NameList &parameters, FormDict &operands);// Parse type-operand pairs
  void  get_effectlist(FormDict &effects, FormDict &operands, bool& has_call); // Parse effect-operand pairs
  char *get_paren_expr(const char *description, bool include_location = false);
  char *get_expr(const char *description, const char *stop_chars);
  char *find_cpp_block(const char *description); // Parse a C++ code block
  void parse_err(int flag, const char *fmt, ...);
  char *get_line_string(int linenum = 0);
  char *end_line_marker() { return (char*)"\n#line 999999\n"; }
  inline char  cur_char(void);
  inline void  next_char(void);
  inline void  next_char_or_line(void);
  inline void  next_line(void);
  void ensure_start_of_line(void);
  void ensure_end_of_line(void);
  void skipws()                { skipws_common(true); }
  void skipws_no_preproc()     { skipws_common(false); }
  void skipws_common(bool do_preproc);
  FileBuff &_buf;               // File buffer to be parsed
  ArchDesc &_AD;                // Architecture Description being built
public:
  ADLParser(FileBuff &buf, ArchDesc &archDesc); // Create new ADLParser object
  ~ADLParser();                 // Destroy ADLParser object
  void parse(void);             // Do the parsing & build forms lists
  int linenum() { return _buf.linenum(); }
  static bool is_literal_constant(const char *hex_string);
  static bool is_hex_digit(char digit);
  static bool is_int_token(const char* token, int& intval);
  static bool equivalent_expressions(const char* str1, const char* str2);
  static void trim(char* &token);  // trim leading & trailing spaces
};
#endif // SHARE_VM_ADLC_ADLPARSE_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/archDesc.cpp
#include "adlc.hpp"
static FILE *errfile = stderr;
inline char toUpper(char lower) {
  return (('a' <= lower && lower <= 'z') ? ((char) (lower + ('A'-'a'))) : lower);
}
char *toUpper(const char *str) {
  char *upper  = new char[strlen(str)+1];
  char *result = upper;
  const char *end    = str + strlen(str);
  for (; str < end; ++str, ++upper) {
    *upper = toUpper(*str);
  }
  *upper = '\0';
  return result;
}
ChainList::ChainList() {
}
void ChainList::insert(const char *name, const char *cost, const char *rule) {
  _name.addName(name);
  _cost.addName(cost);
  _rule.addName(rule);
}
bool ChainList::search(const char *name) {
  return _name.search(name);
}
void ChainList::reset() {
  _name.reset();
  _cost.reset();
  _rule.reset();
}
bool ChainList::iter(const char * &name, const char * &cost, const char * &rule) {
  bool        notDone = false;
  const char *n       = _name.iter();
  const char *c       = _cost.iter();
  const char *r       = _rule.iter();
  if (n && c && r) {
    notDone = true;
    name = n;
    cost = c;
    rule = r;
  }
  return notDone;
}
void ChainList::dump() {
  output(stderr);
}
void ChainList::output(FILE *fp) {
  fprintf(fp, "\nChain Rules: output resets iterator\n");
  const char   *cost  = NULL;
  const char   *name  = NULL;
  const char   *rule  = NULL;
  bool   chains_exist = false;
  for(reset(); (iter(name,cost,rule)) == true; ) {
    fprintf(fp, "Chain to <%s> at cost #%s using %s_rule\n",name, cost ? cost : "0", rule);
  }
  reset();
  if( ! chains_exist ) {
    fprintf(fp, "No entries in this ChainList\n");
  }
}
bool MatchList::search(const char *opc, const char *res, const char *lch,
                       const char *rch, Predicate *pr) {
  bool tmp = false;
  if ((res == _resultStr) || (res && _resultStr && !strcmp(res, _resultStr))) {
    if ((lch == _lchild) || (lch && _lchild && !strcmp(lch, _lchild))) {
      if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {
        char * predStr = get_pred();
        char * prStr = pr?pr->_pred:NULL;
        if (ADLParser::equivalent_expressions(prStr, predStr)) {
          return true;
        }
      }
    }
  }
  if (_next) {
    tmp = _next->search(opc, res, lch, rch, pr);
  }
  return tmp;
}
void MatchList::dump() {
  output(stderr);
}
void MatchList::output(FILE *fp) {
  fprintf(fp, "\nMatchList output is Unimplemented();\n");
}
ArchDesc::ArchDesc()
  : _globalNames(cmpstr,hashstr, Form::arena),
    _globalDefs(cmpstr,hashstr, Form::arena),
    _preproc_table(cmpstr,hashstr, Form::arena),
    _idealIndex(cmpstr,hashstr, Form::arena),
    _internalOps(cmpstr,hashstr, Form::arena),
    _internalMatch(cmpstr,hashstr, Form::arena),
    _chainRules(cmpstr,hashstr, Form::arena),
    _cisc_spill_operand(NULL),
    _needs_clone_jvms(false) {
      for( int i=0; i<_last_opcode; ++i ) {
        _mlistab[i] = NULL;
      }
      initKeywords(_globalNames);    // Initialize the Name Table with keywords
      initBaseOpTypes();
      _TotalLines        = 0;
      _no_output         = 0;
      _quiet_mode        = 0;
      _disable_warnings  = 0;
      _dfa_debug         = 0;
      _dfa_small         = 0;
      _adl_debug         = 0;
      _adlocation_debug  = 0;
      _internalOpCounter = 0;
      _cisc_spill_debug  = false;
      _short_branch_debug = false;
      for (int i = 0; i < _last_opcode; i++) {
        _has_match_rule[i] = false;
      }
      _syntax_errs       = 0;
      _semantic_errs     = 0;
      _warnings          = 0;
      _internal_errs     = 0;
      _ADL_file._name = NULL; _ADL_file._fp = NULL;
      _DFA_file._name    = NULL;  _DFA_file._fp = NULL;
      _HPP_file._name    = NULL;  _HPP_file._fp = NULL;
      _CPP_file._name    = NULL;  _CPP_file._fp = NULL;
      _bug_file._name    = "bugs.out";      _bug_file._fp = NULL;
      _register = NULL;
      _encode = NULL;
      _pipeline = NULL;
      _frame = NULL;
}
ArchDesc::~ArchDesc() {
}
void ArchDesc::addForm(PreHeaderForm *ptr) { _pre_header.addForm(ptr); };
void ArchDesc::addForm(HeaderForm    *ptr) { _header.addForm(ptr); };
void ArchDesc::addForm(SourceForm    *ptr) { _source.addForm(ptr); };
void ArchDesc::addForm(EncodeForm    *ptr) { _encode = ptr; };
void ArchDesc::addForm(InstructForm  *ptr) { _instructions.addForm(ptr); };
void ArchDesc::addForm(MachNodeForm  *ptr) { _machnodes.addForm(ptr); };
void ArchDesc::addForm(OperandForm   *ptr) { _operands.addForm(ptr); };
void ArchDesc::addForm(OpClassForm   *ptr) { _opclass.addForm(ptr); };
void ArchDesc::addForm(AttributeForm *ptr) { _attributes.addForm(ptr); };
void ArchDesc::addForm(RegisterForm  *ptr) { _register = ptr; };
void ArchDesc::addForm(FrameForm     *ptr) { _frame = ptr; };
void ArchDesc::addForm(PipelineForm  *ptr) { _pipeline = ptr; };
void ArchDesc::generateMatchLists() {
  inspectOperands();
  inspectInstructions();
}
void ArchDesc::inspectOperands() {
  _operands.reset();
  OperandForm *op;
  for( ; (op = (OperandForm*)_operands.iter()) != NULL;) {
    op->build_components();
    if ( op->_matrule == NULL )  continue;
    check_optype(op->_matrule);
    build_chain_rule(op);
    MatchRule &mrule = *op->_matrule;
    Predicate *pred  =  op->_predicate;
    const char  *rootOp    = op->_ident;
    mrule._machType  = rootOp;
    if (strcmp(rootOp,"Universe")==0) continue;
    if (strcmp(rootOp,"label")==0) continue;
    assert( strcmp(rootOp,"sReg") != 0, "Disable untyped 'sReg'");
    if (strcmp(rootOp,"sRegI")==0) continue;
    if (strcmp(rootOp,"sRegP")==0) continue;
    if (strcmp(rootOp,"sRegF")==0) continue;
    if (strcmp(rootOp,"sRegD")==0) continue;
    if (strcmp(rootOp,"sRegL")==0) continue;
    const char *costStr     = op->cost();
    const char *defaultCost =
      ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef;
    const char *cost        =  costStr? costStr : defaultCost;
    const char *result      = op->reduce_result();
    bool        has_root    = false;
    buildMatchList(op->_matrule, result, rootOp, pred, cost);
  }
}
void ArchDesc::inspectInstructions() {
  _instructions.reset();
  InstructForm *instr;
  for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {
    instr->build_components();
    if ( instr->_matrule == NULL )  continue;
    MatchRule &mrule = *instr->_matrule;
    Predicate *pred  =  instr->build_predicate();
    const char  *rootOp    = instr->_ident;
    mrule._machType  = rootOp;
    const char *costStr = instr->cost();
    const char *defaultCost =
      ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
    const char *cost    =  costStr? costStr : defaultCost;
    const char *result  = instr->reduce_result();
    if ( instr->is_ideal_branch() && instr->label_position() == -1 ||
        !instr->is_ideal_branch() && instr->label_position() != -1) {
      syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp);
    }
    Attribute *attr = instr->_attribs;
    while (attr != NULL) {
      if (strcmp(attr->_ident,"ins_short_branch") == 0 &&
          attr->int_val(*this) != 0) {
        if (!instr->is_ideal_branch() || instr->label_position() == -1) {
          syntax_err(instr->_linenum, "%s: Only short branch to a label is supported\n", rootOp);
        }
        instr->set_short_branch(true);
      } else if (strcmp(attr->_ident,"ins_alignment") == 0 &&
          attr->int_val(*this) != 0) {
        instr->set_alignment(attr->int_val(*this));
      }
      attr = (Attribute *)attr->_next;
    }
    if (!instr->is_short_branch()) {
      buildMatchList(instr->_matrule, result, mrule._machType, pred, cost);
    }
  }
}
static int setsResult(MatchRule &mrule) {
  if (strcmp(mrule._name,"Set") == 0) return 1;
  return 0;
}
const char *ArchDesc::getMatchListIndex(MatchRule &mrule) {
  if (setsResult(mrule)) {
    return mrule._rChild->_opType;
  } else {
    return mrule._opType;
  }
}
const char *ArchDesc::reduceLeft(char         *internalName) {
  const char *left  = NULL;
  MatchNode *mnode = (MatchNode*)_internalMatch[internalName];
  if (mnode->_lChild) {
    mnode = mnode->_lChild;
    left = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  return left;
}
const char *ArchDesc::reduceRight(char  *internalName) {
  const char *right  = NULL;
  MatchNode *mnode = (MatchNode*)_internalMatch[internalName];
  if (mnode->_rChild) {
    mnode = mnode->_rChild;
    right = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  return right;
}
void ArchDesc::check_optype(MatchRule *mrule) {
  MatchRule *rule = mrule;
}
void ArchDesc::add_chain_rule_entry(const char *src, const char *cost,
                                    const char *result) {
  ChainList *lst = (ChainList *)_chainRules[src];
  if (lst == NULL) {
    lst = new ChainList();
    _chainRules.Insert(src, lst);
  }
  if (!lst->search(result)) {
    if (cost == NULL) {
      cost = ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef;
    }
    lst->insert(result, cost, result);
  }
}
void ArchDesc::build_chain_rule(OperandForm *oper) {
  MatchRule     *rule;
  if ((oper->_matrule) && (oper->_matrule->_lChild == NULL) &&
      (oper->_matrule->_rChild == NULL)) {
    {
      const Form *form = _globalNames[oper->_matrule->_opType];
      if ((form) && form->is_operand() &&
          (form->ideal_only() == false)) {
        add_chain_rule_entry(oper->_matrule->_opType, oper->cost(), oper->_ident);
      }
    }
    if (oper->_matrule->_next) {
      rule = oper->_matrule;
      do {
        rule = rule->_next;
        const Form *form = _globalNames[rule->_opType];
        if ((form) && form->is_operand() &&
            (form->ideal_only() == false)) {
          add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);
        }
      } while(rule->_next != NULL);
    }
  }
  else if ((oper->_matrule) && (oper->_matrule->_next)) {
    rule = oper->_matrule;
    do {
      rule = rule->_next;
      const Form *form = _globalNames[rule->_opType];
      if ((form) && form->is_operand() &&
          (form->ideal_only() == false)) {
        assert( oper->cost(), "This case expects NULL cost, not default cost");
        add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);
      }
    } while(rule->_next != NULL);
  }
}
void ArchDesc::buildMatchList(MatchRule *mrule, const char *resultStr,
                              const char *rootOp, Predicate *pred,
                              const char *cost) {
  const char *leftstr, *rightstr;
  MatchNode  *mnode;
  leftstr = rightstr = NULL;
  if ( mrule->is_chain_rule(_globalNames) ) {
    return;
  }
  intptr_t    index     = _last_opcode;
  const char  *indexStr  = getMatchListIndex(*mrule);
  index  = (intptr_t)_idealIndex[indexStr];
  if (index == 0) {
    fprintf(stderr, "Ideal node missing: %s\n", indexStr);
    assert(index != 0, "Failed lookup of ideal node\n");
  }
  if (index >= _last_opcode) {
    fprintf(stderr, "Invalid match rule %s <-- ( %s )\n",
            resultStr ? resultStr : " ",
            rootOp    ? rootOp    : " ");
    assert(index < _last_opcode, "Matching item not in ideal graph\n");
    return;
  }
  if (!strcmp(mrule->_opType, "Set")) {
    mnode = mrule->_rChild;
    buildMList(mnode, rootOp, resultStr, pred, cost);
    return;
  }
  mnode = mrule->_lChild;
  if (mnode) {
    buildMList(mnode, NULL, NULL, NULL, NULL);
    leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  mnode = mrule->_rChild;
  if (mnode) {
    buildMList(mnode, NULL, NULL, NULL, NULL);
    rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  if ((_mlistab[index] == NULL) ||
      (_mlistab[index] &&
       !_mlistab[index]->search(rootOp, resultStr, leftstr, rightstr, pred))) {
    MatchList *mList =
      new MatchList(_mlistab[index], pred, cost,
                    rootOp, resultStr, leftstr, rightstr);
    _mlistab[index] = mList;
  }
}
void ArchDesc::buildMList(MatchNode *node, const char *rootOp,
                          const char *resultOp, Predicate *pred,
                          const char *cost) {
  const char *leftstr, *rightstr;
  const char *resultop;
  const char *opcode;
  MatchNode  *mnode;
  Form       *form;
  leftstr = rightstr = NULL;
  if ((node) && (node->_lChild == NULL) && (node->_rChild == NULL) &&
      ((form = (Form *)_globalNames[node->_opType]) != NULL) &&
      (!form->ideal_only())) {
    return;
  }
  intptr_t    index     = _last_opcode;
  const char *indexStr  = node ? node->_opType : (char *) " ";
  index            = (intptr_t)_idealIndex[indexStr];
  if (index == 0) {
    fprintf(stderr, "error: operand \"%s\" not found\n", indexStr);
    assert(0, "fatal error");
  }
  mnode = node->_lChild;
  if (mnode) {
    buildMList(mnode, NULL, NULL, NULL, NULL);
    leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  mnode = node->_rChild;
  if (mnode) {
    buildMList(mnode, NULL, NULL, NULL, NULL);
    rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
  }
  if (rootOp == NULL) {
    opcode = (node->_internalop) ? node->_internalop : node->_opType;
  } else {
    opcode = rootOp;
  }
  if (resultOp == NULL) {
    resultop = (node->_internalop) ? node->_internalop : node->_opType;
  }
  else resultop = resultOp;
  if ((_mlistab[index] == NULL) || (_mlistab[index] &&
                                    !_mlistab[index]->search(opcode, resultop, leftstr, rightstr, pred))) {
    MatchList *mList =
      new MatchList(_mlistab[index],pred,cost,
                    opcode, resultop, leftstr, rightstr);
    _mlistab[index] = mList;
  }
}
int  ArchDesc::operandFormCount() {
  int  count = 0; _operands.reset();
  OperandForm *cur;
  for( ; (cur = (OperandForm*)_operands.iter()) != NULL; ) {
    if (cur->_matrule != NULL) ++count;
  };
  return count;
}
int  ArchDesc::opclassFormCount() {
  int  count = 0; _operands.reset();
  OpClassForm *cur;
  for( ; (cur = (OpClassForm*)_opclass.iter()) != NULL; ) {
    ++count;
  };
  return count;
}
int  ArchDesc::instructFormCount() {
  int  count = 0; _instructions.reset();
  InstructForm *cur;
  for( ; (cur = (InstructForm*)_instructions.iter()) != NULL; ) {
    if (cur->_matrule != NULL) ++count;
  };
  return count;
}
char* ArchDesc::get_preproc_def(const char* flag) {
  SourceForm* deff = NULL;
  if (flag != NULL)
    deff = (SourceForm*) _preproc_table[flag];
  return (deff == NULL) ? NULL : deff->_code;
}
void ArchDesc::set_preproc_def(const char* flag, const char* def) {
  SourceForm* deff = (SourceForm*) _preproc_table[flag];
  if (deff == NULL) {
    deff = new SourceForm(NULL);
    _preproc_table.Insert(flag, deff);
    _preproc_list.addName(flag);   // this supports iteration
  }
  deff->_code = (char*) def;
}
bool ArchDesc::verify() {
  if (_register)
    assert( _register->verify(), "Register declarations failed verification");
  if (!_quiet_mode)
    fprintf(stderr,"\n");
  if (!_quiet_mode)
    fprintf(stderr,"---------------------------- Verify Instructions ----------------------------\n");
  _instructions.verify();
  if (!_quiet_mode)
    fprintf(stderr,"\n");
  return true;
}
void ArchDesc::dump() {
  _pre_header.dump();
  _header.dump();
  _source.dump();
  if (_register) _register->dump();
  fprintf(stderr,"\n");
  fprintf(stderr,"------------------ Dump Operands ---------------------\n");
  _operands.dump();
  fprintf(stderr,"\n");
  fprintf(stderr,"------------------ Dump Operand Classes --------------\n");
  _opclass.dump();
  fprintf(stderr,"\n");
  fprintf(stderr,"------------------ Dump Attributes  ------------------\n");
  _attributes.dump();
  fprintf(stderr,"\n");
  fprintf(stderr,"------------------ Dump Instructions -----------------\n");
  _instructions.dump();
  if ( _encode ) {
    fprintf(stderr,"------------------ Dump Encodings --------------------\n");
    _encode->dump();
  }
  if (_pipeline) _pipeline->dump();
}
void ArchDesc::initKeywords(FormDict& names) {
  names.Insert("instruct", NULL);
  names.Insert("operand", NULL);
  names.Insert("attribute", NULL);
  names.Insert("source", NULL);
  names.Insert("register", NULL);
  names.Insert("pipeline", NULL);
  names.Insert("constraint", NULL);
  names.Insert("predicate", NULL);
  names.Insert("encode", NULL);
  names.Insert("enc_class", NULL);
  names.Insert("interface", NULL);
  names.Insert("opcode", NULL);
  names.Insert("ins_encode", NULL);
  names.Insert("match", NULL);
  names.Insert("effect", NULL);
  names.Insert("expand", NULL);
  names.Insert("rewrite", NULL);
  names.Insert("reg_def", NULL);
  names.Insert("reg_class", NULL);
  names.Insert("alloc_class", NULL);
  names.Insert("resource", NULL);
  names.Insert("pipe_class", NULL);
  names.Insert("pipe_desc", NULL);
}
void ArchDesc::internal_err(const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  _internal_errs += emit_msg(0, INTERNAL_ERR, 0, fmt, args);
  va_end(args);
  _no_output = 1;
}
void ArchDesc::syntax_err(int lineno, const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  _internal_errs += emit_msg(0, SYNERR, lineno, fmt, args);
  va_end(args);
  _no_output = 1;
}
int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt,
    va_list args) {
  static int  last_lineno = -1;
  int         i;
  const char *pref;
  switch(flag) {
  case 0: pref = "Warning: "; break;
  case 1: pref = "Syntax Error: "; break;
  case 2: pref = "Semantic Error: "; break;
  case 3: pref = "Internal Error: "; break;
  default: assert(0, ""); break;
  }
  if (line == last_lineno) return 0;
  last_lineno = line;
  if (!quiet) {                        /* no output if in quiet mode         */
    i = fprintf(errfile, "%s(%d) ", _ADL_file._name, line);
    while (i++ <= 15)  fputc(' ', errfile);
    fprintf(errfile, "%-8s:", pref);
    vfprintf(errfile, fmt, args);
    fprintf(errfile, "\n");
    fflush(errfile);
  }
  return 1;
}
static const char *getRegMask(const char *reg_class_name) {
  if( reg_class_name == NULL ) return "RegMask::Empty";
  if (strcmp(reg_class_name,"Universe")==0) {
    return "RegMask::Empty";
  } else if (strcmp(reg_class_name,"stack_slots")==0) {
    return "(Compile::current()->FIRST_STACK_mask())";
  } else {
    char       *rc_name = toUpper(reg_class_name);
    const char *mask    = "_mask";
    int         length  = (int)strlen(rc_name) + (int)strlen(mask) + 5;
    char       *regMask = new char[length];
    sprintf(regMask,"%s%s()", rc_name, mask);
    delete[] rc_name;
    return regMask;
  }
}
const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) {
  const char *reg_mask = "RegMask::Empty";
  if( _register ) {
    RegClass *reg_class  = _register->getRegClass(rc_name);
    if (reg_class == NULL) {
      syntax_err(0, "Use of an undefined register class %s", rc_name);
      return reg_mask;
    }
    reg_mask = getRegMask(rc_name);
  }
  return reg_mask;
}
const char *ArchDesc::reg_mask(OperandForm  &opForm) {
  const char *regMask      = "RegMask::Empty";
  const char *result_class = opForm.constrained_reg_class();
  if (result_class == NULL) {
    opForm.dump();
    syntax_err(opForm._linenum,
               "Use of an undefined result class for operand: %s",
               opForm._ident);
    abort();
  }
  regMask = reg_class_to_reg_mask( result_class );
  return regMask;
}
const char *ArchDesc::reg_mask(InstructForm &inForm) {
  const char *result = inForm.reduce_result();
  if (result == NULL) {
    syntax_err(inForm._linenum,
               "Did not find result operand or RegMask"
               " for this instruction: %s",
               inForm._ident);
    abort();
  }
  if( strcmp(result,"Universe")==0 ) {
    return "RegMask::Empty";
  }
  Form *form = (Form*)_globalNames[result];
  if (form == NULL) {
    syntax_err(inForm._linenum,
               "Did not find result operand for result: %s", result);
    abort();
  }
  OperandForm *oper = form->is_operand();
  if (oper == NULL) {
    syntax_err(inForm._linenum, "Form is not an OperandForm:");
    form->dump();
    abort();
  }
  return reg_mask( *oper );
}
char *ArchDesc::stack_or_reg_mask(OperandForm  &opForm) {
  const char *reg_mask_name = reg_mask(opForm);
  if (reg_mask_name == NULL) {
     syntax_err(opForm._linenum,
                "Did not find reg_mask for opForm: %s",
                opForm._ident);
     abort();
  }
  const char *stack_or = "STACK_OR_";
  int   length         = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1;
  char *result         = new char[length];
  sprintf(result,"%s%s", stack_or, reg_mask_name);
  return result;
}
void ArchDesc::set_stack_or_reg(const char *reg_class_name) {
  if( _register ) {
    RegClass *reg_class  = _register->getRegClass(reg_class_name);
    reg_class->set_stack_version(true);
  }
}
const char *ArchDesc::getIdealType(const char *idealOp) {
  char  last_char = 0;
  const char *ptr = idealOp;
  for (; *ptr != '\0'; ++ptr) {
    last_char = *ptr;
  }
  if (strncmp(idealOp, "Vec",3)==0) {
    switch(last_char) {
    case 'S':  return "TypeVect::VECTS";
    case 'D':  return "TypeVect::VECTD";
    case 'X':  return "TypeVect::VECTX";
    case 'Y':  return "TypeVect::VECTY";
    default:
      internal_err("Vector type %s with unrecognized type\n",idealOp);
    }
  }
  switch(last_char) {
  case 'I':    return "TypeInt::INT";
  case 'P':    return "TypePtr::BOTTOM";
  case 'N':    return "TypeNarrowOop::BOTTOM";
  case 'F':    return "Type::FLOAT";
  case 'D':    return "Type::DOUBLE";
  case 'L':    return "TypeLong::LONG";
  case 's':    return "TypeInt::CC /*flags*/";
  default:
    return NULL;
    break;
  }
  return NULL;
}
OperandForm *ArchDesc::constructOperand(const char *ident,
                                        bool  ideal_only) {
  OperandForm *opForm = new OperandForm(ident, ideal_only);
  _globalNames.Insert(ident, opForm);
  addForm(opForm);
  return opForm;
}
void ArchDesc::initBaseOpTypes() {
  for (int i = 1; i < _last_machine_leaf; ++i) {
    char        *ident   = (char *)NodeClassNames[i];
    constructOperand(ident, true);
  }
  for ( int j = _last_machine_leaf+1; j < _last_opcode; ++j) {
    char         *ident    = (char *)NodeClassNames[j];
    if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") ||
       !strcmp(ident, "ConN") || !strcmp(ident, "ConNKlass") ||
       !strcmp(ident, "ConF") || !strcmp(ident, "ConD") ||
       !strcmp(ident, "ConL") || !strcmp(ident, "Con" ) ||
       !strcmp(ident, "Bool") ) {
      constructOperand(ident, true);
    }
    else {
      InstructForm *insForm  = new InstructForm(ident, true);
      _globalNames.Insert(ident,insForm);
      addForm(insForm);
    }
  }
  { OperandForm *opForm;
  const char *ident = "Universe";
  opForm = constructOperand(ident, false);
  ident = "label";
  opForm = constructOperand(ident, false);
  opForm = constructOperand("sRegI", false);
  opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");
  opForm = constructOperand("sRegP", false);
  opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");
  opForm = constructOperand("sRegF", false);
  opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");
  opForm = constructOperand("sRegD", false);
  opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");
  opForm = constructOperand("sRegL", false);
  opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");
  ident = "method";
  opForm = constructOperand(ident, false);
  }
  {
    const char *ident = "USE";
    Effect     *eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "DEF";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "USE_DEF";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "KILL";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "USE_KILL";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "TEMP";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
    ident = "CALL";
    eForm = new Effect(ident);
    _globalNames.Insert(ident, eForm);
  }
  int idealIndex = 0;
  for (idealIndex = 1; idealIndex < _last_machine_leaf; ++idealIndex) {
    const char *idealName = NodeClassNames[idealIndex];
    _idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);
  }
  for ( idealIndex = _last_machine_leaf+1;
        idealIndex < _last_opcode; ++idealIndex) {
    const char *idealName = NodeClassNames[idealIndex];
    _idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);
  }
}
void ArchDesc::addSunCopyright(char* legal, int size, FILE *fp) {
  size_t count = fwrite(legal, 1, size, fp);
  assert(count == (size_t) size, "copyright info truncated");
  fprintf(fp,"\n");
  fprintf(fp,"// Machine Generated File.  Do Not Edit!\n");
  fprintf(fp,"\n");
}
void ArchDesc::addIncludeGuardStart(ADLFILE &adlfile, const char* guardString) {
  fprintf(adlfile._fp, "\n");
  fprintf(adlfile._fp, "#ifndef %s\n", guardString);
  fprintf(adlfile._fp, "#define %s\n", guardString);
  fprintf(adlfile._fp, "\n");
}
void ArchDesc::addIncludeGuardEnd(ADLFILE &adlfile, const char* guardString) {
  fprintf(adlfile._fp, "\n");
  fprintf(adlfile._fp, "#endif // %s\n", guardString);
}
void ArchDesc::addInclude(ADLFILE &adlfile, const char* fileName) {
  fprintf(adlfile._fp, "#include \"%s\"\n", fileName);
}
void ArchDesc::addInclude(ADLFILE &adlfile, const char* includeDir, const char* fileName) {
  fprintf(adlfile._fp, "#include \"%s/%s\"\n", includeDir, fileName);
}
void ArchDesc::addPreprocessorChecks(FILE *fp) {
  const char* flag;
  _preproc_list.reset();
  if (_preproc_list.count() > 0 && !_preproc_list.current_is_signal()) {
    fprintf(fp, "// Check consistency of C++ compilation with ADLC options:\n");
  }
  for (_preproc_list.reset(); (flag = _preproc_list.iter()) != NULL; ) {
    if (_preproc_list.current_is_signal())  break;
    char* def = get_preproc_def(flag);
    fprintf(fp, "// Check adlc ");
    if (def)
          fprintf(fp, "-D%s=%s\n", flag, def);
    else  fprintf(fp, "-U%s\n", flag);
    fprintf(fp, "#%s %s\n",
            def ? "ifndef" : "ifdef", flag);
    fprintf(fp, "#  error \"%s %s be defined\"\n",
            flag, def ? "must" : "must not");
    fprintf(fp, "#endif // %s\n", flag);
  }
}
const char *ArchDesc::machOperEnum(const char *opName) {
  return ArchDesc::getMachOperEnum(opName);
}
const char *ArchDesc::getMachOperEnum(const char *opName) {
  return (opName ? toUpper(opName) : opName);
}
void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {
  fprintf(fp_hpp, "// Mapping from machine-independent opcode to boolean\n");
  fprintf(fp_hpp, "// Flag cases where machine needs cloned values or instructions\n");
  fprintf(fp_hpp, "extern const char must_clone[];\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "// Mapping from machine-independent opcode to boolean\n");
  fprintf(fp_cpp, "const        char must_clone[] = {\n");
  for (int idealIndex = 0; idealIndex < _last_opcode; ++idealIndex) {
    int         must_clone = 0;
    const char *idealName = NodeClassNames[idealIndex];
    if ( strcmp(idealName,"CmpI") == 0
         || strcmp(idealName,"CmpU") == 0
         || strcmp(idealName,"CmpP") == 0
         || strcmp(idealName,"CmpN") == 0
         || strcmp(idealName,"CmpL") == 0
         || strcmp(idealName,"CmpUL") == 0
         || strcmp(idealName,"CmpD") == 0
         || strcmp(idealName,"CmpF") == 0
         || strcmp(idealName,"FastLock") == 0
         || strcmp(idealName,"FastUnlock") == 0
         || strcmp(idealName,"OverflowAddI") == 0
         || strcmp(idealName,"OverflowAddL") == 0
         || strcmp(idealName,"OverflowSubI") == 0
         || strcmp(idealName,"OverflowSubL") == 0
         || strcmp(idealName,"OverflowMulI") == 0
         || strcmp(idealName,"OverflowMulL") == 0
         || strcmp(idealName,"Bool") == 0
         || strcmp(idealName,"Binary") == 0 ) {
      must_clone = 1;
    }
    fprintf(fp_cpp, "  %d%s // %s: %d\n", must_clone,
      (idealIndex != (_last_opcode - 1)) ? "," : " // no trailing comma",
      idealName, idealIndex);
  }
  fprintf(fp_cpp, "};\n");
}
C:\hotspot-69087d08d473\src\share\vm/adlc/archDesc.hpp
#ifndef SHARE_VM_ADLC_ARCHDESC_HPP
#define SHARE_VM_ADLC_ARCHDESC_HPP
#define  WARN   0
#define  SYNERR 1
#define  SEMERR 2
#define  INTERNAL_ERR 3
class  OutputMap;
class  ProductionState;
class  Expr;
typedef BufferedFile ADLFILE;
class ChainList {
  NameList _name;
  NameList _cost;
  NameList _rule;
public:
  void insert(const char *name, const char *cost, const char *rule);
  bool search(const char *name);
  void reset();
  bool iter(const char * &name, const char * &cost, const char * &rule);
  void dump();
  void output(FILE *fp);
  ChainList();
  ~ChainList();
};
class MatchList {
private:
  MatchList  *_next;
  Predicate  *_pred;          // Predicate which applies to this match rule
  const char *_cost;
public:
  const char *_opcode;
  const char *_resultStr;
  const char *_lchild;
  const char *_rchild;
  MatchList(MatchList *nxt, Predicate *prd): _next(nxt), _pred(prd), _cost(NULL){
    _resultStr = _lchild = _rchild = _opcode = NULL; }
  MatchList(MatchList *nxt, Predicate *prd, const char *cost,
            const char *opcode, const char *resultStr, const char *lchild,
            const char *rchild)
    : _next(nxt), _pred(prd), _cost(cost), _opcode(opcode),
      _resultStr(resultStr), _lchild(lchild), _rchild(rchild) { }
  MatchList  *get_next(void)  { return _next; }
  char       *get_pred(void)  { return (_pred?_pred->_pred:NULL); }
  Predicate  *get_pred_obj(void)  { return _pred; }
  const char *get_cost(void) { return _cost == NULL ? "0" :_cost; }
  bool        search(const char *opc, const char *res, const char *lch,
                    const char *rch, Predicate *pr);
  void        dump();
  void        output(FILE *fp);
};
class ArchDesc {
private:
  FormDict      _globalNames;        // Global names
  Dict          _idealIndex;         // Map ideal names to index in enumeration
  ExprDict      _globalDefs;         // Global definitions, #defines
  int           _internalOpCounter;  // Internal Operand Counter
  FormList      _header;             // List of Source Code Forms for hpp file
  FormList      _pre_header;         // ditto for the very top of the hpp file
  FormList      _source;             // List of Source Code Forms for output
  FormList      _instructions;       // List of Instruction Forms for output
  FormList      _machnodes;          // List of Node Classes (special for pipelining)
  FormList      _operands;           // List of Operand Forms for output
  FormList      _opclass;            // List of Operand Class Forms for output
  FormList      _attributes;         // List of Attribute Forms for parsing
  RegisterForm *_register;           // Only one Register Form allowed
  FrameForm    *_frame;              // Describe stack-frame layout
  EncodeForm   *_encode;             // Only one Encode Form allowed
  PipelineForm *_pipeline;           // Pipeline Form for output
  bool _has_match_rule[_last_opcode];  // found AD rule for ideal node in <arch>.ad
  MatchList    *_mlistab[_last_opcode]; // Array of MatchLists
  OperandForm  *_cisc_spill_operand;
  bool _needs_clone_jvms;
  void gen_match(FILE *fp, MatchList &mlist, ProductionState &status, Dict &operands_chained_from);
  void chain_rule(FILE *fp, const char *indent, const char *ideal,
                  const Expr *icost, const char *irule,
                  Dict &operands_chained_from, ProductionState &status);
  void expand_opclass(FILE *fp, const char *indent, const Expr *cost,
                      const char *result_type, ProductionState &status);
  Expr *calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status);
  void prune_matchlist(Dict &minimize, MatchList &mlist);
  void buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *indent);
public:
  ArchDesc();
  ~ArchDesc();
  int   _TotalLines;                    // Line Counter
  int   _no_output;                     // Flag to disable output of DFA, etc.
  int   _quiet_mode;                    // Do not output banner messages, etc.
  int   _disable_warnings;              // Do not output warning messages
  int   _dfa_debug;                     // Debug Flag for generated DFA
  int   _dfa_small;                     // Debug Flag for generated DFA
  int   _adl_debug;                     // Debug Flag for ADLC
  int   _adlocation_debug;              // Debug Flag to use ad file locations
  bool  _cisc_spill_debug;              // Debug Flag to see cisc-spill-instructions
  bool  _short_branch_debug;            // Debug Flag to see short branch instructions
  int _syntax_errs;                  // Count of syntax errors
  int _semantic_errs;                // Count of semantic errors
  int _warnings;                     // Count warnings
  int _internal_errs;                // Count of internal errors
  void has_match_rule(int opc, const bool b) { _has_match_rule[opc] = b; }
  ADLFILE  _ADL_file;          // Input Architecture Description File
  ADLFILE  _DFA_file;          // File for definition of Matcher::DFA
  ADLFILE  _HPP_file;          // File for ArchNode class declarations
  ADLFILE  _CPP_file;          // File for ArchNode class defintions
  ADLFILE  _CPP_CLONE_file;    // File for MachNode/Oper clone defintions
  ADLFILE  _CPP_EXPAND_file;   // File for MachNode expand methods
  ADLFILE  _CPP_FORMAT_file;   // File for MachNode/Oper format defintions
  ADLFILE  _CPP_GEN_file;      // File for MachNode/Oper generator methods
  ADLFILE  _CPP_MISC_file;     // File for miscellaneous MachNode/Oper tables & methods
  ADLFILE  _CPP_PEEPHOLE_file; // File for MachNode peephole methods
  ADLFILE  _CPP_PIPELINE_file; // File for MachNode pipeline defintions
  ADLFILE  _VM_file;           // File for constants needed in VM code
  ADLFILE  _bug_file;          // DFA debugging file
  int  open_file(bool required, ADLFILE & adf, const char *action);
  void close_file(int delete_out, ADLFILE & adf);
  int  open_files(void);
  void close_files(int delete_out);
  Dict _chainRules;            // Maps user operand names to ChainRules
  Dict _internalOps;           // Maps match strings to internal operand names
  NameList _internalOpNames;   // List internal operand names
  Dict _internalMatch;         // Map internal name to its MatchNode
  NameList      _preproc_list; // Preprocessor flag names
  FormDict      _preproc_table;// Preprocessor flag bindings
  char* get_preproc_def(const char* flag);
  void  set_preproc_def(const char* flag, const char* def);
  FormDict& globalNames() {return _globalNames;} // map global names to forms
  void initKeywords(FormDict& globals);  // Add keywords to global name table
  ExprDict& globalDefs()  {return _globalDefs;}  // map global names to expressions
  OperandForm *constructOperand(const char *ident, bool ideal_only);
  void initBaseOpTypes();            // Import predefined base types.
  void addForm(PreHeaderForm *ptr);  // Add objects to pre-header list
  void addForm(HeaderForm *ptr);     // Add objects to header list
  void addForm(SourceForm *ptr);     // Add objects to source list
  void addForm(EncodeForm *ptr);     // Add objects to encode list
  void addForm(InstructForm *ptr);   // Add objects to the instruct list
  void addForm(OperandForm *ptr);    // Add objects to the operand list
  void addForm(OpClassForm *ptr);    // Add objects to the opclasss list
  void addForm(AttributeForm *ptr);  // Add objects to the attributes list
  void addForm(RegisterForm *ptr);   // Add objects to the register list
  void addForm(FrameForm    *ptr);   // Add objects to the frame list
  void addForm(PipelineForm *ptr);   // Add objects to the pipeline list
  void addForm(MachNodeForm *ptr);   // Add objects to the machnode list
  int  operandFormCount();           // Count number of OperandForms defined
  int  opclassFormCount();           // Count number of OpClassForms defined
  int  instructFormCount();          // Count number of InstructForms defined
  inline void getForm(EncodeForm **ptr)     { *ptr = _encode; }
  bool verify();
  void dump();
  void check_optype(MatchRule *mrule);
  void build_chain_rule(OperandForm *oper);
  void add_chain_rule_entry(const char *src, const char *cost,
                            const char *result);
  const char *getMatchListIndex(MatchRule &mrule);
  void generateMatchLists();         // Build MatchList array and populate it
  void inspectOperands();            // Build MatchLists for all operands
  void inspectOpClasses();           // Build MatchLists for all operands
  void inspectInstructions();        // Build MatchLists for all operands
  void buildDFA(FILE *fp);           // Driver for constructing the DFA
  void gen_dfa_state_body(FILE *fp, Dict &minmize, ProductionState &status, Dict &chained, int i);    // Driver for constructing the DFA state bodies
  const char *reduceLeft (char *internalName);
  const char *reduceRight(char *internalName);
  const char *machOperEnum(const char *opName);       // create dense index names using static function
  static const char *getMachOperEnum(const char *opName);// create dense index name
  void buildMachOperEnum(FILE *fp_hpp);// dense enumeration for operands
  void buildMachOpcodesEnum(FILE *fp_hpp);// enumeration for MachOpers & MachNodes
  RegisterForm *get_registers() { return _register; }
  const char *reg_mask(OperandForm  &opForm);
  const char *reg_mask(InstructForm &instForm);
  const char *reg_class_to_reg_mask(const char *reg_class);
  char *stack_or_reg_mask(OperandForm  &opForm);  // name of cisc_spillable version
  void  set_stack_or_reg(const char *reg_class_name); // for cisc-spillable reg classes
  void  declare_register_masks(FILE *fp_cpp);
  void  build_register_masks(FILE *fp_cpp);
  void  buildMachRegisterNumbers(FILE *fp_hpp);
  void  buildMachRegisterEncodes(FILE *fp_hpp);
  void  declareRegSizes(FILE *fp_hpp);
  void declare_pipe_classes(FILE *fp_hpp);
  void build_pipeline_enums(FILE *fp_cpp);
  void build_pipe_classes(FILE *fp_cpp);
  void build_map(OutputMap &map);
  void buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp);
  void buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp);
  void addSunCopyright(char* legal, int size, FILE *fp);
  void addIncludeGuardStart(ADLFILE &adlfile, const char* guardString);
  void addIncludeGuardEnd(ADLFILE &adlfile, const char* guardString);
  void addInclude(ADLFILE &adlfile, const char* fileName);
  void addInclude(ADLFILE &adlfile, const char* includeDir, const char* fileName);
  void addPreprocessorChecks(FILE *fp);
  void addPreHeaderBlocks(FILE *fp_hpp);
  void addHeaderBlocks(FILE *fp_hpp);
  void addSourceBlocks(FILE *fp_cpp);
  void generate_needs_clone_jvms(FILE *fp_cpp);
  void generate_adlc_verification(FILE *fp_cpp);
  void defineStateClass(FILE *fp);
  void buildMachOperGenerator(FILE *fp_cpp);
  void buildMachNodeGenerator(FILE *fp_cpp);
  void defineExpand      (FILE *fp, InstructForm *node);
  void definePeephole    (FILE *fp, InstructForm *node);
  void defineSize        (FILE *fp, InstructForm &node);
public:
  void defineEvalConstant(FILE *fp, InstructForm &node);
  void defineEmit        (FILE *fp, InstructForm &node);
  void define_postalloc_expand(FILE *fp, InstructForm &node);
  void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals,
                             const char *name, const char *encoding);
  const char *getIdealType(const char *idealOp);
  void declareClasses(FILE *fp_hpp);
  void defineClasses(FILE *fp_cpp);
  void internal_err( const char *fmt, ...);
  void syntax_err  ( int lineno, const char *fmt, ...);
  int  emit_msg(int quiet, int flag, int linenum, const char *fmt,
       va_list args);
  void buildInstructMatchCheck(FILE *fp_cpp) const;
  void buildFrameMethods(FILE *fp_cpp);
  void          build_cisc_spill_instructions(FILE *fp_hpp, FILE *fp_cpp);
  void          identify_cisc_spill_instructions();
  void          identify_short_branches();
  void          identify_unique_operands();
  void          set_cisc_spill_operand(OperandForm *opForm) { _cisc_spill_operand = opForm; }
  OperandForm  *cisc_spill_operand() { return _cisc_spill_operand; }
  bool          can_cisc_spill() { return _cisc_spill_operand != NULL; }
protected:
  void buildMatchList(MatchRule *mrule, const char *resultStr,
                      const char *rootOp, Predicate *pred, const char *cost);
  void buildMList(MatchNode *node, const char *rootOp, const char *resultOp,
                  Predicate *pred, const char *cost);
  friend class ADLParser;
};
class OutputMap {
protected:
  FILE       *_hpp;
  FILE       *_cpp;
  FormDict   &_globals;
  ArchDesc   &_AD;
  const char *_name;
public:
  OutputMap (FILE *decl_file, FILE *def_file, FormDict &globals, ArchDesc &AD, const char *name)
    : _hpp(decl_file), _cpp(def_file), _globals(globals), _AD(AD), _name(name) {};
  FILE        *decl_file() { return _hpp; }
  FILE        *def_file()  { return _cpp; }
  enum position { BEGIN_OPERANDS,
                  BEGIN_OPCLASSES,
                  BEGIN_INTERNALS,
                  BEGIN_INSTRUCTIONS,
                  BEGIN_INST_CHAIN_RULES,
                  END_INST_CHAIN_RULES,
                  BEGIN_REMATERIALIZE,
                  END_REMATERIALIZE,
                  END_INSTRUCTIONS
  };
  virtual void declaration() {}
  virtual void definition()  {}
  virtual void closing()     {  fprintf(_cpp, "};\n"); }
  virtual void map(OperandForm  &oper) { }
  virtual void map(OpClassForm  &opc)  { }
  virtual void map(char         *internal_name) { }
  virtual bool do_instructions()       { return true; }
  virtual void map(InstructForm &inst) { }
  virtual void record_position(OutputMap::position place, int index) {}
};
#endif // SHARE_VM_ADLC_ARCHDESC_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/arena.cpp
#include "adlc.hpp"
void* Chunk::operator new(size_t requested_size, size_t length) throw() {
  return CHeapObj::operator new(requested_size + length);
}
void  Chunk::operator delete(void* p, size_t length) {
  CHeapObj::operator delete(p);
}
Chunk::Chunk(size_t length) {
  _next = NULL;         // Chain on the linked list
  _len  = length;       // Save actual size
}
void Chunk::chop() {
  Chunk *k = this;
  while( k ) {
    Chunk *tmp = k->_next;
    memset(k, 0xBAADBABE, k->_len);
    free(k);                    // Free chunk (was malloc'd)
    k = tmp;
  }
}
void Chunk::next_chop() {
  _next->chop();
  _next = NULL;
}
Arena::Arena( size_t init_size ) {
  init_size = (init_size+3) & ~3;
  _first = _chunk = new (init_size) Chunk(init_size);
  _hwm = _chunk->bottom();      // Save the cached hwm, max
  _max = _chunk->top();
  set_size_in_bytes(init_size);
}
Arena::Arena() {
  _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size);
  _hwm = _chunk->bottom();      // Save the cached hwm, max
  _max = _chunk->top();
  set_size_in_bytes(Chunk::init_size);
}
Arena::Arena( Arena *a )
: _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) {
  set_size_in_bytes(a->size_in_bytes());
}
size_t Arena::used() const {
  size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this Chunk
  register Chunk *k = _first;
  while( k != _chunk) {         // Whilst have Chunks in a row
    sum += k->_len;             // Total size of this Chunk
    k = k->_next;               // Bump along to next Chunk
  }
  return sum;                   // Return total consumed space.
}
void* Arena::grow( size_t x ) {
  size_t len = max(x, Chunk::size);
  register Chunk *k = _chunk;   // Get filled-up chunk address
  _chunk = new (len) Chunk(len);
  if( k ) k->_next = _chunk;    // Append new chunk to end of linked list
  else _first = _chunk;
  _hwm  = _chunk->bottom();     // Save the cached hwm, max
  _max =  _chunk->top();
  set_size_in_bytes(size_in_bytes() + len);
  void* result = _hwm;
  _hwm += x;
  return result;
}
void *Arena::Acalloc( size_t items, size_t x ) {
  size_t z = items*x;   // Total size needed
  void *ptr = Amalloc(z);       // Get space
  memset( ptr, 0, z );          // Zap space
  return ptr;                   // Return space
}
void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) {
  char *c_old = (char*)old_ptr; // Handy name
  if( new_size <= old_size ) {  // Shrink in-place
    if( c_old+old_size == _hwm) // Attempt to free the excess bytes
      _hwm = c_old+new_size;    // Adjust hwm
    return c_old;
  }
  if( (c_old+old_size == _hwm) &&       // Adjusting recent thing
      (c_old+new_size <= _max) ) {      // Still fits where it sits
    _hwm = c_old+new_size;      // Adjust hwm
    return c_old;               // Return old pointer
  }
  void *new_ptr = Amalloc(new_size);
  memcpy( new_ptr, c_old, old_size );
  Afree(c_old,old_size);        // Mostly done to keep stats accurate
  return new_ptr;
}
Arena *Arena::reset(void) {
  Arena *a = new Arena(this);   // New empty arena
  _first = _chunk = NULL;       // Normal, new-arena initialization
  _hwm = _max = NULL;
  return a;                     // Return Arena with guts
}
bool Arena::contains( const void *ptr ) const {
  if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm )
    return true;                // Check for in this chunk
  for( Chunk *c = _first; c; c = c->_next )
    if( (void*)c->bottom() <= ptr && ptr < (void*)c->top())
      return true;              // Check for every chunk in Arena
  return false;                 // Not in any Chunk, so not in Arena
}
void* CHeapObj::operator new(size_t size) throw() {
  return (void *) malloc(size);
}
void CHeapObj::operator delete(void* p){
 free(p);
}
C:\hotspot-69087d08d473\src\share\vm/adlc/arena.hpp
#ifndef SHARE_VM_ADLC_ARENA_HPP
#define SHARE_VM_ADLC_ARENA_HPP
class CHeapObj {
 public:
  void* operator new(size_t size) throw();
  void  operator delete(void* p);
  void* new_array(size_t size);
};
class ValueObj {
 public:
  void* operator new(size_t size) throw();
  void operator delete(void* p);
};
class AllStatic {
 public:
  void* operator new(size_t size) throw();
  void operator delete(void* p);
};
class Chunk: public CHeapObj {
 private:
  void operator delete(void* p);
 public:
  void* operator new(size_t size, size_t length) throw();
  void  operator delete(void* p, size_t length);
  Chunk(size_t length);
  enum {
      init_size =  1*1024,      // Size of first chunk
      size      = 32*1024       // Default size of an Arena chunk (following the first)
  };
  Chunk*       _next;           // Next Chunk in list
  size_t       _len;            // Size of this Chunk
  void chop();                  // Chop this chunk
  void next_chop();             // Chop next chunk
  char* bottom() const { return ((char*) this) + sizeof(Chunk);  }
  char* top()    const { return bottom() + _len; }
};
class Arena: public CHeapObj {
protected:
  friend class ResourceMark;
  friend class HandleMark;
  friend class NoHandleMark;
  Chunk *_first;                // First chunk
  Chunk *_chunk;                // current chunk
  char *_hwm, *_max;            // High water mark and max in current chunk
  void* grow(size_t x);         // Get a new Chunk of at least size x
  size_t _size_in_bytes;          // Size of arena (used for memory usage tracing)
public:
  Arena();
  Arena(size_t init_size);
  Arena(Arena *old);
  ~Arena()                      { _first->chop(); }
  char* hwm() const             { return _hwm; }
  void* Amalloc(size_t x) {
#ifdef _LP64
    x = (x + (8-1)) & ((unsigned)(-8));
#else
    x = (x + (4-1)) & ((unsigned)(-4));
#endif
    if (_hwm + x > _max) {
      return grow(x);
    } else {
      char *old = _hwm;
      _hwm += x;
      return old;
    }
  }
  void *Amalloc_4(size_t x) {
    assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
    if (_hwm + x > _max) {
      return grow(x);
    } else {
      char *old = _hwm;
      _hwm += x;
      return old;
    }
  }
  void Afree(void *ptr, size_t size) {
    if (((char*)ptr) + size == _hwm) _hwm = (char*)ptr;
  }
  void *Acalloc( size_t items, size_t x );
  void *Arealloc( void *old_ptr, size_t old_size, size_t new_size );
  Arena *reset(void);
  bool contains( const void *ptr ) const;
  size_t used() const;
  size_t size_in_bytes() const         {  return _size_in_bytes; }
  void   set_size_in_bytes(size_t size)  { _size_in_bytes = size;   }
};
#endif // SHARE_VM_ADLC_ARENA_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/dfa.cpp
#include "adlc.hpp"
static bool debug_output   = false;
static bool debug_output1  = false;    // top level chain rules
static const char *sLeft   = "_kids[0]";
static const char *sRight  = "_kids[1]";
static const char *dfa_production           = "DFA_PRODUCTION";
static const char *dfa_production_set_valid = "DFA_PRODUCTION__SET_VALID";
static const char *knownInvalid = "knownInvalid";    // The result does NOT have a rule defined
static const char *knownValid   = "knownValid";      // The result must be produced by a rule
static const char *unknownValid = "unknownValid";    // Unknown (probably due to a child or predicate constraint)
static const char *noConstraint  = "noConstraint";   // No constraints seen so far
static const char *hasConstraint = "hasConstraint";  // Within the first constraint
class Production {
public:
  const char *_result;
  const char *_constraint;
  const char *_valid;
  Expr       *_cost_lb;            // Cost lower bound for this production
  Expr       *_cost_ub;            // Cost upper bound for this production
public:
  Production(const char *result, const char *constraint, const char *valid);
  ~Production() {};
  void        initialize();        // reset to be an empty container
  const char   *valid()  const { return _valid; }
  Expr       *cost_lb()  const { return (Expr *)_cost_lb;  }
  Expr       *cost_ub()  const { return (Expr *)_cost_ub;  }
  void print();
};
class ProductionState {
private:
  Dict _production;    // map result of production, char*, to information or NULL
  const char *_constraint;
public:
  ProductionState(Arena *arena) : _production(cmpstr, hashstr, arena) { initialize(); };
  ~ProductionState() { };
  void        initialize();                // reset local and dictionary state
  const char *constraint();
  void    set_constraint(const char *constraint); // currently working inside of constraints
  const char *valid(const char *result);   // unknownValid, or status for this production
  void    set_valid(const char *result);   // if not constrained, set status to knownValid
  Expr           *cost_lb(const char *result);
  Expr           *cost_ub(const char *result);
  void    set_cost_bounds(const char *result, const Expr *cost, bool has_state_check, bool has_cost_check);
  Production *getProduction(const char *result);
  void print();
private:
  ProductionState( )                         : _production(cmpstr, hashstr, Form::arena) {  assert( false, "NotImplemented");  };
  ProductionState( const ProductionState & ) : _production(cmpstr, hashstr, Form::arena) {  assert( false, "NotImplemented");  }; // Deep-copy
};
static void cost_check(FILE *fp, const char *spaces,
                       const char *arrayIdx, const Expr *cost, const char *rule, ProductionState &status) {
  bool state_check               = false;  // true if this production needs to check validity
  bool cost_check                = false;  // true if this production needs to check cost
  bool cost_is_above_upper_bound = false;  // true if this production is unnecessary due to high cost
  bool cost_is_below_lower_bound = false;  // true if this production replaces a higher cost production
  const Expr *previous_ub = status.cost_ub(arrayIdx);
  if( !previous_ub->is_unknown() ) {
    if( previous_ub->less_than_or_equal(cost) ) {
      cost_is_above_upper_bound = true;
      if( debug_output ) { fprintf(fp, "// Previous rule with lower cost than: %s === %s_rule costs %s\n", arrayIdx, rule, cost->as_string()); }
    }
  }
  const Expr *previous_lb = status.cost_lb(arrayIdx);
  if( !previous_lb->is_unknown() ) {
    if( cost->less_than_or_equal(previous_lb) ) {
      cost_is_below_lower_bound = true;
      if( debug_output ) { fprintf(fp, "// Previous rule with higher cost\n"); }
    }
  }
  const char *validity_check = status.valid(arrayIdx);
  if( validity_check == unknownValid ) {
    fprintf(fp, "%sif (STATE__NOT_YET_VALID(%s) || _cost[%s] > %s) {\n",  spaces, arrayIdx, arrayIdx, cost->as_string());
    state_check = true;
    cost_check  = true;
  }
  else if( validity_check == knownInvalid ) {
    if( debug_output ) { fprintf(fp, "%s// %s KNOWN_INVALID \n",  spaces, arrayIdx); }
  }
  else if( validity_check == knownValid ) {
    if( cost_is_above_upper_bound ) {
      return;
    } else if( cost_is_below_lower_bound ) {
    } else {
      fprintf(fp, "%sif ( /* %s KNOWN_VALID || */ _cost[%s] > %s) {\n",  spaces, arrayIdx, arrayIdx, cost->as_string());
      cost_check  = true;
    }
  }
  const char *production = (validity_check == knownValid) ? dfa_production : dfa_production_set_valid;
  fprintf(fp, "%s  %s(%s, %s_rule, %s)", spaces, production, arrayIdx, rule, cost->as_string() );
  if( validity_check == knownValid ) {
    if( cost_is_below_lower_bound ) { fprintf(fp, "\t  // overwrites higher cost rule"); }
   }
   fprintf(fp, "\n");
  if( cost_check || state_check ) {
    fprintf(fp, "%s}\n", spaces);
  }
  status.set_cost_bounds(arrayIdx, cost, state_check, cost_check);
  if( validity_check != knownValid ) {
    status.set_valid(arrayIdx);
  }
}
static void child_test(FILE *fp, MatchList &mList) {
  if (mList._lchild) { // If left child, check it
    const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild);
    fprintf(fp, "STATE__VALID_CHILD(_kids[0], %s)", lchild_to_upper);
    delete[] lchild_to_upper;
  }
  if (mList._lchild && mList._rchild) { // If both, add the "&&"
    fprintf(fp, " && ");
  }
  if (mList._rchild) { // If right child, check it
    const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild);
    fprintf(fp, "STATE__VALID_CHILD(_kids[1], %s)", rchild_to_upper);
    delete[] rchild_to_upper;
  }
}
Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status) {
  fprintf(fp, "%sunsigned int c = ", spaces);
  Expr *c = new Expr("0");
  if (mList._lchild) { // If left child, add it in
    const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild);
    sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper);
    c->add(Expr::buffer());
    delete[] lchild_to_upper;
}
  if (mList._rchild) { // If right child, add it in
    const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild);
    sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper);
    c->add(Expr::buffer());
    delete[] rchild_to_upper;
  }
  const char *mList_cost = mList.get_cost();
  c->add(mList_cost, *this);
  fprintf(fp, "%s;\n", c->as_string());
  c->set_external_name("c");
  return c;
}
void ArchDesc::gen_match(FILE *fp, MatchList &mList, ProductionState &status, Dict &operands_chained_from) {
  const char *spaces4 = "    ";
  const char *spaces6 = "      ";
  fprintf(fp, "%s", spaces4);
  bool has_child_constraints = mList._lchild || mList._rchild;
  const char *predicate_test = mList.get_pred();
  if (has_child_constraints || predicate_test) {
    fprintf(fp, "if( ");
    status.set_constraint(hasConstraint);
    child_test(fp, mList);
    if (predicate_test) {
      if (has_child_constraints) {
        fprintf(fp," &&\n");
      }
      fprintf(fp, "%s  %s", spaces6, predicate_test);
    }
    fprintf(fp," ) ");
  } else {
    status.set_constraint(noConstraint);
  }
  fprintf(fp,"{\n");
  const Expr *cost = calc_cost(fp, spaces6, mList, status);
  cost_check(fp, spaces6, ArchDesc::getMachOperEnum(mList._resultStr), cost, mList._opcode, status);
  expand_opclass( fp, spaces6, cost, mList._resultStr, status);
  const char *rule = /* set rule to "Invalid" for internal operands */
    strcmp(mList._opcode,mList._resultStr) ? mList._opcode : "Invalid";
  chain_rule(fp, spaces6, mList._resultStr, cost, rule, operands_chained_from, status);
  fprintf(fp, "    }\n");
}
void ArchDesc::expand_opclass(FILE *fp, const char *indent, const Expr *cost,
                              const char *result_type, ProductionState &status) {
  const Form *form = _globalNames[result_type];
  OperandForm *op = form ? form->is_operand() : NULL;
  if( op && op->_classes.count() > 0 ) {
    if( debug_output ) { fprintf(fp, "// expand operand classes for operand: %s \n", (char *)op->_ident  ); } // %%%%% Explanation
    op->_classes.reset();
    const char *oclass;
    while( (oclass = op->_classes.iter()) != NULL )
      cost_check(fp, indent, ArchDesc::getMachOperEnum(oclass), cost, result_type, status);
  }
}
void ArchDesc::chain_rule(FILE *fp, const char *indent, const char *operand,
     const Expr *icost, const char *irule, Dict &operands_chained_from,  ProductionState &status) {
  if( operands_chained_from[operand] != NULL ) {
    return;
  } else {
    operands_chained_from.Insert( operand, operand);
  }
  if( debug_output ) { fprintf(fp, "// chain rules starting from: %s  and  %s \n", (char *)operand, (char *)irule); } // %%%%% Explanation
  ChainList *lst = (ChainList *)_chainRules[operand];
  if (lst) {
    const char *result, *cost, *rule;
    for(lst->reset(); (lst->iter(result,cost,rule)) == true; ) {
      if( operands_chained_from[result] != NULL ) {
        continue;
      } else {
        Expr *total_cost = icost->clone();  // icost + cost
        total_cost->add(cost, *this);
        Form *form = (Form *)_globalNames[rule];
        if ( ! form->is_instruction()) {
          const char *reduce_rule = strcmp(irule,"Invalid") ? irule : rule;
          cost_check(fp, indent, ArchDesc::getMachOperEnum(result), total_cost, reduce_rule, status);
          chain_rule(fp, indent, result, total_cost, irule, operands_chained_from, status);
        } else {
          cost_check(fp, indent, ArchDesc::getMachOperEnum(result), total_cost, rule, status);
          chain_rule(fp, indent, result, total_cost, rule, operands_chained_from, status);
        }
        expand_opclass( fp, indent, total_cost, result, status );
      }
    }
  }
}
void ArchDesc::prune_matchlist(Dict &minimize, MatchList &mlist) {
}
void ArchDesc::buildDFA(FILE* fp) {
  int i;
  Dict operands_chained_from(cmpstr, hashstr, Form::arena);
  Dict minimize(cmpstr, hashstr, Form::arena);
  ProductionState status(Form::arena);
  fprintf(fp, "\n");
  fprintf(fp, "//------------------------- Source -----------------------------------------\n");
  fprintf(fp, "\n");
  fprintf(fp, "//------------------------- Attributes -------------------------------------\n");
  _attributes.output(fp);
  fprintf(fp, "\n");
  fprintf(fp, "//------------------------- Macros -----------------------------------------\n");
  fprintf(fp, "#define %s(result, rule, cost)\\\n", dfa_production);
  fprintf(fp, "  _cost[ (result) ] = cost; _rule[ (result) ] = rule;\n");
  fprintf(fp, "\n");
  fprintf(fp, "#define %s(result, rule, cost)\\\n", dfa_production_set_valid);
  fprintf(fp, "  %s( (result), (rule), (cost) ); STATE__SET_VALID( (result) );\n", dfa_production);
  fprintf(fp, "\n");
  fprintf(fp, "//------------------------- DFA --------------------------------------------\n");
  fprintf(fp,
"// DFA is a large switch with case statements for each ideal opcode encountered\n"
"// in any match rule in the ad file.  Each case has a series of if's to handle\n"
"// the match or fail decisions.  The matches test the cost function of that\n"
"// rule, and prune any cases which are higher cost for the same reduction.\n"
"// In order to generate the DFA we walk the table of ideal opcode/MatchList\n"
"// pairs generated by the ADLC front end to build the contents of the case\n"
"// statements (a series of if statements).\n"
);
  fprintf(fp, "\n");
  fprintf(fp, "\n");
  if (_dfa_small) {
    for (i = 1; i < _last_opcode; i++) {
      if (_mlistab[i] == NULL) continue;
      fprintf(fp, "void  State::_sub_Op_%s(const Node *n){\n", NodeClassNames[i]);
      gen_dfa_state_body(fp, minimize, status, operands_chained_from, i);
      fprintf(fp, "}\n");
    }
  }
  fprintf(fp, "bool State::DFA");
  fprintf(fp, "(int opcode, const Node *n) {\n");
  fprintf(fp, "  switch(opcode) {\n");
  for (i = 1; i < _last_opcode; i++) {
    if (_mlistab[i] == NULL) continue;
    if (_dfa_small) {
      fprintf(fp, "  case Op_%s: { _sub_Op_%s(n);\n", NodeClassNames[i], NodeClassNames[i]);
    } else {
      fprintf(fp, "  case Op_%s: {\n", NodeClassNames[i]);
      gen_dfa_state_body(fp, minimize, status, operands_chained_from, i);
    }
    fprintf(fp, "    break;\n");
    fprintf(fp, "  }\n");
  }
  fprintf(fp, "  \n");
  fprintf(fp, "  default:\n");
  fprintf(fp, "    tty->print(\"Default case invoked for: \\n\");\n");
  fprintf(fp, "    tty->print(\"   opcode  = %cd, \\\"%cs\\\"\\n\", opcode, NodeClassNames[opcode]);\n", '%', '%');
  fprintf(fp, "    return false;\n");
  fprintf(fp, "  }\n");
  fprintf(fp, "  return true;\n");
  fprintf(fp, "}\n");
  Expr::check_buffers();
}
class dfa_shared_preds {
  enum { count = 4 };
  static bool        _found[count];
  static const char* _type [count];
  static const char* _var  [count];
  static const char* _pred [count];
  static void check_index(int index) { assert( 0 <= index && index < count, "Invalid index"); }
  static bool valid_loc(char *pred, char *shared) {
    if( shared == pred ) return true;
    char *prev = shared - 1;
    char c  = *prev;
    switch( c ) {
    case ' ':
    case '\n':
      return dfa_shared_preds::valid_loc(pred, prev);
    case '!':
    case '(':
    case '<':
    case '=':
      return true;
    case '"':  // such as: #line 10 "myfile.ad"\n mypredicate
      return true;
    case '|':
      if( prev != pred && *(prev-1) == '|' ) return true;
    case '&':
      if( prev != pred && *(prev-1) == '&' ) return true;
    default:
      return false;
    }
    return false;
  }
public:
  static bool        found(int index){ check_index(index); return _found[index]; }
  static void    set_found(int index, bool val) { check_index(index); _found[index] = val; }
  static void  reset_found() {
    for( int i = 0; i < count; ++i ) { _found[i] = false; }
  };
  static const char* type(int index) { check_index(index); return _type[index]; }
  static const char* var (int index) { check_index(index); return _var [index];  }
  static const char* pred(int index) { check_index(index); return _pred[index]; }
  static void cse_matchlist(MatchList *matchList) {
    for( MatchList *mList = matchList; mList != NULL; mList = mList->get_next() ) {
      Predicate* predicate = mList->get_pred_obj();
      char*      pred      = mList->get_pred();
      if( pred != NULL ) {
        for(int index = 0; index < count; ++index ) {
          const char *shared_pred      = dfa_shared_preds::pred(index);
          const char *shared_pred_var  = dfa_shared_preds::var(index);
          bool result = dfa_shared_preds::cse_predicate(predicate, shared_pred, shared_pred_var);
          if( result ) dfa_shared_preds::set_found(index, true);
        }
      }
    }
  }
  static bool cse_predicate(Predicate* predicate, const char *shared_pred, const char *shared_pred_var) {
    bool result = false;
    char *pred = predicate->_pred;
    if( pred != NULL ) {
      char *new_pred = pred;
      for( char *shared_pred_loc = strstr(new_pred, shared_pred);
      shared_pred_loc != NULL && dfa_shared_preds::valid_loc(new_pred,shared_pred_loc);
      shared_pred_loc = strstr(new_pred, shared_pred) ) {
        if( new_pred == pred ) {
          new_pred = strdup(pred);
          shared_pred_loc = strstr(new_pred, shared_pred);
        }
        strncpy(shared_pred_loc, shared_pred_var, strlen(shared_pred_var));
      }
      if( new_pred != pred ) {
        predicate->_pred = new_pred;
        result = true;
      }
    }
    return result;
  }
  static void generate_cse(FILE *fp) {
    for(int j = 0; j < count; ++j ) {
      if( dfa_shared_preds::found(j) ) {
        const char *shared_pred_type = dfa_shared_preds::type(j);
        const char *shared_pred_var  = dfa_shared_preds::var(j);
        const char *shared_pred      = dfa_shared_preds::pred(j);
        fprintf(fp, "    %s %s = %s;\n", shared_pred_type, shared_pred_var, shared_pred);
      }
    }
  }
};
bool         dfa_shared_preds::_found[dfa_shared_preds::count]
  = { false, false, false, false };
const char*  dfa_shared_preds::_type[dfa_shared_preds::count]
  = { "int", "jlong", "intptr_t", "bool" };
const char*  dfa_shared_preds::_var [dfa_shared_preds::count]
  = { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__", "Compile__current____select_24_bit_instr__" };
const char*  dfa_shared_preds::_pred[dfa_shared_preds::count]
  = { "n->get_int()", "n->get_long()", "n->get_intptr_t()", "Compile::current()->select_24_bit_instr()" };
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) {
  status.initialize();
  MatchList* mList = _mlistab[i];
  do {
    prune_matchlist(minimize, *mList);
    mList = mList->get_next();
  } while(mList != NULL);
  dfa_shared_preds::reset_found();
  dfa_shared_preds::cse_matchlist(_mlistab[i]);
  dfa_shared_preds::generate_cse(fp);
  mList = _mlistab[i];
  do {
    operands_chained_from.Clear();
    gen_match(fp, *mList, status, operands_chained_from);
    mList = mList->get_next();
  } while(mList != NULL);
  operands_chained_from.Clear();  //
  if( debug_output1 ) { fprintf(fp, "// top level chain rules for: %s \n", (char *)NodeClassNames[i]); } // %%%%% Explanation
  const Expr *zeroCost = new Expr("0");
  chain_rule(fp, "   ", (char *)NodeClassNames[i], zeroCost, "Invalid",
             operands_chained_from, status);
}
Expr *Expr::_unknown_expr = NULL;
char  Expr::string_buffer[STRING_BUFFER_LENGTH];
char  Expr::external_buffer[STRING_BUFFER_LENGTH];
bool  Expr::_init_buffers = Expr::init_buffers();
Expr::Expr() {
  _external_name = NULL;
  _expr          = "Invalid_Expr";
  _min_value     = Expr::Max;
  _max_value     = Expr::Zero;
}
Expr::Expr(const char *cost) {
  _external_name = NULL;
  int intval = 0;
  if( cost == NULL ) {
    _expr = "0";
    _min_value = Expr::Zero;
    _max_value = Expr::Zero;
  }
  else if( ADLParser::is_int_token(cost, intval) ) {
    _expr = cost;
    _min_value = intval;
    _max_value = intval;
  }
  else {
    assert( strcmp(cost,"0") != 0, "Recognize string zero as an int");
    _expr = cost;
    _min_value = Expr::Zero;
    _max_value = Expr::Max;
  }
}
Expr::Expr(const char *name, const char *expression, int min_value, int max_value) {
  _external_name = name;
  _expr          = expression ? expression : name;
  _min_value     = min_value;
  _max_value     = max_value;
  assert(_min_value >= 0 && _min_value <= Expr::Max, "value out of range");
  assert(_max_value >= 0 && _max_value <= Expr::Max, "value out of range");
}
Expr *Expr::clone() const {
  Expr *cost = new Expr();
  cost->_external_name = _external_name;
  cost->_expr          = _expr;
  cost->_min_value     = _min_value;
  cost->_max_value     = _max_value;
  return cost;
}
void Expr::add(const Expr *c) {
  const char *external  = compute_external(this, c);
  const char *expr      = compute_expr(this, c);
  int         min_value = compute_min (this, c);
  int         max_value = compute_max (this, c);
  _external_name = external;
  _expr      = expr;
  _min_value = min_value;
  _max_value = max_value;
}
void Expr::add(const char *c) {
  Expr *cost = new Expr(c);
  add(cost);
}
void Expr::add(const char *c, ArchDesc &AD) {
  const Expr *e = AD.globalDefs()[c];
  if( e != NULL ) {
    add(e);
  } else {
    Expr *cost = new Expr(c);
    add(cost);
  }
}
const char *Expr::compute_external(const Expr *c1, const Expr *c2) {
  const char * result = NULL;
  if( c1->_external_name != NULL ) {
    sprintf( string_buffer, "%s", c1->as_string());
    if( !c2->is_zero() ) {
      strcat( string_buffer, "+");
      strcat( string_buffer, c2->as_string());
    }
    result = strdup(string_buffer);
  }
  else if( c2->_external_name != NULL ) {
    if( !c1->is_zero() ) {
      sprintf( string_buffer, "%s", c1->as_string());
      strcat( string_buffer, " + ");
    } else {
      string_buffer[0] = '\0';
    }
    strcat( string_buffer, c2->_external_name );
    result = strdup(string_buffer);
  }
  return result;
}
const char *Expr::compute_expr(const Expr *c1, const Expr *c2) {
  if( !c1->is_zero() ) {
    sprintf( string_buffer, "%s", c1->_expr);
    if( !c2->is_zero() ) {
      strcat( string_buffer, "+");
      strcat( string_buffer, c2->_expr);
    }
  }
  else if( !c2->is_zero() ) {
    sprintf( string_buffer, "%s", c2->_expr);
  }
  else {
    sprintf( string_buffer, "0");
  }
  char *cost = strdup(string_buffer);
  return cost;
}
int Expr::compute_min(const Expr *c1, const Expr *c2) {
  int v1 = c1->_min_value;
  int v2 = c2->_min_value;
  assert(0 <= v2 && v2 <= Expr::Max, "sanity");
  assert(v1 <= Expr::Max - v2, "Invalid cost computation");
  return v1 + v2;
}
int Expr::compute_max(const Expr *c1, const Expr *c2) {
  int v1 = c1->_max_value;
  int v2 = c2->_max_value;
  assert(0 <= v2 && v2 <= Expr::Max, "sanity");
  if (v1 > Expr::Max - v2) {
    return Expr::Max;
  }
  return v1 + v2;
}
void Expr::print() const {
  if( _external_name != NULL ) {
    printf("  %s == (%s) === [%d, %d]\n", _external_name, _expr, _min_value, _max_value);
  } else {
    printf("  %s === [%d, %d]\n", _expr, _min_value, _max_value);
  }
}
void Expr::print_define(FILE *fp) const {
  assert( _external_name != NULL, "definition does not have a name");
  assert( _min_value == _max_value, "Expect user definitions to have constant value");
  fprintf(fp, "#define  %s  (%s)  \n", _external_name, _expr);
  fprintf(fp, "// value == %d \n", _min_value);
}
void Expr::print_assert(FILE *fp) const {
  assert( _external_name != NULL, "definition does not have a name");
  assert( _min_value == _max_value, "Expect user definitions to have constant value");
  fprintf(fp, "  assert( %s == %d, \"Expect (%s) to equal %d\");\n", _external_name, _min_value, _expr, _min_value);
}
Expr *Expr::get_unknown() {
  if( Expr::_unknown_expr == NULL ) {
    Expr::_unknown_expr = new Expr();
  }
  return Expr::_unknown_expr;
}
bool Expr::init_buffers() {
  for( int i = 0; i < STRING_BUFFER_LENGTH; ++i ) {
    external_buffer[i] = '\0';
    string_buffer[i]   = '\0';
  }
  return true;
}
bool Expr::check_buffers() {
  bool ok = true;
  for( int i = STRING_BUFFER_LENGTH - 100; i < STRING_BUFFER_LENGTH; ++i) {
    if( external_buffer[i] != '\0' || string_buffer[i]   != '\0' ) {
      ok = false;
      assert( false, "Expr:: Buffer overflow");
    }
  }
  return ok;
}
ExprDict::ExprDict( CmpKey cmp, Hash hash, Arena *arena )
  : _expr(cmp, hash, arena), _defines()  {
}
ExprDict::~ExprDict() {
}
int ExprDict::Size(void) const {
  return _expr.Size();
}
const Expr  *ExprDict::define(const char *name, Expr *expr) {
  const Expr *old_expr = (*this)[name];
  assert(old_expr == NULL, "Implementation does not support redefinition");
  _expr.Insert(name, expr);
  _defines.addName(name);
  return old_expr;
}
const Expr  *ExprDict::Insert(const char *name, Expr *expr) {
  return (Expr*)_expr.Insert((void*)name, (void*)expr);
}
const Expr  *ExprDict::operator [](const char *name) const {
  return (Expr*)_expr[name];
}
void ExprDict::print_defines(FILE *fp) {
  fprintf(fp, "\n");
  const char *name = NULL;
  for( _defines.reset(); (name = _defines.iter()) != NULL; ) {
    const Expr *expr = (const Expr*)_expr[name];
    assert( expr != NULL, "name in ExprDict without matching Expr in dictionary");
    expr->print_define(fp);
  }
}
void ExprDict::print_asserts(FILE *fp) {
  fprintf(fp, "\n");
  fprintf(fp, "  // Following assertions generated from definition section\n");
  const char *name = NULL;
  for( _defines.reset(); (name = _defines.iter()) != NULL; ) {
    const Expr *expr = (const Expr*)_expr[name];
    assert( expr != NULL, "name in ExprDict without matching Expr in dictionary");
    expr->print_assert(fp);
  }
}
static void dumpekey(const void* key)  { fprintf(stdout, "%s", (char*) key); }
static void dumpexpr(const void* expr) { fflush(stdout); ((Expr*)expr)->print(); }
void ExprDict::dump() {
  _expr.print(dumpekey, dumpexpr);
}
ExprDict::ExprDict( ) : _expr(cmpkey,hashkey), _defines()  {
  assert( false, "NotImplemented");
}
ExprDict::ExprDict( const ExprDict & ) : _expr(cmpkey,hashkey), _defines() {
  assert( false, "NotImplemented");
}
ExprDict &ExprDict::operator =( const ExprDict &rhs) {
  assert( false, "NotImplemented");
  _expr = rhs._expr;
  return *this;
}
bool ExprDict::operator ==(const ExprDict &d) const {
  assert( false, "NotImplemented");
  return false;
}
Production::Production(const char *result, const char *constraint, const char *valid) {
  initialize();
  _result     = result;
  _constraint = constraint;
  _valid      = valid;
}
void Production::initialize() {
  _result     = NULL;
  _constraint = NULL;
  _valid      = knownInvalid;
  _cost_lb    = Expr::get_unknown();
  _cost_ub    = Expr::get_unknown();
}
void Production::print() {
  printf("%s", (_result     == NULL ? "NULL" : _result ) );
  printf("%s", (_constraint == NULL ? "NULL" : _constraint ) );
  printf("%s", (_valid      == NULL ? "NULL" : _valid ) );
  _cost_lb->print();
  _cost_ub->print();
}
void ProductionState::initialize() {
  _constraint = noConstraint;
  DictI iter( &_production );
  const void *x, *y = NULL;
  for( ; iter.test(); ++iter) {
    x = iter._key;
    y = iter._value;
    Production *p = (Production*)y;
    if( p != NULL ) {
      p->initialize();
    }
  }
}
Production *ProductionState::getProduction(const char *result) {
  Production *p = (Production *)_production[result];
  if( p == NULL ) {
    p = new Production(result, _constraint, knownInvalid);
    _production.Insert(result, p);
  }
  return p;
}
void ProductionState::set_constraint(const char *constraint) {
  _constraint = constraint;
}
const char *ProductionState::valid(const char *result) {
  return getProduction(result)->valid();
}
void ProductionState::set_valid(const char *result) {
  Production *p = getProduction(result);
  if( _constraint == noConstraint ) {
    p->_valid = knownValid;
  } else {
    if( p->_valid != knownValid ) {
      p->_valid = unknownValid;
    }
  }
}
Expr *ProductionState::cost_lb(const char *result) {
  return getProduction(result)->cost_lb();
}
Expr *ProductionState::cost_ub(const char *result) {
  return getProduction(result)->cost_ub();
}
void ProductionState::set_cost_bounds(const char *result, const Expr *cost, bool has_state_check, bool has_cost_check) {
  Production *p = getProduction(result);
  if( p->_valid == knownInvalid ) {
    p->_cost_lb = cost->clone();
    p->_cost_ub = cost->clone();
  } else if (has_state_check || _constraint != noConstraint) {
    if( cost->less_than_or_equal(p->_cost_lb) ) {
      p->_cost_lb = cost->clone();
    }
    if( p->_cost_ub->less_than_or_equal(cost) ) {
      p->_cost_ub = cost->clone();
    }
  } else if (has_cost_check) {
    if( cost->less_than_or_equal(p->_cost_lb) ) {
      p->_cost_lb = cost->clone();
    }
    if( cost->less_than_or_equal(p->_cost_ub) ) {
      p->_cost_ub = cost->clone();
    }
  } else {
    p->_cost_lb = cost->clone();
    p->_cost_ub = cost->clone();
  }
}
static void print_key (const void* key)              { fprintf(stdout, "%s", (char*) key); }
static void print_production(const void* production) { fflush(stdout); ((Production*)production)->print(); }
void ProductionState::print() {
  _production.print(print_key, print_production);
}
C:\hotspot-69087d08d473\src\share\vm/adlc/dict2.cpp
#include "adlc.hpp"
#define MAXID 20
static char initflag = 0;       // True after 1st initialization
static char shft[MAXID + 1] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7};
static short xsum[MAXID];
class bucket {
public:
  int          _cnt, _max;      // Size of bucket
  const void **_keyvals;        // Array of keys and values
};
Dict::Dict(CmpKey initcmp, Hash inithash) : _hash(inithash), _cmp(initcmp), _arena(NULL) {
  init();
}
Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena) : _hash(inithash), _cmp(initcmp), _arena(arena) {
  init();
}
void Dict::init() {
  int i;
  if (!initflag) {              // Not initializated yet?
    xsum[0] = (short) ((1 << shft[0]) + 1);  // Initialize
    for( i = 1; i < MAXID; i++) {
      xsum[i] = (short) ((1 << shft[i]) + 1 + xsum[i-1]);
    }
    initflag = 1;               // Never again
  }
  _size = 16;                   // Size is a power of 2
  _cnt = 0;                     // Dictionary is empty
  _bin = (bucket*)_arena->Amalloc_4(sizeof(bucket) * _size);
  memset(_bin, 0, sizeof(bucket) * _size);
}
Dict::~Dict() {
}
void Dict::Clear() {
  _cnt = 0;                     // Empty contents
  for( int i=0; i<_size; i++ )
    _bin[i]._cnt = 0;           // Empty buckets, but leave allocated
}
void Dict::doubhash(void) {
  int oldsize = _size;
  _size <<= 1;                  // Double in size
  _bin = (bucket*)_arena->Arealloc( _bin, sizeof(bucket)*oldsize, sizeof(bucket)*_size );
  memset( &_bin[oldsize], 0, oldsize*sizeof(bucket) );
  for( int i=0; i < oldsize; i++) { // For complete OLD table do
    bucket *b = &_bin[i];       // Handy shortcut for _bin[i]
    if( !b->_keyvals ) continue;        // Skip empties fast
    bucket *nb = &_bin[i+oldsize];  // New bucket shortcut
    int j = b->_max;                // Trim new bucket to nearest power of 2
    while( j > b->_cnt ) j >>= 1;   // above old bucket _cnt
    if( !j ) j = 1;             // Handle zero-sized buckets
    nb->_max = j<<1;
    nb->_keyvals = (const void**)_arena->Amalloc_4( sizeof(void *)*nb->_max*2 );
    int nbcnt = 0;
    for( j=0; j<b->_cnt; j++ ) {  // Rehash all keys in this bucket
      const void *key = b->_keyvals[j+j];
      if( (_hash( key ) & (_size-1)) != i ) { // Moving to hi bucket?
        nb->_keyvals[nbcnt+nbcnt] = key;
        nb->_keyvals[nbcnt+nbcnt+1] = b->_keyvals[j+j+1];
        nb->_cnt = nbcnt = nbcnt+1;
        b->_cnt--;              // Remove key/value from lo bucket
        b->_keyvals[j+j  ] = b->_keyvals[b->_cnt+b->_cnt  ];
        b->_keyvals[j+j+1] = b->_keyvals[b->_cnt+b->_cnt+1];
        j--;                    // Hash compacted element also
      }
    } // End of for all key-value pairs in bucket
  } // End of for all buckets
}
Dict::Dict( const Dict &d ) : _size(d._size), _cnt(d._cnt), _hash(d._hash),_cmp(d._cmp), _arena(d._arena) {
  _bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size);
  memcpy( _bin, d._bin, sizeof(bucket)*_size );
  for( int i=0; i<_size; i++ ) {
    if( !_bin[i]._keyvals ) continue;
    _bin[i]._keyvals=(const void**)_arena->Amalloc_4( sizeof(void *)*_bin[i]._max*2);
    memcpy( _bin[i]._keyvals, d._bin[i]._keyvals,_bin[i]._cnt*2*sizeof(void*));
  }
}
Dict &Dict::operator =( const Dict &d ) {
  if( _size < d._size ) {       // If must have more buckets
    _arena = d._arena;
    _bin = (bucket*)_arena->Arealloc( _bin, sizeof(bucket)*_size, sizeof(bucket)*d._size );
    memset( &_bin[_size], 0, (d._size-_size)*sizeof(bucket) );
    _size = d._size;
  }
  for( int i=0; i<_size; i++ ) // All buckets are empty
    _bin[i]._cnt = 0;           // But leave bucket allocations alone
  _cnt = d._cnt;
  for(int k=0; k<_size; k++ ) {
    bucket *b = &d._bin[k];     // Shortcut to source bucket
    for( int j=0; j<b->_cnt; j++ )
      Insert( b->_keyvals[j+j], b->_keyvals[j+j+1] );
  }
  return *this;
}
const void *Dict::Insert(const void *key, const void *val) {
  int hash = _hash( key );      // Get hash key
  int i = hash & (_size-1);     // Get hash key, corrected for size
  bucket *b = &_bin[i];         // Handy shortcut
  for( int j=0; j<b->_cnt; j++ )
    if( !_cmp(key,b->_keyvals[j+j]) ) {
      const void *prior = b->_keyvals[j+j+1];
      b->_keyvals[j+j  ] = key; // Insert current key-value
      b->_keyvals[j+j+1] = val;
      return prior;             // Return prior
    }
  if( ++_cnt > _size ) {        // Hash table is full
    doubhash();                 // Grow whole table if too full
    i = hash & (_size-1);       // Rehash
    b = &_bin[i];               // Handy shortcut
  }
  if( b->_cnt == b->_max ) {    // Must grow bucket?
    if( !b->_keyvals ) {
      b->_max = 2;              // Initial bucket size
      b->_keyvals = (const void**)_arena->Amalloc_4( sizeof(void *)*b->_max*2 );
    } else {
      b->_keyvals = (const void**)_arena->Arealloc( b->_keyvals, sizeof(void *)*b->_max*2, sizeof(void *)*b->_max*4 );
      b->_max <<= 1;            // Double bucket
    }
  }
  b->_keyvals[b->_cnt+b->_cnt  ] = key;
  b->_keyvals[b->_cnt+b->_cnt+1] = val;
  b->_cnt++;
  return NULL;                  // Nothing found prior
}
const void *Dict::Delete(void *key) {
  int i = _hash( key ) & (_size-1);     // Get hash key, corrected for size
  bucket *b = &_bin[i];         // Handy shortcut
  for( int j=0; j<b->_cnt; j++ )
    if( !_cmp(key,b->_keyvals[j+j]) ) {
      const void *prior = b->_keyvals[j+j+1];
      b->_cnt--;                // Remove key/value from lo bucket
      b->_keyvals[j+j  ] = b->_keyvals[b->_cnt+b->_cnt  ];
      b->_keyvals[j+j+1] = b->_keyvals[b->_cnt+b->_cnt+1];
      _cnt--;                   // One less thing in table
      return prior;
    }
  return NULL;
}
const void *Dict::operator [](const void *key) const {
  int i = _hash( key ) & (_size-1);     // Get hash key, corrected for size
  bucket *b = &_bin[i];         // Handy shortcut
  for( int j=0; j<b->_cnt; j++ )
    if( !_cmp(key,b->_keyvals[j+j]) )
      return b->_keyvals[j+j+1];
  return NULL;
}
int Dict::operator ==(const Dict &d2) const {
  if( _cnt != d2._cnt ) return 0;
  if( _hash != d2._hash ) return 0;
  if( _cmp != d2._cmp ) return 0;
  for( int i=0; i < _size; i++) {       // For complete hash table do
    bucket *b = &_bin[i];       // Handy shortcut
    if( b->_cnt != d2._bin[i]._cnt ) return 0;
    if( memcmp(b->_keyvals, d2._bin[i]._keyvals, b->_cnt*2*sizeof(void*) ) )
      return 0;                 // Key-value pairs must match
  }
  return 1;                     // All match, is OK
}
static void printvoid(const void* x) { printf("%p", x);  }
void Dict::print() {
  print(printvoid, printvoid);
}
void Dict::print(PrintKeyOrValue print_key, PrintKeyOrValue print_value) {
  for( int i=0; i < _size; i++) {       // For complete hash table do
    bucket *b = &_bin[i];       // Handy shortcut
    for( int j=0; j<b->_cnt; j++ ) {
      print_key(  b->_keyvals[j+j  ]);
      printf(" -> ");
      print_value(b->_keyvals[j+j+1]);
      printf("\n");
    }
  }
}
int hashstr(const void *t) {
  register char c, k = 0;
  register int sum = 0;
  register const char *s = (const char *)t;
  while (((c = s[k]) != '\0') && (k < MAXID-1)) { // Get characters till nul
    c = (char) ((c << 1) + 1);    // Characters are always odd!
    sum += c + (c << shft[k++]);  // Universal hash function
  }
  assert(k < (MAXID), "Exceeded maximum name length");
  return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size
}
int hashptr(const void *key) {
#ifdef __TURBOC__
    return (int)((intptr_t)key >> 16);
#else  // __TURBOC__
    return (int)((intptr_t)key >> 2);
#endif
}
int hashkey(const void *key) {
  return (int)((intptr_t)key);
}
int cmpstr(const void *k1, const void *k2) {
  return strcmp((const char *)k1,(const char *)k2);
}
int cmpkey(const void *key1, const void *key2) {
  if (key1 == key2) return 0;
  intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
  if (delta > 0) return 1;
  return -1;
}
void DictI::reset( const Dict *dict ) {
  _d = dict;                    // The dictionary
  _i = (int)-1;         // Before the first bin
  _j = 0;                       // Nothing left in the current bin
  ++(*this);                    // Step to first real value
}
void DictI::operator ++(void) {
  if( _j-- ) {                  // Still working in current bin?
    _key   = _d->_bin[_i]._keyvals[_j+_j];
    _value = _d->_bin[_i]._keyvals[_j+_j+1];
    return;
  }
  while( ++_i < _d->_size ) {   // Else scan for non-zero bucket
    _j = _d->_bin[_i]._cnt;
    if( !_j ) continue;
    _j--;
    _key   = _d->_bin[_i]._keyvals[_j+_j];
    _value = _d->_bin[_i]._keyvals[_j+_j+1];
    return;
  }
  _key = _value = NULL;
}
C:\hotspot-69087d08d473\src\share\vm/adlc/dict2.hpp
#ifndef SHARE_VM_ADLC_DICT2_HPP
#define SHARE_VM_ADLC_DICT2_HPP
class Dict;
typedef int  (*CmpKey)(const void *key1, const void *key2);
typedef int  (*Hash)(const void *key);
typedef void (*PrintKeyOrValue)(const void *key_or_value);
typedef void (*FuncDict)(const void *key, const void *val, Dict *d);
class Dict { // Dictionary structure
 private:
  class Arena *_arena;          // Where to draw storage from
  class bucket *_bin;           // Hash table is array of buckets
  int _size;                    // Size (# of slots) in hash table
  int _cnt;                     // Number of key-value pairs in hash table
  const Hash _hash;             // Hashing function
  const CmpKey _cmp;            // Key comparison function
  void doubhash( void );        // Double hash table size
 public:
  friend class DictI;            // Friendly iterator function
  Dict( CmpKey cmp, Hash hash );
  Dict( CmpKey cmp, Hash hash, Arena *arena );
  void init();
  ~Dict();
  Dict( const Dict & );         // Deep-copy guts
  Dict &operator =( const Dict & );
  void Clear();
  int Size(void) const { return _cnt; }
  const void *Insert(const void *key, const void *val); // A new key-value
  const void *Delete(void *key);                        // Delete & return old
  const void *operator [](const void *key) const;  // Do a lookup
  int operator ==(const Dict &d) const;   // Compare dictionaries for equal
  void print();
  void print(PrintKeyOrValue print_key, PrintKeyOrValue print_value);
};
int hashstr(const void *s);        // Nice string hash
int hashptr(const void *key);
int hashkey(const void *key);
int cmpstr(const void *k1, const void *k2);
int cmpkey(const void *key1, const void *key2);
class DictI {
 private:
  const Dict *_d;               // Dictionary being iterated over
  int _i;                      // Counter over the bins
  int _j;                      // Counter inside each bin
 public:
  const void *_key, *_value;          // Easy access to the key-value pair
  DictI( const Dict *d ) {reset(d);}; // Create a new iterator
  void reset( const Dict *dict );     // Reset existing iterator
  void operator ++(void);             // Increment iterator
  int test(void) { return _i<_d->_size;} // Test for end of iteration
};
#endif // SHARE_VM_ADLC_DICT2_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/filebuff.cpp
#include "adlc.hpp"
using namespace std;
FileBuff::FileBuff( BufferedFile *fptr, ArchDesc& archDesc) : _fp(fptr), _AD(archDesc) {
  _err = fseek(_fp->_fp, 0, SEEK_END);  // Seek to end of file
  if (_err) {
    file_error(SEMERR, 0, "File seek error reading input file");
    exit(1);                    // Exit on seek error
  }
  _filepos = ftell(_fp->_fp);   // Find offset of end of file
  _bufferSize = _filepos + 5;   // Filepos points to last char, so add padding
  _err = fseek(_fp->_fp, 0, SEEK_SET);  // Reset to beginning of file
  if (_err) {
    file_error(SEMERR, 0, "File seek error reading input file\n");
    exit(1);                    // Exit on seek error
  }
  _filepos = ftell(_fp->_fp);      // Reset current file position
  _linenum = 0;
  _bigbuf = new char[_bufferSize]; // Create buffer to hold text for parser
  if( !_bigbuf ) {
    file_error(SEMERR, 0, "Buffer allocation failed\n");
    exit(1);                    // Exit on allocation failure
  }
  _buf = _bigbuf+1;                     // Skip sentinel
  _bufmax = _buf;               // Buffer is empty
  _bufeol = _bigbuf;              // _bufeol points at sentinel
  _filepos = -1;                 // filepos is in sync with _bufeol
  _bufoff = _offset = 0L;       // Offset at file start
  _bufmax += fread(_buf, 1, _bufferSize-2, _fp->_fp); // Fill buffer & set end value
  if (_bufmax == _buf) {
    file_error(SEMERR, 0, "File read error, no input read\n");
    exit(1);                     // Exit on read error
  }
}
FileBuff::~FileBuff() {
  delete _bigbuf;
}
char *FileBuff::get_line(void) {
  char *retval;
  if (_bufeol >= _bufmax) return NULL;
  _linenum++;
  retval = ++_bufeol;      // return character following end of previous line
  if (*retval == '\0') return NULL; // Check for EOF sentinel
  for(_filepos++; *_bufeol != '\n'; _bufeol++)
    _filepos++;                    // keep filepos in sync with _bufeol
  return retval;
}
void FileBuff::file_error(int flag, int linenum, const char *fmt, ...)
{
  va_list args;
  va_start(args, fmt);
  switch (flag) {
  case 0: _AD._warnings += _AD.emit_msg(0, flag, linenum, fmt, args);
  case 1: _AD._syntax_errs += _AD.emit_msg(0, flag, linenum, fmt, args);
  case 2: _AD._semantic_errs += _AD.emit_msg(0, flag, linenum, fmt, args);
  default: assert(0, ""); break;
  }
  va_end(args);
  _AD._no_output = 1;
}
C:\hotspot-69087d08d473\src\share\vm/adlc/filebuff.hpp
#ifndef SHARE_VM_ADLC_FILEBUFF_HPP
#define SHARE_VM_ADLC_FILEBUFF_HPP
#include <iostream>
using namespace std;
class BufferedFile {
 public:
  const char *_name;
  FILE *_fp;
  inline BufferedFile() { _name = NULL; _fp = NULL; };
  inline ~BufferedFile() {};
};
class ArchDesc;
class FileBuff {
 private:
  long  _bufferSize;            // Size of text holding buffer.
  long  _offset;                // Expected filepointer offset.
  long  _bufoff;                // Start of buffer file offset
  char *_buf;                   // The buffer itself.
  char *_bigbuf;                // The buffer plus sentinels; actual heap area
  char *_bufmax;                // A pointer to the buffer end sentinel
  char *_bufeol;                // A pointer to the last complete line end
  int   _err;                   // Error flag for file seek/read operations
  long  _filepos;               // Current offset from start of file
  int   _linenum;
  ArchDesc& _AD;                // Reference to Architecture Description
  void file_error(int flag, int linenum, const char *fmt, ...);
 public:
  const BufferedFile *_fp;           // File to be buffered
  FileBuff(BufferedFile *fp, ArchDesc& archDesc); // Constructor
  ~FileBuff();                  // Destructor
  char *get_line(void);
  int linenum() const { return _linenum; }
  void set_linenum(int line) { _linenum = line; }
  long getoff(const char* s) { return _bufoff + (long)(s - _buf); }
};
#endif // SHARE_VM_ADLC_FILEBUFF_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/forms.cpp
#include "adlc.hpp"
Arena  *Form::arena = Form::generate_arena(); //  = Form::generate_arena();
Arena *Form::generate_arena() {
  return (new Arena);
}
const char  *NameList::_signal   = "$$SIGNAL$$";
const char  *NameList::_signal2  = "$$SIGNAL2$$";
const char  *NameList::_signal3  = "$$SIGNAL3$$";
NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) {
  _names = (const char**)malloc(_max*sizeof(char*));
}
NameList::~NameList() {
}
void   NameList::addName(const char *name) {
  if (_cur == _max) _names =(const char**)realloc(_names,(_max *=2)*sizeof(char*));
  _names[_cur++] = name;
}
void   NameList::add_signal() {
  addName( _signal );
}
void   NameList::clear() {
  _cur   = 0;
  _iter  = 0;
  _justReset = true;
}
int    NameList::count()  const { return _cur; }
void   NameList::reset()   { _iter = 0; _justReset = true;}
const char  *NameList::iter()    {
  if (_justReset) {_justReset=false; return (_iter < _cur ? _names[_iter] : NULL);}
  else return (_iter <_cur-1 ? _names[++_iter] : NULL);
}
const char  *NameList::current() { return (_iter < _cur ? _names[_iter] : NULL); }
const char  *NameList::peek(int skip) { return (_iter + skip < _cur ? _names[_iter + skip] : NULL); }
bool  NameList::current_is_signal() {
  const char *entry = current();
  return is_signal(entry);
}
bool  NameList::is_signal(const char *entry) {
  return ( (strcmp(entry,NameList::_signal) == 0) ? true : false);
}
bool   NameList::search(const char *name) {
  const char *entry;
  for(reset(); (entry = iter()) != NULL; ) {
    if(!strcmp(entry,name)) return true;
  }
  return false;
}
int    NameList::index(const char *name) {
  int         cnt = 0;
  const char *entry;
  for(reset(); (entry = iter()) != NULL; ) {
    if(!strcmp(entry,name)) return cnt;
    cnt++;
  }
  return Not_in_list;
}
const char  *NameList::name(intptr_t  index) {
  return ( index < _cur ? _names[index] : NULL);
}
void   NameList::dump() { output(stderr); }
void   NameList::output(FILE *fp) {
  fprintf(fp, "\n");
  const char *name       = NULL;
  int         iter       = 0;
  bool        justReset  = true;
  while( ( name  = (justReset ?
                    (justReset=false, (iter < _cur ? _names[iter] : NULL)) :
                    (iter < _cur-1 ? _names[++iter] : NULL)) )
         != NULL ) {
    fprintf( fp, "  %s,\n", name);
  }
  fprintf(fp, "\n");
}
NameAndList::NameAndList(char *name) : _name(name) {
}
NameAndList::~NameAndList() {
}
void NameAndList::add_entry(const char *entry) {
  _list.addName(entry);
}
const char *NameAndList::name()  const {  return _name;  }
void        NameAndList::reset()       { _list.reset();  }
const char *NameAndList::iter()        { return _list.iter(); }
const char *NameAndList::operator[](int index) {
  assert( index >= 0, "Internal Error(): index less than 0.");
  _list.reset();
  const char *entry = _list.iter();
  for ( int position = 0; position != index; ++position ) {
    entry = _list.iter();
  }
  return entry;
}
void   NameAndList::dump() { output(stderr); }
void   NameAndList::output(FILE *fp) {
  fprintf(fp, "\n");
  fprintf(fp, "Name == %s", (_name ? _name : "") );
  const char *name;
  fprintf(fp, " (");
  for (reset(); (name = iter()) != NULL;) {
    fprintf(fp, "  %s,\n", name);
  }
  fprintf(fp, ")");
  fprintf(fp, "\n");
}
OpClassForm   *Form::is_opclass()     const {
  return NULL;
}
OperandForm   *Form::is_operand()     const {
  return NULL;
}
InstructForm  *Form::is_instruction() const {
  return NULL;
}
MachNodeForm  *Form::is_machnode() const {
  return NULL;
}
AttributeForm *Form::is_attribute() const {
  return NULL;
}
Effect        *Form::is_effect() const {
  return NULL;
}
ResourceForm  *Form::is_resource() const {
  return NULL;
}
PipeClassForm *Form::is_pipeclass() const {
  return NULL;
}
Form::DataType Form::ideal_to_const_type(const char *name) const {
  if( name == NULL ) { return Form::none; }
  if (strcmp(name,"ConI")==0) return Form::idealI;
  if (strcmp(name,"ConP")==0) return Form::idealP;
  if (strcmp(name,"ConN")==0) return Form::idealN;
  if (strcmp(name,"ConNKlass")==0) return Form::idealNKlass;
  if (strcmp(name,"ConL")==0) return Form::idealL;
  if (strcmp(name,"ConF")==0) return Form::idealF;
  if (strcmp(name,"ConD")==0) return Form::idealD;
  if (strcmp(name,"Bool")==0) return Form::idealI;
  return Form::none;
}
Form::DataType Form::ideal_to_sReg_type(const char *name) const {
  if( name == NULL ) { return Form::none; }
  if (strcmp(name,"sRegI")==0) return Form::idealI;
  if (strcmp(name,"sRegP")==0) return Form::idealP;
  if (strcmp(name,"sRegF")==0) return Form::idealF;
  if (strcmp(name,"sRegD")==0) return Form::idealD;
  if (strcmp(name,"sRegL")==0) return Form::idealL;
  return Form::none;
}
Form::DataType Form::ideal_to_Reg_type(const char *name) const {
  if( name == NULL ) { return Form::none; }
  if (strcmp(name,"RegI")==0) return Form::idealI;
  if (strcmp(name,"RegP")==0) return Form::idealP;
  if (strcmp(name,"RegF")==0) return Form::idealF;
  if (strcmp(name,"RegD")==0) return Form::idealD;
  if (strcmp(name,"RegL")==0) return Form::idealL;
  return Form::none;
}
Form::DataType Form::is_load_from_memory(const char *opType) const {
  if( strcmp(opType,"LoadB")==0 )  return Form::idealB;
  if( strcmp(opType,"LoadUB")==0 )  return Form::idealB;
  if( strcmp(opType,"LoadUS")==0 )  return Form::idealC;
  if( strcmp(opType,"LoadD")==0 )  return Form::idealD;
  if( strcmp(opType,"LoadD_unaligned")==0 )  return Form::idealD;
  if( strcmp(opType,"LoadF")==0 )  return Form::idealF;
  if( strcmp(opType,"LoadI")==0 )  return Form::idealI;
  if( strcmp(opType,"LoadKlass")==0 )  return Form::idealP;
  if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealNKlass;
  if( strcmp(opType,"LoadL")==0 )  return Form::idealL;
  if( strcmp(opType,"LoadL_unaligned")==0 )  return Form::idealL;
  if( strcmp(opType,"LoadPLocked")==0 )  return Form::idealP;
  if( strcmp(opType,"LoadP")==0 )  return Form::idealP;
  if( strcmp(opType,"LoadN")==0 )  return Form::idealN;
  if( strcmp(opType,"LoadRange")==0 )  return Form::idealI;
  if( strcmp(opType,"LoadS")==0 )  return Form::idealS;
  if( strcmp(opType,"LoadVector")==0 )  return Form::idealV;
  assert( strcmp(opType,"Load") != 0, "Must type Loads" );
  return Form::none;
}
Form::DataType Form::is_store_to_memory(const char *opType) const {
  if( strcmp(opType,"StoreB")==0)  return Form::idealB;
  if( strcmp(opType,"StoreCM")==0) return Form::idealB;
  if( strcmp(opType,"StoreC")==0)  return Form::idealC;
  if( strcmp(opType,"StoreD")==0)  return Form::idealD;
  if( strcmp(opType,"StoreF")==0)  return Form::idealF;
  if( strcmp(opType,"StoreI")==0)  return Form::idealI;
  if( strcmp(opType,"StoreL")==0)  return Form::idealL;
  if( strcmp(opType,"StoreP")==0)  return Form::idealP;
  if( strcmp(opType,"StoreN")==0)  return Form::idealN;
  if( strcmp(opType,"StoreNKlass")==0)  return Form::idealNKlass;
  if( strcmp(opType,"StoreVector")==0 )  return Form::idealV;
  assert( strcmp(opType,"Store") != 0, "Must type Stores" );
  return Form::none;
}
Form::InterfaceType Form::interface_type(FormDict &globals) const {
  return Form::no_interface;
}
FormList::~FormList()  {
};
FormDict::FormDict( CmpKey cmp, Hash hash, Arena *arena )
  : _form(cmp, hash, arena) {
}
FormDict::~FormDict() {
}
int FormDict::Size(void) const {
  return _form.Size();
}
const Form  *FormDict::Insert(const char *name, Form *form) {
  return (Form*)_form.Insert((void*)name, (void*)form);
}
const Form  *FormDict::operator [](const char *name) const {
  return (Form*)_form[name];
}
FormDict::FormDict( ) : _form(cmpkey,hashkey) {
  assert( false, "NotImplemented");
}
FormDict::FormDict( const FormDict & fd) : _form(fd._form) {
}
FormDict &FormDict::operator =( const FormDict &rhs) {
  assert( false, "NotImplemented");
  _form = rhs._form;
  return *this;
}
bool FormDict::operator ==(const FormDict &d) const {
  assert( false, "NotImplemented");
  return false;
}
static void dumpkey (const void* key)  { fprintf(stdout, "%s", (char*) key); }
static void dumpform(const void* form) { fflush(stdout); ((Form*)form)->dump(); }
void FormDict::dump() {
  _form.print(dumpkey, dumpform);
}
SourceForm::SourceForm(char* code) : _code(code) { }; // Constructor
SourceForm::~SourceForm() {
}
void SourceForm::dump() {                    // Debug printer
  output(stderr);
}
void SourceForm::output(FILE *fp) {
  fprintf(fp,"\n//%s\n%s\n",classname(),(_code?_code:""));
}
C:\hotspot-69087d08d473\src\share\vm/adlc/forms.hpp
#ifndef SHARE_VM_ADLC_FORMS_HPP
#define SHARE_VM_ADLC_FORMS_HPP
#define TRUE 1
#define FALSE 0
#define INS_ATTR 0
#define OP_ATTR  1
class Form;
class InstructForm;
class MachNodeForm;
class OperandForm;
class OpClassForm;
class AttributeForm;
class RegisterForm;
class PipelineForm;
class SourceForm;
class EncodeForm;
class Component;
class Constraint;
class Predicate;
class MatchRule;
class Attribute;
class Effect;
class ExpandRule;
class RewriteRule;
class ConstructRule;
class FormatRule;
class Peephole;
class EncClass;
class Interface;
class RegInterface;
class ConstInterface;
class MemInterface;
class CondInterface;
class Opcode;
class InsEncode;
class RegDef;
class RegClass;
class CodeSnippetRegClass;
class ConditionalRegClass;
class AllocClass;
class ResourceForm;
class PipeClassForm;
class PeepMatch;
class PeepConstraint;
class PeepReplace;
class MatchList;
class ArchDesc;
class FormDict {
private:
  Dict         _form;              // map names, char*, to their Form* or NULL
  FormDict( );
  FormDict &operator =( const FormDict & );
  bool operator ==(const FormDict &d) const; // Compare dictionaries for equal
public:
  FormDict( CmpKey cmp, Hash hash, Arena *arena );
  FormDict( const FormDict & fd );    // Deep-copy guts
  ~FormDict();
  int Size(void) const;
  const Form  *Insert(const char *name, Form *form); // A new key-value
  const Form  *operator [](const char *name) const;  // Do a lookup
  void dump();
};
class Form {
public:
  static Arena  *arena;            // arena used by forms
private:
  static Arena  *generate_arena(); // allocate arena used by forms
protected:
  int   _ftype;                    // Indicator for derived class type
public:
  Form *_next;                     // Next pointer for form lists
  int   _linenum;                  // Line number for debugging
  virtual OpClassForm   *is_opclass()     const;
  virtual OperandForm   *is_operand()     const;
  virtual InstructForm  *is_instruction() const;
  virtual MachNodeForm  *is_machnode()    const;
  virtual AttributeForm *is_attribute()   const;
  virtual Effect        *is_effect()      const;
  virtual ResourceForm  *is_resource()    const;
  virtual PipeClassForm *is_pipeclass()   const;
  virtual bool           is_cisc_reg(FormDict &globals) const { return false; }
  virtual bool           is_cisc_mem(FormDict &globals) const { return false; }
  Form(int formType=0, int line=0)
    : _next(NULL), _linenum(line), _ftype(formType) { };
  virtual ~Form() {};
  virtual bool ideal_only() const {
    assert(0,"Check of ideal status on non-instruction/operand form.\n");
    return FALSE;
  }
  virtual bool verify()    { return true; }
  virtual void dump()      { output(stderr); }    // Debug printer
  virtual void output(FILE *fp)    { fprintf(fp,"Form Output"); }
public:
  enum DataType {
    none        =  0,  // Not a simple type
    idealI      =  1,  // Integer type
    idealP      =  2,  // Pointer types, oop(s)
    idealL      =  3,  // Long    type
    idealF      =  4,  // Float   type
    idealD      =  5,  // Double  type
    idealB      =  6,  // Byte    type
    idealC      =  7,  // Char    type
    idealS      =  8,  // String  type
    idealN      =  9,  // Narrow oop types
    idealNKlass = 10,  // Narrow klass types
    idealV      = 11   // Vector  type
  };
  Form::DataType  ideal_to_const_type(const char *ideal_type_name) const;
  Form::DataType  ideal_to_sReg_type(const char *name) const;
  Form::DataType  ideal_to_Reg_type(const char *name) const;
  Form::DataType is_load_from_memory(const char *opType) const;
  Form::DataType is_store_to_memory(const char *opType)  const;
  enum CallType {
    invalid_type  =  0,  // invalid call type
    JAVA_STATIC   =  1,  // monomorphic entry
    JAVA_DYNAMIC  =  2,  // possibly megamorphic, inline cache call
    JAVA_COMPILED =  3,  // callee will be compiled java
    JAVA_INTERP   =  4,  // callee will be executed by interpreter
    JAVA_NATIVE   =  5,  // native entrypoint
    JAVA_RUNTIME  =  6,  // runtime entrypoint
    JAVA_LEAF     =  7   // calling leaf
  };
  enum InterfaceType {
    no_interface          =  0,  // unknown or inconsistent interface type
    constant_interface    =  1,  // interface to constants
    register_interface    =  2,  // interface to registers
    memory_interface      =  3,  // interface to memory
    conditional_interface =  4   // interface for condition codes
  };
  virtual Form::InterfaceType interface_type(FormDict &globals) const;
  enum CiscSpillInfo {
    Not_cisc_spillable   =  AdlcVMDeps::Not_cisc_spillable,
    Maybe_cisc_spillable =   0,
    Is_cisc_spillable    =   1
  };
  enum {
    INS,
    OPER,
    OPCLASS,
    SRC,
    ADEF,
    REG,
    PIPE,
    CNST,
    PRED,
    ATTR,
    MAT,
    ENC,
    FOR,
    EXP,
    REW,
    EFF,
    RDEF,
    RCL,
    ACL,
    RES,
    PCL,
    PDEF,
    REGL,
    RESL,
    STAL,
    COMP,
    PEEP,
    RESO
  };
};
class FormList {
private:
  Form *_root;
  Form *_tail;
  Form *_cur;
  int   _justReset;                // Set immediately after reset
  Form *_cur2;                     // Nested iterator
  int   _justReset2;
public:
  void addForm(Form * entry) {
    if (_tail==NULL) { _root = _tail = _cur = entry;}
    else { _tail->_next = entry; _tail = entry;}
  };
  Form * current() { return _cur; };
  Form * iter()    { if (_justReset) _justReset = 0;
                     else if (_cur)  _cur = _cur->_next;
                     return _cur;};
  void   reset()   { if (_root) {_cur = _root; _justReset = 1;} };
  Form * current2(){ return _cur2; };
  Form * iter2()   { if (_justReset2) _justReset2 = 0;
                    else if (_cur2)  _cur2 = _cur2->_next;
                    return _cur2;};
  void   reset2()  { if (_root) {_cur2 = _root; _justReset2 = 1;} };
  int  count() {
    int  count = 0; reset();
    for( Form *cur; (cur =  iter()) != NULL; ) { ++count; };
    return count;
  }
  void dump() {
    reset();
    Form *cur;
    for(; (cur =  iter()) != NULL; ) {
      cur->dump();
    };
  }
  bool verify() {
    bool verified = true;
    reset();
    Form *cur;
    for(; (cur =  iter()) != NULL; ) {
      if ( ! cur->verify() ) verified = false;
    };
    return verified;
  }
  void output(FILE* fp) {
    reset();
    Form *cur;
    for( ; (cur =  iter()) != NULL; ) {
      cur->output(fp);
    };
  }
  FormList() { _justReset = 1; _justReset2 = 1; _root = NULL; _tail = NULL; _cur = NULL; _cur2 = NULL;};
  ~FormList();
};
class NameList {
  friend class PreserveIter;
private:
  int                _cur;         // Insert next entry here; count of entries
  int                _max;         // Number of spaces allocated
  const char       **_names;       // Array of names
protected:
  int                _iter;        // position during iteration
  bool               _justReset;   // Set immediately after reset
public:
  static const char *_signal;      // reserved user-defined string
  static const char *_signal2;      // reserved user-defined string
  static const char *_signal3;      // reserved user-defined string
  enum               { Not_in_list = -1 };
  void  addName(const char *name);
  void  add_signal();
  void  clear();                   // Remove all entries
  int   count() const;
  void  reset();                   // Reset iteration
  const char *iter();              // after reset(), first element : else next
  const char *current();           // return current element in iteration.
  const char *peek(int skip = 1);  // returns element + skip in iteration if there is one
  bool  current_is_signal();       // Return 'true' if current entry is signal
  bool  is_signal(const char *entry); // Return true if entry is a signal
  bool  search(const char *);      // Search for a name in the list
  int   index(const char *);       // Return index of name in list
  const char *name (intptr_t index);// Return name at index in list
  void  dump();                    // output to stderr
  void  output(FILE *fp);          // Output list of names to 'fp'
  NameList();
  ~NameList();
};
class PreserveIter {
 private:
  NameList* _list;
  int _iter;
  bool _justReset;
 public:
  PreserveIter(NameList* nl) {
    _list = nl;
    _iter = _list->_iter;
    _justReset = _list->_justReset;
  }
  ~PreserveIter() {
    _list->_iter = _iter;
    _list->_justReset = _justReset;
  }
};
class NameAndList {
private:
  const char *_name;
  NameList    _list;
public:
  NameAndList(char *name);
  ~NameAndList();
  void        add_entry(const char *entry);
  const char *name() const;
  void        reset();
  const char *iter();
  int count() { return _list.count(); }
  const char *operator[](int index);
  void  dump();                    // output to stderr
  void  output(FILE *fp);          // Output list of names to 'fp'
};
class ComponentList : private NameList {
private:
  int   _matchcnt;                 // Count of match rule operands
public:
  void operator delete( void *ptr ) {}
  void insert(Component *component, bool mflag);
  void insert(const char *name, const char *opType, int usedef, bool mflag);
  int  count();
  int  match_count() { return _matchcnt; } // Get count of match rule opers
  Component *iter();               // after reset(), first element : else next
  Component *match_iter();         // after reset(), first element : else next
  Component *post_match_iter();    // after reset(), first element : else next
  void       reset();              // Reset iteration
  Component *current();            // return current element in iteration.
  Component *operator[](int position);
  Component *at(int position) { return (*this)[position]; }
  const Component *search(const char *name);
  int        num_operands();
  int        operand_position(const char *name, int usedef, Form *fm);
  int        operand_position(const char *name);
  int        operand_position_format(const char *name, Form *fm);
  int        label_position();
  int        method_position();
  void       dump();               // output to stderr
  void       output(FILE *fp);     // Output list of names to 'fp'
  ComponentList();
  ~ComponentList();
};
class SourceForm : public Form {
private:
public:
  char *_code;                     // Buffer for storing code text
  SourceForm(char* code);
  ~SourceForm();
  virtual const char* classname() { return "SourceForm"; }
  void dump();                    // Debug printer
  void output(FILE *fp);          // Write output files
};
class HeaderForm : public SourceForm {
public:
  HeaderForm(char* code) : SourceForm(code) { }
  virtual const char* classname() { return "HeaderForm"; }
};
class PreHeaderForm : public SourceForm {
public:
  PreHeaderForm(char* code) : SourceForm(code) { }
  virtual const char* classname() { return "PreHeaderForm"; }
};
#define STRING_BUFFER_LENGTH  2048
class Expr {
public:
  enum {
    Zero     = 0,
    Max      = 0x7fffffff
  };
  const char *_external_name;  // if !NULL, then print this instead of _expr
  const char *_expr;
  int         _min_value;
  int         _max_value;
  Expr();
  Expr(const char *cost);
  Expr(const char *name, const char *expression, int min_value, int max_value);
  Expr *clone() const;
  bool  is_unknown() const { return (this == Expr::get_unknown()); }
  bool  is_zero()    const { return (_min_value == Expr::Zero && _max_value == Expr::Zero); }
  bool  less_than_or_equal(const Expr *c) const { return (_max_value <= c->_min_value); }
  void  add(const Expr *c);
  void  add(const char *c);
  void  add(const char *c, ArchDesc &AD);   // check if 'c' is defined in <arch>.ad
  void  set_external_name(const char *name) { _external_name = name; }
  const char *as_string()  const { return (_external_name != NULL ? _external_name : _expr); }
  void  print()            const;
  void  print_define(FILE *fp) const;
  void  print_assert(FILE *fp) const;
  static Expr *get_unknown();   // Returns pointer to shared unknown cost instance
  static char *buffer()         { return &external_buffer[0]; }
  static bool  init_buffers();  // Fill buffers with 0
  static bool  check_buffers(); // if buffer use may have overflowed, assert
private:
  static Expr *_unknown_expr;
  static char string_buffer[STRING_BUFFER_LENGTH];
  static char external_buffer[STRING_BUFFER_LENGTH];
  static bool _init_buffers;
  const char *compute_expr(const Expr *c1, const Expr *c2);  // cost as string after adding 'c1' and 'c2'
  int         compute_min (const Expr *c1, const Expr *c2);  // minimum after adding 'c1' and 'c2'
  int         compute_max (const Expr *c1, const Expr *c2);  // maximum after adding 'c1' and 'c2'
  const char *compute_external(const Expr *c1, const Expr *c2);  // external name after adding 'c1' and 'c2'
};
class ExprDict {
private:
  Dict         _expr;              // map names, char*, to their Expr* or NULL
  NameList     _defines;           // record the order of definitions entered with define call
  ExprDict( );
  ExprDict( const ExprDict & );    // Deep-copy guts
  ExprDict &operator =( const ExprDict & );
  bool operator ==(const ExprDict &d) const; // Compare dictionaries for equal
public:
  ExprDict( CmpKey cmp, Hash hash, Arena *arena );
  ~ExprDict();
  int Size(void) const;
  const Expr  *define(const char *name, Expr *expr);
  const Expr  *Insert(const char *name, Expr *expr); // A new key-value
  const Expr  *operator [](const char *name) const;  // Do a lookup
  void print_defines(FILE *fp);
  void print_asserts(FILE *fp);
  void dump();
};
#endif // SHARE_VM_ADLC_FORMS_HPP
C:\hotspot-69087d08d473\src\share\vm/adlc/formsopt.cpp
#include "adlc.hpp"
int RegisterForm::_reg_ctr = 0;
RegisterForm::RegisterForm()
  : _regDef(cmpstr,hashstr, Form::arena),
    _regClass(cmpstr,hashstr, Form::arena),
    _allocClass(cmpstr,hashstr, Form::arena) {
}
RegisterForm::~RegisterForm() {
}
void RegisterForm::addRegDef(char *name, char *callingConv, char *c_conv,
                             char *idealtype, char *encoding, char* concrete) {
  RegDef *regDef = new RegDef(name, callingConv, c_conv, idealtype, encoding, concrete);
  _rdefs.addName(name);
  _regDef.Insert(name,regDef);
}
template <typename T>
T* RegisterForm::addRegClass(const char* className) {
  T* regClass = new T(className);
  _rclasses.addName(className);
  _regClass.Insert(className, regClass);
  return regClass;
}
template RegClass* RegisterForm::addRegClass<RegClass>(const char* className);
template CodeSnippetRegClass* RegisterForm::addRegClass<CodeSnippetRegClass>(const char* className);
template ConditionalRegClass* RegisterForm::addRegClass<ConditionalRegClass>(const char* className);
AllocClass *RegisterForm::addAllocClass(char *className) {
  AllocClass *allocClass = new AllocClass(className);
  _aclasses.addName(className);
  _allocClass.Insert(className,allocClass);
  return allocClass;
}
void RegisterForm::addSpillRegClass() {
  _reg_ctr = (_reg_ctr+7) & ~7;
  const char *rc_name = "stack_slots";
  RegClass* reg_class = new RegClass(rc_name);
  reg_class->set_stack_version(true);
  _rclasses.addName(rc_name);
  _regClass.Insert(rc_name,reg_class);
}
void        RegisterForm::reset_RegDefs() {
  _current_ac = NULL;
  _aclasses.reset();
}
RegDef     *RegisterForm::iter_RegDefs() {
  if ( _current_ac == NULL ) {
    const char *ac_name = _aclasses.iter();
    if( ac_name == NULL )   return NULL;   // No more allocation classes
    _current_ac = (AllocClass*)_allocClass[ac_name];
    _current_ac->_regDefs.reset();
    assert( _current_ac != NULL, "Name must match an allocation class");
  }
  const char *rd_name = _current_ac->_regDefs.iter();
  if( rd_name == NULL ) {
    _current_ac = NULL;
    return iter_RegDefs();
  }
  RegDef *reg_def = (RegDef*)_current_ac->_regDef[rd_name];
  assert( reg_def != NULL, "Name must match a register definition");
  return reg_def;
}
RegDef *RegisterForm::getRegDef(const char *regName) {
  RegDef *regDef = (RegDef*)_regDef[regName];
  return  regDef;
}
RegClass *RegisterForm::getRegClass(const char *className) {
  RegClass *regClass = (RegClass*)_regClass[className];
  return    regClass;
}
bool   RegisterForm::verify() {
  bool valid = true;
  const char *rc_name = NULL;
  _rclasses.reset();
  while ( (rc_name = _rclasses.iter()) != NULL ) {
    RegClass *reg_class = getRegClass(rc_name);
    assert( reg_class != NULL, "InternalError() no matching register class");
  } // end of RegClasses
  RegDef *reg_def = NULL;
  reset_RegDefs();
  uint  num_register_zero = 0;
  while ( (reg_def = iter_RegDefs()) != NULL ) {
    if( reg_def->register_num() == 0 )  ++num_register_zero;
  }
  if( num_register_zero > 1 ) {
    fprintf(stderr,
            "ERROR: More than one register has been assigned register-number 0.\n"
            "Probably because a register has not been entered into an allocation class.\n");
  }
  return  valid;
}
int RegisterForm::RegMask_Size() {
  int words_for_regs = (_reg_ctr + 31)>>5;
  return (words_for_regs + 3 + 1) & ~1;
}
void RegisterForm::dump() {                  // Debug printer
  output(stderr);
}
void RegisterForm::output(FILE *fp) {          // Write info to output files
  const char *name;
  fprintf(fp,"\n");
  fprintf(fp,"-------------------- Dump RegisterForm --------------------\n");
  for(_rdefs.reset(); (name = _rdefs.iter()) != NULL;) {
    ((RegDef*)_regDef[name])->output(fp);
  }
  fprintf(fp,"\n");
  for (_rclasses.reset(); (name = _rclasses.iter()) != NULL;) {
    ((RegClass*)_regClass[name])->output(fp);
  }
  fprintf(fp,"\n");
  for (_aclasses.reset(); (name = _aclasses.iter()) != NULL;) {
    ((AllocClass*)_allocClass[name])->output(fp);
  }
  fprintf(fp,"-------------------- end  RegisterForm --------------------\n");
}
RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, char * encode, char * concrete)
  : _regname(regname), _callconv(callconv), _c_conv(c_conv),
    _idealtype(idealtype),
    _register_encode(encode),
    _concrete(concrete),
    _register_num(0) {
}
RegDef::~RegDef() {                      // Destructor
}
void RegDef::set_register_num(uint32 register_num) {
  _register_num      = register_num;
}
const char* RegDef::register_encode() const {
  return _register_encode;
}
uint32 RegDef::register_num()    const {
  return _register_num;
}
void RegDef::dump() {
  output(stderr);
}
void RegDef::output(FILE *fp) {         // Write info to output files
  fprintf(fp,"RegDef: %s (%s) encode as %s  using number %d\n",
          _regname, (_callconv?_callconv:""), _register_encode, _register_num);
  fprintf(fp,"\n");
}
RegClass::RegClass(const char* classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr, hashstr, Form::arena) {
}
RegClass::~RegClass() {
  delete _classid;
}
void RegClass::addReg(RegDef *regDef) {
  _regDefs.addName(regDef->_regname);
  _regDef.Insert((void*)regDef->_regname, regDef);
}
uint RegClass::size() const {
  return _regDef.Size();
}
const RegDef *RegClass::get_RegDef(const char *rd_name) const {
  return  (const RegDef*)_regDef[rd_name];
}
void RegClass::reset() {
  _regDefs.reset();
}
const char *RegClass::rd_name_iter() {
  return _regDefs.iter();
}
RegDef *RegClass::RegDef_iter() {
  const char *rd_name  = rd_name_iter();
  RegDef     *reg_def  = rd_name ? (RegDef*)_regDef[rd_name] : NULL;
  return      reg_def;
}
const RegDef* RegClass::find_first_elem() {
  const RegDef* first = NULL;
  const RegDef* def = NULL;
  reset();
  while ((def = RegDef_iter()) != NULL) {
    if (first == NULL || def->register_num() < first->register_num()) {
      first = def;
    }
  }
  assert(first != NULL, "empty mask?");
  return first;;
}
int RegClass::regs_in_word( int wordnum, bool stack_also ) {
  int         word = 0;
  const char *name;
  for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) {
    int rnum = ((RegDef*)_regDef[name])->register_num();
    if( (rnum >> 5) == wordnum )
      word |= (1 << (rnum & 31));
  }
  if( stack_also ) {
    for( int i = 0; i < 32; i++ )
      if( wordnum*32+i >= RegisterForm::_reg_ctr )
        word |= (1 << i);
  }
  return word;
}
void RegClass::dump() {
  output(stderr);
}
void RegClass::output(FILE *fp) {           // Write info to output files
  fprintf(fp,"RegClass: %s\n",_classid);
  const char *name;
  for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) {
    ((RegDef*)_regDef[name])->output(fp);
  }
  fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid);
}
void RegClass::declare_register_masks(FILE* fp) {
  const char* prefix = "";
  const char* rc_name_to_upper = toUpper(_classid);
  fprintf(fp, "extern const RegMask _%s%s_mask;\n", prefix,  rc_name_to_upper);
  fprintf(fp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
  if (_stack_or_reg) {
    fprintf(fp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper);
    fprintf(fp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
  }
  delete[] rc_name_to_upper;
}
void RegClass::build_register_masks(FILE* fp) {
  int len = RegisterForm::RegMask_Size();
  const char *prefix = "";
  const char* rc_name_to_upper = toUpper(_classid);
  fprintf(fp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper);
  int i;
  for(i = 0; i < len - 1; i++) {
    fprintf(fp," 0x%x,", regs_in_word(i, false));
  }
  fprintf(fp," 0x%x );\n", regs_in_word(i, false));
  if (_stack_or_reg) {
    fprintf(fp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper);
    for(i = 0; i < len - 1; i++) {
      fprintf(fp," 0x%x,", regs_in_word(i, true));
    }
    fprintf(fp," 0x%x );\n", regs_in_word(i, true));
  }
  delete[] rc_name_to_upper;
}
CodeSnippetRegClass::CodeSnippetRegClass(const char* classid) : RegClass(classid), _code_snippet(NULL) {
}
CodeSnippetRegClass::~CodeSnippetRegClass() {
  delete _code_snippet;
}
void CodeSnippetRegClass::declare_register_masks(FILE* fp) {
  const char* prefix = "";
  const char* rc_name_to_upper = toUpper(_classid);
  fprintf(fp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, _code_snippet);
  delete[] rc_name_to_upper;
}
ConditionalRegClass::ConditionalRegClass(const char *classid) : RegClass(classid), _condition_code(NULL) {
}
ConditionalRegClass::~ConditionalRegClass() {
  delete _condition_code;
}
void ConditionalRegClass::declare_register_masks(FILE* fp) {
  const char* prefix = "";
  const char* rc_name_to_upper = toUpper(_classid);
  const char* rclass_0_to_upper = toUpper(_rclasses[0]->_classid);
  const char* rclass_1_to_upper = toUpper(_rclasses[1]->_classid);
  fprintf(fp, "inline const RegMask &%s%s_mask() {"
              " return (%s) ?"
              " %s%s_mask() :"
              " %s%s_mask(); }\n",
              prefix, rc_name_to_upper,
              _condition_code,
              prefix, rclass_0_to_upper,
              prefix, rclass_1_to_upper);
  if (_stack_or_reg) {
    fprintf(fp, "inline const RegMask &%sSTACK_OR_%s_mask() {"
                  " return (%s) ?"
                  " %sSTACK_OR_%s_mask() :"
                  " %sSTACK_OR_%s_mask(); }\n",
                  prefix, rc_name_to_upper,
                  _condition_code,
                  prefix, rclass_0_to_upper,
                  prefix, rclass_1_to_upper);
  }
  delete[] rc_name_to_upper;
  delete[] rclass_0_to_upper;
  delete[] rclass_1_to_upper;
  return;
}
AllocClass::AllocClass(char *classid) : _classid(classid), _regDef(cmpstr,hashstr, Form::arena) {
}
void AllocClass::addReg(RegDef *regDef) {
  assert( regDef != NULL, "Can not add a NULL to an allocation class");
  regDef->set_register_num( RegisterForm::_reg_ctr++ );
  _regDefs.addName(regDef->_regname);
  _regDef.Insert((void*)regDef->_regname, regDef);
}
void AllocClass::dump() {
  output(stderr);
}
void AllocClass::output(FILE *fp) {       // Write info to output files
  fprintf(fp,"AllocClass: %s \n",_classid);
  const char *name;
  for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) {
    ((RegDef*)_regDef[name])->output(fp);
  }
  fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid);
}
FrameForm::FrameForm() {
  _frame_pointer = NULL;
  _c_frame_pointer = NULL;
  _alignment = NULL;
  _return_addr = NULL;
  _c_return_addr = NULL;
  _in_preserve_slots = NULL;
  _varargs_C_out_slots_killed = NULL;
  _calling_convention = NULL;
  _c_calling_convention = NULL;
  _return_value = NULL;
  _c_return_value = NULL;
  _interpreter_frame_pointer_reg = NULL;
}
FrameForm::~FrameForm() {
}
void FrameForm::dump() {
  output(stderr);
}
void FrameForm::output(FILE *fp) {           // Write info to output files
  fprintf(fp,"\nFrame:\n");
}
PipelineForm::PipelineForm()
  :  _reslist               ()
  ,  _resdict               (cmpstr, hashstr, Form::arena)
  ,  _classdict             (cmpstr, hashstr, Form::arena)
  ,  _rescount              (0)
  ,  _maxcycleused          (0)
  ,  _stages                ()
  ,  _stagecnt              (0)
  ,  _classlist             ()
  ,  _classcnt              (0)
  ,  _noplist               ()
  ,  _nopcnt                (0)
  ,  _variableSizeInstrs    (false)
  ,  _branchHasDelaySlot    (false)
  ,  _maxInstrsPerBundle    (0)
  ,  _maxBundlesPerCycle    (1)
  ,  _instrUnitSize         (0)
  ,  _bundleUnitSize        (0)
  ,  _instrFetchUnitSize    (0)
  ,  _instrFetchUnits       (0) {
}
PipelineForm::~PipelineForm() {
}
void PipelineForm::dump() {
  output(stderr);
}
void PipelineForm::output(FILE *fp) {           // Write info to output files
  const char *res;
  const char *stage;
  const char *cls;
  const char *nop;
  int count = 0;
  fprintf(fp,"\nPipeline:");
  if (_variableSizeInstrs)
    if (_instrUnitSize > 0)
      fprintf(fp," variable-sized instructions in %d byte units", _instrUnitSize);
    else
      fprintf(fp," variable-sized instructions");
  else
    if (_instrUnitSize > 0)
      fprintf(fp," fixed-sized instructions of %d bytes", _instrUnitSize);
    else if (_bundleUnitSize > 0)
      fprintf(fp," fixed-sized bundles of %d bytes", _bundleUnitSize);
    else
      fprintf(fp," fixed-sized instructions");
  if (_branchHasDelaySlot)
    fprintf(fp,", branch has delay slot");
  if (_maxInstrsPerBundle > 0)
    fprintf(fp,", max of %d instruction%s in parallel",
      _maxInstrsPerBundle, _maxInstrsPerBundle > 1 ? "s" : "");
  if (_maxBundlesPerCycle > 0)
    fprintf(fp,", max of %d bundle%s in parallel",
      _maxBundlesPerCycle, _maxBundlesPerCycle > 1 ? "s" : "");
  if (_instrFetchUnitSize > 0 && _instrFetchUnits)
    fprintf(fp, ", fetch %d x % d bytes per cycle", _instrFetchUnits, _instrFetchUnitSize);
  fprintf(fp,"\nResource:");
  for ( _reslist.reset(); (res = _reslist.iter()) != NULL; )
    fprintf(fp," %s(0x%08x)", res, _resdict[res]->is_resource()->mask());
  fprintf(fp,"\n");
  fprintf(fp,"\nDescription:\n");
  for ( _stages.reset(); (stage = _stages.iter()) != NULL; )
    fprintf(fp," %s(%d)", stage, count++);
  fprintf(fp,"\n");
  fprintf(fp,"\nClasses:\n");
  for ( _classlist.reset(); (cls = _classlist.iter()) != NULL; )
    _classdict[cls]->is_pipeclass()->output(fp);
  fprintf(fp,"\nNop Instructions:");
  for ( _noplist.reset(); (nop = _noplist.iter()) != NULL; )
    fprintf(fp, " \"%s\"", nop);
  fprintf(fp,"\n");
}
ResourceForm::ResourceForm(unsigned resmask)
: _resmask(resmask) {
}
ResourceForm::~ResourceForm() {
}
ResourceForm  *ResourceForm::is_resource() const {
  return (ResourceForm *)(this);
}
void ResourceForm::dump() {
  output(stderr);
}
void ResourceForm::output(FILE *fp) {          // Write info to output files
  fprintf(fp, "resource: 0x%08x;\n", mask());
}
void PipeClassOperandForm::dump() {
  output(stderr);
}
void PipeClassOperandForm::output(FILE *fp) {         // Write info to output files
  fprintf(stderr,"PipeClassOperandForm: %s", _stage);
  fflush(stderr);
  if (_more_instrs > 0)
    fprintf(stderr,"+%d", _more_instrs);
  fprintf(stderr," (%s)\n", _iswrite ? "write" : "read");
  fflush(stderr);
  fprintf(fp,"PipeClassOperandForm: %s", _stage);
  if (_more_instrs > 0)
    fprintf(fp,"+%d", _more_instrs);
  fprintf(fp," (%s)\n", _iswrite ? "write" : "read");
}
void PipeClassResourceForm::dump() {
  output(stderr);
}
void PipeClassResourceForm::output(FILE *fp) {         // Write info to output files
  fprintf(fp,"PipeClassResourceForm: %s at stage %s for %d cycles\n",
     _resource, _stage, _cycles);
}
PipeClassForm::PipeClassForm(const char *id, int num)
  : _ident(id)
  , _num(num)
  , _localNames(cmpstr, hashstr, Form::arena)
  , _localUsage(cmpstr, hashstr, Form::arena)
  , _has_fixed_latency(0)
  , _fixed_latency(0)
  , _instruction_count(0)
  , _has_multiple_bundles(false)
  , _has_branch_delay_slot(false)
  , _force_serialization(false)
  , _may_have_no_code(false) {
}
PipeClassForm::~PipeClassForm() {
}
PipeClassForm  *PipeClassForm::is_pipeclass() const {
  return (PipeClassForm *)(this);
}
void PipeClassForm::dump() {
  output(stderr);
}
void PipeClassForm::output(FILE *fp) {         // Write info to output files
  fprintf(fp,"PipeClassForm: #%03d", _num);
  if (_ident)
     fprintf(fp," \"%s\":", _ident);
  if (_has_fixed_latency)
     fprintf(fp," latency %d", _fixed_latency);
  if (_force_serialization)
     fprintf(fp, ", force serialization");
  if (_may_have_no_code)
     fprintf(fp, ", may have no code");
  fprintf(fp, ", %d instruction%s\n", InstructionCount(), InstructionCount() != 1 ? "s" : "");
}
int Peephole::_peephole_counter = 0;
Peephole::Peephole() : _match(NULL), _constraint(NULL), _replace(NULL), _next(NULL) {
  _peephole_number = _peephole_counter++;
}
Peephole::~Peephole() {
}
void Peephole::append_peephole(Peephole *next_peephole) {
  if( _next == NULL ) {
    _next = next_peephole;
  } else {
    _next->append_peephole( next_peephole );
  }
}
void Peephole::add_match(PeepMatch *match) {
  assert( _match == NULL, "fatal()" );
  _match = match;
}
void Peephole::append_constraint(PeepConstraint *next_constraint) {
  if( _constraint == NULL ) {
    _constraint = next_constraint;
  } else {
    _constraint->append( next_constraint );
  }
}
void Peephole::add_replace(PeepReplace *replace) {
  assert( _replace == NULL, "fatal()" );
  _replace = replace;
}
void Peephole::dump() {
  output(stderr);
}
void Peephole::output(FILE *fp) {         // Write info to output files
  fprintf(fp,"Peephole:\n");
  if( _match != NULL )       _match->output(fp);
  if( _constraint != NULL )  _constraint->output(fp);
  if( _replace != NULL )     _replace->output(fp);
  if( _next ) _next->output(fp);
}
PeepMatch::PeepMatch(char *rule) : _max_position(0), _rule(rule) {
}
PeepMatch::~PeepMatch() {
}
void  PeepMatch::add_instruction(int parent, int position, const char *name,
                                 int input) {
  if( position > _max_position ) _max_position = position;
  _parent.addName((char*) (intptr_t) parent);
  _position.addName((char*) (intptr_t) position);
  _instrs.addName(name);
  _input.addName((char*) (intptr_t) input);
}
int   PeepMatch::max_position() {
  return _max_position;
}
const char *PeepMatch::instruction_name(int position) {
  return _instrs.name(position);
}
void  PeepMatch::reset() {
  _parent.reset();
  _position.reset();
  _instrs.reset();
  _input.reset();
}
void  PeepMatch::next_instruction(int &parent, int &position, const char* &name, int &input) {
  parent   = (int) (intptr_t) _parent.iter();
  position = (int) (intptr_t) _position.iter();
  name     = _instrs.iter();
  input    = (int) (intptr_t) _input.iter();
}
bool  PeepMatch::is_placeholder() {
  return _instrs.current_is_signal();
}
void PeepMatch::dump() {
  output(stderr);
}
void PeepMatch::output(FILE *fp) {        // Write info to output files
  fprintf(fp,"PeepMatch:\n");
}
PeepConstraint::PeepConstraint(int left_inst,  char* left_op, char* relation,
                               int right_inst, char* right_op)
  : _left_inst(left_inst), _left_op(left_op), _relation(relation),
    _right_inst(right_inst), _right_op(right_op), _next(NULL) {}
PeepConstraint::~PeepConstraint() {
}
bool PeepConstraint::constrains_instruction(int position) {
  if( _left_inst  == position ) return true;
  if( _right_inst == position ) return true;
  if( _next == NULL )  return false;
  else                 return _next->constrains_instruction(position);
}
void PeepConstraint::append(PeepConstraint *next_constraint) {
  if( _next == NULL ) {
    _next = next_constraint;
  } else {
    _next->append( next_constraint );
  }
}
PeepConstraint *PeepConstraint::next() {
  return _next;
}
void PeepConstraint::dump() {
  output(stderr);
}
void PeepConstraint::output(FILE *fp) {   // Write info to output files
  fprintf(fp,"PeepConstraint:\n");
}
PeepReplace::PeepReplace(char *rule) : _rule(rule) {
}
PeepReplace::~PeepReplace() {
}
void  PeepReplace::add_instruction(char *root) {
  _instruction.addName(root);
  _operand_inst_num.add_signal();
  _operand_op_name.add_signal();
}
void  PeepReplace::add_operand( int inst_num, char *inst_operand ) {
  _instruction.add_signal();
  _operand_inst_num.addName((char*) (intptr_t) inst_num);
  _operand_op_name.addName(inst_operand);
}
void  PeepReplace::reset() {
  _instruction.reset();
  _operand_inst_num.reset();
  _operand_op_name.reset();
}
void  PeepReplace::next_instruction(const char* &inst){
  inst                     = _instruction.iter();
  int         inst_num     = (int) (intptr_t) _operand_inst_num.iter();
  const char* inst_operand = _operand_op_name.iter();
}
void  PeepReplace::next_operand(int &inst_num, const char* &inst_operand) {
  const char* inst = _instruction.iter();
  inst_num         = (int) (intptr_t) _operand_inst_num.iter();
  inst_operand     = _operand_op_name.iter();
}
void PeepReplace::dump() {
  output(stderr);
}
void PeepReplace::output(FILE *fp) {      // Write info to output files
  fprintf(fp,"PeepReplace:\n");
}
C:\hotspot-69087d08d473\src\share\vm/adlc/formsopt.hpp
#ifndef SHARE_VM_ADLC_FORMSOPT_HPP
#define SHARE_VM_ADLC_FORMSOPT_HPP
class Form;
class InstructForm;
class OperandForm;
class OpClassForm;
class AttributeForm;
class RegisterForm;
class PipelineForm;
class SourceForm;
class EncodeForm;
class Component;
class Constraint;
class Predicate;
class MatchRule;
class Attribute;
class Effect;
class ExpandRule;
class RewriteRule;
class ConstructRule;
class FormatRule;
class Peephole;
class PeepMatch;
class PeepConstraint;
class EncClass;
class Interface;
class RegInterface;
class ConstInterface;
class MemInterface;
class CondInterface;
class Opcode;
class InsEncode;
class RegDef;
class RegClass;
class CodeSnippetRegClass;
class ConditionalRegClass;
class AllocClass;
class ResourceForm;
class PipeClassForm;
class PipeClassOperandForm;
class PipeClassResourceForm;
class PeepMatch;
class PeepConstraint;
class PeepReplace;
class MatchList;
class ArchDesc;
class RegisterForm : public Form {
private:
  AllocClass *_current_ac;         // State used by iter_RegDefs()
public:
  NameList    _rdefs;              // List of register definition names
  Dict        _regDef;             // map register name to RegDef*
  NameList    _rclasses;           // List of register class names
  Dict        _regClass;           // map register class name to RegClass*
  NameList    _aclasses;           // List of allocation class names
  Dict        _allocClass;         // Dictionary of allocation classes
  static int  _reg_ctr;         // Register counter
  static int  RegMask_Size();   // Compute RegMask size
  RegisterForm();
  ~RegisterForm();
  void        addRegDef(char *regName, char *callingConv, char *c_conv,
                        char * idealtype, char *encoding, char* concreteName);
  template<typename T> T* addRegClass(const char* className);
  AllocClass *addAllocClass(char *allocName);
  void        addSpillRegClass();
  void        reset_RegDefs();
  RegDef     *iter_RegDefs();
  RegDef     *getRegDef  (const char *regName);
  RegClass   *getRegClass(const char *className);
  uint       reg_mask(char *register_class);
  bool       verify();
  void dump();                     // Debug printer
  void output(FILE *fp);           // Write info to output files
};
class RegDef : public Form {
public:
  const char *_regname;            // ADLC (Opto) Register name
  const char *_callconv;           // Calling convention
  const char *_c_conv;             // Native calling convention, 'C'
  const char *_idealtype;          // Ideal Type for register save/restore
  const char *_concrete;           // concrete register name
private:
  const char *_register_encode;   // The register encoding
  uint32      _register_num;      // Which register am I
public:
  RegDef(char  *regname, char *callconv, char *c_conv,
         char *idealtype, char *encoding, char *concrete);
  ~RegDef();                       // Destructor
  void     set_register_num(uint32 new_register_num);
  const char *register_encode()   const;
  uint32   register_num()      const;
  void dump();                     // Debug printer
  void output(FILE *fp);           // Write info to output files
};
class RegClass : public Form {
public:
  const char *_classid;         // Name of class
  NameList    _regDefs;         // List of registers in class
  Dict        _regDef;          // Dictionary of registers in class
protected:
  bool        _stack_or_reg;    // Allowed on any stack slot
public:
  RegClass(const char *classid);// Constructor
  virtual ~RegClass();
  void addReg(RegDef *regDef);  // Add a register to this class
  uint size() const;            // Number of registers in class
  int regs_in_word( int wordnum, bool stack_also );
  const RegDef *get_RegDef(const char *regDef_name) const;
  const RegDef* find_first_elem();
  void          reset();        // Reset the following two iterators
  RegDef       *RegDef_iter();  // which move jointly,
  const char   *rd_name_iter(); // invoking either advances both.
  void dump();                  // Debug printer
  void output(FILE *fp);        // Write info to output files
  virtual bool has_stack_version() {
    return _stack_or_reg;
  }
  virtual void set_stack_version(bool flag) {
    _stack_or_reg = flag;
  }
  virtual void declare_register_masks(FILE* fp);
  virtual void build_register_masks(FILE* fp);
};
class CodeSnippetRegClass : public RegClass {
protected:
  char* _code_snippet;
public:
  CodeSnippetRegClass(const char* classid);// Constructor
  ~CodeSnippetRegClass();
  void set_code_snippet(char* code) {
    _code_snippet = code;
  }
  char* code_snippet() {
    return _code_snippet;
  }
  void set_stack_version(bool flag) {
    assert(false, "User defined register classes are not allowed to spill to the stack.");
  }
  void declare_register_masks(FILE* fp);
  void build_register_masks(FILE* fp) {
    return;
  }
};
class ConditionalRegClass : public RegClass {
protected:
  char* _condition_code;  // C++ condition code to dynamically determine which register class to use.
  RegClass* _rclasses[2]; // 0 is the register class selected if the condition code returns true
public:
  ConditionalRegClass(const char* classid);// Constructor
  ~ConditionalRegClass();
  virtual void set_stack_version(bool flag) {
    RegClass::set_stack_version(flag);
    assert((_rclasses[0] != NULL), "Register class NULL for condition code == true");
    assert((_rclasses[1] != NULL), "Register class NULL for condition code == false");
    _rclasses[0]->set_stack_version(flag);
    _rclasses[1]->set_stack_version(flag);
  }
  void declare_register_masks(FILE* fp);
  void build_register_masks(FILE* fp) {
    return;
  }
  void set_rclass_at_index(int index, RegClass* rclass) {
    assert((0 <= index && index < 2), "Condition code can select only between two register classes");
    _rclasses[index] = rclass;
  }
  void set_condition_code(char* code) {
    _condition_code = code;
  }
  char* condition_code() {
    return _condition_code;
  }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值