src/share/vm/adlc/adlparse.cpp

Print this page
rev 5661 : 8003854: PPC64 (part 115): Introduce lateExpand that expands nodes after register allocation.

@@ -218,10 +218,12 @@
     }
     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);
+    // Parse late expand keyword.
+    else if (!strcmp(ident, "lateExpand"))     lateExpand_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();

@@ -238,11 +240,11 @@
     else if (!strcmp(ident, "ins_pipe"))        ins_pipe_parse(*instr);
     else {  // Done with staticly defined parts of instruction definition
       // Check identifier to see if it is the name of an attribute
       const Form    *form = _globalNames[ident];
       AttributeForm *attr = form ? form->is_attribute() : NULL;
-      if( attr && (attr->_atype == INS_ATTR) ) {
+      if (attr && (attr->_atype == INS_ATTR)) {
         // Insert the new attribute into the linked list.
         Attribute *temp = attr_parse(ident);
         temp->_next = instr->_attribs;
         instr->_attribs = temp;
       } else {

@@ -256,19 +258,22 @@
     parse_err(SYNERR, "missing '%%}' in instruction definition\n");
     return;
   }
   // Check for "Set" form of chain rule
   adjust_set_rule(instr);
-  if (_AD._pipeline ) {
-    if( instr->expands() ) {
-      if( instr->_ins_pipe )
+  if (_AD._pipeline) {
+    // No pipe required for late expand.
+    if (instr->expands() || instr->lateExpands()) {
+      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 )
+      if (!instr->_ins_pipe) {
         parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident);
     }
   }
+  }
   // Add instruction to tail of instruction list
   _AD.addForm(instr);
 
   // Create instruction form for each additional match rule
   rule = instr->_matrule;

@@ -2855,11 +2860,12 @@
       if (strcmp(rep_var, "constanttablebase") == 0) {
         // This instruct is a MachConstantNode.
         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);
+          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)) {

@@ -3048,10 +3054,152 @@
 
   // Set encode class of this instruction.
   inst._insencode = encrule;
 }
 
+//------------------------------lateExpand_parse-------------------------------
+// Encode rules have the form
+//   lateExpand( encode_class_name(parameter_list) );
+//
+// The "encode_class_name" must be defined in the encode section.
+// The parameter list contains $names that are locals.
+//
+// This is just a copy of ins_encode_parse without the loop.
+void ADLParser::lateExpand_parse(InstructForm& inst) {
+  inst._is_lateExpand = true;
+
+  // Parse encode class name.
+  skipws();                        // Skip whitespace.
+  if (_curchar != '(') {
+
+    parse_err(SYNERR, "missing '(' in lateExpand 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.
+  // identifier is optional.
+  if (_curchar != ')') {
+    ec_name = get_ident();
+    if (ec_name == NULL) {
+      parse_err(SYNERR, "Invalid lateExpand class name after 'lateExpand('.\n");
+      return;
+    }
+    // Check that encoding is defined in the encode section.
+    EncClass *encode_class = _AD._encode->encClass(ec_name);
+
+    // Get list for encode method's parameters
+    NameAndList *params = encrule->add_encode(ec_name);
+
+    // Parse the parameters to this encode method.
+    skipws();
+    if (_curchar == '(') {
+      next_char();                 // Move past '(' for parameters.
+
+      // Parse the encode method's parameters.
+      while (_curchar != ')') {
+        char *param = get_ident_or_literal_constant("encoding operand");
+        if (param != NULL) {
+          // Found a parameter:
+
+          // First check for constant table support.
+
+          // Check if this instruct is a MachConstantNode.
+          if (strcmp(param, "constanttablebase") == 0) {
+            // This instruct is a MachConstantNode.
+            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))  {
+            // This instruct is a MachConstantNode.
+            inst.set_is_mach_constant(true);
+
+            // If the constant keyword has an argument, parse it.
+            if (_curchar == '(') constant_parse(inst);
+          }
+
+          // Else check it is a local name, add it to the list, then check for more.
+          // New: allow hex constants as parameters to an encode method.
+          // New: allow parenthesized expressions as parameters.
+          // New: allow "primary", "secondary", "tertiary" as parameters.
+          // New: allow user-defined register name as parameter.
+          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 == ',') {
+            // More parameters to come.
+            next_char();           // Move past ',' between parameters.
+            skipws();              // Skip to next parameter.
+          } else if (_curchar == ')') {
+            // Done with parameter list
+          } else {
+            // Only ',' or ')' are valid after a parameter name.
+            parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", ec_name);
+            return;
+          }
+
+        } else {
+          skipws();
+          // Did not find a parameter.
+          if (_curchar == ',') {
+            parse_err(SYNERR, "Expected encode parameter before ',' in lateExpand %s.\n", ec_name);
+            return;
+          }
+          if (_curchar != ')') {
+            parse_err(SYNERR, "Expected ')' after lateExpand parameters.\n");
+            return;
+          }
+        }
+      } // WHILE loop collecting parameters.
+      next_char();                 // Move past ')' at end of parameters.
+    } // Done with parameter list for encoding.
+
+    // Check for ',' or ')' after encoding.
+    skipws();                      // Move to character after parameters.
+    if (_curchar != ')') {
+      // Only a ')' is allowed.
+      parse_err(SYNERR, "Expected ')' after lateExpand %s.\n", ec_name);
+      return;
+    }
+  } // Done parsing lateExpand method and their parameters.
+  if (_curchar != ')') {
+    parse_err(SYNERR, "Missing ')' at end of lateExpand description.\n");
+    return;
+  }
+  next_char();                     // Move past ')'.
+  skipws();                        // Skip leading whitespace.
+
+  if (_curchar != ';') {
+    parse_err(SYNERR, "Missing ';' at end of lateExpand.\n");
+    return;
+  }
+  next_char();                     // Move past ';'.
+  skipws();                        // Be friendly to oper_parse().
+
+  // Debug Stuff.
+  if (_AD._adl_debug > 1) fprintf(stderr, "Instruction lateExpand: %s\n", ec_name);
+
+  // Set encode class of this instruction.
+  inst._insencode = encrule;
+}
+
 
 //------------------------------constant_parse---------------------------------
 // Parse a constant expression.
 void ADLParser::constant_parse(InstructForm& inst) {
   // Create a new encoding name based on the name of the instruction